c++ - x86 和 x64 之间浮点运算的差异

标签 c++ c visual-studio-2010 floating-point 64-bit

我偶然发现了针对 x86 和 x64 的 MS VS 2010 版本(两者都在同一台 64 位机器上执行)之间完成浮点运算的方式不同。

这是一个简化的代码示例:

float a = 50.0f;
float b = 65.0f;
float c =  1.3f;
float d = a*c;
bool bLarger1 = d<b;
bool bLarger2 = (a*c)<b;

bool 值 bLarger1 始终为 false(d 在两个构建中都设置为 65.0)。 变量 bLarger2 对于 x64 为假,但对于 x86 为真!

我很清楚浮点运算和发生的舍入效应。我也知道 32 位有时使用与 64 位版本不同的 float 操作指令。但在这种情况下,我遗漏了一些信息。

为什么首先 bLarger1 和 bLarger2 之间存在差异?为什么它只出现在 32 位版本中?

Left: x86, Right: x64

最佳答案

问题取决于这个表达式:

bool bLarger2 = (a*c)<b;

我看的是VS2008下生成的代码,手上没有VS2010。对于 64 位,代码是:

000000013FD51100  movss       xmm1,dword ptr [a] 
000000013FD51106  mulss       xmm1,dword ptr [c] 
000000013FD5110C  movss       xmm0,dword ptr [b] 
000000013FD51112  comiss      xmm0,xmm1 

For 32 bit the code is:

00FC14DC  fld         dword ptr [a] 
00FC14DF  fmul        dword ptr [c] 
00FC14E2  fld         dword ptr [b] 
00FC14E5  fcompp           

So under 32 bit the calculation is performed in the x87 unit, and under 64 bit it is performed by the x64 unit.

And the difference here is that the x87 operations are all performed to higher than single precision. By default the calculations are performed to double precision. On the other hand the SSE unit operations are pure single precision calculations.

You can persuade the 32 bit unit to perform all calculations to single precision accuracy like this:

_controlfp(_PC_24, _MCW_PC);

当您将其添加到您的 32 位程序中时,您会发现 bool 值都设置为 false。

x87 和 SSE 浮点单元的工作方式存在根本差异。 x87 单元对单精度和 double 类型使用相同的指令。数据被加载到 x87 FPU 堆栈中的寄存器中,这些寄存器始终是 10 字节的 Intel 扩展。您可以使用浮点控制字来控制精度。但是编译器编写的指令不知道该状态。

另一方面,SSE 单元对单精度和 double 运算使用不同的指令。这意味着编译器可以发出完全控制计算精度的代码。

所以,x87 单元是这里的坏人。您也许可以尝试说服您的编译器甚至为 32 位目标发出 SSE 指令。当然,当我在 VS2013 下编译您的代码时,我发现 32 位和 64 位目标都发出了 SSE 指令。

关于c++ - x86 和 x64 之间浮点运算的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22710272/

相关文章:

c++ - std::shared_ptr 或 std::unique_ptr 赋值运算符重载

c - SendMessage 适用于 WM_CHAR,但不适用于 WM_KEYDOWN

c - 这个包含 C 源代码的 shell 脚本如何工作?

c# - 在 VS 2010 中创建动态项目模板?

c++ - 在 Visual Studio 中使用子项目

C++ 列表拼接帮助

c++ - 在 Qt 项目中包含 Rcpp 会导致错误影响不同的包含库

c++ - 如何显示以字母开头的结果,例如仅 A

c - 为什么扫描 ("%s",&str);表现为 scanf ("%s",str);?

visual-studio-2010 - 工作流 XAML 智能感知 VS 2010