-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
numbers test failure on ARM #10124
Comments
|
Looks like LLVM's ARM assembly printing needs work? |
Interestingly, the problem seems to only be with unsigned ints:
|
I think this is the highest priority ARM bug, and if we can fix this, we may actually have a usable Julia on arm. There are various other issues, but they are not blockers like this one. |
I'm having this bug right now too. Also, the problem is for Int64 as well right? typemax of Int64 should be (2^63 -1), and i get
|
Is ARM a 32-bit system? On 32-bit systems |
Everything up to and including ARMv7 are. I think I'm the only one working on ARMv8 (AArch64) right now (and I'm stuck in an LLVM assert). |
Then |
@StefanKarpinski
So 1.) I'm not sure how julia is representing that number on a 32-bit system and 2.) why I'm even allowed to mess with 64-bit types on a 32-bit build. In playing around, and assuming that it's okay to emulate 64-bit types on a 32-bit machine, I think now that the problem is in the syntax of the tests and is perhaps not an actual bug in the code? The test
Some follow-ups. I wonder why there are bit-agnostic types Int and UInt, but no type Float? One must specify Float32 or Float64. I wonder why I'm even allowed to use 64-bit types on this build. Is there a way to disallow julia from trying to use 64-bit data types on 32-bit systems? Also, Float64 seems to be the default type even on a 32-bit machine.
|
They can handle 64-bit types just fine, you just have to be explicit about it because Julia's default integer type is a "machine integer".
FURTHER CLARIFICATION: The number of "bits" of a CPU is first and foremost about the size of pointers--that is, how much memory (physical+virtual) the system is capable of addressing. This is often (almost always? I'm not entirely sure) further reflected in the size of the CPU's registers. A consequence is that representing a 64-bit integer requires loading two registers and performing instructions on the both of them, which is slower than working with 32-bit integers. So that's why Julia makes that the default. But "emulating" a 64-bit type is a bit of a strong term for it; it's just that more operations are required. For floating point, the traditional x87 instructions work with both single- and double-precision floating point values, and more recently the extensions made available in SSE and its extensions, and AVX all work with extremely wide registers (128 bits or more) and can address all or part of the register simultaneously, even when the processor is 32-bit. ARM is a bit different: in 32-bit ARM processors with hardware floating-point, there is a scalar unit, confusingly called the "Vector Floating Point" unit or VFP, which can handle both single- and double-precision arithmetic, and a vector unit, which can handle vectorized single-precision only arithmetic using the NEON instruction set. I'm not sure how eager LLVM's JIT is to emit NEON instructions. (Any errors in the above are my own. Corrections are welcomed.) |
Related: this comment. |
System word size has nothing to do with what size floating-point numbers to use – the 8087 already had 64-bit IEEE floating-point registers. |
(I added more details in my comment above, which gets into more detail on floating-point handling on x86 vs. 32-bit ARM. I haven't looked to see what's new for floating point in AArch64.) |
this was an intended change, we are just seeing the new behavior show up first on ARM since on x86_64 we are just getting UB from a processor intrinsic (http://reviews.llvm.org/D2804#75076) |
Chasing failing tests of
This throws an InexactError on my x86_64 machine. It seems like it does modulo instead since:
Is this a related (intended) change, or is this a separate issue? |
This is a good place to capture all these, unless we believe the underlying causes are different. |
no, we need to fix our code to stop relying on undefined behavior of the gcc 4.x x86 compiler. |
As @ihnorton noted in the original issue, wrapping this test in a function does give the correct result.
|
That's the trouble with UB: it's even allowed to return the expected answer at times. |
@ViralBShah Thanks, I'll follow-up on the tests with rationalize in a separate issue (but right now I have no access to my Pi, on vacation) |
"A consequence is that representing a 64-bit integer requires loading two registers and performing instructions on the both of them, which is slower than working with 32-bit integers. So that's why Julia makes that the default." Note also, while 64-bit would not be necessary for pointers, 64-bit for that and some other things would be dangerous as when you do use two instructions, access is no longer atomic. I would rely on that for stuff I'm thinking up.. Because I'm thinking of when Julia will have threads. Until then 64-bit types will look atomic to you. |
I followed the code with
Where
The documentation for So maybe we need to check the floating point value for being representable as a |
that is a good summary. I would only add that the challenge has been in attempting to make this test type-generic. for IEEE float to signed twos-complement integer, I think we can use the test from the libgcc / libsupport_rt libraries http://reviews.llvm.org/diffusion/L/browse/compiler-rt/trunk/lib/builtins/fp_fixint_impl.inc$1 of |
I have written some code according to what @vtjnash said. https://gist.github.com/nkottary/a53749c02697e5434578 I haven't tested it on ARM yet, but it fixes the issue in x86. |
I think the following should be sufficient: function ==(x::$Tf, y::$Ti)
fy = ($Tf)(y)
(x == fy) & (fy != $(Tf(typemax(Ti)))) & (unsafe_trunc($Ti,fy) == y)
end |
Sometimes I wish that code like this was accompanied by a comment explaining the reason behind it. Such as:
I like terse code as much as anybody else, but there's a line when things cross over to magic. Please leave some breadcrumbs for those who joined the Julia project after you. |
@eschnett Good point, I was just being lazy. Here's my attempt at writing up the logic: Suppose that Comparing as floats is easy, but may result in some false positives, as The problem arises when |
@simonbyrne Looks good, except the expression "new part in the middle": Readers of the code won't know which part is new; just "part in the middle" suffices. |
Fix #10124 by adding check for undefined behaviour
On x86:
On ARM:
The text was updated successfully, but these errors were encountered: