在'for-loop'中使用'break'的性能影响

Performance impact of using 'break' inside 'for-loop'

本文关键字:性能 影响 break for-loop      更新时间:2023-10-16

我已经尽了最大的努力,在SO上读了很多问答。是的,但是我还没有找到我的问题的答案。大多数for-loopbreak相关的问题都涉及嵌套循环,而我关心的是性能。

我想知道在for-loop中使用break是否对我的c++代码的性能有影响(假设break几乎从未被调用)。如果有,我也想暂时知道惩罚有多大。

我很怀疑它确实会影响性能(尽管我不知道有多大)。所以我想问你。我的理由如下:

独立于条件语句的额外代码触发break(就像if),它必然是附加的给我的循环的指令。

更进一步,当我的编译器试图展开for-loop,因为它不再知道迭代的次数它将在编译时运行,有效地将其呈现为while-loop .

因此,我怀疑它确实有性能影响,这是可能的对于非常快速和紧密的循环是相当可观的。


这让我想到了一个后续问题。是for-loop &break性能是否等同于while-loop ?就像下面的代码片段一样,我们假设checkCondition()在99.9%的情况下计算为true。我是否失去了for-loop的性能优势?

// USING WHILE
int i = 100;
while( i-- && checkCondition())
{
    // do stuff
}

// USING FOR
for(int i=100; i; --i)
{
    if(checkCondition()) {
        // do stuff
    } else {
        break;
    }
}

我已经在我的电脑上试过了,但是我得到了相同的执行时间。考虑到编译器和它的优化巫术,我想知道概念上的答案。


编辑:

请注意,我在完整的代码中测量了两个版本的执行时间,没有任何真正的差异。此外,我不相信用-s编译(我通常这样做),因为我对编译器的特定结果不感兴趣。我对这个概念本身(在学术意义上)很感兴趣,因为我不确定我是否完全正确:)

主要的答案是避免在类似的微优化上花费时间,直到您已经验证了这样的条件评估是一个瓶颈。

真正的答案是CPU有强大的分支预测电路,经验证明工作得很好。

将会发生的是,你的CPU将选择是否要采取分支,并执行代码,如果if条件甚至不存在。当然,这依赖于多个假设,比如对条件计算没有副作用(因此,body循环的一部分依赖于它),并且该条件总是被求值为假,直到某一点,它将变为真并停止循环。

一些编译器还允许您指定计算的可能性,作为分支预测器的提示。

如果您想看到两个代码版本之间的语义差异,只需使用-S编译它们并检查生成的asm代码,没有其他神奇的方法可以做到这一点。

对于"…对性能的影响是什么",唯一合理的答案是"衡量它"。很少有通用的答案。

在您展示的特定情况下,如果优化编译器为这两个示例生成明显不同的代码,那将是相当令人惊讶的。另一方面,我相信像

这样的循环
unsigned sum = 0;
unsigned stop = -1;
for (int i = 0; i<32; i++)
{
    stop &= checkcondition();  // returns 0 or all-bits-set;
    sum += (stop & x[i]);
}

可能比:

unsigned sum = 0;
for (int i = 0; i<32; i++)
{
    if (!checkcondition())
        break;
    sum += x[i];
}

适用于特定的编译器,特定的平台,设置了正确的优化级别,以及特定的"checkcondition"结果模式。

…但唯一的方法就是测量。