← All writingLLM Infra:让模型高效运行 · 03

SGLang:共享前缀、结构化生成与 PD 分离

从重复系统提示出发理解 RadixAttention,再计算把 KV 跨机器传输的代价。

Read the English edition →

SGLang:共享前缀、结构化生成与 PD 分离

从零开始的完整讲解

从“一次问答”走到多轮与分支工作流

很多应用不是互不相关的短问题,而是共同系统提示下的多轮聊天、同一文档的多个问题、一个任务生成多个候选。它们包含大量重复前缀。若每次从头 prefill,相同内容会被重复计算。SGLang 的一个重要理解入口是如何组织和复用这些共同前缀。

Radix tree 可以先理解为压缩的前缀树:共同开头只存一条路径,出现差异的地方再分叉。这里复用的是匹配 token 前缀的计算状态,不是把相似问题的答案直接复制过来。

一个有共享也有分歧的例子

三个请求分别是 [系统说明, 文档A, 问题1]、[系统说明, 文档A, 问题2]、[系统说明, 文档B, 问题3]。前两条可以共享更长前缀,第三条通常只共享系统说明部分。如果请求把问题放在文档之前,分叉会更早,后面的相同文档未必构成可复用的前缀。

这个例子说明输入布局会影响性能,但布局首先要保证任务语义。RAG 中材料排序不同,模型可能得到不同答案;不能只优化命中率而忽略质量。缓存还需淘汰,显存有限时不是所有历史前缀都能永久保留。

Structured generation 约束了形式,没解决事实

若产品需要 JSON,采样时可限制当前哪些 token 能形成合法语法或满足 schema。与“请输出 JSON”的提示相比,这更直接地约束了解码空间。但 {"price":999} 即使语法完全合法,金额仍可能错误。

字段类型、枚举、必填项、业务规则和事实依据属于不同层次。应分别验证。复杂约束还会产生构建或执行开销,首次请求与缓存后的请求可能不同;压测时需要把约束处理也纳入真实链路。

PD 分离为什么不是免费加速

Prefill 与 decode 的计算形态不同,可以考虑用不同资源分别处理,再将 KV 状态传递给 decode 端。潜在好处是减少阶段互相干扰,分别调节容量;代价是 KV 传输、跨进程协调、路由与容量失衡。

假设需要迁移 512 MiB KV,即便有效链路带宽达到 50 GiB/s,纯数据传输下界也约为 10 ms,此外还有协议、排队和同步。这个数值只是理想估算,不是某个部署的测量。短请求可能难以摊薄这部分额外成本。

如何设计有信息量的 A/B

准备三类请求:无共享前缀、高共享固定前缀、共享前缀但持续变化的尾部。控制输入长度和输出预算,记录命中率、TTFT、ITL、吞吐与缓存占用。若启用 PD 分离,另外观察 KV 传输时间及两侧排队,找出资源是否真的平衡。

结构化输出实验则同时记录 schema 合规率、语义正确率和延迟。不要把格式合规提升直接写成“模型更聪明”。先在小样本中验证输出含义,再扩大流量,是可解释的性能优化顺序。

与其他推理框架怎样比较

vLLM、SGLang 和 TensorRT-LLM 的能力存在交集,支持范围也会随版本变化。没有必要人为把每个特性永久归属于一家。更实用的问题是:你的模型和硬件是否支持,关键工作流是否覆盖,尾部延迟怎样,故障时能否观察,升级成本多少。官方文档用于核实当前接口,本文的前缀、约束与阶段拆分模型用于解释测量结果。

相同开头为什么值得复用?

多轮对话、few-shot 分类和 agent 工具调用经常共享开头。若 token、模型与位置等条件一致,prefix 的 K/V 可以复用。Radix tree 压缩共享前缀,按分叉组织后续部分;它与存储层的分页是不同抽象。RadixAttention 的关键不是把相似句子聚类,而是复用精确匹配的计算。

假设请求分别是 [A,B,C,X] 和 [A,B,C,Y],共有前三个 token。第二个请求可能节约前三个位置的 prefill,但第四个位置与后续 decode 仍需计算。如果开头加入变化的时间戳,后面再长的公共文本也未必能作为连续 prefix 命中。

结构化输出有边界

约束解码可以限制某一步允许生成的 token,使输出满足语法或 schema。合法 JSON 不等于字段事实正确,工具名合法不等于调用合理。评估时分别检查语法通过率、schema 通过率、语义正确率与额外延迟。约束很强时,采样分布被改变,也需要检查质量。

python -m sglang.launch_server \
  --model-path Qwen/Qwen2.5-0.5B-Instruct \
  --host 127.0.0.1 --port 30000

安装和硬件支持按官方文档核对。使用相同模型与请求集比较框架,而不是拿默认配置对默认配置宣称总冠军。

PD 分离不是免费午餐

Prefill worker 生成 KV 后传给 decode worker。传输下界约为 bytes/bandwidth,还要计入调度、协议、布局转换和同步。在教学假设中,2 GiB cache 经有效 25 GiB/s 链路传输至少需 80 ms。这个数字不是 NIC 标称速率推导出的真实延迟,更不代表可以忽略连接与竞争开销。

如果原本 prefill 很短、网络慢、复用差,分离可能更慢。长输入、高并发与不同阶段争抢资源时才更值得验证。当前 SGLang 文档包含 Mooncake、NIXL 等传输路径,适用条件与配置应以所用版本为准。

自测

问题: 两个系统提示意思完全一样但标点不同,prefix cache 一定命中吗?

展开答案不一定,通常依赖 token 级精确前缀及运行上下文。语义相似不是缓存正确性的依据。

原始资料与继续阅读

资料核对:2026-09-10。教学示例不代表生产基准;框架 API 和模型支持请以所链接版本为准。

NOTEBOOK · LIVE PYTHON

在文章里运行 Notebook

逐格改代码、运行,或者一键运行全部。变量在单元之间保留;离开页面或重启内核会清空变量。编辑上游单元后,请重新运行后续单元。

此版用真实 Python 实现可检查的小型计算与训练,不需要 GPU。PyTorch/CUDA 不在此浏览器内核中;完整预训练模型 Notebook 见另一个标签,大模型基础的 Notebook 还提供单独加载真实 MiniLM 的可编辑单元。

内核尚未加载;点击运行开始。

正在加载 Notebook…