4

我是一名使用 CUDA 进行数值积分的数学家。我的理解是每个 Nvidia 流式多处理器都有 8 个 CUDA 内核。所以对我来说,每个块使用超过 8 个线程似乎没有任何好处。然而,当我运行我的代码时,通过使用每个块 32 个线程而不是每个块 8 个线程,我获得了巨大的性能提升。

我还注意到使用超过 12 个块可以获得巨大的收益(即使我的卡只有 12 个流式多处理器)。

是否有一个原因?

4

3 回答 3

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 占用计算器来查看我所描述的不同场景的效果。

于 2012-07-01T23:07:47.277 回答
3

简短的回答是延迟隐藏。

如果你的工作单元(线程和块)与你有核心工作一样多,并且执行会遇到需要数百个时钟周期才能完成的内存操作,那么 GPU 没有其他工作可做,所以核心处于空闲状态直到内存操作完成。那是在浪费计算周期。

如果您提供的工作单元多于您拥有的核心来完成工作,那么当其中一个工作单元遇到长延迟内存操作时,硬件调度程序可以将其他一些工作单元交换到核心中,以便当长延迟内存操作完成时,内核一直忙于进行生产性工作。当混合中存在长延迟内存操作时,过多的线程或块提供了使用所有计算周期的更好机会。

于 2012-07-02T17:50:15.217 回答
2

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

  1. 占用率增加,这意味着线程数超过了隐藏内存延迟所需的线程数。
  2. 每个线程的独立操作增加。这会占用那些具有所需并行度的内核。

考虑这个计算机指令序列来计算大量元素。

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

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

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

希望这会有所帮助~

于 2012-07-24T02:42:24.037 回答