这种优化技术的名称是什么?

时间:2015-03-01 19:21:27

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

以下优化技术的名称是什么?为什么它比以前的实施更好?

const int size = 100;
int arr1[size];
int arr2[size];

来自双循环

for(int i=0; i<size; ++i)
    arr1[i] = 1;

for(int i=0; i<size; ++i)
    arr2[i] = 1;

到单循环

for(int i=0; i<size; ++i) {
    arr1[i] = 1;
    arr2[i] = 1;
}

修改

选项是;

  • 指针别名
  • 循环不变代码动作
  • 复制elison
  • 循环融合
  • 循环展开

3 个答案:

答案 0 :(得分:3)

它被称为loop fusion(或循环干扰,正如维基百科帮助指出的那样),正如您可能理解的那样,任何时候两个相邻的循环可以在相同的范围内迭代而不会相互交叉引用。

请注意,这并不总是能提高速度。

答案 1 :(得分:1)

维基百科将此优化称为loop fusion。这个想法是,两个循环的循环控制流开销不会加倍。如果组合循环具有较差的内存访问模式,但由于示例中的两个循环都按顺序访问连续的内存块,这可能不会对性能产生预期的影响,硬件应该能够有效地处理它。

在转换之前,每个循环都会这样做:

  1. 使用0初始化i
  2. 加载常量size
  3. 如果i >= size,请跳至8.
  4. 加载数组开始的地址arr1
  5. 将常数1存储在地址arr1 + i
  6. i增加一个。
  7. 跳至3。
  8. 结束
  9. 然后又一次:

    1. 使用0初始化i
    2. 加载常量size
    3. 如果i >= size,请跳至16。
    4. 加载数组开始的地址arr2
    5. 将常数1存储在地址arr2 + i
    6. i增加一个。
    7. 跳转到11。
    8. 结束
    9. 任何编译器可能做的第一件事就是将“加载常量size”和“加载地址arr”移出循环体。然而,总工作量与有用工作量的比率并不是很好。将其与组合循环进行比较:

      1. 使用0初始化i
      2. 加载常量size
      3. 如果i >= size,请跳至10。
      4. 加载数组开始的地址arr1
      5. 将常数1存储在地址arr1 + i
      6. 加载数组开始的地址arr2
      7. 将常数1存储在地址arr2 + i
      8. i增加一个。
      9. 跳至3。
      10. 结束
      11. 计算子弹点作为机器指令的衡量标准并不是推断性能的最准确方法。您需要知道实际硬件支持哪些指令才能真正比较所需指令的数量。

答案 2 :(得分:0)

这看起来更像是对我的悲观!

你完全破坏了循环中访问的数据的内存局部性,并可能导致可怕的缓存未命中数。

当然,唯一可以确定的方法是衡量它,但结论是这是一个优化&#34;,只是因为你只做了一半的增量和比较{ {1}},很傻。