这个问题的前言是,引述CUDA C Programming Guide
,
较少寄存器内核使用,更多的线程和线程块 可能驻留在多处理器,它可以提高 性能。
现在,__launch_bounds__
和maxregcount
通过两种不同的机制来限制寄存器的使用。
__launch_bounds__
nvcc
决定要由__global__
函数通过平衡性能和内核启动安装程序的一般性使用的寄存器的数量。换言之,对于每个块的不同数量的线程以及每个多处理器的块,使用的寄存器数量的这种选择“保证有效”。但是,如果在编译时可以获得每个块的最大线程数(可能)和每个多处理器的最小块数(可能)的近似概念,则可以使用此信息来优化内核以进行此类启动。换句话说
#define MAX_THREADS_PER_BLOCK 256
#define MIN_BLOCKS_PER_MP 2
__global__ void
__launch_bounds__(MAX_THREADS_PER_BLOCK, MIN_BLOCKS_PER_MP)
fooKernel(int *inArr, int *outArr)
{
// ... Computation of kernel
}
通知可能的启动配置的编译器,以便nvcc
可以选择寄存器的数量为“最佳”的方式这样的启动配置。
MAX_THREADS_PER_BLOCK
参数是必需参数,而MIN_BLOCKS_PER_MP
参数是可选的。另请注意,如果内核的启动数量大于MAX_THREADS_PER_BLOCK
,则内核启动将失败。
如果指定发射边界,编译器首先从它们 导出上限L
上的内核应使用 确保寄存器的数目:
该限制机构设置在Programming Guide
如下描述那的 maxThreadsPerBlock
线程minBlocksPerMultiprocessor
块(或单个块 如果未指定minBlocksPerMultiprocessor
是)可以驻留在多处理器。所述 编译器将优化寄存器以下列方式使用:在
- 如果初始寄存器使用比
L
更高,编译器进一步降低它,直到它变得小于或等于L
,通常更多的本地为代价内存使用量和/或更高数量的指令;
因此,__launch_bounds__
可导致寄存器溢出。
maxrregcount
maxrregcount
是简单地用__launch_bounds__
hardlimits使用的寄存器的数目由用户设定的数目,在方差,强制编译器将重新安排其使用的寄存器的编译器标志。当编译器不能保持低于规定的限制时,它只会将其泄漏到本地内存中,实际上它是DRAM
。即使这个局部变量存储在全局变量DRAM
中,内存变量也可以缓存在L1,L2中。
也许这是一个简单的答案:你可能需要每个线程40个寄存器,而不是每个块。 - 如果您在答案中误写了它:请提供有关您的GPU的信息。也许你只是在你的计算中犯了一个简单的错误。在你启动内核的两种情况下,块的尺寸是多少? (我假定块的数量足够高) – Shadow
@Shadow你是正确的每线程约40个REG - 我的错误/错字。关于GPU,它运行在采用CC 5.3的Maxwell架构的GPU上。 << >>大小分别为(132,0,0)和(16,16,0),并且可以同时运行2048和螺纹(Tegra的TX1)。内核正确执行在这两种情况下,但使用__launch_bounds__但与-maxrregcount即使每个线程使用寄存器在两种情况下,同样的,当有溢出。 –
Kelsius
你比较过两个版本的运行时间吗? – Shadow