编译器优化导致程序运行速度变慢
我在C中编写了以下代码。它非常简单,因为它恰好为每个for循环移位x
。
int main() { int x = 1; for (int i = 0; i > -2; i++) { x >> 2; } }
现在发生的奇怪的事情是,当我只是编译它而没有任何优化或第一级优化( -O
)时,它运行得很好(我正在计时可执行文件和它的大约1.4s
-O
和5.4s
没有任何优化。
现在当我添加-O2
或-O3
开关进行编译并为生成的可执行文件计时时,它不会停止(我已经测试了多达60s
)。
关于可能导致这种情况的任何想法?
优化的循环产生一个无限循环,这是您依赖于有符号整数溢出的结果。 有符号整数溢出是C
未定义的行为,不应该依赖它。 它不仅会使开发人员感到困惑,而且编译器也可能会对其进行优化。
汇编(无优化): gcc -std=c99 -S -O0 main.c
_main: LFB2: pushq %rbp LCFI0: movq %rsp, %rbp LCFI1: movl $1, -4(%rbp) movl $0, -8(%rbp) jmp L2 L3: incl -8(%rbp) L2: cmpl $-2, -8(%rbp) jg L3 movl $0, %eax leave ret
assembly(优化级别3):gcc -std = c99 -S -O3 main.c
_main: LFB2: pushq %rbp LCFI0: movq %rsp, %rbp LCFI1: L2: jmp L2 #<- infinite loop
通过查看生成的二进制文件(使用objdump
或其他内容),您将获得明确的答案。
但正如其他人所说,这可能是因为你依赖于未定义的行为。 一种可能的解释是编译器可以自由地假设i
永远不会小于-2
,因此将完全消除条件,并将其转换为无限循环。
此外,您的代码没有可观察到的副作用,因此编译器也可以自由地优化整个程序,如果它喜欢的话。
有关为什么整数溢出未定义的其他信息,请访问:
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
搜索“有符号整数溢出”段落。