Cuda 为什么较小的块大小(相同的总线程数)会暴露出更多的并行性?

Cuda 为什么较小的块大小(相同的总线程数)会暴露出更多的并行性?,cuda,Cuda,我正在阅读Cheng等人的“Professional CUDA C Programming”(专业CUDA C编程)。这里有一些例子说明了(非常简单的单行)内核是如何运行的,例如使用运行的内核比使用运行的内核性能差。然后,它们(多次)声明,您可能已经预料到了这个结果,因为第二次运行有更多的块,因此暴露了更多的并行性。但我不明白为什么。并行量不是由SM中并发扭曲的数量决定的吗?块大小与此有什么关系?这些扭曲属于哪个块并不重要-相同的块还是不同的块,那么为什么使用较小的块会暴露更多的并行性(相反,如

我正在阅读Cheng等人的“Professional CUDA C Programming”(专业CUDA C编程)。这里有一些例子说明了(非常简单的单行)内核是如何运行的,例如使用
运行的内核比使用
运行的内核性能差。然后,它们(多次)声明,您可能已经预料到了这个结果,因为第二次运行有更多的块,因此暴露了更多的并行性。但我不明白为什么。并行量不是由SM中并发扭曲的数量决定的吗?块大小与此有什么关系?这些扭曲属于哪个块并不重要-相同的块还是不同的块,那么为什么使用较小的块会暴露更多的并行性(相反,如果块大小太小,我会达到每SM最大块数限制,导致并发扭曲更少)?我能想象的唯一场景是费米上1024个线程的块=32个扭曲,每个SM限制最多有48个并发扭曲。这意味着只有1个并发块和32个并发扭曲是可能的,减少了并行量,但这是一个非常具体的用例

更新:
发布后我想到的另一件事是:在SM中的所有扭曲完成之前,无法从SM中移出一个块。因此,在该块的执行结束时,可能会出现这样的情况,即最后几个“最慢”的扭曲将整个块保持在SM中,而该块中的大部分扭曲已完成并停止,但在这几个执行扭曲完成之前,无法加载新块。因此,在这种情况下,效率变得很低。现在,如果块更小,则仍然会发生这种情况,但相对于执行扭曲,暂停的数量更小,因此效率更高。就是这个吗?

是的,就是这个。你问题的第二段是个好答案

更详细地说,每个SM中的warp调度程序的数量是有限的(通常为2个)。每个扭曲计划程序都会跟踪许多活动扭曲,并且仅当允许扭曲在程序中进一步移动时,才会计划扭曲执行。翘曲计划程序跟踪的活动翘曲数最大(通常为32)。因为在所有扭曲完成之前,线程块拥有的资源(如共享内存)无法为新线程块释放,所以如果一些扭曲需要很长时间才能完成,则较大的块大小可能会导致调度器可用的候选活动扭曲数目的减少。这可能会由于资源闲置或SM无法覆盖内存访问的延迟而导致性能降低。使用
\uuu syncthreads()
或其变体在线程块之间同步时,较大的块大小也会增加扭曲阻塞的概率,因此,可能会导致类似的现象