I wrote some boilerplate code to compare a numerical algorithm using both floats and doubles to compare them with the GPU implementation.
I found that my floating point code was slower, and after exploring with Intel's Vtune Amplifier, I found that g ++ generated additional x86 instructions (cvtps2pd / cvtpd2ps and unpcklps / unpcklpd) to convert some intermediate results from float to double, and then back again. The performance degradation is almost 10% for this application.
After compiling with the -Wdouble-promotion flag (which BTW is not included in -Wall or -Wextra), g ++ probably warned me that the results were progressing.
I reduced this to a simple test case, shown below. Note that ordering C ++ code affects the generated code. The compound operator (T d1 = log (r) / r;) gives a warning, while the split version does not matter (T d = log (r); d / = r;).
The following was compiled with both g ++ - 4.6.3-1ubuntu5 and g ++ - 4.7.3-2ubuntu1 ~ 12.04 with the same results.
Compile flags:
g ++ - 4.7 -O2 -Wdouble-promotion -Wextra -Wall -pedantic -Werror -std = C ++ 0x test.cpp -o test
#include <cstdlib> #include <iostream> #include <cmath> template <typename T> T f() { T r = static_cast<T>(0.001); // Gives no double promotion warning T d = log(r); d/=r; // Promotes to double T d1 = log(r)/r; return d+d1; } int main() { float f1 = f<float>(); std::cout << f1 << std::endl; }
I understand that the C ++ 11 standard allows the compiler to be seen here. But why does the issue matter?
Is it possible to explicitly specify g ++ to use float only for this calculation?
EDIT: SOLVED by Mike Seymour. You must use std :: log to ensure that an overloaded version of the log is loaded instead of calling C double log(double)
. A warning was not created for the shared operator because it is a conversion, not a promotion.
source share