爲什麼不拆解程序並親自查看?但是,我們走了。這是testprogram:
int main() {
int sum = 0;
int i;
for(i = 0; i < 10000; i++) {
if (i < 200 && !(i%20)) {
sum += 0xC0DE;
}
sum += 0xCAFE;
}
printf("%d\n", sum);
return 0;
}
,這是用gcc 4.3.3和-03編譯的反彙編代碼的有趣的部分:
0x08048404 <main+20>: xor ebx,ebx
0x08048406 <main+22>: push ecx
0x08048407 <main+23>: xor ecx,ecx
0x08048409 <main+25>: sub esp,0xc
0x0804840c <main+28>: lea esi,[esi+eiz*1+0x0]
0x08048410 <main+32>: cmp ecx,0xc7
0x08048416 <main+38>: jg 0x8048436 <main+70>
0x08048418 <main+40>: mov eax,ecx
0x0804841a <main+42>: imul esi
0x0804841c <main+44>: mov eax,ecx
0x0804841e <main+46>: sar eax,0x1f
0x08048421 <main+49>: sar edx,0x3
0x08048424 <main+52>: sub edx,eax
0x08048426 <main+54>: lea edx,[edx+edx*4]
0x08048429 <main+57>: shl edx,0x2
0x0804842c <main+60>: cmp ecx,edx
0x0804842e <main+62>: jne 0x8048436 <main+70>
0x08048430 <main+64>: add ebx,0xc0de
0x08048436 <main+70>: add ecx,0x1
0x08048439 <main+73>: add ebx,0xcafe
0x0804843f <main+79>: cmp ecx,0x2710
0x08048445 <main+85>: jne 0x8048410 <main+32>
0x08048447 <main+87>: mov DWORD PTR [esp+0x8],ebx
0x0804844b <main+91>: mov DWORD PTR [esp+0x4],0x8048530
0x08048453 <main+99>: mov DWORD PTR [esp],0x1
0x0804845a <main+106>: call 0x8048308 <[email protected]>
所以我們看到,對於這個特殊的例子,沒有它不是。我們只有一個循環從主+32開始,到主+85結束。如果您在閱讀彙編代碼ecx = i時遇到問題, ebx =總和。
但是你的里程可能會有所不同 - 誰知道這種特殊情況下使用的啓發式算法,因此你必須編譯你想到的代碼,看看更長/更復雜的計算會影響優化器。
儘管在任何現代CPU上,分支預測器在這樣簡單的代碼上都會做的很好,所以在任何情況下都不會看到太多的性能損失。如果您的計算密集型代碼需要數十億個週期,那麼可能會出現少量預測失誤的性能損失是多少?
來源
2011-02-16 15:20:55
Voo
你爲什麼不以它爲基準? – fancyPants 2011-02-16 14:55:47
我當然記得從GCC郵件列表中討論這個問題 - 至少有一些支持。在你的情況下是否真的這樣做可能最容易通過檢查彙編輸出或`-da`來驗證;它可能只是展開了0例或最大循環的情況下,我不記得了。然而在你的情況下(對於200-10000,它將是:測試我<200,++ i,測試我<10000)我懷疑它會產生任何顯着的性能差異 - 按每個循環一個或兩個循環的順序將會被計算代價昂貴的代碼所淹沒。 – Rup 2011-02-16 14:58:51