Skip to content

11 · CUDA Graph:降低 Decode 的启动开销

11 · CUDA Graph:降低 Decode 的启动开销

Eager 模式的隐藏成本

普通 PyTorch 每轮 Decode 都会从 CPU 发起许多 GPU kernel。单个 kernel 很快时,Python、dispatcher 与 kernel launch 的固定开销会变得显著。

CUDA Graph 允许把一段固定 GPU 工作流捕获下来,之后只更新预分配输入缓冲区并 replay,减少 CPU 发射次数。

nano-vLLM 如何捕获

ModelRunner 会为一组 batch size 预先捕获 graph,例如小 batch 的 1、2、4、8,以及更大的固定间隔。捕获过程:

  1. 创建足够大的静态 input_idspositionsslot_mappingcontext_lensblock_tables 与输出缓冲区。
  2. 设置对应 batch size 的 Context。
  3. 先 warmup 一次,触发必要初始化。
  4. torch.cuda.graph(...) 中再次执行模型,完成捕获。
  5. 保存 graph 和共享 graph pool。

为什么形状必须稳定

Graph 记录的是固定内存地址和操作拓扑。若每次输入 shape 都变化,就无法直接 replay。因此运行时会把当前 batch 映射到某个已捕获 batch size,并在静态缓冲区里填充数据。

enforce_eager 的价值

  • True:不捕获 graph,适合调试、验证新功能、观察真实堆栈。
  • False:使用 graph,适合稳定 Decode 路径和性能测量。

任何涉及动态控制流、不同 shape 或新的内存分配的修改,都应先在 Eager 模式验证,再确认可被 graph 捕获。

CUDA Graph 不是免费加速

它需要额外 warmup、图池内存和固定缓冲区;捕获多个 batch size 也增加初始化时间。对长 Prefill 或大矩阵计算,launch 开销占比小,收益可能不如 Decode 明显。

HTML INTERACTIVE LAB11 · CUDA Graph:降低 Decode 的启动开销
单独打开 ↗
课后习题等待完成

为什么 CUDA Graph 通常需要静态输入缓冲区?

动手任务

在 Eager 模式和 Graph 模式各画一条 5-step Decode 时间线,标出 CPU launch 次数的概念差异。

下一节:综合项目

社区教程,与 nano-vLLM 上游项目无官方隶属关系。