cha*_*ris 8 optimization cuda loop-unrolling
在CUDA中,可以使用#pragmaunroll指令展开循环,以通过提高指令级并行性来提高性能.该#pragma可选地跟着一个数字,指定多少次循环必须展开.
不幸的是,文档没有给出关于何时应该使用该指令的具体指示.由于编译器已经展开了具有已知行程计数的小循环,是否应该#pragma在较大的循环上展开?在带有可变计数器的小循环上?那么可选的展开数量呢?还有关于cuda特定循环展开的推荐文档吗?
nju*_*ffa 12
没有任何快速和严格的规则.CUDA编译器至少有两个展开器,一个在NVVM或Open64前端内,另一个在PTXAS后端.一般来说,他们倾向于非常积极地展开循环,所以我发现自己#pragma unroll 1比任何其他展开属性更频繁地使用(以防止展开).关闭循环展开的原因有两个:
(1)当循环完全展开时,套准压力会增加.例如,小型本地内存数组的索引可能成为编译时常量,允许编译器将本地数据放入寄存器.完全展开也可能会延长基本块,允许更积极地调度纹理和全局负载,这可能需要额外的临时变量,因此需要寄存器.由于寄存器溢出,寄存器压力增加会导致性能降低.
(2)部分展开的循环通常需要一定量的预计算和清理代码来处理不完全是展开因子倍数的循环计数.对于具有短行程计数的循环,此开销可以淹没从展开的循环中获得的任何性能增益,从而导致展开后的性能降低.虽然编译器包含用于在这些限制下找到合适循环的启发式方法,但启发式方法并不总能提供最佳决策.
在极少数情况下,我发现手动提供比编译器自动使用的更高的展开因子对性能有一个小的有益影响(典型增益为单位数百分比).这些通常是内存密集型代码的情况,其中较大的展开因子允许更积极地调度全局或纹理负载,或者非常紧密的计算绑定循环,其受益于最小化循环开销.
使用展开因子应该在优化过程的后期发生,因为编译器默认涵盖了在实践中将遇到的大多数情况.
Cra*_*sta -1
这是一个可用于展开循环的工具。何时应该/不应该使用它的细节将根据您的代码(例如循环内的内容)而有很大差异。实际上没有任何好的通用技巧,除了想想你的代码展开与滚动的样子,并思考它是否会更好地展开。