【问题标题】:Handling for loop special cases处理循环特殊情况
【发布时间】:2016-05-16 00:51:29
【问题描述】:

在 Java、C# 或 C++ 中,假设我们有一个非常常见的情况,我们需要迭代大量时间并执行函数 doX,但仅在一次迭代中我们应该执行函数 doY。

int index = 123456;
for(int i = 0; i < 1000000; i++)
{
    if(i == index) doY();
    else doX();
}

在我看到真正的性能问题的情况下,我通常会在 2 中中断循环,但这可能会非常痛苦,尤其是在循环体很大的情况下。编译后的代码是否真的在每次迭代时检查条件,还是可以由编译器优化?再者,如果index在编译时不是常量,能有这样的优化吗?

【问题讨论】:

  • GCC 的loop splitting 不喜欢拆分这种形式的循环,我不知道有任何补丁可以添加该功能,但可以做到。
  • 您希望如何学习与 3 种不同编程语言相关的有意义且具体的性能知识,每种编程语言都运行在不同的平台(CLR、JVM、本机)上?我认为您需要选择一种语言才能成为有效的单个问题。
  • 看,如果 nothing 只占一小部分时间,那么它就是一个性能问题。在doX() 中花费了多少个周期?如果它小于if(i==index) 测试的 10 倍,可能是性能问题。当然,如果循环体很大,它就不会很大。

标签: java c++ c for-loop optimization


【解决方案1】:

这通常不会导致严重的性能问题。这是由于branch predicting。参考这个famous question

分支预测基本上是程序集猜测 if 语句将评估为哪种方式的方式。如果它猜对了,几乎不需要时间。如果它猜错了,它将回溯并导致性能问题。分支预测器通常会使用它之前的分支路线作为下一个分支的“猜测”。

由于您的 if 语句几乎在时间上评估为 false。分支预测器几乎每次都会正确预测。

所以要回答您的问题“编译后的代码是否真的在每次迭代时检查条件?”。 不,它没有。虽然它不是由编译器优化的,而是由汇编管道本身优化的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多