CUDA 块/翘曲/线程如何映射到 CUDA 核心?

我已经使用 CUDA 几个星期了,但是我对块/经线/线程的分配有一些疑问。 我是从一个教学的角度来研究建筑的(大学项目) ,所以达到最高性能不是我关心的问题。

首先,我想知道我是否理解了这些事实:

  1. 程序员编写一个内核,并将其执行组织在一个由线程块组成的网格中。

  2. 每个块被分配给一个流式多处理器(SM)。一旦分配,它就不能迁移到另一个 SM。

  3. 每个 SM 将自己的块分割成 Warps (目前最大大小为32个线程)。一个翘曲中的所有线程在 SM 的资源上并发执行。

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

  5. 如果一个经纱包含20个螺纹,但目前只有16个核心可用,经纱将不会运行。

  6. 另一方面,如果一个块包含48个线程,它将被分成2个翘曲,并且它们将并行执行,前提是有足够的内存可用。

  7. 如果一个线程在一个核心上启动,那么它会因为内存访问或长时间的浮点操作而停止,它的执行可能会在另一个核心上恢复。

他们说的对吗?

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

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

  1. 我创建了8个由48个线程组成的块,这样每个 SM 有1个块可以执行。在这种情况下,48个线程将在 SM 中并行执行(利用所有可用的48个核) ?

  2. 如果我启动64个6个线程的块,有什么区别吗?(假设它们将被均匀地映射到 SMs 中)

  3. 如果我将 GPU“淹没”在预定的工作中(例如,每个线程创建1024个块,每个块1024个线程) ,是否可以合理地假设所有的内核都将在某个特定的点上使用,并将执行相同的计算(假设线程从未停止) ?

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

  5. 这些东西有什么参考资料吗?我阅读了 CUDA 编程指南和“大规模并行处理机编程处理器”和“ CUDA 应用程序设计与开发”中有关硬件体系结构的章节,但我无法得到准确的答案。

75544 次浏览

两个最好的参考是

  1. 费米计算机体系结构白皮书
  2. GF104检讨

我会尽量回答你们每个人的问题。

程序员将工作划分为线程,线程划分为线程块,线程块划分为网格。计算工作分发服务器将线程块分配给流式多处理器(SM)。一旦一个线程块被分配给 SM,线程块的资源就被分配(翘曲和共享内存) ,线程被分成32个线程组,称为翘曲。一旦分配了曲速,它就被称为活跃曲速。两个翘曲调度程序每个周期挑选两个活动翘曲,并将翘曲分派给执行单元。有关执行单元和指令调度的详细信息,请参阅 1第7-10页和 2

4’ 在 laneid (一个翘曲的线程索引)和一个内核之间有一个映射。

5’。如果一个翘曲包含少于32个线程,它将在大多数情况下执行相同,如果它有32个线程。翘曲可以有少于32个活动线程的原因有几个: 每个块的线程数量不能被32整除,程序执行一个发散块,所以没有采用当前路径的线程被标记为非活动线程,或者一个线程在翘曲退出。

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

7’。执行单元不会在内存操作上停止。如果资源不可用时,指令是准备发送的指令将再次发送,当资源可用的时候。翘曲可以停止在屏障,在内存操作,纹理操作,数据依赖,... 一个停止翘曲是不符合选择的翘曲调度程序。在费米上,每个周期至少有2个合格的翘曲是有用的,这样翘曲调度器就可以发出指令。

有关 GTX480和 GTX560之间的差异,请参阅参考 2

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

1’。如果您启动 kernel < < < 8,48 > > > ,您将获得8个块,每个块包含2个32和16个线程。不能保证这8个区块将被分配给不同的 SM。如果2块分配给一个 SM,那么每个翘曲调度程序可以选择一个翘曲并执行翘曲。您将只使用48个核心中的32个。

2’。由48个线程组成的8个块和由6个线程组成的64个块之间有很大的区别。假设内核没有发散,每个线程执行10条指令。

  • 8块48线程 = 16条经线 * 10条指令 = 160条指令
  • 64块6个线程 = 64条曲线 * 10条指令 = 640条指令

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

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

并行 Nsight 和 Visual Profiler 显示

执行的 IPC

签发的 IPC

每活动周期有效翘曲

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

翘曲失速的原因(仅限视觉)

每执行一条指令的活动线程

探查器不显示任何执行单元的利用率百分比。对于 GTX560一个粗略的估计将发布 IPC/MaxIPC。 对于 MaxIPC 来说 GF100(GTX480)是2 GF10x (GTX560)是4,但目标是3是一个更好的目标。

如果一根经线包含20根线,但目前只有16根可用的芯,则不能进行经线运行

是不正确的。你正在混淆核心在他们通常的意义上(也用于 CPU)-在一个 GPU 的“多处理器”的数量,与核心在 nVIDIA 的营销说法(“我们的卡有数以千计的 CUDA 核心”)。

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

数字“48翘曲”是在具有计算能力2的 nVIDIA 图形处理器上,每个多处理器上有效翘曲的最大数目(在任何给定的周期中,可以选择在下一个周期中安排工作的翘曲)。这个数字对应于1536 = 48x32个线程。

基于 这个网络研讨会的答案