为什么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?

查看:233
本文介绍了为什么g ++(4.6和4.7)将这个分区的结果提升为双重?我可以停止吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一些模板化的代码,使用浮点和双精度值来比较数值算法,以便与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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