Serving Runtime Scheduler + KV Cache Speculative Decoding CUDA Graph / FlashInfer / Triton

SGLang 为什么这么快:架构、精髓、和高吞吐的真正来源

SGLang 的核心不是“某一个神奇 kernel”,而是一整条为在线推理吞吐优化的系统链路:请求编排、前后处理、动态批处理、KV Cache 复用、attention backend 选择、speculative decoding、CUDA Graph、并行与观测体系,一层一层把 GPU 从“偶尔很忙”推到“几乎一直很忙”。

先说结论

SGLang 之所以吞吐高,不是因为它只做了“快推理”,而是因为它把在线服务里最贵的几个环节都做了系统级优化:请求怎么进入、怎么合批、怎么复用 prefix、怎么组织 KV cache、怎么选 attention kernel、怎么降低 launch overhead、怎么在 decode 阶段少走弯路。

本质 01

把 prefix 复用做成一等公民

很多线上请求并不完全独立。系统提示词、聊天模板、RAG 前缀、agent tool scaffolding 都会重复。SGLang 直接把 prefix 复用放到 runtime 中心,而不是事后补丁。

本质 02

让调度器决定 GPU 的忙碌方式

高吞吐不是“模型单步快”,而是“GPU 每一步都在干最值钱的活”。SGLang 的 scheduler 决定哪些请求进 batch、prefill 和 decode 怎么穿插、缓存怎么命中、草稿模型怎么协同。

本质 03

把软硬件细节都吃干榨尽

它同时利用 FlashInfer、Triton、自定义 backend、CUDA Graph、分块 prefill、speculative decoding、不同并行策略和大量 launch 参数,把“理论性能”尽量变成“稳定吞吐”。

系统架构

从代码结构看,SGLang 的 serving runtime 不是一个薄 HTTP 壳子,而是一套完整的在线推理执行系统。入口有 HTTP server,核心有 tokenizer / scheduler / model runner / attention backend / KV cache / speculative worker 等模块。

Client / OpenAI API / Native API │ ▼ HTTP Server (entrypoints/http_server.py) │ ▼ TokenizerManager / request preprocessing │ ▼ Scheduler (managers/scheduler.py) ├─ batching / admission / policy ├─ prefix matching via RadixCache ├─ prefill / decode orchestration ├─ speculative decoding coordination └─ worker / IPC / parallel runtime control │ ▼ ModelRunner (model_executor/model_runner.py) ├─ forward batch construction ├─ KV cache allocation ├─ attention backend dispatch ├─ CUDA graph / piecewise graph path └─ logits + sampling pipeline │ ▼ Attention / Kernels ├─ FlashInfer backend ├─ Triton backend ├─ FlashAttention / MLA / sparse variants └─ hardware-specific backends │ ▼ Streaming tokens / metrics / tracing

入口层:HTTP Server

HTTP 入口负责协议兼容和请求接入。官方 bench 文档明确区分了在线 benchmark(经过 HTTP server 和 scheduler)与离线 benchmark(直接走 Engine / ModelRunner),这也说明 SGLang 很清楚“HTTP、调度、模型执行”是不同层级的成本。

编排层:Scheduler

源码里 scheduler.py 直接写明它是 “A scheduler that manages a tensor parallel GPU worker.”。它不是配角,而是 serving runtime 的大脑。这里还直接引入了 RadixCache、调度策略模块、以及 speculative decoding 相关类型。

执行层:ModelRunner

model_runner.py 顶部说明非常直白:ModelRunner runs the forward passes of the models. 也就是说,Scheduler 决定做什么,ModelRunner 负责把这件事在 GPU 上真正跑出来。

Kernel 层:多 attention backend

flashinfer_backend.py 顶部,SGLang 直接写了:现在有 FlashInfer 和 Triton 两类 backend,FlashInfer 更快,Triton 更容易定制;而且 prefill 和 decode 是分开优化的。

一条请求在 SGLang 里怎么跑

理解这条链路,你就知道它为什么快。核心就是:在进入 GPU 之前就尽量做好组织,在进入 GPU 之后尽量避免重复算。

