CUDA块/线程/线程如何映射到CUDA内核?


142

我已经使用CUDA几周了,但是我对块/线程/线程的分配有一些疑问。 我正在从教学角度(大学项目)研究体系结构,因此达到最佳性能不是我的关注。

首先,我想了解一下我是否明白这些事实:

  1. 程序员编写内核,并在线程块网格中组织其执行。

  2. 每个块都分配给一个流多处理器(SM)。分配后,便无法迁移到另一个SM。

  3. 每个SM将自己的块拆分为Warp(当前最大为32个线程)。扭曲中的所有线程均在SM的资源上同时执行。

  4. 线程的实际执行由SM中包含的CUDA核心执行。线程和核心之间没有特定的映射。

  5. 如果warp包含20个线程,但是当前只有16个内核可用,则warp将无法运行。

  6. 另一方面,如果一个块包含48个线程,则它将拆分为2个扭曲,并在有足够内存可用的情况下并行执行。

  7. 如果线程在内核上启动,则由于内存访问或长时间浮点操作而被暂停,则其执行可以在其他内核上恢复。

他们正确吗?

现在,我有一个GeForce 560 Ti,因此根据规格它配备了8个SM,每个包含48个CUDA内核(总共384个内核)。

我的目标是确保体系结构的每个核心都执行SAME指令。假设我的代码不需要比每个SM中可用的更多的寄存器,我想到了不同的方法:

  1. 我创建了8个块,每个块有48个线程,因此每个SM都有1个块要执行。在这种情况下,这48个线程是否将在SM中并行执行(利用所有48个可用的内核)?

  2. 如果我启动64个6线程块,会有什么区别?(假设它们将在SM之间平均映射)

  3. 如果我将GPU“淹没”在计划的工作中(例如,创建1024个线程块,每个线程有1024个线程),则可以合理地假设所有内核将在某个时刻使用,并且将执行相同的计算(假设线程永不停止)?

  4. 有什么方法可以使用探查器检查这些情况吗?

  5. 这个东西有参考吗?我阅读了《 CUDA编程指南》以及“对大型并行处理器进行编程”和“ CUDA应用程序设计与开发”中有关硬件体系结构的章节;但是我找不到确切的答案。


我想补充一下什么是“ CUDA核心”。“ CUDA内核”或“执行单元”是完全流水线的整数ALU和FPU,它们在一个cuda线程中每个时钟周期执行一个算术指令。
bruziuz

Answers:


123

最好的两个参考是

  1. NVIDIA Fermi计算架构白皮书
  2. GF104评论

我将尽力回答您的每个问题。

程序员将工作划分为多个线程,将多个线程划分为多个线程块,并将多个线程块划分为多个网格。计算工作分配器将线程块分配给流多处理器(SM)。将线程块分配给SM后,将分配该线程块的资源(扭曲和共享内存),并将线程分为32个线程组,称为扭曲。一旦分配了翘曲,就称为活动翘曲。两个warp调度程序每个周期选择两个活动warp,然后将warp分配给执行单元。有关执行单元和指令分配的更多详细信息,请参见1 p.7-10和2

4'。Laneid(线程束中的线程索引)与内核之间存在映射。

5'。如果一个warp包含少于32个线程,则在大多数情况下,其执行方式与包含32个线程的情况相同。由于以下几个原因,warp的活动线程数少于32个:每个块的线程数不能被32整除;程序执行一个发散的块,因此未采用当前路径的线程被标记为非活动状态,或者退出了warp中的线程。

6'。线程块将分为WarpsPerBlock =(ThreadsPerBlock + WarpSize-1)/ WarpSize不需要Warp调度程序从同一线程块中选择两个Warp。

7'。执行单元不会因存储操作而停顿。如果准备分派指令时资源不可用,则将来在资源可用时会再次分派指令。扭曲可能会在屏障,内存操作,纹理操作,数据依存关系等方面停滞不前。扭曲的调度程序无法选择停滞的扭曲。在Fermi上,每个周期至少有2个合格的经纱是有用的,以便经纱调度程序可以发出指令。

有关GTX480和GTX560之间的差异,请参见参考资料2

如果您阅读参考资料(几分钟),我认为您会发现目标没有意义。我会尽力回应您的观点。

