0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

星星科技指导员 来源:NVIDIA 作者:Tu Jiqun 2022-10-11 09:43 次阅读

自从CUDA Graphs在CUDA 10中引入以来,CUDA Graph已经用于各种应用中。图形将一组CUDA内核和其他CUDA操作组合在一起,并使用指定的依赖关系树执行它们。它通过结合与CUDA内核启动和CUDA API调用相关的驱动程序活动来加快工作流。它还通过硬件加速强制实施依赖关系,而不是在可能的情况下仅依赖CUDA流和事件。

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

使用显式API调用构造CUDA图

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

使用显式API构建CUDA图的好处是,cudaGraphAdd*Node API返回节点句柄(cudaGraph Node_t),可以用作未来节点更新的引用。例如,可以使用cudaGraphExecKernelNodeSetParams以最低成本更新实例化图中内核节点的内核启动配置和内核函数参数。

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

使用流捕获构建CUDA图

通过这种构建CUDA图的方法,cudaStreamBeginCapture和cudaStream EndCapture被放置在代码块的前后。代码块启动的所有设备活动都会被记录、捕获并分组到CUDA图中。节点之间的依赖关系是从流捕获区域内的CUDA流或事件API调用中推断出来的。

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

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

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

重新捕获工作流。当重新捕获的图与实例化的图具有相同的节点拓扑时,不需要重新实例化,并且可以使用cudaGraphExecUpdate执行整个图更新。

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

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

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

综合方法

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

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

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

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

cudaStream_t stream;
std::vector _node_list;
cudaGraphExec_t _graph_exec;

if (not using_graph) {
  
  first_static_kernel<<<1, 1, 0, stream>>>(static_parameters);
  second_static_kernel<<<1, 1, 0, stream>>>(static_parameters);
  dynamic_kernel<<<1, 1, 0, stream>>>(dynamic_parameters);

} else {

  if (capturing_graph) {

    cudaStreamBeginCapture(stream, cudaStreamCaptureModeGlobal);

    first_static_kernel<<<1, 1, 0, stream>>>(static_parameters);
    second_static_kernel<<<1, 1, 0, stream>>>(static_parameters);

    // Get the current stream capturing graph
    cudaGraph_t _capturing_graph;
    cudaStreamCaptureStatus _capture_status;
    const cudaGraphNode_t *_deps;
    size_t _dep_count;
    cudaStreamGetCaptureInfo_v2(stream, &_capture_status, nullptr &_capturing_graph, &_deps, &_dep_count);

    // Manually add a new kernel node
    cudaGraphNode_t new_node;
    cudakernelNodeParams _dynamic_params_cuda;
    cudaGraphAddKernelNode(&new_node, _capturing_graph, _deps, _dep_count, &_dynamic_params_cuda);
    // ... and store the new node for future references
    _node_list.push_back(new_node);

    // Update the stream dependencies
    cudaStreamUpdateCaptureDependencies(stream, &new_node, 1, 1); 

    // End the capture and instantiate the graph
    cudaGraph_t _captured_graph;
    cudaStreamEndCapture(stream, &_captured_graph);

    cudaGraphInstantiate(&_graph_exec, _captured_graph, nullptr, nullptr, 0);

  } else if (updating_graph) {
    cudakernelNodeParams _dynamic_params_updated_cuda;
  
    cudaGraphExecKernelNodeSetParams(_graph_exec, _node_list[0], &_dynamic_params_updated_cuda);

  }
}

在此示例中,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图的方法。它提供了一种以最低成本为具有动态参数的工作流重用实例化图的方法。

关于作者

Tu Jiqun在加入NVIDIA担任高级计算机开发技术工程师之前,曾获得哥伦比亚大学晶格QCD物理学博士学位。在NVIDIA,他致力于在最新的NVIDIAGPU上使用最新的硬件和软件功能,以加速广泛的HPC应用程序。

审核编辑:郭婷

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • NVIDIA
    +关注

    关注

    14

    文章

    4597

    浏览量

    101750
  • API
    API
    +关注

    关注

    2

    文章

    1384

    浏览量

    60996
  • CUDA
    +关注

    关注

    0

    文章

    119

    浏览量

    13462
