CUDA 10中任务图的用途是什么?

CUDA 10中任务图的用途是什么?,cuda,Cuda,CUDA 10增加了运行时API调用,用于将流(=队列)置于“捕获模式”,这样,它们就不会执行,而是以“图形”的形式返回。然后可以使这些图实际执行,也可以克隆它们 但这一特征背后的基本原理是什么?不太可能执行同一个“图形”两次吗?毕竟,即使运行“相同的代码”,至少数据是不同的,即内核所采用的参数可能会改变。或者-我错过了什么 PS-我略读了一下,但仍然没有理解。任务图是可变的 存在用于更改/设置各种任务图节点参数的API调用,因此可以使用任务图作为模板,这样就可以在每次执行之前更改每个节点的参数

CUDA 10增加了运行时API调用,用于将流(=队列)置于“捕获模式”,这样,它们就不会执行,而是以“图形”的形式返回。然后可以使这些图实际执行,也可以克隆它们

但这一特征背后的基本原理是什么?不太可能执行同一个“图形”两次吗?毕竟,即使运行“相同的代码”,至少数据是不同的,即内核所采用的参数可能会改变。或者-我错过了什么


PS-我略读了一下,但仍然没有理解。

任务图是可变的

存在用于更改/设置各种任务图节点参数的API调用,因此可以使用任务图作为模板,这样就可以在每次执行之前更改每个节点的参数,而不是在每次执行之前将单个节点排队(可能并非所有节点都需要更改其参数)


例如,请参阅文档。

在培训深度学习模型时,经常会以相同的顺序重新运行相同的内核集,但会使用更新的数据。另外,我希望Cuda通过静态地知道下一个内核是什么来进行优化。我们可以想象,Cuda在了解整个图形的情况下可以获取更多指令或调整其调度策略。

我对图形的经验是,它们确实不是那么易变的。您可以使用“cudaGraphHostNodeSetParams”更改参数,但为了使参数更改生效,我必须使用“cudaGraphInstantiate”重新生成图形可执行文件。这个调用花费的时间太长,使用图形的任何收益都会丢失(在我的例子中)。设置参数仅在我手动构建图形时对我有效。通过流捕获获取图形时,我无法设置节点的参数,因为您没有节点指针。您可能认为在流捕获图上调用“cudaGraphGetNodes”会返回节点。但对于我来说,返回的节点指针为NULL,即使“numNodes”变量的编号正确。文档明确提到了这一可能性,但没有解释原因

另一个有用的特性是并发内核执行。在手动模式下,可以在图中添加具有依赖关系的节点。它将使用多个流自动探索并发性。该功能本身并不是新功能,但使其自动化对于某些应用程序来说非常有用。

CUDA Graphs试图解决一个问题,即在存在太多小内核调用的情况下,您会看到相当多的时间花在GPU的CPU调度工作上(开销)

它允许您交换资源(时间、内存等)来构建内核图,您可以使用来自CPU的单个调用,而不是执行多个调用。如果您没有足够的调用,或者您的算法每次都不同,那么构建一个图就不值得了

这对于任何使用相同计算的迭代都非常有效(例如,需要收敛到某个位置的算法),并且在许多对GPU非常有用的应用程序中非常突出(例如,想想下面的例子)

如果您有一个只调用一次的算法,或者如果您的内核很大,您将不会看到很好的结果;在这种情况下,CPU调用开销不是瓶颈。一个简洁的解释,当你需要它存在于


然而,当您将程序定义为具有依赖关系的任务时,基于任务图的范例会大放异彩。您为驱动程序/调度器/硬件提供了很大的灵活性来自行进行调度,而无需开发人员进行太多微调。我们花费数年时间来探索HPC中的优化思想,这是有原因的。

我不相信您希望基于了解计划的内核而进行的优化。只是说说而已。如果不创建一个新实例,你就不能设置节点参数吗?是的,这是我的经验,我需要用更新的参数从图中重建图的可执行文件(通过CudaGraph实例化)。除非,还有另一种方法,但我没有找到。好吧,我相信你的话。看看API引用,它是在单个流上启动图形的。@einpoklum,是的,启动图形需要一个流,但是内核的执行是在多个流中完成的(如果存在任何并发),你可以在nvvp中看到这一点。非常有用的功能,已经尝试过几次;)也许这里的注释很有趣。那么我们为什么还要指定一个流呢-(我猜原因是允许并发启动多个图形。有一个解释来自。引用:“图形中的分支仍然并发执行,即使图形被启动到流中”我不知道CUDA图形如何解决“太多小内核”的问题与向GPU异步调度工作不同。毕竟,队列上的每个异步内核调度都对应于向图中添加一个节点,反之亦然;事件依赖项和图边也是如此。如果您有两个内核,而没有CUDA图,则需要为异步调用支付2倍的费用。使用CUDA图,则你会付X的