CUDA - 多处理器,Warp大小和每个块的最大线程数:确切的关系是什么?

Ufu*_*ici 23 memory textures caching cuda

我知道CUDA GPU上有多处理器,其中包含CUDA核心.在我的工作场所,我使用的是GTX 590,它包含512个CUDA内核,16个多处理器,其warp大小为32.因此,这意味着每个多处理器中有32个CUDA内核,它们在同一个warp中完全相同的代码.最后,每块大小的最大线程数为1024.

我的问题是块大小和多处理器数量 - warp大小是如何完全相关的.让我告诉我对情况的理解:例如,我在GTX 590上分配了最大threadPerBlock大小为1024的N个块.据我从CUDA编程指南和其他来源的理解,这些块首先由硬件枚举. .在这种情况下,来自N个块的16被分配给不同的多处理器.每个块包含1024个线程,硬件调度程序将32个这些线程分配给单个多处理器中的32个核心.同一多处理器(warp)中的线程处理代码的同一行,并使用当前多进程的共享内存.如果当前的32个线程遇到像存储器读写这样的片外操作,则它们将替换为来自当前块的另一组32个线程.所以,实际上有32个线程,其中在单个块恰好在任何给定时间并行运行在多处理器,而不是整个的1024的最后,如果一个块完全被多处理器中,从一个新的线程块处理N个线程块的列表插入到当前的多处理器中.最后,在执行CUDA内核期间,GPU中总共有512个并行运行的线程.(我知道如果一个块使用的寄存器多于单个多处理器上可用的寄存器,那么它被分成两个多处理器,但我们假设在我们的情况下每个块可以适合单个多处理器.)

那么,我的CUDA并行执行模型是否正确?如果没有,有什么不对或缺失?我想微调我正在处理的当前项目,所以我需要最正确的工作模型.

Rog*_*ahl 19

在我的工作场所,我使用的是GTX 590,它包含512个CUDA内核,16个多处理器,其warp大小为32.因此,这意味着每个多处理器中有32个CUDA内核,它们在同一个warp中完全相同的代码.最后,每块大小的最大线程数为1024.

GTX590包含您提到的数字的2倍,因为卡上有2个GPU.下面,我专注于单个芯片.

让我告诉我对情况的理解:例如,我在GTX 590上分配了最大threadPerBlock大小为1024的N个块.据我从CUDA编程指南和其他来源的理解,这些块首先由硬件枚举. .在这种情况下,来自N个块的16被分配给不同的多处理器.

块不一定均匀分布在多处理器(SM)上.如果你准确地安排了16个块,那么一些SM可以获得2个或3个块,而其中一些块空闲.我不知道为什么.

每个块包含1024个线程,硬件调度程序将32个这些线程分配给单个多处理器中的32个核心.

线程和核心之间的关系并不直接.每个SM中有32个"基本"ALU.那些处理诸如单精度浮点和大多数32位整数和逻辑指令之类的东西.但是只有16个加载/存储单元,因此如果当前正在处理的warp指令是加载/存储,则必须将其调度两次.并且只有4个特殊功能单元,用于执行三角测量等操作.所以这些指令必须安排32/4 = 8次.

同一多处理器(warp)中的线程处理代码的同一行,并使用当前多进程的共享内存.

不,在一个SM中可以同时"飞行"多于32个线程.

如果当前的32个线程遇到像存储器读写这样的片外操作,则它们将替换为来自当前块的另一组32个线程.因此,在一个块中实际上有32个线程在任何给定时间内在多处理器上并行运行,而不是整个1024.

不,不仅是内存操作会导致更换warp.ALU也是深度流水线的,因此新的warp将被交换,因为仍然在管道中的值会发生数据依赖性.因此,如果代码包含两个指令,其中第二个使用第一个的输出,则warp将被保持,而第一个指令的值通过管道.

最后,如果块由多处理器完全处理,则来自N个线程块列表的新线程块将插入当前多处理器.

多处理器一次可以处理多个块,但是一旦处理开始,块就无法移动到另一个MP.当前正在运行的块中的线程数取决于块使用的资源数量.CUDA占用计算器将根据特定内核的资源使用情况,告诉您同时有多少块将在飞行中.

最后,在执行CUDA内核期间,GPU中总共有512个并行运行的线程.(我知道如果一个块使用的寄存器多于单个多处理器上可用的寄存器,那么它被分成两个多处理器,但我们假设在我们的情况下每个块可以适合单个多处理器.)

不,块不能分为两个多处理器.整个块总是由单个多处理器处理.如果给定的多处理器没有足够的资源来处理内核中至少一个块,则会出现内核启动错误,并且程序根本不会运行.

这取决于您如何将线程定义为"正在运行".GPU通常会有超过512个线程同时消耗芯片上的各种资源.

请参阅@harrism在这个问题中的答案:CUDA:总共有多少并发线程?