SGLang 性能分析:Torch Profiler 重叠启发式(Overlap Heuristics)判读指南
2026/9/10 7:15:41 网站建设 项目流程

SGLang 性能分析:Torch Profiler 重叠启发式(Overlap Heuristics)判读指南

【免费下载链接】sglangSGLang is a high-performance serving framework for large language models and multimodal models.项目地址: https://gitcode.com/GitHub_Trending/sg/sglang

导读

本文面向使用 SGLang 进行 torch.profiler 分析、需要判断 GPU 内核(kernel)之间是否真的存在重叠(overlap)机会的开发者。它系统讲解分析器所采用的重叠启发式规则:mapping/formal 双 trace 的分工、内核"隐藏"(hidden)的判定标准、内核分类方法、重叠机会表(overlap-opportunity table)的读取方式、依赖信号的生成逻辑及其边界限制。读完本文,你将能够正确解读 SGLang profiler 分析报告中的headroomlow-roi-hidden、依赖风险标签与try overlap / try fusion / check deps等建议,并将其与仓库中的重叠目录(catalog)和源码实现相互印证,避免把已知优化误判为"新机会"。

本文对应的分析器说明文档位于 .claude/skills/llm-torch-profiler-analysis/references/heuristics.md,统一入口脚本为 .claude/skills/llm-torch-profiler-analysis/scripts/analyze_llm_torch_profile.py,重叠计算与依赖信号的核心实现位于 .claude/skills/llm-torch-profiler-analysis/scripts/triage_overlap_helpers.py。

一个前提:分析器是"刻意保守"的

文档开篇就点明了整套启发式的设计基调:"This analyzer is intentionally conservative"(本分析器刻意保持保守)。这意味着:

  • 它不会因为两个内核出现在不同 CUDA 流上就断言它们"应该"重叠;
  • 它不会把 Python 作用域(scope)映射当作数据依赖的证明;
  • 它在给出"值得优化"的结论之前,会先排除明显的串行链(serial chain)风险。

保守的目的是避免产生误导性的性能优化建议——尤其是避免把通信内核(如 all-reduce)误报为"干净的 overlap 候选"。下面所有规则都可以在这个前提下理解。

mapping trace 与 formal trace:两个 trace 各司其职

重叠分析支持两种 trace 输入,它们的定位截然不同(对应 SKILL.md 中的--mapping-input/--formal-input双 trace triage 流程):

Trace 类型生成方式用于计算什么定位
mapping tracegraph 关闭或低融合配置下采集,保证可读性kernel -> cpu_op -> python scope的调用链映射、启动点(launch-site)调用链更易读,但不是最终服务调度形态
formal trace真实服务优化全部开启时采集hidden ratio(隐藏比)、exclusive ratio(独占比)、overlap headroom(重叠余量)、ASCII 时间线反映真实 serving 形态

两条 trace 的分工原则是:mapping trace 负责"这个内核从哪段 Python 代码启动"formal trace 负责"这个内核在真实调度下到底被藏住了多少"。因此文档明确建议,不要把 mapping trace 叫做"快速 profile"——它存在的唯一目的是恢复kernel -> cpu_op -> python scope这条调用链(源码实现见 triage_overlap_helpers.py 中的build_kernel_source_map,它通过External id -> CPU op -> 活跃 Python scope的时间线重建来给内核打上源位置标记)。

对应的两条命令(出自 SKILL.md):

# 双 trace 已有存量 trace python3 scripts/analyze_llm_torch_profile.py \ --mapping-input /path/to/graph_off_profile_dir \ --formal-input /path/to/graph_on_profile_dir # 双 trace 从运行中的 SGLang 服务实时采集 python3 scripts/analyze_llm_torch_profile.py \ --framework sglang \ --mapping-url http://127.0.0.1:31025 \ --formal-url http://127.0.0.1:31026 \ --num-steps 5 \ --profile-by-stage

"隐藏"(hidden)的判定标准

一个内核在某段时间片段(segment)内被判定为hidden,需要同时满足两个条件:

  1. 该内核在该片段内处于活跃状态(即其tsts+dur覆盖该片段);
  2. 至少有一个位于不同流上的其他内核也在该片段内活跃

如果与之重叠的内核是 compute 类内核,分析器还会单独记录一条"在 compute 之下被隐藏"(hidden under compute)的统计,用于区分"被计算掩盖"与"被通信掩盖"两种情况。

这段逻辑在源码中有精确对应。见 triage_overlap_helpers.py 的analyze_overlap:它对所有内核的ts / end做扫描线(sweep line)处理,维护活跃事件集合active;当某一片段内活跃内核涉及的不同流数量 >= 2时,该片段被计入total_overlap,同时每个内核累积hidden_us;若重叠对象中存在category == "compute"的内核,则额外累积hidden_by_compute_us;没有重叠对象的片段则累积为exclusive_us(独占时间)。最终聚合出两个核心指标(见AggregateStats的属性定义,triage_overlap_helpers.py):

  • hidden_ratio = hidden_us / total_us:该内核总时间中被其他流掩盖的比例;
  • exclusive_ratio = exclusive_us / total_us:该内核总时间中"独占 GPU、无其他流并发"的比例。

