考虑以下循环:编译器如何优化这一段代码
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
你如何计时循环? –