CUDA模型-什么是warp大小?

51
最大工作组大小和warp大小之间有什么关系?假设我的设备有240个CUDA流处理器(SP),并返回以下信息 -
CL_DEVICE_MAX_COMPUTE_UNITS: 30
CL_DEVICE_MAX_WORK_ITEM_SIZES: 512 / 512 / 64
CL_DEVICE_MAX_WORK_GROUP_SIZE: 512
CL_NV_DEVICE_WARP_SIZE: 32
这意味着每个流多处理器(即计算单元)有8个SP。现在,warp大小= 32与这些数字有什么关系?
3个回答

131

直接回答:Warp大小是一个warp中的线程数,它是硬件实现中用于合并内存访问和指令分派的子细分。

建议阅读:

如@Matias所提到的,建议阅读CUDA C最佳实践指南(需要滚动到底部列出的部分)。你可能需要仔细观察第164页的附录G.1中的表格。

解释:

CUDA是一种语言,提供了两个级别的并行性。你有线程和线程块。当你执行一个Kernel时,你需要在<<< >>>之间指定每个线程块的大小以及线程块的数量。

然而,CUDA没有告诉你的是实际上有四个级别的并行性。在后台,你的线程块实际上被划分为称为“warp”的子块。这里有一个简短的比喻来帮助解释正在发生的事情:

简短的比喻:

假设你是一名对高中毕业生当前的数学能力感兴趣的教育工作者/研究人员/政治家。你的计划是给10,240名学生进行测试,但你不能只是把他们都放在一个足球场或其他地方,然后给他们测试。最简单的方法是对数据进行细分(并行化)--所以你去了20个不同的高中,要求他们每个有512名毕业生参加数学测试。

高中数量20相当于“块”的数量/”线程块的数量”。512名毕业生的数量类似于每个块内的线程数,也就是“每个块的线程数”。

你收集数据,这是你关心的全部内容。但你不知道(也并没有真正在意),每所学校实际上都被分成了教室。因此,你的512名高中毕业生实际上被分成了16组32人。而且,这些学校中没有一个真正拥有所需的资源,每个教室只有16台计算器。因此,在任何时候,每个教室只有一半的学生能参加你的数学测试。

512位高中毕业生的数量表示启动CUDA Kernel时请求的每个线程块的数量。实施硬件可以进一步将其分成16个连续的32个线程块,以处理请求的所有线程数,即512。数字32是warp大小,但这可能因不同的硬件版本而有所不同。

我可以继续发挥愚蠢的规则,比如任何一所学校最多只有八个教室可以同时参加考试,因为他们只有八名教师。你不能同时抽样超过30所学校,因为你只有30个监考员......

回到您的问题:

使用这个比喻,你的程序想要尽快计算出结果(你想收集数学测试)。你发出一个包含一定数量的块(学校)和每个块中一定数量的线程(学生)的内核。你一次只能运行这么多块(收集调查响应需要每所学校有一个监考员)。在CUDA中,线程块在流式多处理器(SM)上运行。变量:CL_DEVICE_MAX_COMPUTE_UNITS告诉你一个特定的卡有多少个SM,30。这根据硬件而大不相同--请查看CUDA C最佳实践指南附录A中的表格。请注意,每个SM无论计算能力(1.X还是2.X),都只能同时运行八个块。

线程块具有最大维度:CL_DEVICE_MAX_WORK_ITEM_SIZES。将线程排列成网格,每行不能超过512个线程。每列不能超过512个线程。并且不能将超过64个线程堆叠在一起。此外,线程块的最大数量为CL_DEVICE_MAX_WORK_GROUP_SIZE,即512个可以分组在一个块中的线程。因此,线程块的尺寸可以是:

512 x 1 x 1

1 x 512 x 1

4 x 2 x 64

64 x 8 x 1

等等...

请注意,自计算能力2.X起,您的块最多可具有1024个线程。最后,变量CL_NV_DEVICE_WARP_SIZE指定了warp大小,即32(每个教室的学生人数)。在计算能力为1.X的设备上,内存传输和指令调度发生在半warp粒度下(每个教室只有16台计算机)。在计算能力2.0中,内存传输被分组为warp,因此同时进行32个提取,但指令调度仍然只按半warp分组。对于计算能力2.1,内存传输指令调度都以warp方式进行,即32个线程。这些内容在未来的硬件中可能会发生变化。

因此,言归正传:

总结:

我已经描述了warp/thread布局等细微差别,但是这里有一些需要记住的事情。首先,你的内存访问应该可以以16或32个为一组。因此,请将您块的X维设为32的倍数。其次,最重要的是要最大化占用率以获得特定GPU的最佳性能。不要有5个拥有512个线程的块。也不要有1,000个只有10个线程的块。我强烈建议查看基于Excel的电子表格(在OpenOffice中也可以使用)它会告诉您特定内核调用(线程布局共享内存需求)的GPU占用率将是多少。希望这次解释有所帮助!


3
非常好的回答和比喻。只想补充一点,AMD 也有类似的概念叫做 Wavefront,目前每个 Wavefront 可以处理64个线程。 - elmattic
1
@M.Tibbits 您能告诉我您正在引用哪个 Excel 工作表吗? - mkuse
请点击此链接下载CUDA Occupancy计算器:http://developer.download.nvidia.com/compute/cuda/CUDA_Occupancy_calculator.xls - M. Tibbits
@M.Tibbits,你刚才写道“请注意,每个SM只能同时运行八个块,无论计算能力是1.X还是2.X。”,但我猜你的意思是每个SM只能允许八个warp同时工作,对吗? - Yan An
是的,@Kelsius,你说得对,我刚刚误解了。 - Yan An
显示剩余5条评论

4

Warp大小是一个多处理器同时执行的线程数。NVIDIA多处理器可以同时使用硬件多线程执行同一块中的几个线程。

考虑Warp大小非常重要,因为所有内存访问都被合并成Warp大小的倍数(32字节、64字节、128字节),这会提高性能。

CUDA C最佳实践指南包含了所有关于这些优化的技术信息。


2
直接的答案很简洁:在Nvidia中,由THREAD组成的BLOCK是由程序员设置的,而WARP是32(由32个线程组成),它是计算单元同时执行的最小单位。在AMD中,WARP被称为WAVEFRONT(“波浪”)。
在OpenCL中,WORKGROUPs代表CUDA中的BLOCKs,此外,WORKITEMs代表CUDA中的THREADs。

2
这是一个在某种程度上具有信息性的答案;然而,它并没有真正告诉我们关于warp以及如何在编写代码时将其纳入考虑。正如理查德·费曼曾经说过的那样,“知道某个东西的名字并不意味着你理解它。” 要进行良好的教学,您应该解释某个东西的操作方式或用法。 - Engineer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接