block,thread的选取的原则 ,和你是1维fdtd,3维fdtd还是神马其他算法,基本上没有关系。
其首要原则是尽量挖掘GPU的效能。
而如何尽量发掘GPU的效能呢?一般的方法是尽量提高GPU的占用率。
而为何尽量提高GPU的占用率就能提高效能呢?因为GPU在运行的时候,实际上是通过线程按warp为单位切换来隐藏计算/访存的延迟的。
大致为,SM上的scheduler会从当前的resident threads里面抓取一个就绪的warp,发射给SM里面的执行单元(包括sp阵列,SFU和LSU等),此warp在执行了一条或多条指令之后,如果遇到长延迟的操作,比如等待访存结果等,那么它将被切换出去(并立即换一个warp进来继续计算/访存),直到该warp的比如说访存结果已经拿到,那么它将重新变为就绪状态的warp,等待scheduler下一次抓取。GPU在运行的时候,就是靠这种不停地切换,使得GPU上的计算单元尽可能保持满载状态,达到较高的吞吐量。
那么,既如此,一个SM上的resident threads越多,scheduler就越好调度,越容易尽可能掩盖各种延迟。
以fermi架构为例,一个SM上最多可以resident 1536个threads;但同时,一个SM上最多resident 8个blocks。如果仅考虑这个约束(不考虑SM上寄存器和shared memory等资源限制,也不考虑算法有否特殊要求),那么,每个block应该有不少于1536/8=192threads。一般地,192~512都是比较典型的用法。
如果按照您的使用方法,每个block内只有32线程,那么每个SM上resident threads只有32*8=256个,只有最大resident threads的1/6,一般会导致SM内的计算单元经常处于等待状态(因为scheduler切换warp已经换无可换),这就是前文中“吃不饱”的含义。
而,一共需要多少个block呢?这其实不是个问题。
因为您的计算规模如果决定了,每个block的规模也决定了,两者相除就是block的数量。
此外,如果计算规模小到了block/thread数量甚至不足以铺满GPU上的SM阵列,那么除了测试和验证以及或许可以用多kernel并发以外,用GPU跑是没什么意义的。如同您的1维算例,1个block 1024个线程或者32个block,32*32=1024线程,这种规模,用来验证算法跑跑是可以的,实际使用的话,用GPU跑没啥大的意义,还可能被CPU秒杀。
上述是block,threads数量选择的首要原则。
在满足该原则的情况下,程序员可以选择对自己实现算法方便,明了的block形状的组织形式。
以方便自己控制寻址或者其他用途。
大致如上。
类似讨论,本版近期已经讨论过多次,就在第一页上,如:
http://cudazone.nvidia.cn/forum/forum.php?mod=viewthread&tid=6241&extra=page%3D1
http://cudazone.nvidia.cn/forum/forum.php?mod=viewthread&tid=6280&extra=page%3D1
http://cudazone.nvidia.cn/forum/forum.php?mod=viewthread&tid=6205&extra=page%3D1
等
祝您编码愉快~
再补充一个链接
http://cudazone.nvidia.cn/forum/forum.php?mod=viewthread&tid=6282&extra=page%3D1