Live data from Hacker News

GNU GCC does not round floating-point divisions to the nearest value

lemire.me

41–50 of 87 posts

Re: GNU GCC does not round floating-point divisions to the nearest value

#41

Earlier quoted context omitted.

-ffast-math should rebrand itself to -ffast-and-more-correct-math ;)

It’s normally not more correct.

I thought fast-math meant (among other things) that the compiler could algebraically simplify things using some rules for real numbers that don't apply to 32-/64-bit floating point numbers. I'd expect that reducing the number of operations would more often than not reduce the error due to rounding, which is what most people would want when they talk about "correctness".

Which step in this (very naive) argument is wrong?

Re: GNU GCC does not round floating-point divisions to the nearest value

#42

Earlier quoted context omitted.

It’s normally not more correct.

I thought fast-math meant (among other things) that the compiler could algebraically simplify things using some rules for real numbers that don't apply to 32-/64-bit floating point numbers. I'd expect that reducing the number of operations would more often than not reduce the error due to rounding, which is what most people would want when they talk about "correctness". Which step in this (very naive) argument is wro…

The code lacking -ffast-math doing math incorrectly, and -ffast-math ending up doing it correctly by accident.

Re: GNU GCC does not round floating-point divisions to the nearest value

#43

An example where this matters -- a new Mario 64 trick on the Virtual Console version because summing round-towards-zero numbers over a sine wave cycle produces a small delta which builds up over a couple of days to make a jump possible https://www.kotaku.com.au/2018/06/the-mario-64-trick-that-ta...

A small clarification: this trick is not new. It was discovered very early on in the investigation of the Wii VC release of Super Mario 64. It was rediscovered by a group of people who were interested in an application of it (which enables one to beat SM64 without the A button) a couple of years ago, and the discovery that the glitch is a result of inaccurate rounding mode emulation followed a couple weeks later.

Re: GNU GCC does not round floating-point divisions to the nearest value

#44

Earlier quoted context omitted.

It’s normally not more correct.

I thought fast-math meant (among other things) that the compiler could algebraically simplify things using some rules for real numbers that don't apply to 32-/64-bit floating point numbers. I'd expect that reducing the number of operations would more often than not reduce the error due to rounding, which is what most people would want when they talk about "correctness". Which step in this (very naive) argument is wro…

Stuff like Kahan summation breaks horribly with -ffast-math, because if you assume that sum is associative the error term, which is ((s+x)-s)-x, simplifies to zero.

https://en.m.wikipedia.org/wiki/Kahan_summation_algorithm

Re: GNU GCC does not round floating-point divisions to the nearest value

#45
post #44

Earlier quoted context omitted.

I thought fast-math meant (among other things) that the compiler could algebraically simplify things using some rules for real numbers that don't apply to 32-/64-bit floating point numbers. I'd expect that reducing the number of operations would more often than not reduce the error due to rounding, which is what most people would want when they talk about "correctness". Which step in this (very naive) argument is wro…

Stuff like Kahan summation breaks horribly with -ffast-math, because if you assume that sum is associative the error term, which is ((s+x)-s)-x, simplifies to zero. https://en.m.wikipedia.org/wiki/Kahan_summation_algorithm

Yeah, that's the obvious counterexample, but that's why I said "more often than not". The statement I was questioning was that fast-math is "normally not more correct."

Re: GNU GCC does not round floating-point divisions to the nearest value

#46
post #28
post #18

Earlier quoted context omitted.

Are you sure? The FPU instruction set is the same.

The platform ABI can differ on the same cpu. I originally had the wrong answer here, but I'm including below for historical purposes and embarrassment. Re-reading on my laptop meant I didn't misread/read-the-expected? Basically by default when compiling for IA32 gcc assumes that there is no SSE unit, and so must use the x87 fpu. Alas the x87 unit doesn't have either 32 or 64 bit ieee floating point types, so the calc…

> Anyway it is not sound to round twice in any numeric operation, and by doing the calculation at one precision and then rounding that to the required precision that is what gcc is doing. > > This is a bug in GCC, floating point is well defined, there isn’t randomness to it, and they’ve introduced additional rounding that is not valid.

Except the C standard has a way to communicate how the extra rounding is being introduced, and it's not random (for C, not C++).

There is simply no way around this issue with the x87 instruction set, GCC (again only for C only, not C++) implements FLT_EVAL_METHOD==2 which is the most sensible that can be implemented with decent performance and without breaking 80-bit long double.

If you are sure you don't need long doubles, use -mpc64.

Re: GNU GCC does not round floating-point divisions to the nearest value

#48

Clang with default settings seems to get it right: https://imgur.com/a/d3LBlLK

It may gets it right for this particular test case, but it will get others wrong. It's impossible to say "it gets it right" from a single testcase or three, you have to look at the compiler innards.

See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 for the gory details; clang works the same as GCC's C++ frontend and the same that GCC <4.5 used to behave for C.

Re: GNU GCC does not round floating-point divisions to the nearest value

#49

An example where this matters -- a new Mario 64 trick on the Virtual Console version because summing round-towards-zero numbers over a sine wave cycle produces a small delta which builds up over a couple of days to make a jump possible https://www.kotaku.com.au/2018/06/the-mario-64-trick-that-ta...

For anyone else interested in similar tricks, here is an in-depth video where someone talks about getting a star with half a button press. It starts out straightforward enough, but eventually gets really interesting when they start talking about parallell worlds that you can only access by abusing bugs to reach unrealistic speeds.

https://www.youtube.com/watch?v=kpk2tdsPh0A&t=77s

Re: GNU GCC does not round floating-point divisions to the nearest value

#50
post #19
post #4

Earlier quoted context omitted.

But then why does python and JavaScript on the same machines get it right?

Because they're compiled to use SSE instructions instead of x87 FPU instructions. If you are still writing 32 bit x86 C code, it's probably some embedded or legacy CPU, and it's wrong to assume SSE instructions are available. So GCC correctly defaults to using FPU instructions instead of SSE instructions on 32 bit x86. Javascript and python will basically never be run in embedded environments, and their legacy enviro…

Plus JavaScript is interpreted and JITed, it can detect and decide at runtime whether to use SSE or x87.
Post reply on HN