1. 请求进入 HTTP Server 支持 OpenAI-compatible 和 native endpoint。真实线上 benchmark 默认走这里,因为这一步会带上 HTTP、异步客户端、scheduler 等真实开销。
2. Tokenizer / 前处理整理请求 把 prompt、采样参数、流式输出模式、多模态输入等整理成调度器可处理的结构。
3. Scheduler 做准入、合批和 cache 匹配 它决定哪些请求一起 prefill,哪些请求进入 decode,哪些请求共享已有前缀,是否启用 speculative path,是否需要不同并行策略。
4. RadixCache 复用 prefix 如果不同请求共享系统提示词、模板、长前缀,SGLang 可以避免从头重算整段 prefill。这个收益在线上 agent、chat、RAG 场景特别大。
5. ModelRunner 构造 forward batch 把 batch、KV cache、attention 元数据、采样与 logits 处理准备好,交给具体 backend 执行。
6. Attention backend 选择最合适实现 prefill 和 decode 用的实现不一定一样。FlashInfer 路径偏极致性能,Triton 路径偏灵活和定制,SGLang 让两者并存。
7. Decode 阶段尽量把 GPU 喂满 真正长期吞吐高不靠单次 prefill 峰值,而靠 decode 持续高效。SGLang 会通过动态批处理、分页 KV cache、speculative decoding、CUDA Graph 等手段把 decode 做厚。
8. 输出 token,同时暴露 metrics / tracing 生产环境可以打开 Prometheus 指标,并进一步分析 TTFT、ITL、吞吐、token 统计和估算内存使用。

SGLang 的精髓

如果只记三个词,我会选:prefix-awarescheduler-centrickernel-pragmatic

精髓一:把“程序结构”变成“服务结构”

SGLang 最早不是只想做一个 server,而是想让 LLM generation 有更强的结构表达能力。这件事延伸到 serving,就自然走向 prefix 复用、约束生成、批量管理、多请求共享执行状态。它不是把模型 API 包一层,而是在重写“请求应该怎样组织”。

精髓二:prefill 和 decode 分开看

很多系统把“推理”当成一件事,但 SGLang 很清楚 prefill 与 decode 的瓶颈不同、最优 kernel 不同、调度方式也不同。官方 attention backend 文档式源码就写明:backend 同时支持 extend(带 cached prefix 的 prefill)和 decode,两者分别优化。

精髓三:高性能不是单点,而是整条链

在线推理会被很多小损耗拖死:host-to-device copy、kernel launch、KV 分配、批次抖动、无谓 prefill、低 accept-rate 的 speculative path。SGLang 的设计很明显是在削这些边角料,让每个阶段都别拖后腿。

精髓四:工程上非常务实

它不执着一种 backend。FlashInfer 快就用 FlashInfer,Triton 好改就保留 Triton;能开 CUDA Graph 就开;不适合就切换;launch 参数多到像赛车调教台,因为他们追求的是现实机器上的最优解,不是论文里的整洁感。

真正厉害的地方是:SGLang 把“模型推理”从一个函数调用,升级成了一个高密度资源调度问题,然后用 runtime 设计去解它。

它怎么做到这么高的吞吐

下面这些因素叠起来,才构成 SGLang 的高吞吐。少一个点,它都还是快;但真正可怕的是它把这些点串成了一套组合拳。

01

Prefix / KV Cache 复用

Scheduler 里直接依赖 RadixCache。这意味着 prefix 命中不是外围特性,而是核心调度路径的一部分。共享 system prompt、相同模板、类似上下文的请求,能跳过大量重复 prefill。

02

动态批处理把 decode 做厚

高并发服务时,decode 阶段往往是长期主战场。SGLang 通过调度器不断把活跃请求拼成合适 batch,让 GPU 在每一步 decode 里处理尽可能多 token,而不是被很多小请求打碎。

03

把 prefill 和 decode 用不同实现打磨

FlashInfer backend 顶部直接说明:它区分 extend 和 decode;Triton backend 也专门为 forward metadata、kv splits、窗口化 attention 等准备不同逻辑。阶段分治本身就是吞吐来源。

04

Paged KV / 分页式 attention 执行

从 FlashInfer backend 中出现的 BatchDecodeWithPagedKVCacheWrapperBatchPrefillWithPagedKVCacheWrapper 就能看出,SGLang 明确围绕分页 KV cache 设计 attention 执行路径。这让长上下文和动态 batch 更可控。

05

CUDA Graph 降低 launch overhead

ModelRunner 和多个 runtime 路径都集成了 CUDA graph / piecewise graph。对稳定批次和重复图来说,这能明显减少 CPU 发射 kernel 的开销,尤其是在小步 decode 高频调用时很值钱。

06

Speculative Decoding 提高有效输出速度

