构造具有动态参数的CUDA图表

网友投稿 386 2022-10-29

构造具有动态参数的CUDA图表

构造CUDA图有两种主要方法:显式API调用和流捕获。

使用显式API调用构造CUDA图

通过这种构建CUDA图的方法,由CUDA内核和CUDA内存操作形成的图节点通过调用cudaGraphAdd*节点API添加到图中,其中*被替换为节点类型。节点之间的依赖关系是用API显式设置的。

缺点是,在使用CUDA图加速现有代码的场景中,使用显式API调用构造CUDA图通常需要大量代码更改,尤其是有关代码的控制流和函数调用结构的更改。

使用流捕获构建CUDA图

使用流捕获构建CUDA图的好处是,对于现有代码,需要的代码更改更少。原始代码结构可以基本保持不变,图形构造是以自动方式执行的。

这种构建CUDA图的方法也有缺点。在流捕获区域内,所有内核启动配置和内核函数参数以及CUDA API调用参数都按值记录。每当任何配置和参数发生更改时,捕获的然后实例化的图形就会过期。

在《在动态环境中使用CUDA图》一文中提供了两种解决方案:

以配置和参数集作为键缓存CUDA图。每组配置和参数都与缓存中的不同CUDA图相关联。在运行工作流时,配置和参数集首先被抽象为一个键。然后在缓存中找到相应的图(如果它已经存在)并启动。

然而,在某些工作流中,两种解决方案都不能很好地工作。重新捕获然后更新方法在纸面上很有效,但在某些情况下,重新捕获和更新本身的成本很高。也有一些情况下,无法将每组参数与CUDA图相关联。例如,具有浮点数字参数的情况很难缓存,因为可能存在大量的浮点数字。

用显式API构造的CUDA图很容易更新,但这种方法可能过于繁琐,灵活性较差。CUDA图可以通过流捕获灵活地构造,但生成的图很难更新,而且更新成本很高。

综合方法

在本文中,我提供了一种使用显式API和流捕获方法构建CUDA图的方法,从而实现两者的优点,避免两者的缺点。

例如,在顺序启动三个内核的工作流中,前两个内核具有静态启动配置和参数,而最后一个内核具有动态启动配置和属性。

使用流捕获来记录前两个内核的启动,并调用显式API将最后一个内核节点添加到捕获图中。然后,显式API返回的节点句柄用于在每次启动图之前用动态配置和参数更新实例化图。

下面的代码示例说明了这个想法:

在此示例中,cudaStreamGetCaptureInfo_v2提取当前正在记录并捕获到的CUDA图形。在调用cudaStreamUpdateCaptureDependencies更新当前捕获流的依赖项树之前,会将一个内核节点添加到此图中,并返回和存储节点句柄(new_node)。最后一步是必要的,以确保随后捕获的任何其他活动都在这些手动添加的节点上正确设置了它们的依赖项。

使用这种方法,即使参数是动态的,也可以通过轻量级的cudaGraphExecKernelNodeSetParams调用直接重用相同的实例化图(cudaGraph Exec_t对象)。本文中的第一张图片显示了这种用法。

此外,捕获和更新代码路径可以组合成一段代码,与启动最后两个内核的原始代码相邻。这会造成最少的代码更改,并且不会破坏原始的控制流和函数调用结构。

新方法在带有动态参数的蜂树/cuda图独立代码示例中详细显示。cudaStreamGetCaptureInfo_v2和cudaStream UpdateCaptureDependencies是CUDA 11.3中引入的新CUDA运行时API。

绩效结果

使用带有动态参数的蜂巢树/cuda图独立代码示例,我用三种不同的方法测量了运行受内核启动开销约束的相同动态工作流的性能:

在没有CUDA图形加速的情况下运行

使用重新捕获然后更新方法运行CUDA图

使用本文介绍的组合方法运行CUDA图

表1显示了结果。本文中提到的方法的提速很大程度上取决于底层工作流。

结论

在本文中,我介绍了一种结合显式API和流捕获方法构建CUDA图的方法。它提供了一种以最低成本为具有动态参数的工作流重用实例化图的方法。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:kubernetes二进制部署1.15版本(1)
下一篇:深度解读!阿里统一应用管理架构升级的教训与实践
相关文章

 发表评论

暂时没有评论,来抢沙发吧~