GPU上的线程和线程组

l3u*_*fly 11 multithreading gpu dispatch threadgroup directcompute

我想知道我可以在GPU上发送的线程/线程组的"网格".我正在使用Direct Compute,所以我将使用该API给出一个具体的例子.例如,如果我调用Dispatch(2,2,2),我理解它总共调度2x2x2 = 8个线程组.但是,如果我调用Dispatch(8,1,1),它还调度8x1x1 = 8个线程组,那有什么区别?有任何性能差异吗?

PS与GPU上的线程相同的问题.在计算(.hlsl)文件中声明的numthreads(2,2,2)和numthreads(8,1,1)之间的区别是什么?

任何帮助,将不胜感激.

Jas*_*son 13

从纯粹的性能角度来看,本身确实没有差异,因为定义线程组或块的网格维度的能力更多是为了正确地将工作负载应用于问题本身的抽象而不是性能.换句话说,如果您的问题很好地抽象到3D体积网格,那么虽然可以使用将3D问题转换为1D线性表示的映射来创建相同数量的线程组/块,但是该映射的抽象处理起来可能有点麻烦.此外,如果映射过于复杂,则可能会造成较小的性能损失.

您创建的线程组/块的数量以及这些块中的线程数很重要.在Nvidia GPU的情况下,每个线程组被分配给GPU上的SMX处理器,并且将多个线程块及其相关联的线程映射到SMX对于隐藏由于存储器访问等引起的延迟是必要的.此外,您想要在线程组/块中拥有足够的线程,以便利用GPU的SIMT(相同指令/多线程)功能.这意味着对于Nvidia GPU的SMX内部的每个时钟周期(或一组时钟周期),它可以在锁定步骤中同时执行X个线程.这个数字称为"线程扭曲"大小.您希望块中有足够的线程来填充此warp计数,否则当GPU在各个SMX处理器上运行时,GPU核心流处理器的资源不会被耗尽.这个数字是Nvidia Fermi GPU上的32个主题.在CUDA中,您可以根据您正在使用的GPU查询此信息,尽管我假设使用DirectCompute,这将被抽象掉.ATI卡也具有到其流处理器的"线程宽度",即每个"波前"64个线程.

理想情况下,您最终希望在块中有足够的线程来填充wavefront中的线程数或GPU的warp大小,然后可以映射到GPU上的每个流处理器的大量块,以便它们无论何时遇到高延迟操作,都可以保持在飞行中并在流处理器上交换.这最大化了GPU的计算带宽.