收藏 人收藏

    评论

    相关推荐

    动态环境中使用CUDA图提高实际应用程序性能

    具有许多小 CUDA 内核的应用程序通常可以使用 CUDA 图进行加速,即使内核启动模式在整个应用程序中发生变化。鉴于这种动态环境,最佳方法取决于应用程序的具体情况。希望您能发现本文中
    的头像 发表于 04-01 16:39 3410次阅读
    在<b class='flag-5'>动态</b>环境中使用<b class='flag-5'>CUDA</b>图提高实际应用程序性能

    轿车参数化分析模型的构造研究及应用

    轿车参数化分析模型的构造研究及应用概念设计阶段是车身结构设计中保证性能的重要阶段这个阶段留下的缺陷往往很难在后续的设计中弥补因而在车身开发中受到广泛重视目前国内外在这方面都展开了详细的研究尤其是国外
    发表于 04-16 13:40

    CUDA/OpenCL支持

    是否有关于GRID vGPU的CUDA / OpenCL支持的更新信息?以上来自于谷歌翻译以下为原文Is there any updated information about CUDA/OpenCL support for GRID vGPU ?
    发表于 09-07 16:42

    Grid K2 cuda下载位置是?

    我们有一个使用Grid K2机器的系统。我试图在一个vm的侧面设置cuda。当我使用驱动程序下载页面时,它指向NVIDIA-Linux-x86_64-367.57版本的驱动程序似乎工作(它们安装
    发表于 10-10 17:02

    CUDA编程教程

    Nvidia CUDA 2.0编程教程
    发表于 03-05 07:30

    安装cuda-9.0的过程

    [cuda] Linux系统多版本cuda环境下的cuda-90安装
    发表于 06-19 17:04

    linux安装GPU显卡驱动、CUDA和cuDNN库

    lib64目录下的动态文件进行复制和链接: cd ..cd lib64sudo cp lib* /usr/local/cuda/lib64/ #复制动态链接库cd /usr/local/cu
    发表于 07-09 07:45

    LInux安装cuda sdk

    1.安装toolkit(1)cd /home/CUDA_train/software/cuda4.1(2)./cudatoolkit_4.1.28_linux_64_rhel6.x.run
    发表于 07-24 06:11

    CUDA教程之Linux系统下CUDA安装教程

    CUDA教程之1:Linux系统下CUDA安装教程
    发表于 06-02 16:53

    什么是CUDA

    在大家开始深度学习时,几乎所有的入门教程都会提到CUDA这个词。那么什么是CUDA?她和我们进行深度学习的环境部署等有什么关系?通过查阅资料,我整理了这份简洁版CUDA入门文档,希望能帮助大家用最快
    发表于 07-26 06:28

    什么是CUDA

    什么是CUDA
    发表于 09-28 07:37

    基于车辆动态信息的路由构造及筛选策略

    中引入车辆动态参数作为构造依据并结合链路有效时间( LET. link expiration time)进行路径筛选,提高了转发路径的稳定性及可靠性;仿真表
    发表于 01-21 11:13 0次下载
    基于车辆<b class='flag-5'>动态</b>信息的路由<b class='flag-5'>构造</b>及筛选策略

    CUDA学习笔记第一篇:一个基本的CUDA C程序

    1、CUDA的简介 2、GPU架构和CUDA介绍3、CUDA架构4、开发环境说明和配置5、开始第一个Hello CUDA程序    5.1、VS2017创建NVIDIA
    的头像 发表于 12-14 23:40 687次阅读

    CUDA简介: CUDA编程模型概述

    CUDA 编程模型中,线程是进行计算或内存操作的最低抽象级别。 从基于 NVIDIA Ampere GPU 架构的设备开始,CUDA 编程模型通过异步编程模型为内存操作提供加速。 异步编程模型定义了与 CUDA 线程相关的异
    的头像 发表于 04-20 17:16 2498次阅读
    <b class='flag-5'>CUDA</b>简介: <b class='flag-5'>CUDA</b>编程模型概述

    支持动态并行的CUDA扩展功能和最佳应用实践

      本文档描述了支持动态并行的 CUDA 的扩展功能,包括为利用这些功能而对 CUDA 编程模型进行必要的修改和添加,以及利用此附加功能的指南和最佳实践。
    的头像 发表于 04-28 09:31 977次阅读
    支持<b class='flag-5'>动态</b>并行的<b class='flag-5'>CUDA</b>扩展功能和最佳应用实践