【发布时间】:2014-07-10 01:40:28
【问题描述】:
我对在 GPU 上运行的内核的吞吐量有疑问。假设它的占用率为 0.5,块大小为 256:编程指南指出最好有很多块,这样它们可以隐藏内存延迟等。但我不明白为什么这是正确的。因为一旦内核每个 Streaming Multi-processor = 24 的 warp 数,即 3 个块,它将达到峰值吞吐量。因此,拥有超过 24 个 warp(或 3 个块)不会对吞吐量产生任何影响。
我错过了什么吗?谁能纠正我?
【问题讨论】:
我对在 GPU 上运行的内核的吞吐量有疑问。假设它的占用率为 0.5,块大小为 256:编程指南指出最好有很多块,这样它们可以隐藏内存延迟等。但我不明白为什么这是正确的。因为一旦内核每个 Streaming Multi-processor = 24 的 warp 数,即 3 个块,它将达到峰值吞吐量。因此,拥有超过 24 个 warp(或 3 个块)不会对吞吐量产生任何影响。
我错过了什么吗?谁能纠正我?
【问题讨论】:
虽然低占用率的 SM 确实无法充分隐藏延迟,但了解这一点很重要:
更高的入住率!= 更高的吞吐量!
占用率只是衡量 SM 在任何给定时刻可供选择的工作量。拥有更多常驻 warp 使 SM 更有能力做有用的工作,而其他 warp 正在等待结果(内存访问或计算的结果 - 两者都具有非零延迟)。
吞吐量是衡量每秒完成多少工作的指标,虽然它可能受到延迟(因此占用率)的限制,但它也可能受到内存带宽、指令吞吐量(执行单元的数量)和其他因素。
编程指南指出拥有多个线程块比只有一个大线程块更好的原因是因为有时不仅能够从其他线程块发出工作,而且还能够从其他块发出工作。这是一个例子:
假设您的大线程块必须从全局内存(高延迟)加载数据并将其存储到共享内存(低延迟),然后必须立即执行__syncthreads()。在这种情况下,当一个 warp 完成加载其数据并将其写入共享内存时,它必须等待直到块中的所有其他线程完成相同的操作。对于一个大街区来说,这可能需要相当长的时间。但是如果有多个较小的线程块占用 SM,那么 SM 可以在等待第一个块中满足__syncthreads 的同时从其他块切换并开始工作。这有助于减少 GPU 空闲时间并提高效率。
您不一定希望拥有非常小的块(因为 Fermi 上的 SM 最多支持 8 个常驻块),但拥有 128-512 个线程的块通常比使用具有 1024 个线程的块更有效。
【讨论】:
如果您的启用 cuda 的卡中只有 一个 SM,那么在您的情况下,拥有 3 个以上的块不会改变吞吐量。通常一个 GPU 中有 8 个或更多 SM。
此外,在一个 SM 上运行的块数不仅仅取决于 warp 的数量。这只是一个限制因素,还有许多其他因素。 CUDA Occupancy Calculator 是查看内核占用率的绝佳工具。
【讨论】: