2012-04-25 71 views
4

我在C++中编写了这个小程序来检查CPU负载情况。x64性能与x86相比

#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: %d\r\n", t2-t1); 
    getchar(); 
} 

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

+4

什么编译器?什么优化? – GManNickG 2012-04-25 14:39:23

+3

我也可能在最后打印'x',以确保优化器不会决定它可以丢弃'x * ='计算线。 – Rup 2012-04-25 14:40:27

+0

我正在使用vs2010 express与“Microsoft Visual C++ 2010 Service Pack 1:Windows SDK 7.1编译器更新”。我在调试模式下将其编译为无优化。 – Idov 2012-04-25 14:41:19

回答

12

寻找与/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:

  • 86,/Ox:22704蜱
  • 64,/Ox:822蜱
  • 86,/Ox /arch:SSE2:3432蜱
  • 64,/Ox /favor:INTEL64:1014只蜱
  • x86,/Ox /arch:SSE2 /fp:fast:834 ticks
3

这里的许多可能性与x86和x64没有多大关系。一种明显的可能性是大多数(所有?)编译器都使用SSE作为浮点数,其中大多数情况下通常使用x86模式下的8087式指令。由于你的代码在浮点上很重,这可能会产生很大的不同。

另一种可能性是,在x64的过程或重写过程中,他们发现/解决了代码生成器中的一些问题,至少在某些情况下,它可以生成更好的代码。

尽管它看起来并不适用于此,但一些代码也可从64位模式下可用寄存器的增加的大小和/或数量中获益。

5

原因确实与上证所有关。默认情况下,VS中的64位版本生成SSE2指令,但您必须使用/arch:SSE2开关明确地为32位版本启用它。当你这样做的时候,你会得到32位和64位版本的可比较的运行时间。

1

它的一部分绝对是SSE,但是为什么x64使用SSE模式有一个很大的原因:所有AMD64 CPU都需要SSE2。另一部分也可能是增加的寄存器数

+0

暂时抛开浮点,这已经被其他海报覆盖了,增加的寄存器组f或整数标量通用寄存器,添加r8 r9等rax rbx等帮助巨大的注册压力,以前杀死程序员。 – 2017-08-31 01:30:10