因为我的指针都指向非重叠的内存,所以我全力以赴,将我传递给内核的指针(及其内联函数)替换为限制,并使它们成为常量,尽可能。然而,这增加了一些内核的寄存器使用并减少了其他内核的使用。这对我来说没有多大意义。
有人知道为什么会这样吗?
答案 0 :(得分:6)
是的,它可以增加注册用量。
参考__restrict__
的{{3}}:
这里的效果是减少了内存访问次数并减少了计算次数。这是由于"缓存"引起的注册压力增加而平衡的。加载和公共子表达式。
由于寄存器压力是许多CUDA代码中的一个关键问题,因为占用率降低,使用受限制的指针会对CUDA代码产生负面的性能影响。
const __restrict__
可能有益于至少两个原因:
在支持它的体系结构上,它可以使编译器发现programming guide的用途,这可能是一种性能增强功能。
如上面的链接编程指南部分所示,它可以使编译器能够进行其他优化(例如,减少指令和存储器访问),如果相应的寄存器压力不能提高性能,也可以提高性能成为一个问题。
减少指令和存储器访问导致寄存器压力增加可能是不直观的。让我们考虑上面编程指南链接中给出的示例:
void foo(const float* a, const float* b, float* c) {
c[0] = a[0] * b[0];
c[1] = a[0] * b[0];
c[2] = a[0] * b[0] * a[1];
c[3] = a[0] * a[1];
c[4] = a[0] * b[0];
c[5] = b[0]; ... }
如果我们在上面的例子中允许指针别名,那么编译器就不能进行很多优化,并且编译器基本上简化为完全按照编写的方式执行代码。第一行代码:
c[0] = a[0] * b[0];
需要3个寄存器。下一行代码:
c[1] = a[0] * b[0];
还需要3个寄存器,因为所有内容都是按写入方式生成的,所以它们可以是相同的3个寄存器,可以重复使用。对于示例的其余部分,可能会发生类似的寄存器重用,导致整体寄存器使用/压力较低。
但是如果我们允许编译器重新排序,那么我们必须为每个预先加载的值分配寄存器,并保留直到该值退役。这种重新排序可以增加寄存器使用/压力,但最终可能导致更快的代码(或者如果寄存器压力成为性能限制器,则可能导致代码变慢。)