为CUDA内核使用不同的流可以使并发内核执行成为可能。因此,n
流上的n
内核理论上可以同时运行,如果它们适合硬件,对吧?
现在我遇到了以下问题:没有n
个不同的内核,n*m
需要按顺序执行m
个内核。例如,n=2
和m=3
会导致以下带有流的执行方案:
Stream 1: <<<Kernel 0.1>>> <<<Kernel 1.1>>> <<<Kernel 2.1>>>
Stream 2: <<<Kernel 0.2>>> <<<Kernel 1.2>>> <<<Kernel 2.2>>>
我天真的假设是内核x.0和y.1应该同时执行(从理论的角度来看)或者至少不是连续的(从实际的角度来看)。但是我的测量表明我并非如此,似乎连续执行(即K0.0,K1.0,K2.0,K0.1,K1.1,K2.1)。内核本身非常小,因此并发执行应该不是问题。
现在我的方法是完成一种调度,以确保内核以交错方式排列到GPU上的调度程序中。但是当处理大量流/内核时,这可能弊大于利。
好的,直截了当地说:解决这种情况的适当(或至少是不同的)方法是什么?
编辑:使用CUDA事件进行测量。我已经测量了完全解决计算所需的时间,i。即GPU必须计算所有n * m
内核。假设是:在完全并发的内核执行时,执行时间大约(理想地)是按顺序执行所有内核所需时间的1/n
倍,因此必须可以同时执行两个或更多内核。我现在只使用两个不同的流来确保这一点。
我可以测量使用所描述的流和调度内核交错之间的执行时间的明显差异,即: E:
Loop: i = 0 to m
EnqueueKernel(Kernel i.1, Stream 1)
EnqueueKernel(Kernel i.2, Stream 2)
与
Loop: i = 1 to n
Loop: j = 0 to m
EnqueueKernel(Kernel j.i, Stream i)
后者会导致更长的运行时间。
编辑#2:将流编号更改为1(而不是0,请参阅下面的评论)。
编辑#3:硬件是NVIDIA Tesla M2090(即费米,计算能力2.0)
答案 0 :(得分:5)
在Fermi(又名Compute Capability 2.0)硬件上,最好将内核启动交错到多个流,而不是将所有内核启动到一个流,然后启动下一个流等。这是因为硬件可以立即启动内核到不同的如果有足够的资源,则流,而如果后续启动到同一个流,则通常会引入延迟,从而降低并发性。这就是你的第一种方法表现更好的原因,这种方法是你应该选择的方法。
启用分析也可以禁用Fermi的并发性,所以要小心。另外,在启动循环期间要小心使用CUDA事件,因为这些事件可能会干扰 - 例如,最好使用事件来处理整个循环的时间。