按照CUDA的执行模型,grid中的各个block会被分配到GPU的各个SM中执行。下面我们给出一些建议,如何确定合适的Grid和block尺寸。在设计时,应该优先考虑block的尺寸,而grid的尺寸一般来说越大越好。
在Tesla架构GPU的每个SM中,至少有6个active warp才能有效地隐藏流水线延迟。此外,如果所有的active warp都来自同一block,当这个block中的线程进行存储器访问或者同步时,执行单元就会闲置。基于以上原因,最好让每个SM上拥有至少2个active block。
一个SM上的active warp和active block数量计算方法如下:
(1)确定每个SM使用的资源数量
使用nvcc的--keep编译选项,或者在.cu编译规则(cuda build rule)中选择保留中间文件,得到.cubin文件。用写字板打开.cubin文件,在每个内核函数的开始部分,可以看到:
lmem=0
smem=256
reg =8
其中,lmem和reg分别代表内核函数中每个线程使用的local memory数量和寄存器数量,smem代表每个block使用的shared memory数量。也就是说:这个内核函数的每个线程使用了0Byte local memory,8个寄存器文件(每个寄存器文件的大小是32bit);每个block使用了256Byte的shared memory。
(2)根据硬件确定SM上的可用资源
可以用SDK中的deviceQuery获得每个SM钟的资源。要注意到:在程序编译时,要使目标代码和目标硬件版本与实际使用的硬件一致(使用-arch、-gencode和-code编译选项)。不同的架构,限制也是不一样的。
(3)计算每个block使用的资源,并确定active block和active warp数量
假设每个block中有64个线程,每个block使用256 Byte shared memory,8个寄存器文件,那么有:
1、每个block使用的shared memory是:256Byte
2、每个block使用的寄存器文件数量:8*64=512
3、每个block中的warp数量:64/32=2
然后根据每个block使用的资源,就可以计算出由每个因素限制的最大active block数量。这里,假设在G80/G92 GPU中运行:
1、由shared memory数量限制的active block数量:16384/256=64
2、由寄存器数量限制的active block数量:8192/512=16
3、由warp数量限制的active block数量:24/2=12
4、每个SM中的最大active block数量:8
这样就确定了grid中active block的数量。各位小伙伴,可以去试一试!