内核分类启发式:按名字归类,仅用于优先级排序

分析器按内核名称做五类划分(文档原文,与源码关键词表一一对应):

类别覆盖范围(文档)源码关键词证据(triage_overlap_helpers.py)
computeGEMM、attention、cutlass、cublas、类 matmul 的 Triton 内核cublascudnncutlasstritongemmmatmulgrouped_mmflashattentionmarlinfused_moemmawgmmabmm
communicationNCCL、all-reduce、reduce-scatter、all-gather、DeepEP dispatch/combine强关键词allreduceall_reducereduce_scatterallgathernccldeepepa2aalltoallmooncake;弱关键词broadcastdispatchcombine
elementwisesigmoid、top-k、gate、rmsnorm、layernorm、rope、类型转换sigmoidsilugelusoftmaxlayernormrmsnormrotaryropetopkgate_castgatherscatter
memorymemcpy、memset、fill、copy强关键词memcpymemsetdmaprefetch;弱关键词fillcopy
other其余一切兜底返回

分类优先级固定且确定(classify_kernel中先判 memory/communication 强关键词,再判 compute/elementwise,最后兜底other),并配有一个类别优先级表CATEGORY_PRIORITY = {compute: 4, communication: 3, memory: 2, elementwise: 1, other: 0},用于决定"谁是主导重叠对象"(见dominant_overlap_name)。

需要特别强调:这些类别只服务于优先级排序(prioritization),本身不代表任何性能结论。比如一个elementwise内核被标记为"被隐藏",并不意味着它不重要——它可能只是当前调度下恰好被掩盖了。

如何阅读重叠机会表(Action Table)

重叠机会表故意不是完整的内核转储("intentionally not a full kernel dump")。它只保留已经带有动作导向标签(action-oriented label)的行,标签只有两种:

  • headroom:该内核在 formal trace 中仍有可观的暴露时间;
  • low-roi-hidden:该内核已经被其他流大部分掩盖。

裁剪规则与 1% 门槛

排完优先级后,表会裁剪非常小的headroom行:

  • 如果某headroom行因低于默认的1% GPU 时间占比(share bar)而被判为P5,则从表中删除;
  • low-roi-hidden行即使很小也保留,因为它们是"别先追这个"(do not chase this first)的重要信号。

1% 门槛在统一入口脚本中有直接对应:MIN_RENDER_SHARE_PCT = 1.0(analyze_llm_torch_profile.py),内核表、重叠表、融合表默认都只渲染 GPU 时间占比 >= 1.0% 的行。

headroom行的解读

  • 该内核在 formal trace 中仍花费了有意义的暴露时间(exclusive 占比高);
  • 映射到的 Python scope 是检查调度或融合机会的好位置;
  • 在把它当作严肃的重叠候选之前,仍应先检查依赖信号

low-roi-hidden行的解读

  • 该内核已经被其他流大部分隐藏;
  • 单独优化它,不太可能推动端到端延迟;
  • 应把注意力转向融合(fusion)、减少 launch 次数,或周边调度,而不是单独调这个内核。

这两个标签的建议文本在源码中由build_headroom_suggestion/build_hidden_suggestion生成,例如 hidden 行会给出"Mostly hidden under {重叠对象} (X us). Revisit only if schedule or fusion changes."这类提示(triage_overlap_helpers.py)。

依赖信号(Dependency Signal):相邻性启发式,而非数据流证明

表中还包含一个来自 formal trace 的面向依赖的相邻性信号。它的构建输入是:

  • 同一流上最近的前一个与后一个内核;
  • mapping trace 的源归属(source attribution)。

为什么通信内核被"更保守"对待

文档强调通信内核的处理比以前更保守:

  • 如果紧邻的内核看起来像可能的生产者或消费者(producer/consumer),即使它们的 Python scope 名称不同,表也会提高依赖风险
  • 这避免了仅因为 all-reduce 类内核的邻居映射到不同函数,就过度宣称它是干净的 overlap 候选。

源码中对应的判定函数是classify_dependency_signal(triage_overlap_helpers.py),核心规则:

  • 紧邻判定:tight_gap_threshold = max(2.0, min(20.0, current.dur * 0.15)),即间隙不超过该阈值视为"紧邻";
  • 风险判定三要素:邻居与当前内核属于同一 scope 家族(same_scope_family)、CPU 启动操作相同、或满足类别依赖关系(如communication内核的邻居是compute/elementwise/memory类,见is_neighbor_dependency_like);
  • 当紧邻但源归属太弱、无法做出更强断言时,标记为adjacency unclear

