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