我正在分析一个内核,该内核在 GTX480 中每个线程使用 25 个寄存器,每个块使用 3568 字节的共享内存。内核配置为启动 16x16 线程,线程缓存首选项设置为共享。
根据 GTX480 的规格,该设备每个 SM 有 32768 个寄存器,因此可以25 regs x 256 threads per block x 6 blocks per SM同时运行多个块。
但是,Compute Visual Profiler 和 Cuda Occupancy Calculator 报告每个 SM 只有 4 个块将处于活动状态。我想知道为什么只有 4 个块会处于活动状态,而不是我预期的 5 个。
我发现的原因是 CUDA 将使用的寄存器数量向上舍入为 26,在这种情况下,活动块的数量为 4。
为什么 CUDA 对寄存器的数量进行四舍五入?因为每个线程有 25 个寄存器,每个块有 256 个线程,所以每个 SM 最多可以有 5 个块,这显然是一个优势。
环境设置:
Device 0: "GeForce GTX 480"
CUDA Driver Version / Runtime Version 5.0 / 4.0
ptxas info: Compiling entry function '_Z13kernellS_PiS0_iiS0_' for 'sm_20'
ptxas info: Used 25 registers, 3568+0 bytes smem, 80 bytes cmem[0], 16 bytes cmem[2]
0 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
kernel config: 16x16 threads per block
kernel config: cudaFuncCachePreferShared
Run Code Online (Sandbox Code Playgroud)
您没有正确解释正在发生的事情。这里没有对每个线程的寄存器数量进行四舍五入,而是对每个 warp的寄存器数量进行四舍五入。
您的 GPU 以每个扭曲为基础分配寄存器,寄存器“页面大小”为 64 个寄存器(请注意,我松散地使用该术语,我不了解精确的寄存器文件设计)。在您的情况下,warp 需要 25*32 = 800 个寄存器,必须四舍五入到最接近的“页面大小”64,每个 warp 提供 832 个寄存器。每个块包含 8 个扭曲(256 个线程),因此每个块需要 6656 个寄存器。这个内核的每个 SM 的最大块数是 32768 / 6656 向下舍入到最接近的整数,即。每个 SM 4 个块,而不是您期望的 5 个。
因此,非常简短的答案是寄存器文件分配粒度和页面大小决定了在这种情况下每个 SM 可以运行多少块。
| 归档时间: |
|
| 查看次数: |
1528 次 |
| 最近记录: |