典型标签

文档列出的完整标签集合:

标签含义
serial risk low相邻内核不像同代码路径上的紧密串行链
prev-side serial risk前一个相邻内核看起来与当前内核紧密绑定在同一代码路径
next-side serial risk后一个相邻内核看起来与当前内核紧密绑定在同一代码路径
both-side serial risk两侧都像是紧密串行链
adjacency unclear时序很紧,但源归属太弱,不足以支撑更强断言

可读表格会把这些压缩为更短的标签(dependency_risk_label映射,triage_overlap_helpers.py):

  • low(serial risk low)
  • high(prev/next/both-side serial risk)
  • unclear(adjacency unclear)

文档特别提醒:把它当作强启发式,而不是数据流的证明("a strong heuristic, not proof of dataflow")。

建议标签(Recommendation Labels)

重叠机会表的推荐标签刻意保持简短:

  • try overlap:依赖风险低、类别权重高,值得尝试与其他流重叠;
  • try fusion:适合先做融合而非跨流重叠;
  • check deps:依赖信号不明确,先核实依赖再动手;
  • skip overlap:不值得追(如low-roi-hidden或 share 低于 1% 的 P5 行);
  • manual check:需要人工核查;
  • observe later:暂缓观察。

这些推荐连同 P1–P5 优先级由build_priority_and_recommendation统一生成(triage_overlap_helpers.py):例如headroom+ 依赖low+communication类别 →P1 / try overlapheadroom+ 依赖low+ 非通信 →P1 / try fusionheadroom+ 依赖非 low →P2 / check deps;share < 1% →P5 / skip

实战:拿到重叠机会表后如何与仓库证据对照

这是整套技能最关键的一步(见 SKILL.md 的 Workflow):在宣称任何"新"优化之前,先把表中最顶部的行与仓库中的两个目录对照

  1. references/overlap-catalog.md:只收录在 profiler 中可见为 GPU 内核/集合通信内核/流式内核家族的 overlap 模式;
  2. references/fuse-overlap-catalog.md:源背书的融合与重叠模式查找表。

对照结论应优先落在四种表述上:

  • 已存在、但在此 trace 中缺失/被禁用/回归/后端不支持的路径;
  • 已存在、但未应用到当前模型形态的路径;
  • 上游其他框架已有、本地缺失的模式;
  • 只有当目录中没有任何一行能对上时,才允许称为"真正的新机会"。

例如,如果重叠表里出现 MoE combine 内核与 down-gemm 相邻暴露,目录会引导你先对照 SGLang 的 Single-batch Overlap(SBO)家族(python/sglang/srt/batch_overlap/single_batch_overlap.py,开关enable_single_batch_overlap位于 python/sglang/srt/server_args.py);如果出现 Q/K norm 分流的 trace,则先对照apply_qk_normalt_stream家族(python/sglang/srt/models/utils.py);出现 allreduce + RMSNorm 分离时,先核对 FlashInferallreduce_fusion路径(python/sglang/srt/layers/layernorm.py 中的forward_with_allreduce_fusion)。

重要限制(Important Limits)

文档以四条限制收尾,这也是保守设计的具体体现:

  1. trace 只显示"实际发生了什么重叠",不显示"什么可以合法地重叠"(A trace shows what overlapped, not what could legally overlap)。不同流上并发的两个内核,并不能证明它们相互独立、没有数据依赖。
  2. 不同流上的两个内核不证明它们无依赖(Two kernels on different streams do not prove they are dependency-free)。
  3. 映射到的 Python scope 只是启动点线索,不是唯一相关的代码位置(A mapped Python scope is a launch-site clue, not the only relevant code location)。真实依赖可能来自更外层的作用域或张量别名。
  4. 被隐藏的内核仍然可能重要:如果它改变了占用率(occupancy)、launch 次数或周边调度,即使当前被掩盖,也可能在别的配置下成为瓶颈(A hidden kernel can still matter if it changes occupancy, launch count, or surrounding schedule)。

小结

SGLang 的 torch profiler 重叠启发式本质上是一套"宁缺毋滥"的三步流水线:先靠 mapping trace 恢复内核到 Python 源码的调用链,再靠 formal trace 用扫描线算法算出每个内核的 hidden/exclusive 比例与 headroom,最后用同一流相邻性与源归属构造依赖信号、压低通信内核的误报,产出带 P1–P5 优先级与六种动作建议的重叠机会表。理解这些规则后,你在解读 analyze_llm_torch_profile.py 输出的三表报告时,就能区分"真实的 overlap 余量"与"只是恰好并行"的假象,并借助 overlap-catalog.md 与 fuse-overlap-catalog.md 把每个机会落到具体的源码路径上验证。

【免费下载链接】sglangSGLang is a high-performance serving framework for large language models and multimodal models.项目地址: https://gitcode.com/GitHub_Trending/sg/sglang

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询