CUDA:为什么每个块超过8个线程会有好处?

4
我是一名数学家,使用CUDA进行数字积分。据我理解,每个Nvidia流多处理器具有8个CUDA核心。因此,在我的看来,每个块中使用超过8个线程是没有任何好处的。然而,当我运行代码时,使用每个块32个线程与每个块8个线程相比,可以获得巨大的性能提升。
另外,我注意到即使我的显卡只有12个流多处理器,使用超过12个块也可以获得很大的性能提升。
这是为什么呢?

5
我认为你需要阅读CUDA编程指南中“warp”概念的部分。CUDA执行模型类似于SIMD架构,每个“warp”包含32个线程。每个多处理器具有许多管线和内存延迟,需要大量并发的“warp”来隐藏延迟并实现峰值吞吐量。编程指南中详细讨论了这些内容。 - talonmies
1
talonmies解释得非常清楚。我只想补充一点,通常最好的块大小应该是64的倍数,以避免寄存器内存冲突。至少对于旧版本的CUDA来说是这样的。我不确定寄存器内存冲突是否仍然是最新CUDA版本的问题。 - chaohuang
顺便提一下,只有sm_1x SM才有8个Cuda核心。sm_2x(Fermi)SM有32个Cuda核心,而sm_3x(Kepler)SMX有192个Cuda核心。此外,每个块至少使用64个线程可能会带来更多的好处,因为您的硬件每个SM限制为8个块,因此使用32个线程块可能会限制占用率。 - harrism
寄存器分配和指令调度是以 warp 粒度完成的。一般来说,当少于WARP_SIZE线程处于活动状态时,发出指令将不会带来任何性能提升。由于8个线程可能引用的缓存行比32个线程少,因此内存指令可能会看到提高的性能,每条指令的事务也会减少。CUDA核心仅指SM中的一种执行单元类型。Fermi和Kepler白皮书提到了其他执行单元。 - Greg Smith
3个回答

8
talonmies和chaohuang在评论中提供了有用的信息,你应该查看一下(不确定为什么这些不是答案,但这是他们的决定)。无论如何,我将提供一个缩写的部分答案来解释一些你可能没有考虑到的东西。
假设你有8个控制线程和8个处理器。如果所有8个线程中的所有指令都是芯片上的指令,只需要一个周期,那么所有8个线程将在n个周期内完成(假设每个线程总共有n个指令)。
现在假设每个控制线程由n个指令组成,其中一部分r是离芯片存储器指令,需要例如100个周期才能完成。这8个线程现在需要[(1-r)+100r]n个周期才能完成。如果r=0.1,则这大约比前面的情况多11倍。
现在假设我们有16个线程。当第一批8个线程被阻塞在慢速操作上时,其他线程就可以执行;芯片上的指令可以执行,离芯片指令也可以开始执行。因此,完成所有线程可能只需要略微多于[(1-r)+100r]n个周期。实质上,因为你有一些空间可以重叠等待线程和其他线程,你可以免费添加更多线程。
这是GPU模型的巨大优势:通过大规模并行来克服长延迟。做一点工作需要很长时间,但做更多的工作不需要更多的时间。请注意,当算术强度(与上述公式中的r有关)很高时,占用率(与你准备隐藏延迟的工作量(以线程为单位)有关)对于峰值性能并不是非常重要。你可以尝试使用CUDA占用率计算器来查看我描述的不同情况的影响。

+1. 两点评论:首先,@Patrick87所描述的通常被称为“隐藏延迟”。其次,占用率计算器无法告诉您有关运行时间的任何信息。更高的占用率并不一定等同于更高的性能,但它是一个不错的衡量隐藏延迟能力的指标。 - harrism
@harrism 关于占用率与性能无关的观点很好。我试图表达这一点,但可能有点令人困惑。 - Patrick87
不是你的错:占用率是一个令人困惑的指标。它与性能有关,但并非直接相关。 - harrism

3
简短的答案是隐藏延迟。
如果你只有与核心数量相同的工作单元(线程和块)来处理它们,当执行需要数百个时钟周期才能完成的内存操作时,GPU没有其他工作可做,因此核心会闲置,直到内存操作完成。这浪费了计算周期。
如果您提供的工作单元超过您所拥有的核心,则当其中一个工作单元遇到长延迟的内存操作时,硬件调度程序可以将其他工作单元换入核心,以便在长延迟的内存操作完成时保持核心忙于进行生产性工作。具有多余的线程或块提供了更好的机会,在混合了长延迟内存操作时使用所有计算周期。

2

在GPU中,基本上有两种隐藏内存延迟的方法:

  1. 增加占用率,这意味着比所需的线程数更多的线程来隐藏内存延迟。
  2. 增加每个线程的独立操作。这将占用那些具有所需并行性的核心。

考虑以下计算大量元素的计算机指令序列。

a = b + c;
d = a + c;

第二条指令会停顿,因为它在等待第一条指令的结果完成。

当您只使用8个线程时,这些线程正在等待,GPU内核处于空闲状态。 然而,如果您有更多的线程,GPU能够安排其他元素的计算在当前warp等待时进行计算。这就是为什么增加线程数会使性能更好的原因。它更有效地利用了CPU内核=)

希望这可以帮助您~


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接