Prhub

#28551 Add opt-in CUDA-graph capture-trace export

原始 PR 作者 luccafong 合并时间 2026-06-19 09:51 文件变更 3 提交数 2 评论 6 代码增减 +36 / -0

执行摘要

新增 CUDA-Graph 捕获跟踪导出功能

现有的 --enable-profile-cuda-graph 只能输出 key_averages 摘要表格,缺少 kernel 级别的 shape/identity 记录,不便于离线分析每次捕获的细节。通过导出台面 trace,可以更好地排查 CUDA-Graph 捕获阶段的性能瓶颈。

简单实用的调试增强,值得快速合入。设计上保持了最小侵入性(默认关闭),值得学习。

讨论亮点

review 中 merrymercy 建议将 import 移到模块顶部("move imports to the top whenever possible"),luccafong 已采纳并提交修复。

实现拆解

  1. environ.py 新增环境变量:定义 SGLANG_ENABLE_CUDA_GRAPH_CAPTURE_TRACE,默认 False,使用 EnvBool 封装。
  2. profile_utils.py 添加导出函数:新增 export_cuda_graph_capture_trace(prof_context, *, runner_name, tp_rank),检查环境变量开关,若开启则将 prof_context 的 chrome trace 导出为 <SGLANG_TORCH_PROFILER_DIR>/graph_capture_profile/cuda_graph_capture-{runner_name}-TP-{tp_rank}.json.gz,确保多 runner 和多 TP rank 不互相覆盖。
  3. decode_cuda_graph_runner.py 的捕获后处理中调用:在 _post_process_after_profile 方法末尾(保持原有摘要日志不变)调用 export_cuda_graph_capture_trace。注意首次提交中 import 在函数内部,经 review 后调整为模块顶部全局 import。
  4. 不涉及测试、配置或部署配套变更:该功能为调试辅助,不添加单元测试。
文件 模块 状态 重要度
python/sglang/srt/utils/profile_utils.py profile 工具 modified 6.88
python/sglang/srt/model_executor/runner/decode_cuda_graph_runner.py 解码器 runner modified 6.15
python/sglang/srt/environ.py 环境配置 modified 4.75

关键符号

export_cuda_graph_capture_trace _post_process_after_profile

关键源码片段

python/sglang/srt/utils/profile_utils.py core-logic

新增核心导出函数 `export_cuda_graph_capture_trace`

# python/sglang/srt/utils/profile_utils.pydef export_cuda_graph_capture_trace(prof_context, *, runner_name: str, tp_rank: int):
    """Persist a CUDA-graph capture profiler trace (chrome trace) to disk.    Opt-in via ``SGLANG_ENABLE_CUDA_GRAPH_CAPTURE_TRACE`` (no-op otherwise). The
    capture profiler must have run with ``record_shapes=True`` so the trace can
    be inspected offline as a per-kernel shape/identity record. The file lands in
    ``<SGLANG_TORCH_PROFILER_DIR>/graph_capture_profile/`` and is namespaced by
    runner class and TP rank so concurrent capture passes (e.g. EAGLE3
    target/draft/draft-extend) and ranks don't overwrite each other.
    """
    if not envs.SGLANG_ENABLE_CUDA_GRAPH_CAPTURE_TRACE.get():
        return
    # 使用已有的 `SGLANG_TORCH_PROFILER_DIR` 作为基准目录
    output_dir = os.path.join(
        envs.SGLANG_TORCH_PROFILER_DIR.get(), "graph_capture_profile"
    )
    os.makedirs(output_dir, exist_ok=True)
    # 用 runner 名称 + TP rank 命名,避免并发覆盖
    path = os.path.join(
        output_dir, f"cuda_graph_capture-{runner_name}-TP-{tp_rank}.json.gz"
    )
    prof_context.export_chrome_trace(path)
    logger.info(f"CUDA graph capture trace saved to: {path}")

评论区精华

import 位置应放模块顶部 style

merrymercy 指出 `export_cuda_graph_capture_trace` 的 import 应在函数外部的模块顶部,而不是在 `_post_process_after_profile` 内部。

结论:luccafong 已修改为模块顶部全局 import · 已解决

风险与影响

风险极低:导出仅在 warmup 结束时一次性写入,不影响稳态服务性能。os.makedirsexport_chrome_trace 可能因权限或磁盘问题抛出异常,但异常会自然冒泡,不会静默失败。

仅影响 CUDA-Graph 捕获调试流程,对普通用户完全透明。开发者可通过设置 SGLANG_ENABLE_CUDA_GRAPH_CAPTURE_TRACE=1 获取 trace 文件。

磁盘写入可能失败 权限问题

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论