我是一名使用CUDA进行数值积分的数学家。我的理解是每个Nvidia流多处理器都有8个CUDA核心。所以对我来说,每个块使用超过8个线程似乎没有任何好处。但是,当我运行我的代码时,通过每块使用32个线程而不是每个块8个线程,我获得了巨大的性能提升。
另外我注意到使用超过12个块有很大的收益(即使我的卡只有12个流多处理器)。
这有什么理由吗?
答案 0 :(得分:8)
talonmies和chaohuang在评论中提供了很好的信息,你应该调查一下(不知道为什么这些不是答案,但这是他们的电话)。无论如何,我将提供一个简短的部分答案来解释你可能不会考虑的事情。
假设您有8个控制线程和8个处理器。如果所有8个线程中的所有指令都是仅占用一个周期的片上指令,那么所有8个线程将在n
个周期内完成(假设每个线程有n
个总指令)。
现在假设每个控制线程由n
个指令组成,其中这些指令的一小部分r
是片外存储器指令,例如需要100个周期才能完成。这8个线程现在将完成[(1 - r) + 100r]n
个周期。如果是r=0.1
,这比前一个案例大约多11倍。
现在让我们说我们有16个线程。当第一批8个线程在慢速操作时被阻塞时,其他线程可以执行;可以执行片上指令,并且可以启动片外指令。因此,您可能只需要2[(1 - r) + 100r]n
,而不需要[(1 - r) + 100r]n
个周期来完成所有线程。从本质上讲,因为你有一些空间可以将等待线程与其他线程重叠,所以你可以免费添加更多线程。
这是GPU模型的强大优势:克服长延迟的大规模并行性。做一点工作需要很长时间,但没有多少时间做更多的工作。请注意,当您的算术强度(与上述公式中的r
相关)较高时,与您准备隐藏延迟的工作量(线程中)相关的占用率对于峰值性能并不是那么重要。您可以使用CUDA占用计算器来查看我针对不同场景所描述的效果。
答案 1 :(得分:2)
简短的回答是延迟隐藏。
如果你只拥有与核心一样多的工作单元(线程和块)来处理它们并且执行需要数百个时钟周期才能完成的内存操作,那么GPU就没有别的办法了核心处于空闲状态,直到内存操作完成。那是在浪费计算周期。
如果您提供的工作单元数多于核心工作单元,那么当其中一个工作单元遇到长延迟内存操作时,硬件调度程序可以将其他一些工作单元交换到核心(s)这样,在长延迟内存操作完成时,内核仍然忙着进行高效工作。当混合中存在长延迟内存操作时,拥有过多的线程或块可以更好地使用所有计算周期。
答案 2 :(得分:2)
基本上有两种方法来记忆GPU中的延迟隐藏:
考虑这一系列计算机指令来计算大量元素。
a = b + c;
d = a + c;
第二条指令在等待第一条指令完成的结果时会停止。
当您仅使用8个线程时,这些线程正在等待并且GPU核心处于空闲状态。 但是,如果您有更多线程,GPU可以安排在当前warp等待时计算其他元素的计算。这就是为什么当你增加线程数时,它的表现会更好。它更有效地利用CPU核心=)
希望这会有所帮助〜