我有GeForce GTX460 SE,所以它是:6 SM x 48 CUDA核心= 288 CUDA核心。 众所周知,在一个Warp中包含32个线程,并且在一个块中同时(一次)只能执行一个Warp。 也就是说,在单个多处理器(SM)中,即使有48个可用核心,也可以同时只执行一个Block,一个Warp和32个线程?
此外,可以使用threadIdx.x和blockIdx.x来分发具体的Thread和Block的示例。要分配它们,请使用内核<<<块,线程>>> ()。 但是如何分配特定数量的Warp-s并分发它们,如果不可能那么为什么还要去了解Warps?
答案 0 :(得分:32)
情况比你描述的要复杂得多。
ALU(核心),加载/存储(LD / ST)单元和特殊功能单元(SFU)(图像中的绿色)是流水线单元。它们在完成的各个阶段同时保留许多计算或操作的结果。因此,在一个周期内,他们可以接受新操作并提供很久以前开始的另一个操作的结果(如果我没记错的话,ALU大约需要20个周期)。因此,理论上单个SM具有同时处理48 * 20个周期= 960个ALU操作的资源,即每个warp = 30个warp的960/32个线程。此外,它可以处理LD / ST操作和SFU操作,无论其延迟和吞吐量如何。
warp调度程序(图像中的黄色)可以为每个warp = 64个线程安排2 * 32个线程到每个周期的管道。这就是每个时钟可以获得的结果数量。因此,考虑到混合的计算资源,48核心,16 LD / ST,8 SFU,每个具有不同的延迟,同时处理混合的warp。在任何给定的周期,warp调度程序都会尝试“配对”两个warp以进行调度,以最大限度地利用SM。
如果指令是独立的,则warp调度程序可以从不同的块或同一块中的不同位置发出warp。因此,可以同时处理来自多个块的变形。
增加复杂性,执行少于32个资源的指令的warp必须多次发出才能为所有线程提供服务。例如,有8个SFU,这意味着包含需要SFU的指令的warp必须安排4次。
简化了该描述。还有其他限制可以确定GPU如何安排工作。您可以在网上搜索“fermi architecture”来查找更多信息。
所以,提出你的实际问题,
为什么还要了解Warps?
当您尝试最大化算法的性能时,了解warp中的线程数并将其考虑在内变得非常重要。如果您不遵守这些规则,则会失去性能:
在内核调用<<<Blocks, Threads>>>
中,尝试选择多个线程,这些线程与warp中的线程数均分。如果不这样做,最终会启动包含非活动线程的块。
在内核中,尝试让warp中的每个线程遵循相同的代码路径。如果不这样做,就会得到所谓的经线发散。发生这种情况是因为GPU必须通过每个不同的代码路径运行整个warp。
在内核中,尝试将每个线程置于warp加载中并以特定模式存储数据。例如,让warp中的线程在全局内存中访问连续的32位字。
答案 1 :(得分:2)
线程必须按顺序分组为Warps,1 - 32,33 - 64 ......?
是的,编程模型保证线程按特定顺序分组为warp。
作为优化发散代码路径的一个简单示例,可以使用32个线程组中的块中所有线程的分离?例如:switch(threadIdx.s / 32){case 0:/ * 1 warp * / break;案例1:/ * 2 warp * / break; / * Etc * /}
确切地说:)
单个Warp一次必须读取多少字节:4个字节* 32个线程,8个字节* 32个线程或16个字节* 32个线程?据我所知,一次全局内存的一个事务接收128个字节。
是,全局内存的事务是128个字节。因此,如果每个线程从连续地址读取一个32位字(它们可能也需要128字节对齐),则warp中的所有线程都可以使用单个事务进行服务(4个字节* 32个线程= 128个字节) )。如果每个线程读取更多字节,或者地址不连续,则需要发出更多事务(对于每个被触摸的单独128字节行,都有单独的事务)。
这在CUDA编程手册4.2,F.4.2节“全局存储器”中有描述。在那里还有一个模糊的说法,情况与仅在L2中缓存的数据不同,因为L2缓存具有32字节的缓存行。我不知道如何安排仅在L2中缓存数据或者最终会有多少交易。