Why does g ++ (4.6 and 4.7) help ensure that the result of this division is double? Can I stop him?

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.

+4
source share
1 answer

Problem

 log(r) 

In this implementation, it seems that the only log in the global namespace is the C library function, double log(double) . Remember that he did not indicate whether the C library headers in the C ++ library dump their definitions into the global namespace, as well as namespace std .

Do you want to

 std::log(r) 

to provide additional overloads defined by the C ++ library.

+5
source

Source: https://habr.com/ru/post/1501490/


All Articles