2015-04-24 59 views
14

我正在嘗試使用以下簡單的C代碼來描述計算sqrt所花費的時間,其中readTSC()是讀取CPU循環計數器的函數。爲什麼編譯器會在編譯的彙編代碼中生成額外的sqrts

double sum = 0.0; 
int i; 
tm = readTSC(); 
for (i = 0; i < n; i++) 
    sum += sqrt((double) i); 
tm = readTSC() - tm; 
printf("%lld clocks in total\n",tm); 
printf("%15.6e\n",sum); 

然而,正如我打印出一個Intel機器上使用

gcc -S timing.c -o timing.s 

彙編代碼,結果(如下所示)是令人驚訝的?

爲什麼在彙編代碼中有兩個sqrts,一個使用sqrtsd指令,另一個使用函數調用?它是否與循環展開並試圖在一次迭代中執行兩個sqrt相關?

以及如何理解行

ucomisd %xmm0, %xmm0 

爲什麼它比較%xmm0本身?

//----------------start of for loop---------------- 
call readTSC 
movq %rax, -32(%rbp) 
movl $0, -4(%rbp) 
jmp .L4 
.L6: 
cvtsi2sd -4(%rbp), %xmm1 
// 1. use sqrtsd instruction 
sqrtsd %xmm1, %xmm0 
ucomisd %xmm0, %xmm0 
jp .L8 
je .L5 
.L8: 
movapd %xmm1, %xmm0 
// 2. use C funciton call 
call sqrt 
.L5: 
movsd -16(%rbp), %xmm1 
addsd %xmm1, %xmm0 
movsd %xmm0, -16(%rbp) 
addl $1, -4(%rbp) 
.L4: 
movl -4(%rbp), %eax 
cmpl -36(%rbp), %eax 
jl .L6 
//----------------end of for loop---------------- 
call readTSC 
+3

這必須是未優化的代碼。 [真正的代碼](http://goo.gl/CewylI)正確地設置了分支(在非NaN情況下沒有采用分支),並且遺漏了'je',因爲它在ucomisd後總是成立'。 –

回答

23

它使用庫sqrt函數進行錯誤處理。請參閱glibc的文檔:20.5.4 Error Reporting by Mathematical Functions:數學函數集errno與不具有IEEE754異常標誌的系統兼容。相關:glibc的math_error(7)手冊頁。

作爲一種優化,它首先嚐試通過內聯sqrtsd指令來執行的平方根,然後使用ucomisd指令設定所述標誌如下檢查結果針對其自身:

CASE (RESULT) OF 
    UNORDERED: ZF,PF,CF 111; 
    GREATER_THAN: ZF,PF,CF 000; 
    LESS_THAN: ZF,PF,CF 001; 
    EQUAL:  ZF,PF,CF 100; 
ESAC; 

特別是,將QNaN與自身進行比較將返回UNORDERED,如果您嘗試取負數的平方根,就會得到這個結果。這由jp分支覆蓋。檢查je只是偏執狂,檢查確切的平等。


還要注意,GCC有一個-fno-math-errno option這會犧牲這個錯誤處理的速度。此選項是-ffast-math的一部分,但可以在不啓用任何結果更改優化的情況下自行使用。

sqrtsd本身正確地產生負NaN和NaN輸入的NaN,並設置IEEE754無效標誌。檢查和分支僅爲以保留大多數代碼不依賴的設置語義。

-fno-math-errno是Darwin(OS X)上的默認值,其中數學庫從不設置errno,因此可以在沒有此檢查的情況下內聯函數。

+2

請注意,' - 數學'不僅僅是犧牲錯誤處理速度。特別是,它也違反了IEEE 754標準,即謹慎使用,只有在知道自己在做什麼的情況下才適用。另見http://stackoverflow.com/questions/7420665/what-does-gccs-ffast-math-actually-do – godfatherofpolka

+0

@godfatherofpolka是的,一般。然而,在這種情況下,就是這樣。 – Jester

+2

是的,這是對的,我只是覺得每一個提及快速數學標誌都應該帶有警告標籤,這就是爲什麼我添加了該評論。 – godfatherofpolka

相關問題