x64 性能与 x86 的比较

x64 performance compared to x86

本文关键字:比较 x86 性能 x64      更新时间:2023-10-16

我用 c++ 编写了这个小程序来检查 CPU 负载情况。

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>
int main()
{
    double x = 1;
    int t1 = GetTickCount();
    srand(10000);
    for (unsigned long i = 0; i < 10000000; i++)
    {
        int r = rand();
        double l = sqrt((double)r);
        x *= log(l/3) * pow(x, r);
    }
    int t2 = GetTickCount();
    printf("Time: %drn", t2-t1);
    getchar();
}

我在win7 x64上为x86和x64编译了它。
由于某种原因,当我运行 x64 版本时,它在大约 3 秒
内完成运行但是当我尝试使用 x86 版本时,它花了 48 (!!) 秒。
我尝试了很多次,总是得到类似的结果。
什么可能导致这种差异?

查看/Ox(最大优化)的汇编器输出,x86 和 x64 构建之间的速度差异很明显:

; cl /Ox /Fa tick.cpp
; x86 Line 17: x *= log(l/3) * pow(x, r)
fld     QWORD PTR _x$[esp+32]
mov     eax, esi
test    esi, esi
; ...

我们看到 x87 指令用于此计算。将此与 x64 版本进行比较:

; cl /Ox /Fa tick.cpp
; x64 Line 17: x *= log(l/3) * pow(x, r)
movapd  xmm1, xmm8
mov     ecx, ebx
movapd  xmm5, xmm0
test    ebx, ebx
; ...

现在我们看到正在使用 SSE 指令。

你可以通过/arch:SSE2来尝试和调整Visual Studio 2010来生成类似的指令,但看起来64位编译器只是为你手头的任务生成更好的更快的程序集。

最后,如果放宽浮点模型,x86 和 x64 的性能几乎相同。

时间,不科学的3个最佳:

  • x86, /Ox : 22704 刻度
  • x64, /Ox : 822 刻度
  • x86, /Ox /arch:SSE2 : 3432 刻度
  • x64, /Ox /favor:INTEL64 : 1014 刻度
  • x86, /Ox /arch:SSE2 /fp:fast : 834 刻度

原因确实与SSE有关。 VS 中的 64 位发布版本默认生成 SSE2 指令,但您必须使用 /arch:SSE2 开关为 32 位构建显式启用它。执行此操作时,您将获得 32 位和 64 位构建的可比运行时间。

这里的许多可能性与x86与x64几乎没有关系。一个明显的可能性是大多数(所有?)编译器使用 SSE 作为浮点数,其中大多数编译器通常在 x86 模式下使用 8087 样式的指令。由于您的代码在浮点上很重,这可能会产生重大差异。

另一种可能性是,在x64的过程或重写过程中,他们注意到/修复了代码生成器中的一些问题,至少在某些情况下,这些问题可以生成更好的代码。

虽然它看起来不适用于这里,但一些代码也从 64 位模式下可用的寄存器大小和/或数量的增加中受益匪浅。

其中一部分肯定是SSE,但x64使用SSE模式有很大的原因:所有AMD64 CPU都需要有SSE2。另一部分也可能是增加的寄存器数量