const * __restrict__ 可以增加 cuda 寄存器的使用吗?

Can a const * __restrict__ increase cuda register usage?

因为我的指针都指向非重叠内存,所以我全力以赴将传递给内核(及其内联函数)的指针替换为 restricted,并且在可能的情况下也使它们成为常量。然而,这增加了一些内核的寄存器使用,而减少了其他内核的使用。这对我来说没有多大意义。

有人知道为什么会这样吗?

是的,它可以增加寄存器的使用。

参考 programming guide for __restrict__:

The effects here are a reduced number of memory accesses and reduced number of computations. This is balanced by an increase in register pressure due to "cached" loads and common sub-expressions.

Since register pressure is a critical issue in many CUDA codes, use of restricted pointers can have negative performance impact on CUDA code, due to reduced occupancy.

const __restrict__ 可能至少有两个好处:

  1. 在支持它的体系结构上,它可能使编译器能够发现 constant cache 的用途,这可能是一种性能增强功能。

  2. 如上面 linked 编程指南部分所述,它可以使编译器进行其他优化(例如减少指令和内存访问),这也可以提高性能 如果相应的套准压力没有成为问题

减少导致寄存器压力增加的指令和内存访问可能是不直观的。让我们考虑上面编程指南中给出的示例 link:

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 个寄存器,可以重复使用。对于该示例的其余部分,可能会发生类似的寄存器重用,从而导致总寄存器较低 usage/pressure.

但是如果我们允许编译器重新排序,那么我们必须为预先加载的每个值分配寄存器,并保留到该值退出为止。这种重新排序可以 增加 寄存器 usage/pressure,但最终可能会导致更快的代码(或者它可能会导致更慢的代码,如果寄存器压力成为性能限制因素。)