[HN Gopher] Weird compiler bug - Same code, different results
___________________________________________________________________
Weird compiler bug - Same code, different results
Author : zaitanz
Score : 38 points
Date : 2021-01-29 21:24 UTC (1 hours ago)
(HTM) web link (blog.zaita.com)
(TXT) w3m dump (blog.zaita.com)
| [deleted]
| lysium wrote:
| I would have never thought that the output of some floating point
| operations depend on the ,,reset of the floating point package".
| What gives?
| comex wrote:
| The processor itself supports configuring some aspects of
| floating point behavior; on x86 this is the MXCSR register. The
| most important one is rounding mode: you can choose round-to-
| nearest, round-down, round-up, or round-towards-zero. Less
| common options include whether to raise an exception on various
| out-of-range conditions, and whether to treat denormal numbers
| as zero (faster but less accurate and not IEEE 754 compliant).
|
| The C standard library has functions to do this configuration;
| search for fesetenv. _fpreset is not a standard function but,
| at least in Wine's implementation [1], just resets the relevant
| configuration registers to an initial state.
|
| [1] https://github.com/wine-
| mirror/wine/blob/e909986e6ea5ecd49b2...
| brucehoult wrote:
| At a minimum, when there is a switch between threads the
| floating point state of the old thread needs to be saved and
| the floating point state of the incoming thread loaded. This
| includes such things as rounding mode.
|
| If the thread package was not setting up the "saved" state for
| a new thread before switching to it then that state could be
| not what was desired. The best thing to do would probably be to
| copy the current FP state of the parent at the moment the
| thread is created.
|
| On a long series of calculations changing the rounding mode
| could well be enough to cause the difference in results the
| poster saw.
|
| I would tend to the opinion that redoing the calculation with
| different rounding modes is in fact a not bad way to figure out
| how reliable the results are in the first place.
|
| (the rounding mode is not the only thing affected by not saving
| and restoring the FP state correctly)
| willxinc wrote:
| Things like rounding mode and denornal behavior could be
| controlled by CPU flags. Imy not familiar with x86, but this is
| defiy the case in PPC.
| cperciva wrote:
| Probably the author is accidentally getting 80-bit "extended
| double" arithmetic.
| wiml wrote:
| Some kind of internal state specific to Microsoft's libm? It
| doesn't look like _fpreset() is present anywhere else.
|
| Though in general, IEEE-754 math does have a small amount of
| global state, for stuff like rounding modes and subnormals.
| Perhaps the spawned thread's fenv was unexpected.
|
| I'm not super convinced by this blog post anyway, since it
| immediately confuses associativity with commutativity.
| brucehoult wrote:
| If you read the article you find that this is a bug in MinGW64
| libraries.
|
| It's not a compiler bug, it's not a problem in C/C++, or even in
| IEEE-754 floating point math. The MinGW64 thread library simply
| forgot to initialize the FPU correctly.
|
| He'd have had the same problem if he wrote his code in assembly
| language and then ran it in a MinGW64 thread.
| gus_massa wrote:
| > _This means that floating point arithmetic is non-associative.
| In that A + B != B + A._
|
| The equation is the commutative property, not associative. IIRC
| addition in IEEE-754 is commutative.
|
| The property that fails is (A+B)+C = A+(B+C).
| titzer wrote:
| Do _not_ use C /C++ for numerical code where accuracy is needed.
| These languages are not specified to conform to IEEE 754 and you
| are absolutely asking for trouble.
| parekhnish wrote:
| So, what _should_ be used?
| cratermoon wrote:
| COBOL
|
| Seriously? Anything but floating point if you care about
| precision and accuracy.
| jcranmer wrote:
| In practice, all of the C compilers will (or can be made to)
| conform to IEEE 754, although #pragma STDC FENV_ACCESS ON
| support is very spotty (and consequently non-default rounding-
| mode support), although Clang/LLVM has been working on this for
| the past several months.
|
| (That reminds me, I need to harangue the llvm-libc folks to add
| that pragma to their fpenv code for correctness sake).
| cperciva wrote:
| My copy of C11 says Annex F (normative)
| IEC 60559 floating-point arithmetic F.1
| Introduction This annex specifies C language support for
| the IEC 60559 floating-point standard [...] previously
| designated ANSI/IEEE 754-1985.
| titzer wrote:
| C "supports" whatever the hardware and compiler feel like
| supporting. It absolutely does not mandate anything. In
| particular, there are a number of particularly simple
| compiler optimizations that are not forbidden, though they
| are not technically correct according to IEEE 754, such as
| algebraic reassociation and simple commutativity. Moreover, C
| allows subexpressions to be computed in higher precision
| (e.g. 80 bit "long double"), which is observable. That last
| one is primarily due to the x87 FPU coprocessor design that
| has given us a good 35 years of headaches. Good riddance to
| that!
| shakna wrote:
| > Support for Annex F (IEEE-754 / IEC 559) of C99/C11
|
| > The Clang compiler does not support IEC 559 math
| functionality. Clang also does not control and honor the
| definition of __STDC_IEC_559__ macro. Under specific options
| such as -Ofast and -ffast-math, the compiler will enable a
| range of optimizations that provide faster mathematical
| operations that may not conform to the IEEE-754
| specifications. The macro __STDC_IEC_559__ value may be
| defined but ignored when these faster optimizations are
| enabled.
|
| If you make use of Clang, you won't find support for Annex F,
| and in point of fact you can't even macro check to see if it
| even will support Annex F.
|
| The story with GCC is... More complicated. It guarantees
| it'll follow Annex F for only some operations [0].
|
| So the upshot is... Most people can't tell when and how Annex
| F might be followed.
|
| [0] https://gcc.gnu.org/onlinedocs/gcc-7.4.0/gcc/Floating-
| point-...
___________________________________________________________________
(page generated 2021-01-29 23:01 UTC)