Cuda 动态并行-启动许多小内核非常慢

Cuda 动态并行-启动许多小内核非常慢,cuda,dynamic-parallelism,Cuda,Dynamic Parallelism,我正在尝试使用动态并行来改进CUDA中的一个算法。在我最初的CUDA解决方案中,每个线程计算每个块的一个公共数字。我想做的是首先启动一个粗略(或低分辨率)内核,其中线程只计算一次公共值(就像每个线程代表一个块)。然后每个线程创建一个由1个块(16x16个线程)组成的小网格,并为其启动一个子内核,传递公共值。理论上,它应该更快,因为这样可以节省许多冗余操作。但是在实践中,这个解决方案非常慢,我不知道为什么 这是代码,非常简单,只是想法 __global__ coarse_kernel( param

我正在尝试使用动态并行来改进CUDA中的一个算法。在我最初的CUDA解决方案中,每个线程计算每个块的一个公共数字。我想做的是首先启动一个粗略(或低分辨率)内核,其中线程只计算一次公共值(就像每个线程代表一个块)。然后每个线程创建一个由1个块(16x16个线程)组成的小网格,并为其启动一个子内核,传递公共值。理论上,它应该更快,因为这样可以节省许多冗余操作。但是在实践中,这个解决方案非常慢,我不知道为什么

这是代码,非常简单,只是想法

__global__ coarse_kernel( parameters ){
    int common_val = compute_common_val();
    dim3 dimblock(16, 16, 1);
    dim3 dimgrid(1, 1, 1);
    child_kernel <<< dimgrid, dimblock >>> (common_val, parameters);

}

__global__ child_kernel( int common_val, parameters ){
    // use common value
    do_computations(common_val, parameters);
}
\uuuuu全局\uuuuuuuuuu粗内核(参数){
int common_val=compute_common_val();
dim3 dimblock(16,16,1);
dim3 dimgrid(1,1,1);
子内核>(公共值、参数);
}
__全局子内核(int common val,参数){
//使用公共值
进行计算(常用值、参数);
}
子线程的数量很多,每个线程一个,必须有大约400x400个线程。据我所知,GPU应该并行处理所有这些内核,对吗

或者子内核以某种方式顺序处理


我的结果表明,性能比我原来的解决方案慢了10倍多。

启动内核是有成本的,无论是父内核还是子内核。如果您的子内核没有提取太多并行性,并且与非并行内核相比没有太多好处,那么子内核启动开销可能会抵消您微弱的好处


在公式中,让
to
为执行子内核的开销,
te
为其执行时间,
ts
为在没有动态并行帮助的情况下执行相同代码的时间。使用动态并行所产生的加速比是
ts/(to+te)
。也许(但这不能从您的代码中想象)
t启动内核(无论是父内核还是子内核)都会有成本。如果您的子内核没有提取太多并行性,并且与非并行内核相比没有太多好处,那么您微弱的好处可能会被子内核启动开销抵消。@JackOLantern但是这些子内核不应该并行执行以填充GPU吗??或者他们一个接一个地执行?我试着用公式解释我上面的意思。让
to
执行子内核的开销,
te
其执行时间,
ts
在没有动态并行性帮助的情况下执行相同代码的时间。使用动态并行所产生的加速比是
ts/(to+te)
。也许(但这不能从你的代码中看到)
teI理解谢谢。我必须检查有关开销的文档,并查看并行执行的子内核数量的限制。大多数internet动态并行示例通常显示线性递归(仅从线程0启动一个子内核)或至多一个二进制分支。我将检查是否可以减少子内核的数量并使网格更大。我认为开普勒GK110中同时出现的最大流数是32。我想我已经超出了这个值很多了。杰克,你认为当超过32个内核发布时,$到$真的会爆炸吗?我不是说,
to
真的爆炸了。我只是解释一下您的代码可能会发生什么,但是上面代码片段中的细节太少,无法提供明确的答案。如果您的子内核没有太多工作要做,那么子内核启动开销可能会阻止您观察动态并行的使用带来的任何改进。我将继续对此进行研究,但我开始看到DP正常工作的必要条件。谢谢你的帮助。