[HN Gopher] The Ffast and the Furious ___________________________________________________________________ The Ffast and the Furious Author : mmastrac Score : 64 points Date : 2022-09-07 22:43 UTC (1 days ago) (HTM) web link (gist.github.com) (TXT) w3m dump (gist.github.com) | jwilk wrote: | Related: | | https://news.ycombinator.com/item?id=32738206 ("Someone's Been | Messing with My Subnormals", 2 days ago, over 120 comments) | warmwaffles wrote: | Reminds me of "The Geometry of Innocent Flesh on the Bone: | Return-into-libc without Function Calls (on the x86)" [1] | | [1]: https://hovav.net/ucsd/dist/geometry.pdf | StefanKarpinski wrote: | The Julia ecosystem (BinaryBuilder specifically) forbids | libraries built with -ffast-math for exactly this kind of reason. | an1sotropy wrote: | The author admits this ia a contrived demo, but I'm still trying | to understand its ostensible logic. The FTZ/DAZ problem is on | line 20: if (x >= nextafterf(0.0, INFINITY)) { | | I think the idea here is: test if x is large enough so that the | subsequent ceilf() will give you an integer i_x >= 1 (because the | actual array index will be PIXBUF_WIDTH - i_x, and the max array | index is PIXBUF_WIDTH-1). With FTZ/DAZ, nextafterf(0.0, INFINITY) | == 0, which breaks the test. | | But in this scenario, wouldn't you just test "if (x > 0)", since | that implies that ceilf(x) must be >= 1? | moyix wrote: | Updates welcome to make it less contrived! :) It's clearly very | confused code, but it does work under normal FP behavior. | MauranKilom wrote: | If I understand correctly, the nextafterf implementation in | crtfastmath.o linked in by the empty file compiled with -ffast- | math does not handle infinities, so nextafterf(0.0, INFINITY) | returns 0.0 (?) and thus i_x = 0 (whereas it should be 1 at | minimum since we access PIXBUF_WIDTH - i_x). | | Did I get that right? | moyix wrote: | Not quite. nextafterf() is trying to return the smallest float | after 0.0 in the direction of infinity (infinity is still valid | even when the FPU is configured to flush denormal numbers to 0; | infinity isn't a denormal number). But since the smallest float | after zero is denormal, when a shared library built with | -ffast-math is loaded (which sets the FPU's FTZ and DAZ bit) | denormal numbers get forced to zero, and so nextafterf returns | 0.0 and the comparison becomes (x >= 0.0), which means that | x=0.0 passes the check and ceilf returns 0.0 rather than 1.0. | ridiculous_fish wrote: | `nextafterf` does not in fact return 0. FTZ flushes denormals | to zero when they are the result of an FP calculation, but | `nextafter` is implemented using _integer_ arithmetic, | because it is much easier: simply add 1 as an integer, with | special handling for Inf /NaN/-0. | | It's only later that it gets treated as zero by DAZ: in the | FP comparison, and then the call to ceil(), both of which use | the FPU. | | edit: confirmed, you can see it in action on this gist. When | compiled with -ffast-math then the denormal does not compare | greater than zero (it is flushed to zero by the comparison), | but its bit pattern is integer value 1, which is | nextafter(0). | | https://gist.github.com/ridiculousfish/bfa7ed6b1d76c114e19b3. | .. | duped wrote: | Another victim of shared libraries. | 323 wrote: | Victim of shared state, not shared libraries. | | You can change floating point modes dynamically, and it's | commonly done, and then it doesn't matter if the library was | dynamically or statically linked. | vitiral wrote: | But if you forget to change it back you may break other | invariants, right? | | Also, what about threads or fibers? I would guess it is | thread-local but not fiber-local? | 323 wrote: | If you're using fibers it's assumed you know what your | doing. | tlb wrote: | That's true about many cpu registers, but compilers take | care of it correctly for everything except floating point | flags. | amluto wrote: | I filed this bug almost 10 years ago. Sigh. | | https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55522 | jcranmer wrote: | Annoyingly, Clang seems unwilling to make any changes until gcc | changes its mind. | wffurr wrote: | "fun and safe" math. Never-ending source of weird graphics bugs. ___________________________________________________________________ (page generated 2022-09-08 23:01 UTC)