c ++:编译器能否优化此代码段?

use*_*784 7 c++ compiler-construction optimization performance compiler-optimization

void foo(const int constant)
{
    for(int i = 0; i < 1000000; i++) {
        // do stuff
        if(constant < 10) {              // Condition is tested million times :(
            // inner loop stuff
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

对于外循环的每次执行,都检查"常量"的值.但是,常量永远不会改变,所以浪费了大量的CPU时间来测试条件常数<10?一遍又一遍地.人类会在前几次传球后意识到常数永远不变,并且智能地避免一遍又一遍地检查它.编译器是否注意到这一点并对其进行智能优化,或者重复if循环是否不可避免?

就个人而言,我认为这个问题是不可避免的.即使编译器在外部循环之前进行比较并设置某种布尔变量"skip_inner_stuff",仍然必须为外部for循环的每次传递检查此变量.

你对此事有何看法?有没有更有效的方法来编写上述代码段,以避免这个问题?

Oak*_*Oak 6

您描述的优化也称为循环非切换.多年来它一直是优化编译器的标准部分 - 但是如果你想确保你的编译器执行它,请编译你的示例代码并使用一些优化级别(例如gcc中的-O2)并检查生成的代码.

但是,如果编译器无法证明一段代码在整个循环中是不变的 - 例如调用在编译时不可用的外部函数 - 那么实际上,手动将代码提升到循环外部可以净化非常大的性能提升.

  • @EJP我认为这里问题的核心是关于循环内部不会改变的东西,不一定是编译时常量.所以`if`必须在运行时执行,它只能在循环外提升. (3认同)
  • @EJP:`constant`不是编译时常量,除非调用`foo`被内联到一个编译时常量作为参数表达式传递的地方.不要被`const`所欺骗 - 除非指针或对`constant`的引用转义为这个函数,`constant`被声明为`const`的事实既不会帮助也不会阻碍优化器. (2认同)

Bas*_*tch 0

一个好的编译器会优化它(当启用优化时)。

如果使用GCC你可以

-Wall养成始终使用from gcc(或if 编译 C++ 代码)询问所有警告的习惯g++

顺便说一句,在实践中,这样的优化(“循环不变代码提升”,如另一个答案所解释的)是必不可少的,因为这种中间代码经常发生,例如在函数内联之后......(想象一下要内联的几个调用foo。 ..)