CUDA 编程(九)- CUDA Graphs 和 Events
发布网友
发布时间:2024-10-03 20:20
我来回答
共1个回答
热心网友
时间:2024-10-03 22:31
CUDA 图提供了 CUDA 中一个新的工作提交模型。图是一系列操作,如内核启动,由依赖项连接,依赖项与执行分开定义。这允许只定义一次图,然后重复启动。将图形的定义与其执行分离开来可以实现许多优化。
图的工作提交分为三个不同的阶段:定义、实例化和执行。一个操作在图中形成一个节点。操作之间的依赖关系就是边。这些依赖关系限制了操作的执行顺序。一个操作可以在它所依赖的节点完成后的任何时间被调度。调度是留给CUDA系统的。
节点类型包括但不限于操作节点、事件节点等。图节点可以是操作节点、事件节点等类型。定义和执行图形的 API 提供了创建图形的两种机制:显式 API 和流捕获。通过显式 API 创建图,通过流捕获将工作启动到流中的一段代码捕获为图形。
使用流捕获的图形创建提供了从现有的基于流的 API 创建图形的机制。将工作启动到流中的一段代码,包括现有的代码,可以用调用 cudaStreamBeginCapture() 和 cudaStreamEndCapture() 括起来。当在处于捕获模式的流中记录事件时,它将导致 captured event。捕获的事件表示 capture graph 中的一组节点。流捕获可以在任何 CUDA 流上使用,除了 cudaStreamLegacy(“NULL stream”)。注意,它可以在 cudaStreamPerThread 上使用。捕获流可以通过 cudaStreamIsCapturing() 查询。
跨流依赖和事件处理通过使用 cudaEventRecord() 和 cudaStreamWaitEvent() 表示。当在捕获流中记录事件时,它将导致 captured event。当 caputred event 被流等待时,如果流还没有进入捕获模式,它就会将流置于捕获模式,并且流中的下一项将对捕获事件中的节点有额外的依赖关系。所有被捕获到同一捕获图的流在 cudaStreamEndCapture() 时被从捕获模式中取出。如果流捕获中存在跨流依赖,必须在调用 cudaStreamBeginCapture() 的同一流中调用 cudaStreamEndCapture()。
同步或查询正在被捕获的流或被捕获事件的执行状态是无效的。在捕获同一上下文中的任何流时,并且它不是用 cudaStreamNonBlocking 创建的,任何试图使用遗留流的尝试都是无效的。因此,在这种情况下调用同步 API 也是无效的。当一个依赖关系将捕获的东西与未捕获的东西连接起来并进入队列等待执行时,CUDA 倾向于返回一个错误,而不是忽略该依赖。在将流放入或退出捕获模式时设置一个例外;这切断了在模式转换前后立即添加到流中的项之间的依赖关系。通过等待从正在被捕获的流中捕获的事件并与与该事件相关联的不同捕获图来合并两个独立的捕获图是无效的。
当流捕获期间尝试无效操作时,任何关联的捕获图都将失效。更新实例化的图形分为两种机制:整个图形更新和单个节点更新。对于小量的参数更新,使用单个节点更新会更有效。CUDA 还提供了一种机制,可以在不影响节点当前参数的情况下启用和禁用单个节点。
图形的执行是在流中完成的,以便与其他异步工作排序。然而,该流仅用于排序;它不限制图的内部并行性,也不影响图节点的执行位置。事件提供了密切监视设备进度的方法,并允许应用程序在程序中的任何点异步记录事件,执行精确的计时。
通过使用 CUDA 图和事件,开发者可以实现高效的图形计算,优化工作流,提高程序性能。