C 编译器优化导致程序运行较慢
下面是我用C编写的一段代码。它相当简单,因为它对for的每个循环都有正确的位移位C 编译器优化导致程序运行较慢,c,gcc,compiler-optimization,C,Gcc,Compiler Optimization,下面是我用C编写的一段代码。它相当简单,因为它对for的每个循环都有正确的位移位x int main() { int x = 1; for (int i = 0; i > -2; i++) { x >> 2; } } 现在发生的一件奇怪的事情是,当我编译它时没有任何优化,或者使用一级优化(-O),它运行得很好(我正在使用-O和5.4s对可执行文件及其大约1.4s进行计时,没有任何优化) 现在,当我为编译添加-O2或-O3开关并为生成的可执行文件计
x
int main() {
int x = 1;
for (int i = 0; i > -2; i++) {
x >> 2;
}
}
现在发生的一件奇怪的事情是,当我编译它时没有任何优化,或者使用一级优化(-O
),它运行得很好(我正在使用-O
和5.4s
对可执行文件及其大约1.4s
进行计时,没有任何优化)
现在,当我为编译添加-O2
或-O3
开关并为生成的可执行文件计时时,它不会停止(我已经测试了多达60秒
)
你知道是什么导致了这种情况吗?你可以通过查看生成的二进制文件(使用
objdump
或其他方法)得到明确的答案
但正如其他人所指出的,这可能是因为您依赖于未定义的行为。一种可能的解释是编译器可以自由地假设i
永远不会小于-2
,因此将完全消除条件,并将其转换为无限循环
此外,您的代码没有明显的副作用,因此编译器也可以随意优化整个程序,如果它喜欢的话。优化的循环会产生一个无限循环,这是您根据有符号整数溢出产生的结果。
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
组件(优化级别3):gcc-std=c99-S-O3 main.c
_main:
LFB2:
pushq %rbp
LCFI0:
movq %rsp, %rbp
LCFI1:
L2:
jmp L2 #<- infinite loop
\u main:
LFB2:
pushq%rbp
立法会十题:
movq%rsp,%rbp
立法会一题:
L2:
jmp L2#有关未定义整数溢出的原因的其他信息,请参见此处:
搜索“有符号整数溢出”一段。当i
总是大于-2溢出是技术上未定义的行为时,循环应该如何停止,因此任何事情都可能发生(无论优化设置如何)。实际上pmg是正确的。不,未定义的行为不是在C中所做的事情。而且“技术上”不应该work@mtahmed:正如您所注意到的,对于不同的优化设置,结果可能不同。对于不同体系结构上的不同编译器,或者对于不同的月相,结果也可能不同…:)@pmg:诅咒那些月相!出于好奇,整数溢出的行为在C中没有定义吗?@tskuzzy,有符号整数溢出是UB<代码>无符号
整数表现良好,只需换行即可。因此,OP的循环在转换为无符号设置时会非常有效。还有两篇博文:我真的说不出这些文章有多好。除此之外,这些文章确实明确和具体地解释了为什么某些神秘的优化可能会删除看似必要的代码。在C社区中,UB的原因和后果不是很清楚,这些文章是关于这个主题的最好的阅读材料。再次感谢!