2012-04-25 242 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