1'。如果启动kernel <<< 8,48 >>>,则将获得8个块,每个块具有2个32和16线程的线程。不能保证将这8个块分配给不同的SM。如果将2个块分配给一个SM,则每个Warp调度程序都可以选择一个Warp并执行Warp。您将只使用48个内核中的32个。

2'。8个48个线程块和64个6个线程块之间有很大的区别。假设您的内核没有差异,并且每个线程执行10条指令。

  • 8个带有48个线程的块= 16个扭曲* 10条指令= 160条指令
  • 带6个线程的64个块= 64个扭曲* 10条指令= 640条指令

为了获得最佳效率,工作分工应为32个线程的倍数。硬件不会合并来自不同线程束的线程。

3'。如果内核不最大化寄存器或共享内存,则GTX560一次可以有8个SM * 8个块= 64个块,或者8个SM * 48个扭曲= 512个扭曲。在任何给定时间,部分工作将在SM上进行。每个SM具有多个执行单元(超过CUDA内核)。在任何给定时间使用哪些资源取决于翘曲调度程序和应用程序的指令组合。如果不执行TEX操作,则TEX单元将处于空闲状态。如果您不执行特殊的浮点运算,则SUFU单元将闲置。

4'。并行Nsight和Visual Profiler显示

一个。执行的IPC

b。发行的IPC

C。每个活动周期的活动经线

d。每个活动周期符合条件的经线(仅Nsight)

e。经纱失速原因(仅Nsight)

F。每个指令执行的活动线程

探查器未显示任何执行单元的利用率百分比。对于GTX560,粗略估算为IssuedIPC / MaxIPC。对于MaxIPC,假设GF100(GTX480)为2 GF10x(GTX560)为4,但目标为3是更好的目标。


1
谢谢您的回答。我阅读了参考资料,但是您的回答中有些内容我还是不明白。在以下问题中,我假设我们正在使用具有48个核心(16个核心* 3个“核心组”)的Fermi架构:1.您提到了核心和Laneid之间的映射。这是什么样的映射?2.从参考文献中,我得到每个“核心组”每个时钟周期最多执行半弯曲(16个线程)。因此,从理论上讲,如果我们在同一块中有48个线程,它们将被组织为3个半线程,并在48个内核上并行执行。我对吗?
代达罗斯

1
CUDA核心是单精度FP单元的数量。根据CUDA核心来考虑执行是不正确的。每个经线都有32个线程。这些线程将被发布给一组执行单元(例如16个cuda内核)。为了在单个时钟中向所有48个内核发出指令,两个warp调度程序之一需要选择一个满足超标量对要求的warp,并且这两个指令都必须是CUDA内核执行的类型。此外,另一个warp调度程序还必须选择一个warp,其下一条指令将由CUDA内核执行。
格雷格·史密斯

1
不需要将warp放在同一块中或将warp放在同一程序计数器中。
格雷格·史密斯

2
在您的示例中,每个调度程序都在选择翘曲并发出1条指令。在这种情况下,将仅使用2组执行单元。为了使用更多的执行单元,调度程序1必须双重发行。如参考文献中所述,存在多种类型的执行单元(不仅仅是cuda核心的实现单元),并且对于调度程序进行双重发布,必须满足指令配对规则(文档不足)。
格雷格·史密斯

1
@GregSmith我正在网上搜索,以找出Fermi架构中每个SM的8个活动块来自何处。费米白皮书中甚至没有提到它。您对此有更多参考吗?
Greg K.

8

“ E.如果一个warp包含20个线程,但是当前只有16个内核可用,则warp将无法运行。”

是不正确的。您会混淆通常意义上的内核(也用于CPU),即GPU中“多处理器”的数量以及nVIDIA市场营销中的内核(“我们的卡具有数千个CUDA内核”)。

扭曲本身只能在单个内核(=多处理器)上进行调度,并且可以同时运行多达32个线程。它不能使用多个内核。

数字“ 48个扭曲”是在具有Compute Capability 2.x的nVIDIA GPU上,每个多处理器的活动扭曲(可以选择在下一个周期,在任何给定周期内安排运行的扭曲)的最大数量。该数字对应于1536 = 48 x 32线程。

基于此网络研讨会的答案


@GregSmith:编辑了答案以解决此问题。您耐心等待没事,但是-已经有五年了……
einpoklum

单核(=多处理器)?我认为问题假设术语是单核=处理器而不是多处理器。用您的术语,您的答案是正确的。
Adarsh
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.