考慮以下循環:編譯器如何優化這一段代碼
unsigned long x = 0;
for(unsigned long i = 2314543142; i > 0; i--)
x+=i;
std::cout << x << std::endl;
當我編譯這通常它需要大約6.5秒執行該循環
。但是當我使用-O3優化進行編譯時,循環會在10^-6秒內執行。這怎麼可能?編譯器肯定不知道x的閉式表達式如何...
考慮以下循環:編譯器如何優化這一段代碼
unsigned long x = 0;
for(unsigned long i = 2314543142; i > 0; i--)
x+=i;
std::cout << x << std::endl;
當我編譯這通常它需要大約6.5秒執行該循環
。但是當我使用-O3優化進行編譯時,循環會在10^-6秒內執行。這怎麼可能?編譯器肯定不知道x的閉式表達式如何...
如果使用優化進行編譯,您並不需要知道關於程序集的所有信息,以查看編譯器在編譯時確定x的值。
我稍微修改了您的代碼,以便能夠使用在線工具Compiler Explorer,將std::cout << x << std::endl
更改爲extern unsigned long foo;
和foo = x;
。沒有必要,但它使輸出更清潔。
與-02編譯:
test():
movabs rax, 2678554979246887653
mov QWORD PTR foo[rip], rax
ret
編譯時-O0:
test():
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], 0
mov DWORD PTR [rbp-16], -1980424154
mov DWORD PTR [rbp-12], 0
jmp .L2
.L3:
mov rax, QWORD PTR [rbp-16]
add QWORD PTR [rbp-8], rax
sub QWORD PTR [rbp-16], 1
.L2:
cmp QWORD PTR [rbp-16], 0
setne al
test al, al
jne .L3
mov rax, QWORD PTR [rbp-8]
mov QWORD PTR foo[rip], rax
leave
ret
另:未定義行爲由於i >= 0
代碼的第一個版本僅僅輸出:
test():
.L2:
jmp .L2
:-)
所以看起來編譯器在編譯時正在計算某些東西。但是我無法在任何地方找到輸出值2678554979246887653 ... – user3726947
@ user3726947對不起,我不小心使用了'extern unsigned foo'而不是'extern unsigned long foo'。更新後的答案顯示正確的輸出值。 – gurka
編譯器確定循環後x的值,並在輸出語句中使用該值。
相對於程序的長度,這必須是一個相當慢的編譯。 –
雖然我沒有測量它,但編譯時間幾乎是瞬間的。當然不會超過沒有-O3優化的編譯時間。 – user3726947
您是否嘗試過使用匯編語言輸出來查看生成的代碼? –
不幸的是,我不知道任何程序集 – user3726947
你如何計時循環? –