在CUDA中启动许多小内核有多糟糕?

Mic*_*ael 7 cuda

我有一个矩形网格.这些矩形中的每一个都由矩形网格点组成.矩形内的所有点都可以通过内核中完全相同的指令序列来处理.我将能够启动一个具有10000个点的内核来处理,其中每个线程将处理大约10-50个点.然而,矩形的边缘和角上的点将导致大量不同的指令序列.

从设计的角度来看,使用相同的指令序列为每组点启动内核会更容易.这意味着一些内核启动只会处理非常少的点,可能少于10.

所以我可能有4个内核启动,10000个点可以处理(每个线程10-50个点),也许30-100个内核启动,每个只有几个点(通常每个线程1个点).

我完全不知道这是否可以接受,或者它是否会完全破坏我的表现.我很高兴你能给我一个粗略的估计或至少一些提示,考虑什么来估计.

Jez*_*Jez 14

这里有两个因素,我称之为启动开销执行开销.

启动开销:启动内核的开销约为10us(即0.01ms).它可能会少一点,它可能会更多,它将取决于您的系统整体以及相关内核.此值假定您没有在Windows上作为图形卡运行(即没有WDDM).

如果在启动之前有大量非阻塞GPU调用,则可以完全隐藏此启动开销.想到这一点的一种方法是,您已经准备好在GPU上执行任务队列,并且可以在执行某些操作时添加到该队列.启动开销是添加到队列的成本.只要队列中包含某些内容,您就不会看到启动开销会使GPU匮乏.

执行开销:一旦内核到达此队列的前端,它就会被执行.这里的开销也很小.我希望这可能是3-4us,但你的里程可能会有所不同.这与初始化和从全局内存移动数据以使内核运行有关.它还包括关闭成本.

通过使用流可以减少执行开销.如果将小内核放在单独的流中,并将它们并发执行,则可以通过GPU上的其他计算隐藏此执行开销.您不会让整个GPU等待一个小问题通过它,而只有少量资源将等待,而GPU的其余部分继续处理您的主要问题.


sro*_*drb 5

也许这应该是扩展评论而不是答案,但我希望它无论如何都能为您提供一些指导。

由于内核启动开销,启动许多小内核而不是大内核的性能限制。这个答案应该解释一下,还链接了有趣的资源。

但是还有其他方法可以执行任务。假设您的系统 (RAM) 内存上有这么大的矩形网格,您必须以某种方式将其传输到 GPU 内存。这提供了使用内核传输重叠方法隐藏小内存传输时间的机会,即异步传输。只有当您的内核花费足够的时间来完成矩形的计算时,这种方法才会有效。

如果您的所有网格一次都适合您的 GPU 主内存,那么您可以从内核启动多个内核。在这里,您可以找到有关该主题的更多信息(动态并行性),这里是另一个有关该方法变慢的有趣问题。这种方法可能不会产生任何性能提升,因为启动这些内核也需要一些时间,但它是您提议的替代方案,并保持了简单,在您的主代码中隐藏了一些复杂性。

作为一般建议,与大量较小的数据相比,更喜欢少量的大数据传输,因为这同样适用于内核,以最大限度地减少开销。