版权归原作者所有,如有侵权,请联系我们

[科普中国]-循环展开

科学百科
原创
科学百科为用户提供权威科普内容,打造知识科普阵地
收藏

循环展开,英文中称(Loop unwinding或loop unrolling),是一种牺牲程序的尺寸来加快程序的执行速度的优化方法。可以由程序员完成,也可由编译器自动优化完成。

循环展开最常用来降低循环开销,为具有多个功能单元的处理器提供指令级并行。也有利于指令流水线的调度。

定义可以由程序员完成,也可由编译器自动优化完成。循环展开通过将循环体代码复制多次实现。循环展开能够增大指令调度的空间,减少循环分支指令的开销。循环展开可以更好地实现数据预取技术。1

优缺点展开循环的好处

由于展开能够消除分支以及一些管理归纳变量的代码,因此可以摊销一些分支开销。

展开可以积极调度(或管道化)循环以掩盖一些延迟。如果有足够的空闲寄存器使变量保持活动状态,因为通过展开相关性链展露了关键路径,这将非常有用。

如果迭代次数是可预测的,并且循环中没有条件分支,则英特尔(R) 奔腾(R) 4 处理器可以正确预测迭代次数为 16 次或更少的内部循环的退出分支。因此,如果循环体不是太大,并且已知可探测的迭代次数,则可以展开内部循环,直到它们的迭代次数达到最大值 16。对于奔腾 III 或奔腾 II 处理器,请不要展开迭代次数大于 4 的循环。

展开循环的可能开销

通常增加程序代码大小可能是不合需要的,特别是对于嵌入式应用程序。 也可能导致指令缓存未命中增加,这可能会对性能产生负面影响。

除非优化编译器透明地执行,否则代码可能会变得不那么可读。

如果循环体中的代码涉及函数调用,则可能无法将展开与内联组合,因为代码大小的增加可能过多。 因此,可以在两个优化之间进行权衡。

在单次迭代中可能增加寄存器使用以存储临时变量,这可能会降低性能,尽管很大程度上取决于可能的优化。2

除了非常小而简单的代码之外,包含分支的展开循环甚至比递归更慢。

静态循环展开手动(或静态)循环展开涉及程序员分析循环并将迭代解释为一系列指令,这将减少循环开销。 这与由编译器完成的动态展开形成对比。

C中的简单手动示例

计算机程序中的过程是从集合中删除100个项目。 这通常是通过调用函数delete(item_number)的for循环来完成的。 如果要优化程序的这一部分,并且与delete(x)循环相比,循环的开销需要大量资源,则可以使用展开来加速它。

正常循环

int x; for (x = 0; x