为什么g ++(4.6和4.7)将这个分区的结果提升为双重?我可以停止吗? [英] Why does g++ (4.6 and 4.7) promote the result of this division to a double? Can I stop it?
问题描述
我正在编写一些模板化的代码,使用浮点和双精度值来比较数值算法,以便与GPU实现进行比较。
I was writing some templated code to benchmark a numeric algorithm using both floats and doubles, in order to compare against a GPU implementation.
我发现我的浮点代码慢,使用来自英特尔的Vtune放大器调查后,我发现g ++生成额外的x86指令(cvtps2pd / cvtpd2ps和unpcklps / unpcklpd)将一些中间结果从float转换为double,然后再次。
I discovered that my floating point code was slower and after investigating using Vtune Amplifier from Intel I discovered that g++ was generating extra 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.
在使用标志-Wdouble-promotion(BTW不包括-Wall或-Wextra)编译后,肯定会出现性能降低几乎为10%足够的g ++警告我结果正在被推广。
After compiling with the flag -Wdouble-promotion (which BTW is not included with -Wall or -Wextra), sure enough g++ warned me that the results were being promoted.
我把这个简化为一个简单的测试用例,如下所示。请注意,c ++代码的顺序会影响生成的代码。复合语句(T d1 = log(r)/ r;)产生警告,而分离版本不(T d = log(r); d / = r;)。
I reduced this to a simple test case shown below. Note that the ordering of the c++ code affects the generated code. The compound statement (T d1 = log(r)/r;) produces a warning, whilst the separated version does not (T d = log(r); d/=r;).
以下是用g ++ - 4.6.3-1ubuntu5和g ++ - 4.7.3-2ubuntu1〜12.04编译的,结果相同。
The following was compiled with both g++-4.6.3-1ubuntu5 and g++-4.7.3-2ubuntu1~12.04 with the same results.
编译flags是:
g ++ - 4.7 -O2 -Wdouble-promotion -Wextra -Wall -pedantic -Werror -std = c ++ 0x test.cpp -o test
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;
}
我意识到c ++ 11标准允许编译器自由裁量权。但为什么秩序重要?
I realise that the c++11 standard allows the compiler discretion here. But why does the order matter?
我可以明确指示g ++只使用浮点数进行此计算吗?
Can I explicitly instruct g++ to use floats only for this calculation?
编辑:由Mike Seymour解决。需要使用std :: log来确保获取重载的日志版本,而不是调用C double log(double)
。
SOLVED by Mike Seymour. Needed to use std::log to ensure picking up the overloaded version of log instead of calling the C double log(double)
. The warning was not generated for the separated statement because this is a conversion and not a promotion.
推荐答案
问题是
log(r)
$ b b
在这个实现中,似乎全局命名空间中只有 log
是C库函数, double log(double) code>。请记住,没有指定C库中的C库头文件是否将它们的定义转储到全局命名空间以及
namespace std
中。
您想要
std::log(r)
以确保C ++库定义的额外重载可用。
to ensure that the extra overloads defined by the C++ library are available.
这篇关于为什么g ++(4.6和4.7)将这个分区的结果提升为双重?我可以停止吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!