dnb*_*ise 54 cuda nvidia dimensions matrix-multiplication
我是CUDA范例的新手.我的问题是确定每个块的线程数和每个网格的块数.有点艺术和试验吗?我发现很多例子都是为这些东西选择了看似随意的数字.
我正在考虑一个问题,我可以将矩阵 - 任何大小 - 传递给乘法方法.因此,C的每个元素(如在C = A*B中)将由单个线程计算.在这种情况下,您如何确定线程/块,块/网格?
小智 88
通常,您希望调整块/网格的大小以匹配您的数据,同时最大化占用率,即一次激活多少个线程.影响占用率的主要因素是共享内存使用情况,寄存器使用情况和线程块大小.
支持CUDA的GPU将其处理能力分为SM(流式多处理器),SM的数量取决于实际的卡,但为了简单起见,我们将专注于单个SM(它们都表现相同).每个SM具有有限数量的32位寄存器,共享存储器,最大活动块数和最大活动线程数.这些数字取决于您的GPU的CC(计算能力),可以在维基百科文章http://en.wikipedia.org/wiki/CUDA的中间找到.
首先,您的线程块大小应该始终是32的倍数,因为内核在warp(32个线程)中发出指令.例如,如果你有一个50个线程的块大小,GPU仍然会向64个线程发出命令,你只是在浪费它们.
其次,在担心共享内存和寄存器之前,请尝试根据与卡的计算能力相对应的最大线程数和块数来调整块的大小.有时候有多种方法可以做到这一点......例如,CC 3.0卡每个SM可以有16个活动块和2048个活动线程.这意味着如果每个块有128个线程,则在达到2048线程限制之前,可以在SM中容纳16个块.如果你使用256个线程,你只能使用8个,但你仍然使用所有可用的线程,并且仍然可以完全占用.但是,如果命中16个块限制,则每个块使用64个线程将仅使用1024个线程,因此只占50%的占用率.如果共享内存和寄存器使用不是瓶颈,那么这应该是您主要考虑的问题(除了您的数据维度).
关于网格的主题......网格中的块分布在SM上以启动,然后将剩余的块放入管道中.只要SM中有足够的资源来阻止块,就会将块移动到SM中进行处理.换句话说,当SM中的块完成时,新的块将被移入.您可以使得具有较小块(在前一示例中为128而不是256)的参数可以更快地完成,因为特别慢的块将占用更少的资源,但是这非常依赖于代码.
关于寄存器和共享内存,请看下一步,因为它可能会限制您的占用率.共享内存对于整个SM是有限的,因此尝试使用它的数量允许尽可能多的块仍然适合SM.寄存器使用也是如此.同样,这些数字取决于计算能力,可以在维基百科页面上找到.祝好运!
jmi*_*loy 19
http://developer.download.nvidia.com/compute/cuda/CUDA_Occupancy_calculator.xls
CUDA占用计算器允许您通过给定的CUDA内核计算GPU 的多处理器占用率.多处理器占用率是活动warp与GPU多处理器上支持的最大warp数之比.设备上的每个多处理器都有一组N个寄存器,可供CUDA程序线程使用.这些寄存器是在多处理器上执行的线程块之间分配的共享资源.CUDA编译器尝试最小化寄存器使用,以最大化同时在机器中激活的线程块数.如果程序试图启动一个内核,每个线程使用的寄存器次数,线程块大小大于N,则启动将失败...
Hea*_*ink 15
除了极少数例外,每个块应使用恒定数量的线程.然后,每个网格的块数由问题大小确定,例如在矩阵乘法的情况下的矩阵维度.
选择每个块的线程数非常复杂.大多数CUDA算法都承认了大量的可能性,并且选择的依据是内核运行效率最高的原因.由于线程调度硬件的工作原理,它几乎总是32的倍数,至少是64.第一次尝试的好选择是128或256.