循环展开与循环平铺
Posted
技术标签:
【中文标题】循环展开与循环平铺【英文标题】:Loop unrolling vs Loop tiling 【发布时间】:2011-07-23 14:12:33 【问题描述】:谁能告诉这两种优化技术是相同还是不同?
另外,这是程序员或编译器的责任吗?
【问题讨论】:
【参考方案1】:这两种技术是不同的。请参阅 Loop unrolling 和 Loop tiling 的说明。
循环展开是为了消除循环的开销。它(通常)仅对迭代次数很少且在编译时已知的相当小的循环有用。它主要由编译器完成。
在较早的时候,当计算机速度较慢且编译器更原始时,程序员会手动展开循环,但现在程序员这样做并不常见 - 可能对于限制性非常强的嵌入式系统除外。
循环平铺通常用于非常大的数据集。目的是:将一些数据加载到缓存中,并在分页一些新数据之前对其执行所有操作。
根据正在执行的操作和数据的内部组织,一个简单的循环可能会跳转到不同的数据页面,从而导致大量缓存未命中(和页面加载)。仔细规划执行顺序可以显着提高某些问题的运行时间。
虽然编译器可能会执行循环平铺,但有时程序员可能会手动执行此操作,并且可能比编译器做得更好。
一般来说,不要尝试进行这些类型的优化,因为它们会为代码增加很多复杂性(和错误),并且通常只能提供适度的性能提升。但是,如果您的代码很慢并且分析表明存在特定类型的瓶颈,则应考虑使用循环平铺之类的方法,这可能会带来很大的性能提升。
【讨论】:
这些类型的优化对性能至关重要。我很想看到没有它们的高性能 matmul。我同意它会增加复杂性并因此增加潜在的错误,但即使是那些也可以通过良好的实践来管理。平铺和展开是所有处理繁重数学的程序员都应该熟悉的优化。 即使迭代次数很大或未知,展开小循环也很重要。编译器可以展开例如8 次并添加代码来处理最后的 0-7 次迭代。 (罐头。你必须检查他们是否真的这样做。)【参考方案2】:这是两种完全不同的性能优化。
循环展开是一种代码优化,其中代码在循环中被复制,循环迭代的总数减少。好处是减少了循环开销(通常只与非常小的循环相关),以及在超标量 CPU 中减少依赖停顿的更好的指令调度。这可以手动和/或作为编译器优化来完成。
平铺是一种内存优化,旨在通过处理平铺(较大数据结构中的小块)更好地利用缓存,通常在图像或其他 2D 数据结构的上下文中。这通常在源代码级别实现,作为算法实现的整体设计的一部分。
【讨论】:
循环展开是一种速度优化。两种优化(实际上都是)都应用于代码。 @delnan:它们都是性能(即速度)优化,但循环展开通过提高代码效率来实现这一点,而平铺通过更好地使用缓存来实现性能提升/内存层次结构。以上是关于循环展开与循环平铺的主要内容,如果未能解决你的问题,请参考以下文章