循环展开的条件是有益的,返回边际减少的点?

时间:2013-06-21 20:48:27

标签: c++ c performance optimization compiler-construction

有人可以首先解释在什么时候展开循环(在C / C ++中)成为一个有用的优化?

其次,与第一个问题相关,在什么时候应该不再进行展开?是否应始终将展开操作拆分为2次?或者它与您的CPU可以执行多少计算有关?比率是您的缓存行大小的乘数?等

例如,如果我有一个从0到99的for循环哪个更好/我如何确定哪个(除了试验和错误) - 是否有科学方法:

  • 0到49以及每个循环两次“操作”
  • 0到24以及每个循环四次“操作”
  • 0到19和每个循环五次“操作”
  • 每个循环0到9和10个“操作”

1 个答案:

答案 0 :(得分:6)

我不能在没有提到Duff's Device的情况下让关于循环展开的问题没有得到答复。此实现与经典版本略有不同,但它仍然有效。

假设您正在将掩码应用于内存块:

while (n-- > 0) {
    *ptr++ &= mask;
}

然后,这可以像这样展开:

switch (n % 4) do {
case 0: *ptr++ &= mask;
case 3: *ptr++ &= mask;
case 2: *ptr++ &= mask;
case 1: *ptr++ &= mask;
} while ((n -= 4) > 0);

如果迭代跳转的成本占循环迭代内完成工作成本的很大一部分,则循环展开非常有用。一个好的优化编译器可以在足够的优化级别为您找出答案。如果你的编译器没有这样做,你只需要自己展开它。

如评论中所述,一旦与展开的循环体的计算相比,跳跃的计算成本不再显着,则无需展开。从极端开始,循环展开可能会导致指令缓存捶打,从而损害性能(类似于过度使用函数内联)。