CUDA 块和变形
Posted
技术标签:
【中文标题】CUDA 块和变形【英文标题】:CUDA Blocks & Warps 【发布时间】:2013-03-09 18:13:06 【问题描述】:好的,我知道相关问题已被一遍又一遍地提出,我阅读了几乎所有我发现的关于此的内容,但事情仍然不清楚。可能也是因为我发现并阅读了相互矛盾的东西(可能是因为来自不同的时代,他们提到了具有不同计算能力的设备,它们之间似乎有很大的差距)。我希望提高效率,以减少我的执行时间,因此我需要确切地知道有多少线程/warp/块可以同时并行运行。此外,我正在考虑对此进行概括,并仅根据我知道我必须执行的操作数量(对于更简单的程序)和系统规范来计算要传递给我的内核的线程和块的最佳数量。
我有一台 GTX 550Ti,顺便说一句,计算能力为 2.1。 4 个 SM x 48 个内核 = 192 个 CUDA 内核。
好吧,我不清楚的是:
可以在多处理器 (SM) 上一次(并行)运行 1 个以上的块吗?我读到最多可以将 8 个块分配给一个 SM,但没有关于它们是如何运行的。从我每个 SM 的最大线程数(1536)几乎不大于我每个块的最大线程数(1024)这一事实,我认为这些块不是并行运行的(可能是 1 个半?)。或者如果我有最大数量的线程,至少不会。此外,如果我将块数设置为 4(我的 SM 数),它们会分别发送到不同的 SM 吗? 或者我无法真正控制所有这些在硬件上的分布方式,然后这是一个有争议的问题,我的执行时间将根据我的设备的突发奇想而有所不同......
其次,我知道一个块会将其线程划分为并行运行的 32 个线程组,称为 warp。现在这些扭曲(假设它们彼此没有关系)也可以并行运行?因为在 Fermi 架构中,它声明 2 个 warp 是同时执行的,从每个 warp 发送一条指令到一组 16 个(?)核心,而在其他地方我读到每个核心处理一个 warp,这可以解释 1536 个最大线程( 32 * 48)但似乎有点多。 1个CUDA核心可以同时处理32个线程吗?
简单地说,我要问的是:(例如)如果我想在第三个向量中求和 2 个向量,我应该给它们多长(操作数)以及我应该如何将它们分成块和线程让我的设备以最大容量同时(并行)工作(没有空闲内核或 SM)。
很抱歉,如果之前有人问过这个问题,但我没有得到它或没有看到它。希望您能够帮助我。谢谢!
【问题讨论】:
【参考方案1】:工作的分布和并行执行由启动配置和设备决定。启动配置说明了网格尺寸、块尺寸、每个线程的寄存器和每个块的共享内存。根据此信息和设备,您可以确定可以在设备上同时执行的块和扭曲的数量。在开发内核时,您通常会查看 SM 上可以活动的 warp 与设备的每个 SM 的最大 warp 数的比率。这称为理论占用率。 CUDA Occupancy Calculator 可用于调查不同的启动配置。
当网格启动时,计算工作分配器将对网格进行光栅化并将线程块分配给 SM,并为线程块分配 SM 资源。如果 SM 有足够的资源,可以在 SM 上同时执行多个线程块。
为了启动 warp,SM 将 warp 分配给 warp 调度程序并为 warp 分配寄存器。此时,经线被视为活动经线。
每个 warp 调度器管理一组 warp(Fermi 上 24 个,Kepler 上 16 个)。未停止的经线称为合格经线。在每个周期,warp 调度程序选择一个符合条件的 warp 并将该 warp 的指令发布到执行单元,例如 int/fp 单元、双精度浮点单元、特殊功能单元、分支解析单元和加载存储单元。执行单元是流水线的,允许许多 warp 每个周期有 1 条或更多条指令在运行。 Warp 可以在指令获取、数据依赖、执行依赖、障碍等方面停止。
每个内核都有不同的最佳启动配置。 Nsight Visual Studio Edition 和 NVIDIA Visual Profiler 等工具可以帮助您调整启动配置。我建议您尝试以灵活的方式编写代码,以便您可以尝试多种启动配置。我会先使用一个至少 50% 占用率的配置,然后尝试增加和减少占用率。
每个问题的答案
问:在多处理器 (SM) 上可以同时运行 1 个以上的块(并行)吗?
是的,最大数量取决于设备的计算能力。 See Tabe 10. Technical Specifications per Compute Capability : Maximum number of residents blocks per multiprocessor 确定值。通常,启动配置会限制运行时间值。有关详细信息,请参阅占用计算器或 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)但似乎有点很多。 1个CUDA核心可以同时处理32个线程吗?
是的。 CUDA cores 是整数和浮点执行单元的数量。 SM 有我上面列出的其他类型的执行单元。 GTX550 是 CC 2.1 设备。在每个周期,一个 SM 有可能在每个周期最多分派 4 条指令(128 个线程)。根据执行的定义,每个周期运行的线程总数可以从数百到数千不等。
【讨论】:
扩展问题:1个CUDA核心可以同时处理32个线程吗?,这32个线程必须是同一个块吗?一个CUDA核心是否有可能同时执行来自不同块的两个线程 一个CUDA核心不是一个“核心”,它是一个整数/浮点执行管道。 warp 中的线程通道 id (ptx %laneid) 和执行管道之间存在固定映射。在 CC 3.x 设备上,来自一个 warp 的 32 个线程被分派到一个 32 宽的 int/fp 执行路径。在 CC 2.x 设备上,来自一个 warp 的 32 个线程在 2 个热时钟上被分派到一个 16 宽的双时钟输入/fp 执行路径。双精度单元没有那么宽,因此在多个周期中会出现翘曲问题。所有线程都必须属于同一条经线。 是的,我知道。所有线程必须是同一包裹的一部分。 GPU 中等效的 CPU 核心是一个 SM,它以包裹的形式执行线程(32 个线程)。每个SP处理一个线程。让我感到困惑的是,一个 SM 可以有多个驻留块,即多个线程块可以在一个多处理器上同时执行。如果一个 SM 有 8 个 SP,它一次可以有 8 个驻留块,每个块有 64 个线程,那么是否有必要在前 8 个周期中只处理一个块? 问题“如果我将块数设置为 4(我的 SM 数),它们会分别发送到不同的 SM 吗?”很有趣。 @GregSmith这是否意味着将工作分配给SM是完全随机的,我们必须通过尝试和错误来找出答案(这只对特定的GPU或架构有效)?一定有某种算法可以将工作负载分配给 SM,对吧?我猜 Block/SM 的分配将取决于这些块中的线程数......但是当一个 SM 被认为是“满的”时仍然必须有一个标准?! NVIDIA 没有记录线程块工作分配算法。 CUDA 编程模型支持 cudaLaunchCooperativeKernel 支持网格同步。这保证了所有线程块是共同驻留的。使用这个和扭曲占用技巧(在一个 SM 中分配所有共享内存)可用于确保每个 SM 有 1 个线程块。线程块和 warp 占用率基于 SM 资源、SM 配置(例如 L1/SHM)、每个块的共享内存、每个块的线程、每个线程的寄存器等。【参考方案2】:我希望提高效率,以减少我的执行时间,因此我需要确切地知道有多少线程/warp/blocks 可以同时并行运行。
简而言之,可以并发运行的线程/warp/块的数量取决于几个因素。 CUDA C 最佳实践指南在Execution Configuration Optimizations 上有一篇文章,解释了这些因素,并提供了一些关于如何塑造应用程序的推理技巧。
【讨论】:
【参考方案3】:对我来说,我花了一段时间才深入了解的概念之一是 CUDA 芯片上对上下文切换的硬件支持效率。
因此,每次内存访问都会发生上下文切换,从而允许在许多上下文中交替进行计算,而其他上下文则等待内存访问。 GPGPU 架构实现性能的一种方式是能够以这种方式并行化,除了在多个内核上并行化。
当没有内核等待内存访问时,可以实现最佳性能,并且通过有足够的上下文来确保这种情况发生。
【讨论】:
这不是真的。 warp 调度器可以选择每个周期从符合条件的活动 warp 集中发出指令。如果一个 warp 没有因为执行依赖、数据依赖、获取等原因而停止,则它是合格的。以上是关于CUDA 块和变形的主要内容,如果未能解决你的问题,请参考以下文章