Issue
I'm getting a massive speedup from using this option when compiling my code. From the man page it says that this option:
Do not set "errno" after calling math functions that are executed with a single instruction, e.g., "sqrt"
Its not clear to me what the 'errno' is, and how it is used elsewhere (is this the same as the exit code of a program?) Furthermore, the man page says:
A program that relies on IEEE exceptions for math error handling may want to use this flag for speed while maintaining IEEE arithmetic compatibility.
Its not clear to me what this means, are the IEEE exceptions standard for c++ or common libraries of c++ (e.g. Eigen, Boost, etc.)
Essentially, I'm trying to determine if this is a 'safe' option to use in my code, or what side-effects I should be aware of from its use. A previous answer says this may affect 'thread local variables' but I have no clue what that means.
EDIT: My code is a simple one-off procedural code to handle a scientific problem. It is not going to be part of a deeply embeded system that requires complex error-handling. However, the code must not fail in subtle, silent ways.
Solution
C introduced the concept of a single errno
or "error number" that could be used to determine the precise cause of the failure of some standard functions, including mathematical functions, to perform their duties. POSIX extended errno
, and C++11 picked up some of those extensions too.
When one of these functions fails, the global integer errno
is set to a value that tells you why. Obviously that incurs a performance penalty.
GCC is saying that this flag disables this behaviour for certain mathematical functions, speeding up your program at the cost of diagnostic utility and standard-compliance.
If you're already not observing errno
when any of the affected functions fails, and you're probably not because you'd never heard of it, then you won't lose any functionality. This may be the case if you're writing a really time-constrained program, or when the particular reason for a failure doesn't dictate what your code does next. (However I advise looking into error checking more broadly to ensure that your code is as robust as it ought to be.)
However, it is possible for you to accidentally observe side-effects if you have a bug. Imagine if you were doing something like the following:
std::some_maths_function(42);
if (errno == ERANGE)
exit(-1);
Oops! We are checking errno
even when some_maths_function(42)
succeeded. Let's say that above this code is a call to std::some_other_maths_function(999)
which usually fails and results in errno
being set to EDOM
. That masked the bug in the code above.
Now turn on the compiler flag. If some_other_maths_function
is one of the functions that no longer sets errno
, your bug will be unmasked, and it may take you a few moments to realise that you ought to have written something more like:
if (std::some_maths_function(42) == -1)
{
if (errno == RANGE)
exit(-1);
}
Of course it's hardly GCC's fault that you had a bug, but this does show how the behaviour of your program can differ after enabling this "optimisation" flag. Indeed, the documentation says:
This option is not turned on by any -O option since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions. It may, however, yield faster code for programs that do not require the guarantees of these specifications.
In other words, this flag sends you off-book. But it may be worth it.
The variable errno
must be thread-local (that is, there is actually one of them for each thread in your program) otherwise it'd be useless in a multi-threaded program. You can research the term "thread-local" for more information on this subject.
Answered By - Lightness Races in Orbit