这是一个关于如何确定 CUDA 网格、 block 和线程大小的问题。这是对发布的问题 here 的一个附加问题.
在此链接之后,talonmies 的答案包含一个代码片段(见下文)。我不明白“通常通过调整和硬件限制选择值”的评论。
我在 CUDA 文档中没有找到很好的解释或说明来解释这一点。总之,我的问题是如何根据以下代码确定最佳 block 大小(线程数):
const int n = 128 * 1024;
int blocksize = 512; // value usually chosen by tuning and hardware constraints
int nblocks = n / nthreads; // value determine by block size and total work
madd<<<nblocks,blocksize>>>mAdd(A,B,C,n);
最佳答案
这个答案有两个部分(我写的)。一部分很容易量化,另一部分则更具经验性。
硬件限制:
这是容易量化的部分。当前 CUDA 编程指南的附录 F 列出了许多硬限制,这些限制限制了内核启动时每个 block 可以拥有的线程数。如果超过其中任何一个,您的内核将永远不会运行。大致可以概括为:
- 每个 block 的线程总数不能超过 512/1024 个(分别为 Compute Capability 1.x 或 2.x 及更高版本)
- 每个 block 的最大尺寸限制为 [512,512,64]/[1024,1024,64](计算1.x/2.x或更高版本)
- 每个 block 消耗的寄存器总数不能超过 8k/16k/32k/64k/32k/64k/32k/64k/32k/64k (计算1.0,1.1/1.2,1.3/2.x-/3.0/3.2/3.5-5.2/5.3/6-6.1/6.2/7.0)
- 每个 block 不能消耗超过 16kb/48kb/96kb 的共享内存(计算 1.x/2.x-6.2/7.0)
如果您保持在这些限制范围内,您可以成功编译的任何内核都将毫无错误地启动。
性能调整:
这是实证部分。您在上述硬件限制内选择的每个 block 的线程数可以并且确实会影响在硬件上运行的代码的性能。每个代码的行为方式都会有所不同,量化它的唯一真正方法是通过仔细的基准测试和分析。但同样,非常粗略地总结一下:
- 每个 block 的线程数应为 warp 大小的整数倍,在所有当前硬件上为 32。
- GPU 上的每个流式多处理器单元必须具有足够的事件扭曲,以充分隐藏架构的所有不同内存和指令管道延迟并实现最大吞吐量。这里的正统方法是尝试实现最佳硬件占用(Roger Dahl's answer 指的是)。
第二点是一个巨大的主题,我怀疑是否有人会尝试在一个 StackOverflow 答案中涵盖它。有人围绕问题各个方面的定量分析撰写博士论文(参见加州大学伯克利分校 Vasily Volkov 的 this presentation 和多伦多大学 Henry Wong 的 this paper 来了解问题到底有多复杂)。
在入门级别,您应该主要意识到您选择的 block 大小(在上述约束定义的合法 block 大小范围内)可以而且确实会影响代码的运行速度,但这取决于在您拥有的硬件和您正在运行的代码上。通过基准测试,您可能会发现大多数重要代码在每 block 128-512 个线程范围内都有一个“最佳点”,但您需要进行一些分析才能找到最佳点。好消息是,由于您正在处理扭曲大小的倍数,因此搜索空间非常有限,并且相对容易找到给定代码段的最佳配置。
关于performance - 如何为 CUDA 内核选择网格和 block 尺寸?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9985912/