关于如何选择#blocks& blockSize,但我仍然遗漏了一些东西。我的许多问题都解决了这个问题:How CUDA Blocks/Warps/Threads map onto CUDA Cores?(为了简化讨论,有足够的perThread和perBlock内存。内存限制在这里不是问题。)
kernelA<<<nBlocks, nThreads>>>(varA,constB, nThreadsTotal);
1)为了让SM尽可能忙,我应该将nThreads
设置为warpSize
的倍数。真?
2)SM一次只能执行一个内核。这就是SM的所有HWcores只执行kernelA。 (不是某些HWcores运行kernelA,而其他运行kernelB。)因此,如果我只有一个线程可以运行,那么我就“浪费”了其他的HWcores。真?
3)如果warp-scheduler以warpSize
(32个线程)为单位发出工作,并且每个SM有32个HWcores,则SM将被充分利用。 SM有48个HWcores时会发生什么?当调度程序以32块为单位发布工作时,如何充分利用所有48个核心? (如果上一段是真的,如果调度程序以HWcore大小为单位发布工作会不会更好?)
4)看起来warp-scheduler一次排队2个任务。因此,当当前正在执行的内核停止或阻塞时,第二个内核被交换。(目前尚不清楚,但我猜这里的队列深度超过2个内核。)这是正确的吗?
5)如果我的HW的上限为每块512个线程(nThreadsMax),这并不意味着具有512个线程的内核在一个块上运行得最快。 (同样,mem也不是问题。)如果我将512线程内核分布在多个块上,而不仅仅是一个块,那么我很有可能获得更好的性能。该块在一个或多个SM上执行。真?
5a)我认为越小越好,但是我做出的nBlocks
有多小也一样重要?问题是,如何选择合适的nBlocks
的价值? (不一定是最优的。)是否有选择nBlocks
的数学方法,或者它只是试验性错误。
答案 0 :(得分:5)
1)是的。
2)CC 2.0 - 3.0设备可同时执行多达16个网格。每个SM限制为8个块,因此为了达到完全并发,设备必须至少有2个SM。
3)是的,warp调度程序会在时间选择并发出warp。忘掉他们无关的CUDA核心概念。为了隐藏延迟,您需要具有高指令级并行性或高占用率。对于CC 1.x,建议具有> 25%,对于CC&gt; = 2.0,建议具有> 50%。通常,由于调度程序加倍,CC 3.0需要比2.0设备更高的占用率,但每SM的warp仅增加33%。 Nsight VSE问题效率实验是确定您是否有足够的扭曲来隐藏指令和内存延迟的最佳方法。不幸的是,Visual Profiler没有这个指标。
4)没有记录warp调度程序算法;但是,它不考虑线程块发起的网格。对于CC 2.x和3.0设备,CUDA工作分配器将在从下一个网格分配块之前分配网格中的所有块;但是,编程模型无法保证这一点。
5)为了保持SM忙,你必须有足够的块来填充设备。在此之后,您需要确保有足够的经线以达到合理的占用率。使用大型线程块有利有弊。大螺纹块通常使用较少的指令缓存并且在缓存上具有较小的占用空间;然而,大型线程块在syncthreads处停滞(SM可能变得效率较低,因为可以选择较少的warp)并且倾向于使指令在类似的执行单元上执行。我建议每个线程块尝试128或256个线程来启动。较大和较小的螺纹块都有充分的理由。 5a)使用占用率计算器。挑选太大的线程块大小通常会导致您受到寄存器的限制。挑选太小的线程块大小可能会发现您受限于共享内存或每SM限制8个块。
答案 1 :(得分:3)
让我试着逐一回答你的问题。
根据NVIDIA Fermi Compute Architecture Whitepaper:“SM调度32个并行线程组中的线程称为warps。每个SM都有两个warp调度器和两个指令调度单元,允许两个warp同时发出和执行.Fermi的双warp调度器选择两个warp,并从每个warp发出一条指令到一组16个内核,16个加载/存储单元或4个SFU。因为warp独立执行,所以Fermi的调度程序不需要检查来自内部的依赖关系。指令流“。
此外,NVIDIA Keppler Architecture Whitepaper状态:“Kepler的quad warp调度程序选择四个warp,每个warp可以在每个周期调度两个独立的指令。”
因此,通过一次安排多个warp来使用“多余”核心。
warp调度程序调度相同内核的warp,而不是不同的内核。