我正在阅读&#34;专业CUDA C编程&#34;由Cheng等人。并且有一些示例表明如何运行(非常简单的单行)内核,例如<<<1024, 512>>>
执行的内核比使用<<<2048, 256>>>
的内核更差。然后他们说(你好几次)你可能已经预料到这个结果,因为第二次运行有更多的块,因此暴露出更多的并行性。我无法弄明白为什么。不是由SM中的并发warp数控制的并行数量?块大小与块大小有什么关系 - 这些warp属于哪个块并不重要 - 相同的块或不同的块,为什么使用较小的块会暴露更多的并行性(相反,如果块大小)太小我没有达到每SM限制的最大块数,导致更少的并发扭曲)?我可以设想的唯一场景是在Fermi上有1024个线程的块= 32个warp,每个SM限制最多有48个并发warp。这意味着只有1个并发块,只有32个并发warp,减少了并行度,但这是一个非常具体的用例。
更新: 在发布之后我想到的另一件事:在它完成所有的经线之前,不能从SM中驱逐一个块。因此,在该块的执行结束时,可能存在一些最后“最慢”的情况。 warps将整个块保存在SM中,该块中的大多数warp都已完成并停止,但是在完成少量执行warp之前,无法加载新块。所以在这种情况下效率会降低。现在,如果块较小,则仍然会发生这种情况,但相对于执行扭曲的停滞次数较少,因此效率较高。这是吗?
答案 0 :(得分:4)
是的,就是这样。你问题的第二段是一个很好的答案。
更详细地说,每个SM内部的warp调度程序的数量是有限的(通常为2)。每个warp调度程序都会跟踪多个活动warp,并仅在允许warp在程序中进一步移动时调度warp才能执行。 warp调度程序跟踪的活动warp的数量最大(通常为32)。因为在所有warp完成之前无法为新线程块释放线程块所拥有的资源(例如共享内存),所以如果有一些warp,则较大的块大小会导致调度程序可以使用减少的候选活动warp数量需要很长时间才能完成。由于资源空闲或SM无法覆盖存储器访问的延迟,这可能导致性能降低。当使用__syncthreads()
或其中一个变体在线程块中进行同步时,更大的块大小也会增加经线阻塞的可能性,因此可能会导致类似的现象。