CUDA块和线程束 - 在单个SM上可以并行运行吗?

20

好的,我知道之前已经有很多关于这个问题的相关提问,并且我已经阅读了大部分与此相关的内容,但情况仍然不太清楚。可能也是因为我找到并阅读了一些相互矛盾的东西(也许是因为它们来自不同的时间,涉及具有不同计算能力的设备,它们之间似乎存在相当大的差距)。我想要更加高效,减少执行时间,因此我需要知道在并行环境下可以同时运行多少个线程/线程束/块。此外,我正在考虑将其泛化,并基于我所知道的操作数量(对于简单程序)和系统规格计算传递给我的内核的最佳线程和块数。

我有一张 GTX 550Ti 显卡,它的计算能力为 2.1。 4 个 SM 每个拥有 48 个核心 = 192 CUDA 核心。

那么对我来说不清楚的是:

是否可以有多个块在一个多处理器(SM)上同时运行(并行)?我读到最多可以分配 8 个块给一个 SM,但没有关于它们如何运行的信息。从每个 SM 上的最大线程数(1536)几乎与每个块上的最大线程数(1024)相差无几这一事实来看,我认为块并不是并行运行的(也许只有一个半?)。或者至少不会在每个块上都有最大线程数的情况下运行。另外,如果我将块的数量设置为,比如 4(我的 SM 数量),它们会被发送到不同的 SM 上吗? 或者我实际上无法控制所有这些硬件上的分布,那么这就是一个无意义的问题,我的执行时间将根据我的设备的心情而变化…

其次,我知道一个块会将其线程分成32个并行运行的组,称为warp。现在这些warp(假设它们彼此没有关系)也可以并行运行吗?因为在Fermi架构中它指出同时执行2个warp,从每个warp发送一条指令到一组16(?)个核心,而我在其他地方读到每个核心处理一个warp,这将解释1536最大线程(32 * 48),但似乎有点过多。1个CUDA核心能同时处理32个线程吗?

更简单地说,我的问题是:(例如)如果我想将两个向量相加得到第三个向量,我应该给它们什么长度(操作数)和如何将它们分割成块和线程,以使我的设备以全容量并发(并行)工作(没有空闲的核心或SMs)。

很抱歉如果之前已经问过这个问题,我没有理解或看到它。希望你能帮助我。谢谢!

3个回答

19
启动配置和设备确定了工作的分发和并行执行。启动配置包括网格维度、块维度、每个线程的寄存器和每个块的共享内存。根据这些信息和设备,可以确定可以同时在设备上执行的块数和warp数。开发内核时,通常会查看可以在SM上活动的warp比上设备每个SM的最大warp数的比率。这被称为理论占用率。CUDA占用率计算器可用于研究不同的启动配置。
当启动网格时,计算工作分配器将栅格化网格并将线程块分配给SM,并为线程块分配SM资源。如果SM具有足够的资源,则多个线程块可以同时在SM上执行。
为了启动warp,SM将warp分配给warp调度程序并为warp分配寄存器。此时,warp被视为活动warp。
每个warp scheduler管理一组warp(Fermi上有24个,Kepler上有16个)。没有停滞的warp称为eligible warps。在每个周期中,warp scheduler选择一个eligible warp并向int / fp单元,双精度浮点单元,特殊功能单元,分支分辨单元和加载存储单元等执行单元发出指令。执行单元是流水线化的,允许许多warp每个周期都有1个或多个指令在运行。warp可以在指令获取,数据依赖性,执行依赖性,屏障等方面被阻塞。
每个内核都有不同的最佳启动配置。诸如Nsight Visual Studio Edition和NVIDIA Visual Profiler之类的工具可以帮助您调整启动配置。我建议您尝试以灵活的方式编写代码,以便可以尝试多个启动配置。我会从使用至少50%占用率的配置开始,然后尝试增加和减少占用率。 每个问题的答案 问:多个块可以同时(并行)在一个多处理器(SM)上运行吗?

是的,最大数量取决于设备的计算能力。请参见表10。每个计算能力的技术规格:每个多处理器的最大居民块数来确定该值。通常,启动配置限制了运行时的值。有关详细信息,请参阅占用率计算器或其中一个NVIDIA分析工具。

问:由于我的每个SM的最大线程数(1536)几乎与每个块的最大线程数(1024)相同,我认为块不会并行运行(也许只有1个半?)。

启动配置确定每个SM的块数。将每个块的最大线程数与每个SM的最大线程数的比率设置为允许开发人员在如何分割工作方面具有更大的灵活性。

