c++ exp 函数在 i7-3770 和 i7-4790 上 x64 下的不同结果
c++ exp function different results under x64 on i7-3770 and i7-4790
当我使用以下代码执行一个简单的 x64 应用程序时,我在 Windows 配备 i7-3770 和 i7-4790 CPU 的 PC 上得到不同的结果
#include <cmath>
#include <iostream>
#include <limits>
void main()
{
double val = exp(-10.240990982718174);
std::cout.precision(std::numeric_limits<double>::max_digits10);
std::cout << val;
}
i7-3770 上的结果:
3.5677476354876406e-05
i7-4790 上的结果:
3.5677476354876413e-05
当我修改代码调用
unsigned int control_word;
_controlfp_s(&control_word, _RC_UP, MCW_RC);
在调用 exp 函数之前,两个 CPU 都提供相同的结果。
我的问题:
- 有没有人知道 i7-3770 和 i7-4790 之间的差异原因?
- 有没有办法在 Visual Studio 2015/2017 C++ 项目中为整个项目设置浮点精度或一致性,而不仅仅是为以下函数调用? "Floating Point Model" 设置 (/fp) 对这里的结果没有任何影响。
假设 double 使用 IEEE-754 编码,并使用这个 decimal to binary converter,你可以看到:
3.5677476354876406e-05 is represented in hexa as 0x3F02B48CC0D0ABA8
3.5677476354876413e-05 is represented in hexa as 0x3F02B48CC0D0ABA9
仅在最后一位不同,可能是由于舍入错误。
我做了一些进一步的调查,发现了以下事实:
- 使用不同的编译器 (Intel)Windows 时也会出现此问题
- 在 linux 系统上两个值相等
我也将这个问题发布到 Visual Studio 社区。我得到的信息是,Haswell 和更新的 CPU 使用 FMA3。您可以在程序开头使用 _set_FMA3_enable(0) 禁用此功能。当我这样做时,结果是一样的。
当我使用以下代码执行一个简单的 x64 应用程序时,我在 Windows 配备 i7-3770 和 i7-4790 CPU 的 PC 上得到不同的结果
#include <cmath>
#include <iostream>
#include <limits>
void main()
{
double val = exp(-10.240990982718174);
std::cout.precision(std::numeric_limits<double>::max_digits10);
std::cout << val;
}
i7-3770 上的结果:
3.5677476354876406e-05
i7-4790 上的结果:
3.5677476354876413e-05
当我修改代码调用
unsigned int control_word;
_controlfp_s(&control_word, _RC_UP, MCW_RC);
在调用 exp 函数之前,两个 CPU 都提供相同的结果。
我的问题:
- 有没有人知道 i7-3770 和 i7-4790 之间的差异原因?
- 有没有办法在 Visual Studio 2015/2017 C++ 项目中为整个项目设置浮点精度或一致性,而不仅仅是为以下函数调用? "Floating Point Model" 设置 (/fp) 对这里的结果没有任何影响。
假设 double 使用 IEEE-754 编码,并使用这个 decimal to binary converter,你可以看到:
3.5677476354876406e-05 is represented in hexa as 0x3F02B48CC0D0ABA8 3.5677476354876413e-05 is represented in hexa as 0x3F02B48CC0D0ABA9
仅在最后一位不同,可能是由于舍入错误。
我做了一些进一步的调查,发现了以下事实:
- 使用不同的编译器 (Intel)Windows 时也会出现此问题
- 在 linux 系统上两个值相等
我也将这个问题发布到 Visual Studio 社区。我得到的信息是,Haswell 和更新的 CPU 使用 FMA3。您可以在程序开头使用 _set_FMA3_enable(0) 禁用此功能。当我这样做时,结果是一样的。