Scheduler 里直接解析 SpeculativeAlgorithm,并在初始化时启动 model worker 与 draft worker。也就是说 speculative decoding 不是外围插件,而是主路径能力。accept length 越好,真实吞吐就越高。

07

Kernel backend 可切换,贴硬件调优

FlashInfer 更快,Triton 更可定制,这是源码直接写出来的取舍。SGLang 不赌单一路线,而是让 runtime 根据模型、硬件、功能需求走最合适 backend。

08

大量 launch 参数暴露真实性能旋钮

官方 server arguments 文档里,和并行、memory、chunked prefill、attention backend、speculative、hybrid kvcache ratio、load watch 等相关的参数非常多。说明团队把性能当成“可调系统”,不是黑盒。

09

在线 benchmark 体系很完整

bench_serving 会直接测 TTFT、ITL、吞吐、端到端延迟,还会在 SGLang 场景下查询 /get_server_info 报 speculative accept length。能持续测,才能持续压性能。

高吞吐的底层逻辑,可以压缩成一个公式

吞吐 ≈ 更少重复计算 + 更少 GPU 空转 + 更少 launch 开销 + 更高 batch 利用率 + 更高 cache 命中率 + 更高 speculative accept 效率。

你会发现,SGLang 的每个核心模块几乎都在为这几个项服务。

瓶颈 SGLang 的应对 为什么有效
相同前缀重复 prefill RadixCache / prefix reuse 直接省掉最贵的一段算力和内存流量
请求碎片化导致 batch 太小 scheduler 动态合批 提高每步 decode 的有效 token 数
prefill / decode 瓶颈不同 分阶段 backend 和元数据组织 每个阶段各用最优路径
KV cache 管理混乱 Paged KV + allocator 更适合长上下文和动态请求生命周期
kernel launch 太频繁 CUDA Graph / piecewise graph 降低 CPU 发射与图构建成本
decode decode 每步只出一个 token 太慢 speculative decoding 高 accept 时显著提升有效输出速率
不同硬件最优路径不同 FlashInfer / Triton / 多 backend 避免单一路径吃遍所有场景

生产环境怎么证明它真的快

不是看一句“我们很高效”,而是看它能不能稳定把关键指标吐出来。SGLang 这点做得也挺完整。

Benchmark 分层很清楚

  • bench_serving:走 HTTP server 和 scheduler,最接近真实线上。
  • bench_one_batch_server:测单批次端到端延迟,含 HTTP 和调度开销。
  • bench_offline_throughput:绕开 HTTP,直测 Engine 级最大吞吐。
  • bench_one_batch:更接近 kernel / 单静态 batch 剖析。

可观测指标不只吞吐

  • TTFT(首 token 时间)
  • ITL / TPOT(token 间延迟)
  • 端到端请求延迟
  • prompt / generation token 总量
  • 推测解码 accept length
  • Prometheus 指标与 Grafana 面板
一个 serving 系统只有在你能分清“HTTP 慢、调度慢、kernel 慢、还是 prefix 命中差”的时候,性能优化才不是玄学。SGLang 已经把这个诊断面铺出来了。

引用与依据

下面这些说法都尽量落在可见文档或源码上,不吹玄学。

SGLang README:项目自述和整体定位,来源:sgl-project/sglang README
Scheduler 角色python/sglang/srt/managers/scheduler.py:14 写明 “A scheduler that manages a tensor parallel GPU worker.”;同文件引入 RadixCache(约第 183 行)和 SpeculativeAlgorithm(约第 201 行)。
ModelRunner 角色python/sglang/srt/model_executor/model_runner.py 顶部注释写明 “ModelRunner runs the forward passes of the models.”
FlashInfer / Triton backend 取舍python/sglang/srt/layers/attention/flashinfer_backend.py 顶部说明:FlashInfer 更快,Triton 更易定制;都支持 extend 与 decode。
Paged KV 迹象:同文件直接使用 BatchDecodeWithPagedKVCacheWrapperBatchPrefillWithPagedKVCacheWrapper
Benchmark 分层benchmark_and_profiling.md 列出四类 benchmark,对应 HTTP server、scheduler、Engine、ModelRunner 不同层级。
Serving 指标bench_serving.md 说明 TTFT、ITL、throughput、accept length 等测量方式。
生产观测production_metrics.md 给出 Prometheus 指标与 Grafana 支持。
可调性能参数server_arguments.md 展示了 attention backend、memory、parallelism、chunked prefill、speculative 等大量参数。