问:如果我将块数设置为4(我的SM数),它们将被发送到每个不同的SM吗?还是我无法真正控制所有这些在硬件上的分布,然后这就是一个无意义的问题,我的执行时间将根据我的设备的心情而变化...

您对工作分配的控制是有限的。您可以通过分配更多的共享内存来限制占用,从而人为地控制这一点,但这是一种高级优化。

问:其次,我知道一个块会将它的线程分成32个线程一组并行运行,称为warp。现在这些warp(假设它们彼此无关)也可以并行运行吗?

是的,warp可以并行运行。

问:因为在Fermi架构中指出了同时执行2个warp

每个Fermi SM有2个warp调度器。每个warp调度器可以在每个周期为1个warp分派指令。指令执行是流水线式的,所以许多warp每个周期可以有1个或多个指令正在处理。

问:将每个warp的一条指令发送到一组16(?)个核心,而在其他地方读到每个核心处理一个warp,这可以解释最大1536个线程(32x48),但似乎过多。一个CUDA核心可以同时处理32个线程吗?

是的。CUDA核心是整数和浮点执行单元的数量。SM具有我上面列出的其他类型的执行单元。GTX550是一个CC 2.1设备。在每个周期内,SM最多可以分派4条指令(128个线程)每个周期。根据执行的定义,每个周期飞行中的总线程数可以从几百到几千不等。

延伸问题:一个CUDA核心能同时处理32个线程吗?,这32个线程必须是同一块吗?是否可能一个CUDA核心同时执行来自不同块的两个线程? - haccks
一个CUDA核心不是“核心”,它是一个整数/浮点执行管道。线程在warp中的id(ptx%laneid)与执行管道之间有固定的映射关系。在CC 3.x设备上,来自warp的32个线程被分派到32位int / fp执行路径。在CC 2.x设备上,来自warp的32个线程被分派到16位双时钟in / fp执行路径上,持续2个热时钟。双精度单元不如宽,因此warp在多个周期内发出。所有线程必须是同一个warp的一部分。 - Greg Smith
是的,我知道。所有线程必须属于同一个wrap。在GPU中,CPU核心的等效物是SM,它以wrap(32个线程)的形式执行线程。每个SP处理一个线程。让我困惑的是,一个SM可以同时拥有多个块,也就是说多个线程块可以在一个多处理器上并行执行。如果一个SM有8个SP,并且它可以同时拥有8个常驻块,每个块都有64个线程,那么在前8个周期内只会处理一个块吗? - haccks
“如果我将块的数量设置为4(我的SM数量),它们会被发送到不同的SM吗?”这个问题很有趣。@GregSmith 这是否意味着工作如何分配给SM是完全随机的,我们必须通过尝试和错误来找出(这仅对某些GPU或架构有效)?肯定有一些算法将工作负载分配给SM,对吧?我猜块/SM分配将取决于这些块中的线程数...但仍然必须有一个标准来判断何时SM被认为是“满”的! - Silicomancer
NVIDIA没有记录线程块工作分配算法。CUDA编程模型支持cudaLaunchCooperativeKernel,支持网格同步。这保证了所有线程块都是共存的。利用这一点和warp占用技巧(在SM中分配所有共享内存)可以确保每个SM只有1个线程块。线程块和warp占用基于SM资源、SM配置(例如L1/SHM)、每个块的共享内存、每个块的线程数、每个线程的寄存器等。 - Greg Smith

1
我希望能够更高效,减少执行时间,因此需要知道有多少线程/线程束/块可以同时并行运行。简而言之,并发运行的线程/线程束/块的数量取决于几个因素。CUDA C最佳实践指南中有执行配置优化的介绍,解释了这些因素并提供了一些关于如何构建应用程序的提示。

-2

对我来说,需要一段时间才能理解的概念之一是CUDA芯片上的硬件支持上下文切换的效率。

因此,每次内存访问都会发生上下文切换,允许计算在许多上下文中交替进行,而其他上下文则等待其内存访问。 GPGPU架构实现性能的一种方式是能够以这种方式并行化,除了在多个核心上并行化之外。

当没有任何核心在等待内存访问时,可以实现最佳性能,并且通过具有足够的上下文来确保发生这种情况。


这是不正确的。Warp调度程序可以在每个周期从符合条件的活动warp集合中选择发出指令。如果warp由于执行依赖、数据依赖、获取等而被阻塞,则该warp就不符合条件。 - Greg Smith

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