一句话定义:CUDA Graph 是 CUDA 提供的一种执行方式——把一连串 GPU 操作(kernel 启动、内存拷贝等)预先"录制"成一张有向无环图,之后每次只提交一次,就能整段回放。
为什么需要"录"
CUDA 里 CPU 和 GPU 是异步的:CPU 负责把命令排进队列,GPU 负责执行。麻烦在于,每启动一个 kernel 都要走一遍参数检查、入队、下发的流程,单次开销虽然只有微秒级,但架不住数量多。当模型里是一堆小算子时,CPU 发令的时间可能比 GPU 干活的时间还长,GPU 频繁"等饭吃",整体变成 CPU 瓶颈——这就是启动开销(launch overhead)。
打个比方:做一桌菜,正常流程是你(CPU)每缺一样食材就跑一趟菜市场,来回路上花的时间远超做菜本身。CUDA Graph 的做法是:先按整份采购清单走一遍(捕获 capture),把采购员和路线固定下来(实例化 instantiate),之后照着清单一次性买齐(回放 launch)。菜市场还是那个菜市场,只是不再一趟趟折腾。
三个关键动作
- 捕获(Capture):在一段流(Stream)里照常执行一遍,运行时把期间所有操作记下来组成图。
- 实例化(Instantiate):把图变成可执行形式,确定参数与内存地址,这一步本身有成本,通常只做一次。
- 回放(Replay):一次提交整张图,重复执行多少次都行。
和相邻概念的区别
| 概念 | 解决什么 | 手段 |
|---|---|---|
| CUDA Stream(流) | 命令的顺序与并发 | 排队,仍逐条提交 |
| CUDA Graph | CPU 下发命令的开销 | 打包成图,一次提交 |
| 算子融合(fusion) | GPU 内重复读写与小 kernel | 改写计算本身 |
关键差别:融合是改"算什么",Graph 是改"怎么把计算交出去",两者可以叠加使用。另外,流捕获(Stream Capture)只是生成图的一种方式,不是替代它的东西。
对从业者的实际意义
固定形状、固定流程、反复执行的负载最受益:小 batch 推理、训练中每一步都一样的迭代、小算子密集的模型结构。收益主要在三处:CPU 侧开销下降,GPU 更容易被喂饱;延迟抖动(长尾)通常更平稳;省出来的 CPU 线程可以去做数据处理或调度。代价也很实在:图里的内存地址和形状在回放时是固定的,遇到动态 shape、动态控制流,就得重新捕获或更新图,否则可能报错或反而更慢;如果本来就是大 kernel 长计算,收益相当有限。工程上通常把它做成推理引擎或训练框架里的一个开关,先实测再决定开不开,具体 API 与支持范围以官方文档为准。
