在啥类型的循环中最好在 CUDA 中使用 #pragma unroll 指令?
Posted
技术标签:
【中文标题】在啥类型的循环中最好在 CUDA 中使用 #pragma unroll 指令?【英文标题】:In what types of loops is it best to use the #pragma unroll directive in CUDA?在什么类型的循环中最好在 CUDA 中使用 #pragma unroll 指令? 【发布时间】:2012-10-24 16:50:49 【问题描述】:在 CUDA 中,可以使用 #pragma
unroll 指令展开循环,通过增加指令级并行度来提高性能。 #pragma
后面可以选择跟随一个数字,指定循环必须展开多少次。
不幸的是,文档没有给出何时使用该指令的具体说明。由于具有已知行程计数的小循环已经被编译器展开,#pragma
unroll 是否应该用于较大的循环?在带有可变计数器的小循环上?那么可选的展开次数呢?还有关于 cuda 特定循环展开的推荐文档吗?
【问题讨论】:
【参考方案1】:没有任何快速而硬性的规则。 CUDA 编译器至少有两个展开器,一个在 NVVM 或 Open64 前端,一个在 PTXAS 后端。一般来说,它们倾向于非常积极地展开循环,所以我发现自己使用#pragma unroll 1
(以防止展开)比任何其他展开属性都更频繁。关闭循环展开的原因有两个:
(1) 当一个循环完全展开时,套准压力会增加。例如,小型本地内存数组的索引可能成为编译时常量,允许编译器将本地数据放入寄存器。完全展开也可能会延长基本块,允许更积极地调度纹理和全局加载,这可能需要额外的临时变量,因此需要寄存器。套准压力增加可能会因套准溢出而导致性能下降。
(2) 部分展开的循环通常需要一定数量的预计算和清理代码来处理不完全是展开因子倍数的循环计数。对于行程数较短的循环,这种开销可能会淹没展开循环所获得的任何性能提升,从而导致展开后的性能降低。虽然编译器包含在这些限制下寻找合适循环的启发式方法,但启发式方法并不总是提供最佳决策。
在极少数情况下,我发现手动提供比编译器自动使用的展开因子更高的展开因子对性能的有益影响很小(典型增益为个位数百分比)。这些通常是内存密集型代码的情况,其中较大的展开因子允许更积极地调度全局或纹理加载,或者从最小化循环开销中受益的非常紧密的计算绑定循环。
使用展开因子应该在优化过程的后期进行,因为编译器的默认设置涵盖了人们在实践中会遇到的大多数情况。
【讨论】:
所以基本上是反复试验?有一个完成的、优化的代码,然后尝试展开各种循环,看看它是否对性能有任何影响?由于 --ptxas-options=-v 将报告循环展开导致的寄存器使用增加,因此不容易跟踪寄存器溢出? 循环展开可能增加注册压力,但不一定如此。您可以从 -Xptxas -v 获取溢出统计信息,正确。循环展开只是编译器已知的众多优化之一,因此存在许多复杂的交互,主要由启发式驱动。在大多数情况下,启发式设置为“做正确的事”,因此我建议不要在优化过程后期进行手动干预。这适用于一般的优化编译器,而不是特定于 CUDA 编译器。 @njuffa:对不起,我的大脑处于“LaTeX 写作模式”。【参考方案2】:这是一个可用于展开循环的工具。何时应该/不应该使用它的细节会根据您的代码(例如循环内的内容)而有很大差异。没有任何好的通用技巧,除了想想你的代码在展开和滚动时会是什么样子,然后想想它是否会更好地展开。
【讨论】:
以上是关于在啥类型的循环中最好在 CUDA 中使用 #pragma unroll 指令?的主要内容,如果未能解决你的问题,请参考以下文章
avr单片机中spi通信 要取从机的数据,从机数据在啥时候写入SPDR寄存器?最好有例子。
delphi7 的 inputbox 具体在啥地方,最好截图!