【问题标题】:Compilers, If statements and loops编译器、If 语句和循环
【发布时间】:2014-06-27 16:39:35
【问题描述】:

这是 C++ 的一般效率问题。我不熟悉编译器的内部工作原理,所以假设我有几个循环和一个潜在的 if 语句,例如:

for(int i=0; ...) 
{
    for(int j=0; ...)
    { 
        if( ... )
        {
            ...
        }
        else
        {
            ... (slightly different)
        }
    }
}

但是,这个 if 语句独立于循环。如果我改为在循环外部定义 if/else 语句并在内部循环,是否存在显着的速度差异?例如:

if( ... )
{
    for(int i=0; ...) 
    {
        for(int j=0; ...)
        { 
            ...
        }
    }
}
else
{
    for(int i=0; ...) 
    {
        for(int j=0; ...)
        { 
            ... (slightly different)
        }
    }
}

如果是这样,或者如果不是这样,为什么会这样?我有一些想法,编译器会识别一遍又一遍地执行相同的 if 语句,但这对我来说是非常陌生的领域。

我检查了对这个问题的回答: Would compiler optimize conditional statement in loop by moving it ouside the loop? 他讨论了 gcc 中不同级别的优化,以及 -O3(我认为)如何做到这一点。但是这样的事情会自动完成吗?如果不是,那么在循环中这样的 if 语句的成本有多大?

【问题讨论】:

  • 即使您的编译器没有将您的代码优化为第二种形式,您的处理器的分支预测也应该能够以最小的开销轻松处理这个问题。
  • 您可以将代码移动到两个函数中,然后在循环之前选择一个。
  • 不完全相同,但相同的想法。这是一个视频,Lavavej 先生试图说服我们不要打扰编译器的工作。链接:Don’t Help the Compiler.
  • @Drop,我同意当性能不是主要考虑因素时,不应该过早地优化并尝试第二次猜测编译器。但是,当需要优化并且您需要更高的性能时,您应该坚决不信任编译器。您应该考虑所有选项。

标签: c++ performance compiler-construction


【解决方案1】:

唯一真正的答案是也许。如果条件是循环 不变的,那么你建议的换位是合法的,如果 编译器可以识别循环不变性,然后它可以使 换位。做不做取决于 编译器:g++ /O3,至少在 64 位模式下,cl /Ox /Os 至少在 32 位模式下不会; g++ 也展开这两个循环。 至少在我的测试中;我或多或少保证 编译器可以确定条件是循环不变量 通过将循环包装在一个函数中,条件是 bool const 类型的函数参数;取决于 条件,编译器可能或多或少难以 证明循环不变性。当然,事实上 编译器有更多的寄存器可以在 64 位模式下使用 也会影响其优化。

另外:虽然我本能地希望 g++ 版本是 更快,它明显更大;在某些情况下,这可能 对各种内存缓存产生负面影响,导致 代码实际上运行速度较慢。

最后,我总是写第一个。如果探查器稍后 显示它是一个瓶颈,返回没有问题 并按照第二个的行重写它,然后测量 看看它是否有所作为,一种或另一种方式,以及如何 它有很大的不同。并注意最好的结果 可能取决于您的编译器和架构 定位。

【讨论】:

    【解决方案2】:

    这个问题不能说哪个更快。

    只要记住 80-20 规则 (http://en.wikipedia.org/wiki/Pareto_principle#In_software) 并通过 profiling 找到代码。

    无论如何,首先编写可读和可维护的代码。如果您遇到性能问题,请分析代码。

    【讨论】:

      【解决方案3】:

      视情况而定,但我敢打赌第二种选择更快。这是因为不会发生分支,编译器更有可能用一些 MMX/SSE 指令组替换大量代码。

      至少在理论上,在第一种情况下,CPU 必须在每个 for() 循环中解决相同的 if()。在第二种情况下, if() 不在外观范围内,应该更快。但同样,现代编译器通常可以发现这个问题并神奇地解决它。

      但是,是的,通常编写代码以提高可读性很重要,除非性能是真正的大问题。

      【讨论】:

      • 这取决于编译器。如果它有意义并且如果它可以证明条件是循环不变量,一个好的编译器会将第一种情况优化为第二种情况。
      • 所有人都说“取决于编译器”,但它也取决于代码。即使对于编译器,有些代码也不是那么容易理解。取决于两者。我同意,好的编译器可以做得很好。但不是奇迹。
      • 编译器能做的真正关键是我的第二个子句:“if 它可以证明条件是循环不变量。”如果程序员知道它是一个循环不变量,但认为编译器可能无法看到它,则使用它来初始化循环外的bool const 变量可能是编译器进行优化所需的全部内容。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-06-09
      • 2013-10-18
      • 2013-02-06
      • 2016-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多