Graph Runner、Attention Backend 与执行路径选择#
这章解决什么问题#
执行模型讲到这里,读者通常已经理解了 ForwardBatch -> forward -> sample 这条主循环。但真实 runtime 还有一层很容易让人困惑的问题:为什么同一套执行模型在不同环境下会走不同 graph runner、不同 attention backend,甚至表现出完全不同的约束和限制?如果不补这一层,execution model 章节仍然会显得像“抽象闭环图”,而不像一个真的会在不同硬件与配置下变化的系统。
ModelRunner 为什么不只是一种执行路径#
从 python/sglang/srt/model_executor/model_runner.py 可以看到,ModelRunner 并不是简单地“直接 forward 模型”。它同时持有 CudaGraphRunner、CPUGraphRunner、PiecewiseCudaGraphRunner 等不同 runner 逻辑,也显式管理 ATTENTION_BACKENDS、hybrid attention backend 以及 capture / replay 相关路径。
这意味着 execution model 并不只是一套抽象控制流,它还包含“在当前环境下应该选哪条执行路径”的选择问题。把这一层省略掉,读者很容易误以为 forward 过程总是同样的,只是速度有快慢;但从源码和文档看,差异远不止速度。
attention backend 为什么会改变理解方式#
官方 docs/advanced_features/attention_backend.md 已经强调,不同 attention backend 有不同的 pros and cons,而且 speculative decoding、deterministic inference、quantized KV cache 等能力对 backend 的要求并不相同。这说明 backend 不是“底层实现细节”,而是会反向影响上层行为边界的执行条件。
例如,如果某个 backend 不支持某类 KV cache 或某种 graph capture 语义,那么你在上层看到的就不只是吞吐差异,而可能是功能边界、行为限制甚至调试路径都不一样。也正因为这样,本章要把 backend 视为 execution model 的一部分,而不是附录说明。
graph runner 在执行链里的位置#
cuda_graph_runner.py、cpu_graph_runner.py 和 piecewise_cuda_graph_runner 这一类路径存在,说明 SGLang 不是总以一种“朴素 eager forward”方式工作。相反,它会根据设备、mode 和配置选择不同 graph runner 来驱动执行。
这层的关键价值,不是替读者穷举所有实现细节,而是解释“为什么同一个 ForwardMode,在不同 runner 下会有不同约束”。例如,某些 graph runner 明确不支持 LoRA、PP、speculative inference 或 gathered buffer;这些限制不是偶然,而是 graph execution 语义的直接结果。
一个更贴近真实系统的执行路径图#
flowchart TD
A["ForwardBatch / ForwardMode"] --> B{"执行路径选择"}
B --> C["eager forward"]
B --> D["CudaGraphRunner"]
B --> E["CPUGraphRunner"]
B --> F["PiecewiseCudaGraphRunner"]
C --> G["attention backend"]
D --> G
E --> G
F --> G
G --> H["logits / sample / next token"]这张图要解释的不是“内部类名很多”,而是“execution model 其实还有一层路径选择”。也就是说,ForwardBatch 之后并不总是同一条绝对固定的 forward 过程,而是会先经过 graph runner 和 backend 选择。
tradeoff:统一抽象 vs 多条真实路径#
从写作角度看,把所有 runner 和 backend 差异都展开会很容易把一章写成手册;但如果完全不讲,读者又会得到一个过于理想化的执行模型。因此更合理的策略是:保留统一抽象,同时明确告诉读者它在真实系统里会经过哪些路径分化。
这也是为什么本章不是单纯的“性能章”。它真正补的是“抽象统一、实现多态”这层工程现实。
调试时这一层意味着什么#
如果你看到的现象是“相同逻辑在不同设备或配置下行为不同”,优先就应该怀疑 graph runner 和 attention backend 路径,而不是一开始就怀疑上层 request lifecycle。因为这里控制的是“同一批数据最终怎样被执行”,而不是“请求有没有进入系统”。
这类问题最难的地方,恰恰在于它们常常不是业务逻辑 bug,而是执行路径差异。所以本章的调试价值,在于帮读者把这种差异从“神秘性能问题”重新落回具体 runner 和 backend 选择上。
本章对应哪些代码路径#
这一章最重要的锚点包括 python/sglang/srt/model_executor/model_runner.py、python/sglang/srt/model_executor/cuda_graph_runner.py、python/sglang/srt/model_executor/cpu_graph_runner.py、docs/advanced_features/attention_backend.md、docs/advanced_features/speculative_decoding.md 与 docs/advanced_features/piecewise_cuda_graph.md。
小结#
执行模型不是一条单一路径,而是一套统一抽象下的多条真实执行路径。把 graph runner 和 attention backend 放进 execution model 章节之后,读者才能真正理解“同样的逻辑为什么会在不同环境下表现不同”,而不仅仅把差异理解成性能数字。
叶王 © 2013-2026 版权所有。如果本文档对你有所帮助,可以请作者喝饮料。