CUDA 扭曲和每个块的最佳线程数
Posted
技术标签:
【中文标题】CUDA 扭曲和每个块的最佳线程数【英文标题】:CUDA Warps and Optimal Number of Threads Per Block 【发布时间】:2015-12-27 14:59:56 【问题描述】:根据我对 Kepler GPU 和一般 CUDA 的了解,当单个 SMX 单元在块上工作时,它会启动由 32 个线程组成的 warp。现在这是我的问题:
1) 如果 SMX 单元可以在 64 个 warp 上工作,这意味着每个 SMX 单元有 32x64 = 2048 个线程的限制。但是 Kepler GPU 有 4 个 warp 调度器,那么这是否意味着在一个 GPU 内核中只能同时处理 4 个 warp?如果是这样,这是否意味着我真的应该寻找具有 128 个线程的倍数的块(假设线程没有分歧)而不是推荐的 32 个?当然,这会忽略任何分歧,甚至忽略全局内存访问之类的情况会导致 warp 停止并让调度程序切换到另一个的情况。
2) 如果以上是正确的,那么单个 SMX 单元同时在 128 个线程上工作的最佳结果是什么?对于具有 14 个 SMX 单元的 GTX Titan 之类的东西,总共 128x14 = 1792 个线程?我看到网上的数字不是这样的。 Titan 可以同时运行 14x64(每个 SMX 的最大扭曲)x32(每个 SMX 的线程)= 28,672。 SMX 单元怎么会启动 warp,并且只有 4 个 warp 调度程序?他们不能一次启动每个 SMX 的所有 2048 个线程吗?也许我对 GPU 可以同时启动的最大线程数的定义感到困惑,你可以排队吗?
感谢您对此的回答和澄清。
【问题讨论】:
您的编程相关工作在哪里? 【参考方案1】:这是否意味着在一个 GPU 内核中只能同时处理 4 个扭曲?
可以在开普勒 SMX 上在任何给定的时钟周期调度来自多达 4 个 warp 的指令。然而,由于执行单元中的流水线,在任何给定的时钟周期,指令可能处于流水线执行的各个阶段,从当前驻留在 SMX 上的任何以及最多所有 warp。
如果是这样,这是否意味着我真的应该寻找具有 128 个线程的倍数的块(假设线程没有分歧)而不是推荐的 32 个?
我不确定您是如何从上一点跳到这一点的。由于指令组合可能因经线而异(因为不同的经线可能位于指令流中的不同点)并且指令组合在指令流中从一个地方到另一个地方不同,所以我看不到可调度的 4 个经线之间的任何逻辑联系给定的时钟周期,并且任何需要有 4 个扭曲组。一个给定的warp可能处于其指令高度可调度的点(可能在一系列SP FMA上,需要大量的SP核心),另外3个warp可能位于指令流中的另一个点,它们的指令是“更难安排”(可能需要 SFU,但数量较少)。因此,将经线任意分组为 4 组并没有多大意义。请注意,我们不需要发散来使扭曲彼此不同步。调度程序的自然行为加上不同的执行资源可用性可能会创建最初在一起的warp,它们位于指令流中的不同点。
对于第二个问题,我认为您的基本知识差距在于理解 GPU 如何隐藏延迟。假设一个 GPU 有一组 3 条指令通过一个 warp 发出:
LD R0, a[idx]
LD R1, b[idx]
MPY R2, R0, R1
第一条指令是来自全局内存的 LD,它可以发出并且不会停止 warp。同样可以发出第二条指令。然而,由于全局内存的延迟,warp 将在第三条指令处停止。在 R0 和 R1 正确填充之前,不能调度乘法指令。来自主存储器的延迟阻止了它。 GPU通过(希望)准备好可以转向的“其他工作”来解决这个问题,即处于未停止状态的其他经线(即具有可以发出的指令)。促进这种延迟隐藏过程的最佳方法是为 SMX 提供 许多 扭曲。这没有任何粒度(例如需要 4 个经纱)。一般来说,网格中的线程/扭曲/块越多,GPU 隐藏延迟的机会就越大。
因此,GPU 确实无法在单个时钟周期内“启动”2048 个线程(即从 2048 个线程发出指令)。但是,当一个 warp 停止时,它会被放入等待队列中,直到停止条件解除为止,在此之前,让其他 warp “准备好”,以用于下一个时钟周期是有帮助的。
GPU 延迟隐藏是一个经常被误解的话题。如果您搜索它们,有许多可用资源可以了解它们。
【讨论】:
我真的很感激。它有很大帮助。我同意这并不被普遍理解,而且很难找到这些资源。我的很多搜索最终都让我回到了 ***,另一个用户问了一个类似但不相同的问题。此外,当全局内存调用会停止扭曲时,这就是我的意思。但是我没有意识到可以连续进行多个内存调用而不会停止,尽管我明白为什么会这样。以上是关于CUDA 扭曲和每个块的最佳线程数的主要内容,如果未能解决你的问题,请参考以下文章