Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can -ffast-math be safely used on a typical project?

While answering a question where I suggested -ffast-math, a comment pointed out that it is dangerous.

My personal feeling is that outside scientific calculations, it is OK. I also asume that serious financial applications use fixed point instead of floating point.

Of course if you want to use it in your project the ultimate answer is to test it on your project and see how much it affects it. But I think a general answer can be given by people who tried and have experience with such optimizations:

Can ffast-math be used safely on a normal project?

Given that IEEE 754 floating point has rounding errors, the assumption is that you are already living with inexact calculations.


This answer was particular illuminating on the fact that -ffast-math does much more than reordering operations that would result in a slightly different result (does not check for NaN or zero, disables signed zero just to name a few), but I fail to see what the effects of these would ultimately be in a real code.


I tried to think of typical uses of floating points, and this is what I came up with:

  • GUI (2D, 3D, physics engine, animations)
  • automation (e.g. car electronics)
  • robotics
  • industrial measurements (e.g. voltage)

and school projects, but those don't really matter here.

like image 315
bolov Avatar asked Aug 16 '16 15:08

bolov


2 Answers

One of the especially dangerous things it does is imply -ffinite-math-only, which allows explicit NaN tests to pretend that no NaNs ever exist. That's bad news for any code that explicitly handles NaNs. It would try to test for NaN, but the test will lie through its teeth and claim that nothing is ever NaN, even when it is.

This can have really obvious results, such as letting NaN bubble up to the user when previously they would have been filtered out at some point. That's bad of course, but probably you'll notice and fix it.

A more insidious problem arises when NaN checks were there for error checking, for something that really isn't supposed to ever be NaN. But perhaps through some bug, bad data, or through other effects of -ffast-math, it becomes NaN anyway. And now you're not checking for it, because by assumption nothing is ever NaN, so isnan is a synonym of false. Things will go wrong, spuriously and long after you've already shipped your software, and you will get an "impossible" error report - you did check for NaN, it's right there in the code, it cannot be failing! But it is, because someone someday added -ffast-math to the flags, maybe you even did it yourself, not knowing fully what it would do or having forgotten that you used a NaN check.

So then we might ask, is that normal? That's getting quite subjective, but I would not say that checking for NaN is especially abnormal. Going fully circular and asserting that it isn't normal because -ffast-math breaks it is probably a bad idea.

It does a lot of other scary things as well, as detailed in other answers.

like image 54
harold Avatar answered Oct 22 '22 10:10

harold


I wouldn't recommend to avoid using this option, but I remind one instance where unexpected floating-point behavior struck back.

The code was saying like this innocent construct:

float X, XMin, Y;
if (X < XMin)
{
    Y= 1 / (XMin - X);
}

This was sometimes raising a division by zero error, because when the comparison was carried out, the full 80 bits representation (Intel FPU) was used, while later when the subtraction was performed, values were truncated to the 32 bits representation, possibly being equal.

like image 45
Yves Daoust Avatar answered Oct 22 '22 11:10

Yves Daoust