有利于循环展开的条件和返回边际减小的点

Conditions for loop unrolling to be beneficial and the point at which margins of return decrease?

本文关键字:回边 返回 循环展开 条件 有利于      更新时间:2023-10-16

谁能先解释一下在什么时候展开循环(在C/c++)成为一个有用的优化做?

第二,与第一个问题相关,在什么情况下不应该再执行展开?展开是否应该总是将操作分成2次幂的批?或者它是否与CPU可以执行多少计算有关?一个比率,它是缓存线大小的乘数?等

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

  • 0到49,每个循环两次"操作"
  • 0到24,每个循环4个"操作"
  • 0到19,每个循环5个"操作"
  • 每个循环0到9和10个"操作"

我不能让一个关于循环展开的问题没有回答这么长时间而不提到达夫设备。这个实现与经典版本略有不同,但它仍然可以工作。

假设你在一个内存块上应用一个掩码:

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);
如果迭代跳转的成本占循环迭代内完成的工作成本的很大比例,那么

循环展开是有用的。一个好的优化编译器可以在足够的优化级别上为您解决这个问题。只有当编译器无法展开时,你才需要自己展开。

正如在注释中提到的,一旦跳跃的计算成本与展开循环体的计算相比不再显著,就不需要展开循环。在极端情况下,循环展开可能导致指令缓存震荡,损害性能(类似于过度使用函数内联)。