深度研究 · 推理引擎
vLLM 与 SGLang:两个推理引擎到底在解决什么 ——兼论 PD 分离的原理与最佳实践
写给要落地、要选型、要调优的一般技术人员。不堆基准数字,而是把「显存怎么管、请求怎么排、两阶段为什么必须拆开」这三件事讲透,让你可以推导出自己的结论,而不是记住别人的结论。
主题:LLM 推理服务引擎 · KV Cache 管理 · Prefill/Decode 分离
证据截止:2026-09
摘要
共同语言
KV Cache
vLLM·分页
vLLM·调度
SGLang·基树
SGLang·结构化
正面交锋
PD·为何拆
PD·怎么拆
PD·最佳实践
反模式
结论
来源
00 摘要:十条核心论断
如果只看一页,看这一页。每条论断都可在后文找到推导与证据;带「观点」标记的是本文判断,不是社区共识。
两个引擎做的是同一件事:把 GPU 显存和算力换成「被服务的 token」。 差别在于 KV Cache 的组织方式 ——vLLM 用分页(PagedAttention),SGLang 用基树索引(RadixAttention)。而基树是建在分页块之上 的:树里存的是块索引,不是另一套内存分配器。二者是组合关系,不是竞争关系。这条如果理解错,后面所有对比都会看歪。
PagedAttention 的本质是「按需分配 + 引用计数共享」,把显存利用率从 20–40% 拉到 90% 以上。 传统实现按最大长度预留连续空间,一个只用 100 token 的请求也占着 4K 的坑。分页后碎片趋近于零,直接换成更大的并发 batch。论文实测 Kwon et al., 2023
连续批处理是吞吐的另一半,且和分页是两个独立创新。 调度粒度从「一批请求」下沉到「每一个 forward step」:谁生成完了谁立刻出列,排队里的请求立刻补位。短请求不再被长请求钉住,吞吐基本不受请求长度方差影响。
RadixAttention 的本质是「跨请求、任意深度的自动前缀复用」。 多轮对话、RAG、Agent 的每一轮都在重复上一轮的 prompt。基树把 prefill 从「全量重算」变成「只算增量」,并且默认开启——维护开销实测 <0.3%。论文实测 Zheng et al., 2023
2025–2026 两个引擎已经在工程上收敛,选型依据应该是负载形状,不是「谁更快」。 vLLM V1 把 prefill/decode 统一成 token 预算调度,chunked prefill 与前缀缓存默认开;SGLang 补上零开销 overlap 调度器、XGrammar 结构化输出、EAGLE-3/MTP 投机解码。观点 任何「X 比 Y 快 N 倍」的说法都必须附带 batch 大小、命中率、模型三个前提。
PD 分离的动机不是「更快」,而是「解耦两个 SLO」。 prefill 计算密集、decode 带宽密集,放在同一个 GPU 池里会互相干扰(一条长 prefill 插进 decode batch,整批的每 token 延迟全部被拉高),还被迫共享同一套并行策略。DistServe 报告:同 SLO 下可服务 4.48× 请求,或把 SLO 收紧 10.2× (>90% 请求达标)。OSDI 2024
PD 分离把「显存管理问题」变成了「网络问题」,这是它最容易被低估的代价。 每个请求都要把整个 KV Cache 从 prefill 池搬到 decode 池,长 prompt 下是 GB 级。铁律:搬运 KV 的时间必须小于它替你省下的时间,否则净亏 。Anyscale 实测:传输层从 RDMA 退回 TCP,吞吐劣化最高 19× 。受控实验 Anyscale, 2026
P:D 配比是负载的函数,不是一个常数。配错会全面劣于不分离。 长入短出 2P:1D;长入长出 1P:3D;多轮高命中 1P:2D。DeepSeek 线上是 4 节点 prefill : 40 节点 decode——那是他们 的流量,不是通用答案。受控实验 Anyscale, 2026
vLLM 官方文档一句话说死了边界:「Disaggregated prefill DOES NOT improve throughput」。 它买的是 TTFT 与 ITL 独立可调 、以及尾部 ITL 可控;吞吐增益来自整套配置(池配比、路由、并行策略、缓存复用、负载形状),不是「把两阶段拆开」这个动作本身。官方文档 vLLM Docs, 2026
落地路径必须是渐进的,直接上 PD 分离是最常见的错误。 共址 + 连续批处理 + 前缀缓存 → 加 chunked prefill → 多副本时上 cache-aware router → 只有在「长 prompt + 高并发 + RDMA 就位」三条件同时成立时,才上 PD 分离。观点
01 先建立共同语言:一次请求到底在干什么
后面所有的优化,本质上都是在对付下面这张图里的两个方块。理解它们的差异,比记住任何基准数字都重要。
Prefill 预填充
一次并行算完整个 prompt
Decode 解码:每步只产出一个 token,严格串行
每一步都要读一遍完整 KV Cache
首个 token 诞生
TTFT = prefill 时长 + 排队时长
ITL / TPOT:相邻 token 间隔(平均值叫 TPOT)
E2E = TTFT + TPOT × 输出 token 数
用户体感延迟由这两段共同决定,但它们的优化手段几乎相反
图 1 一次请求的生命周期。Prefill 是「一口气读完整本书」——所有 prompt token 可以并行做矩阵乘,算力吃满,属于计算密集型 ;Decode 是「一个字一个字写」——每步只算一个新 token,但要反复读取整个 KV Cache,属于显存带宽密集型 。硬件胃口相反,是后面 PD 分离全部动机的根源。
四个必须分清的指标
指标 定义 谁最在意 主要受什么影响
TTFT 从发出请求到收到第一个 token 交互式对话、实时补全 prompt 长度、prefill 算力、排队时间、缓存命中率
TPOT / ITL 后续每个 token 的间隔(TPOT 是均值,ITL 看分布) 流式输出的「打字机手感」 显存带宽、decode batch 大小、是否被 prefill 插队
E2E 整条响应的总耗时 批处理、离线任务 TTFT + TPOT × 输出长度
Goodput 在满足 SLO 前提下的 有效请求速率所有线上服务(真正的钱) 上面三者 + SLO 达成率(如 90% 请求达标)
为什么「吞吐」是个容易骗人的指标
把一个 GPU 塞满、每秒吐出 10000 个 token,听起来很美——但如果其中一半请求的 TPOT 超过了 200ms 的用户忍耐线,这些 token 对业务毫无价值。Goodput(有效吞吐)才是线上真正的目标函数 :它只统计「在 SLO 之内完成」的请求。DistServe 论文之所以用「per-GPU goodput」而不是 raw throughput 做优化目标,正是因为这个差别;PD 分离的全部收益也必须用 goodput 来衡量,而不是 token/s。
一句话概括两个引擎的分工层次
它们都处在 AI 应用栈的最底层 :上面是网关、Agent 框架、业务代码,它们决定「要问哪些 token」;引擎只负责「把 GPU 资源换成 token」。两者都提供 OpenAI 兼容 API,因此换引擎通常是一次配置改动,而不是一次代码重写 ——这一点决定了你完全可以在生产里同时跑两个引擎,用网关按请求类型分流。
02 战场:KV Cache 才是那个决定一切的东西
不理解 KV Cache 的量级,就不会理解为什么「显存管理」能带来 2–4 倍吞吐差距,也不会理解为什么 PD 分离会变成一个网络问题。
KV Cache 是什么
Transformer 每生成一个新 token,都要拿它去和此前所有 token 做注意力计算。如果每次都重算历史 token 的 Key / Value 向量,代价是平方级增长。于是工程上把它们缓存下来,这就是 KV Cache——可以理解为模型的「短期记忆草稿纸」 :prompt 越长、并发越多,草稿纸越大。
它有多大:一个可以自己验算的公式
KV Cache 字节数 ≈ 2 × 层数 × n_kv_heads × head_dim × 序列长度 × 每参数字节数
拿 Llama-3-70B(80 层、GQA 8 个 KV head、head_dim 128、bf16 = 2 字节)来算:
每 token: 2 × 80 × 8 × 128 × 2 B = 327,680 B ≈ 0.32 MB
单条 4096 token 的请求:≈ 1.34 GB
并发 32 条: ≈ 42.9 GB ← 一张 A100 40GB 直接装不下
这个数字说明的三件事
① 显存是并发度的直接天花板 ——能塞进多少条并发请求,几乎线性决定吞吐;② 显存里哪怕只浪费 30%,也等于白扔三分之一的 GPU;③ 一旦要跨机搬运 KV Cache(PD 分离),长 prompt 下就是 GB 级数据量 要在网络上跑,网络带宽直接变成 TTFT 的一部分。vLLM 原始论文就指出:在 A100 40GB 上,KV Cache 可以占到约 30GB,把 batch 大小死死卡住。
同一批请求(max_len 预留 4096 token),两种分配方式的显存占用
① 传统方式:按最大长度连续预留,用不用都占着
请求 A 实际 880
已用 880
预留但浪费 3216
请求 B 实际 3800
已用 3800
请求 C 实际 900
已用 900
浪费 3196
合计占用 12288 slot,实际只用了 5580 → 利用率 45%
② PagedAttention:切成固定大小的块,用多少拿多少
请求 A 实际 880
55 个块
请求 B 实际 3800
238 个块
请求 C 实际 900
57 个块
合计占用 5580 slot(块大小 16 token,尾部碎片 ≤ 15 token/请求)
图 2 分页分配把「预留」变成「占用」。图中比例尺为示意:横轴 640px 对应 4096 token 的预留空间,实际用量按比例换算(137px=880 token)。这是 vLLM 能把显存利用率做到 90% 以上的全部原因——不是算得更快,而是不再浪费 。
三个由此推导出的工程动作
动作一
任何重复计算同一段前缀 的机会都必须抓住。缓存命中率是 prefill 成本的第一杠杆,也是 SGLang 相对 vLLM 最大的差异化来源。
动作二
显存一紧张,先问是不是被碎片和预留吃掉了 ,再考虑加卡。--gpu-memory-utilization 这类参数的意义就在这里。
动作三
涉及跨机搬 KV 的方案,先验算传输量 。0.32 MB/token × 32k prompt ≈ 10 GB,在 100 Gbps 网络上光传输就要 ~0.8 s(理论值),这已经超过很多场景的 TTFT 预算。
03 vLLM 核心能力一:PagedAttention —— 把操作系统那套搬进显存
一句话:显存不够用,往往不是真的不够,而是被「预留」和「碎片」吃掉了。PagedAttention 用虚拟内存分页的思路把这两块浪费还给你。
机制:三张表解决一件事
操作系统怎么管理内存,vLLM 就怎么管理 KV Cache:把每个序列的 KV Cache 切成固定大小的块 (默认 16 个 token 一块),用一张块表 记录「逻辑位置 → 物理块」的映射。生成新 token 时按需申请新块,请求结束立刻释放。
逻辑上连续,物理上离散 —— 分页映射的全貌
请求视角(逻辑块)
块表 Block Table
GPU 显存(物理块池)
逻辑块 0 token 0–15
逻辑块 1 token 16–31
逻辑块 2 token 32–47
逻辑块 3 token 48–(未满)
0 → 物理块 5
1 → 物理块 1
2 → 物理块 4
3 → 物理块 2
物理块 0 空闲
物理块 1 已分配(本请求)
物理块 2 已分配(本请求)
物理块 3 空闲
物理块 4 已分配(本请求)
物理块 5 已分配(另一请求共享)
注意:物理块 5 的引用计数为 2 —— 两段不同序列的公共前缀指向同一个块,这就是共享(橙色线)。
块是「可替代的商品」:释放后进入空闲队列,谁需要谁拿,因此不存在外部碎片。
图 3 PagedAttention 的三层结构。请求看到的是连续的 token 序列,块表负责翻译,GPU 显存里的块可以任意摆放。正因为摆位自由,才有了后面两件事:共享 (多条序列引用同一块,配合引用计数)与零碎片 回收。
三个直接后果
碎片趋近于零 ,显存利用率从传统实现的 20–40% 提升到 90% 以上(vLLM 论文实测)。不是算得快,是不再浪费。
共享成为可能 :相同前缀的多条请求可以指向同一批物理块;beam search / 并行采样在分叉前共享,分叉时才触发写时复制(copy-on-write)。
显存不够时可以整体换出 :vLLM 的换出粒度是「整个请求」而非单个块,这样实现简单且在简化架构下开销更低(V1 在显存压力下默认选择重算而非换出)。
一个常见误解
「块不连续 → 读取变慢」。实际上 PagedAttention 的 kernel 会按块表合并读取,块内仍然是连续的高带宽访问;分页带来的是调度自由度 ,代价只是多一次索引查表。这个交易在任何并发场景都是划算的。
04 vLLM 核心能力二:连续批处理与 V1 的统一调度器
分页解决了「能不能塞进来」,连续批处理解决「塞进来之后 GPU 有没有一直在干活」。这是两个独立的创新,缺一个都拿不到完整收益。
同一组请求,两种批处理方式的 GPU 时间线
① 静态批处理:一批同时开始、同时结束,短请求陪着长请求空转
请求 A(短)
槽位空转,等待批次结束
请求 B(长)
请求 C(中)
空转
批次边界
下一批才能开始
GPU 有效利用率受最长请求拖累,且批次之间有空档
② 连续批处理:谁生成完谁立刻出列,队列里的请求立刻补位
请求 A(短)
请求 B(长)
请求 C(补位)
A 在 x=310 结束 → C 立刻从这里补位
图 4 连续批处理的调度粒度是「每一次 forward」,不是「每一批请求」。请求 A 一结束,它的槽位在同一次迭代里就被 C 填上了;GPU 只要有排队需求就一直满载。这也带来一个副作用:新请求随时可能插进来做 prefill ,从而打断正在解码的请求——这正是 PD 分离要解决的问题(见第 08 章)。
V1:把 prefill 和 decode 当成同一种东西来调度
vLLM 在 2025 年完成了核心架构重写(V1,2025 年 1 月发布,v0.8.0 起成为默认引擎,v0.11.0 完成 V0 代码移除)。最重要的一处变化是调度器:
调度决策 = { request_id: 本步处理多少 token } ← 不再区分 prefill / decode
每个 step 在固定 token 预算(budget)内分配,chunked prefill 由此自然实现
这个「统一表示」带来三个好处,且都是默认开启、零配置 的:
Chunked Prefill
长 prompt 被切成小块,避免一个 32k 的 prefill 独占一整个 step、把同批 decode 全部卡住。
Prefix Caching
按块哈希 + LRU 淘汰。V1 把开销压到极致:即使 0% 命中率,吞吐损失也 <1% ,所以敢默认打开。
投机解码
草稿模型一次提议多个 token、目标模型并行验证,走的是同一条调度路径,不需要另开一套机制。
一条 8000 token 的长 prompt 到达时,chunked prefill 做了什么
① 不切块:一个 step 独吞 8000 token,同批 decode 全部停顿
Prefill 8000 token
这 3 步的 ITL 全部被拉高 → 用户感到卡顿
step 1
step 2
step 3
step 4
② 切块:每 step 只处理 2000 token,decode 继续按自己的节奏走
块1
块2
块3
块4
decode
decode
decode
decode
step 1
step 2
step 3
step 4
step 5
代价:TTFT 略升(prefill 被摊到多个 step);收益:TPOT 不再出现尖刺,尾部延迟可控。
这就是 vLLM 官方文档说的「chunked prefill 也能控制尾部 ITL,但块大小很难调;PD 分离更可靠」。
图 5 chunked prefill 的本质是用一点 TTFT 换平滑的 ITL 。它和 PD 分离目标相同、手段不同:一个是在时间上切片,一个是在空间上分池。
还有几处让 V1 变快的工程细节
CPU 任务卸载 :tokenization、多模态预处理、detokenization、流式输出移到独立进程,与 EngineCore 并行,避免 Python 侧拖慢 GPU。官方文档
Persistent Batch :缓存输入张量、每步只打增量(diff),并用 Numpy 替代大量 Python 循环,压低调度开销。
torch.compile + 分段 CUDA Graph :自动优化模型执行,同时保留动态 shape 的灵活性。
对称 TP 架构 :请求状态缓存在 worker 侧,调度器只传增量,单卡与多卡行为一致。
综合效果:官方报告 V1 相对 V0 最高带来 1.7× 吞吐提升 ,多模态模型上更明显。
05 SGLang 核心能力一:RadixAttention —— 让「重复的东西只算一次」
vLLM 问的是「显存怎么不浪费」;SGLang 多问了一句「这些显存里的内容,有没有可能根本不用再算一遍」。对 Agent、多轮对话、RAG 来说,第二个问题的答案往往是「一大半都不用算」。
机制:一棵以 token 前缀为边的树 + LRU
RadixAttention 把所有已计算过的 KV Cache 段组织成一棵基树(radix tree) :树的每条边是一段 token 序列,每个节点持有对应 KV 块的索引。新请求进来,先在树上找最长匹配前缀 ,命中部分直接复用,只 prefill 没命中的后缀。
两个会话共享同一段系统提示,基树自动发现并复用
根(空)
系统提示 1500 token
共享:命中率最高的一段
会话 A · 第一轮提问
会话 B · 第一轮提问
+800
+1200
会话 A · 第二轮追问
+300(只算增量)
会话 B · 第二轮(最久未访问)
LRU 淘汰从这类的「冷叶子」开始剥;正在被请求引用的节点有引用计数保护(lock_ref),不会被淘汰。
四个原子操作:match(找最长前缀)→ split(分叉处拆边)→ insert(只 prefill 后缀)→ evict(按 LRU 回收叶子)。
图 6 RadixAttention 的关键在于「任意深度、跨请求、自动 」三个词同时成立:不需要手工指定共享前缀,不是只有系统提示那一层能共享,会话深处的一段追问也能命中。SGLang 论文实测维护这棵树的开销 <0.3%(100 个请求共 74.3 s,树操作只占 0.2 s),所以可以默认常开。
最容易踩的一个坑:多副本把命中率洗掉了
基树是单进程内 的结构。一旦横向扩容到 N 个副本,若用普通 round-robin 负载均衡,一条会话的第二轮只有 1/N 的概率落在持有它 KV Cache 的那个副本上——共享前缀还在(每条副本都会各自缓存一次系统提示),但会话级的复用基本归零。修法 :用缓存感知路由(SGLang 的 sglang-router,或 vLLM 侧的 prefix-aware routing)做会话粘滞;同时监控 cached_tokens 字段,别假设缓存一定在生效。最常见的 bug :往"共享"的系统提示里塞了时间戳、会话 ID、用户 ID——每条 prompt 都变得独一无二,命中率直接归零,而你看日志完全看不出来。
和 PagedAttention 的关系:不要搞成二选一
基树里存的是分页块的索引 ,不是另一套内存分配器。也就是说 SGLang 的分页机制和 vLLM 是同类,基树是建在分页之上的一层索引 。所以二者是组合关系。vLLM 同样支持前缀缓存(Automatic Prefix Caching,按块哈希),差别主要在两点:SGLang 的匹配是树结构、任意深度、默认开启、带缓存感知调度 ;vLLM 的 APC 更偏块级精确匹配。
06 SGLang 核心能力二:结构化输出、零开销调度与投机解码
这三项加起来,构成 SGLang 在「Agent 型负载」上的实际优势。它们解决的是三类完全不同的开销。
压缩有限状态机:让 JSON 不再是「一个 token 一个 token 吐」
约束解码(grammar / JSON Schema / regex)的原理是:每步用一张掩码把不合法的 token 概率压到 −∞。朴素实现每步都要重算掩码,成本显著。SGLang 的压缩 FSM 做了一件聪明事:当 FSM 走到「只有唯一合法路径」的位置(比如 JSON 里固定出现的 ":{"),就一次性吐出整段 forced token ,跳过逐步采样。
生成一段 JSON 时,两种约束解码的步数对比
① 逐步掩码:每个 token 都要走一次完整采样
…共 9 个 forward step
其中 6 个位置的下一个 token 是被语法唯一确定的,仍然各花了一步
② 压缩 FSM + jump-forward:唯一确定的部分一次吐完
jump-forward:一次写入 6 个 token
→ 3 个 forward step
论文实测:压缩 FSM 带来 1.6× 吞吐;但状态机必须预处理并跨请求复用 —— 每请求重做预处理反而慢 2.4×。
现代版本以 XGrammar 为后端,掩码更新做到个位数微秒级。
图 7 结构化输出的优化空间不在「算得更快」,而在「能跳过的步骤就跳过 」。这也解释了为什么大量 tool-call / JSON 输出的 Agent 场景,SGLang 的优势会被放大。
零开销调度器:把 CPU 的调度时间藏进 GPU 的计算时间里
解码是毫秒级的短步骤,CPU 调度一旦不重叠,GPU 就出现气泡
朴素调度
GPU 前向
CPU 调度
GPU 前向
CPU 调度
GPU 前向
GPU 有气泡
重叠调度
GPU 前向
GPU 前向
GPU 前向
GPU 前向
CPU 提前准备下一批
CPU 提前准备下一批
CPU 提前准备下一批
SGLang v0.4 起默认启用:调度器提前一批运行,把 radix 树匹配这类较贵的操作也一并藏起来。
图 8 SGLang v0.4 引入的 overlap scheduler。Nsight 实测连续多个 decode batch 中 GPU 全程高负载、无空闲区间。这类优化在小模型和大规模张量并行场景下收益最明显——因为单个 step 越短,CPU 占比越高。
另外三件值得知道的事
投机解码
EAGLE-2 / EAGLE-3、Medusa、以及 DeepSeek 原生的 MTP。小草稿模型提议、大模型并行验证。SGLang 是首个支持 EAGLE-3 的引擎,也是首个把 DeepSeek MTP 落地的开源引擎(公开基准约 60% 输出吞吐提升)。
前端 DSL
gen / select / fork / join 让你用 Python 写出分叉、并行、条件的多调用程序,运行时能保证 前缀共享并协同调度并行分支,而不是靠运气命中。
RL 训练后端
SGLang 是多个主流 RL 框架(如 AReaL、verl、Slime)的 rollout 后端。这是它在「引擎选型」之外被采用的第二大理由。
07 正面交锋:能力对照与选型决策树
先说一句可能不受欢迎的话:2026 年的现实是两者已经高度收敛。真正的差异体现在负载形状上,而不是「谁更快」。
能力对照矩阵
维度 vLLM SGLang 怎么理解这个差异
KV Cache 核心 PagedAttention(分页 + 块表 + 引用计数) RadixAttention(基树索引,建于分页块之上) 不是二选一:基树存的是块索引。差异在「要不要自动做跨请求前缀复用」
前缀复用 块级哈希 + LRU(APC),默认开启 树结构、任意深度、默认开启,且带缓存感知调度 共享前缀越深、分支越多,SGLang 优势越大
结构化输出 FSM 掩码(xgrammar 等后端) 压缩 FSM + jump-forward(XGrammar) 输出 JSON 占比高时,差异会被放大
调度器 V1 统一 token 预算调度,CPU 任务进程外卸载 overlap 调度器,提前一批准备,藏掉 CPU 开销 目标一致:消灭 GPU 气泡。小模型/大 TP 时差异更明显
投机解码 支持(含 MTP 等) EAGLE-2/3、Medusa、MTP,V2 为默认路径 与前缀缓存、约束解码叠加使用
模型 / 硬件覆盖 最广(含 Apple Silicon、Trainium、Gaudi 等插件生态) 覆盖主流(NVIDIA / AMD / TPU / Ascend / CPU) 冷门架构、非主流硬件,vLLM 更稳
K8s / 生产成熟度 官方镜像 + Helm Chart,文档与部署指南最丰富 支持,文档相对薄;K8s 原生度部分 运维人力紧张时,这是个真实成本
RL 场景 可用 多个 RL 框架的首选 rollout 后端 做后训练 / RLHF 时倾向 SGLang
PD 分离 experimental,9 种 KV connector(NIXL / LMCache / Mooncake 等) 一等公民特性,自带 router,DeepSeek 大规模参考实现 见第 09–10 章
关于「谁更快」:先看这里再引用任何数字
公开资料里能同时找到方向相反的结论:有来源称在 Llama-3.3-70B FP8 单卡小 batch 流式场景下 SGLang 的 p95 延迟更低(约 48 ms vs 85 ms),但换成大 batch 吞吐后 vLLM 反超 5–10%;也有来源称 SGLang 在 DeepSeek 系列上快 3.1 倍、在 RAG/多轮场景吞吐最高提升 6.4 倍。这些数字并不互相矛盾,因为它们测的是不同东西。 决定结论的三个变量是:① batch 大小;② 前缀命中率;③ 模型与并行方式。观点 凡是没写清这三个前提的性能对比,都不应该作为选型依据——请用自己的真实流量回放压测。
按负载形状选型:从上往下依次判断
目标是极限吞吐?(大 batch 离线批处理)
短请求、互不相关、前缀重叠低
是
vLLM
大 batch 吞吐与生态成熟度优先
否
请求之间大量共享前缀?
多轮对话 / RAG / Agent / 长 system prompt
是
SGLang
RadixAttention 直接砍掉重复 prefill
否
冷门模型 / 非主流硬件 / 要现成 K8s 方案?
昇腾、Gaudi、Trainium、小众架构
是
vLLM
覆盖最广,踩坑的人最多
否
大量 JSON / 语法约束输出?
tool-call、结构化抽取、批量评测
是
SGLang
压缩 FSM 省掉大量强制 token 步骤
否
两者皆可:先用 vLLM 跑通,再用真实流量回放压测
两者都是 OpenAI 兼容 API,换引擎是配置改动不是代码重写
图 9 决策树的顺序是有讲究的:先问负载,再问硬件,最后才是偏好 。很多团队反过来——先选了熟悉的引擎,再用它去适应负载,结果在最难优化的地方硬扛。观点
生产里最常见、也最合理的答案:两个都跑
两个引擎都暴露 OpenAI 兼容接口,因此完全可以在网关层按请求类型分流:
交互式 / Agent 路径 → SGLang(低 p95、高前缀命中)
批处理 / 吞吐型路径 → vLLM(大 batch 吞吐、生态成熟)
用 LiteLLM 之类的网关按请求路由,业务代码完全不需要知道背后是谁在服务
08 PD 分离(一):为什么非拆不可
PD 分离(Prefill-Decode Disaggregation,也写作 P/D、xPyD)把两个阶段放到不同的 GPU 池。它解决的不是「算得慢」,而是「两个脾气完全相反的客人被塞进了同一间房」。
两阶段的硬件胃口是相反的
维度 Prefill 预填充 Decode 解码
瓶颈 算力(FLOPs):大矩阵乘法 显存带宽:反复读 KV Cache
输入形态 一次吃进成千上万个 token,高度并行 每步只有 1 个 token(投机解码除外),严格串行
batch 的作用 加到一定程度就饱和(计算已打满) batch 越大越好——一次读权重可以给更多请求用,是摊薄带宽成本的关键
对应的 SLO TTFT TPOT / ITL
想要的并行策略 偏小的 EP/DP 度,把长 prompt 高效处理完 偏大的 EP/DP 度(DeepSeek 线上 decode 用 EP≈256),把 GroupGEMM 与吞吐拉满
共址部署的两个具体病症
病症一:干扰 —— 一条长 prefill 插进来,整批人的 ITL 一起被拉高
理想:纯 decode 批次
每步时长均匀 → ITL 平稳
现实:第 4 步被插入一条 32k 的 prefill
Prefill 32k token 占满算力
这一步的 ITL 是平时的 5 倍
同批次所有并发请求在这一步集体卡顿
这就是为什么 P99 / P99.9 的 ITL 往往比平均值难看得多 —— 尖刺来自被 prefill 打断的那几步。
chunked prefill 能缓解(把长 prompt 切片),但块大小需要针对负载反复调;PD 分离从物理上杜绝了这件事。
图 10 干扰的本质是队头阻塞 :decode 是延迟敏感型、prefill 是吞吐型,两者混在一个队列里,前者必然被后者拖累。这和数据库里「OLAP 查询拖垮 OLTP 事务」是同一类问题。
病症二:资源耦合
两个阶段住在同一批 GPU 上,就被迫共享同一套资源分配和同一个并行策略 。而它们想要的是相反的:prefill 要小 EP 度 + 大 batch,decode 要大 EP 度 + 高并发。结果只能按更紧的那个 SLO 去调,再为另一个过度配置——两头都不最优。
分离之后得到什么
① 两个池独立扩缩容 、独立选并行策略;② TTFT 与 TPOT 独立可调 ;③ 尾部 ITL 不再被 prefill 打断;④ 每个池都能贴近各自的理论上限。
量化证据
4.48×
DistServe(OSDI 2024):同 SLO 下可服务的请求数;或把 SLO 收紧 10.2×,且 >90% 请求达标
2.1×
13B 模型单 A100:共址 goodput 约 1.6 rps,按 2P:1D 拆分后每 GPU 3.3 rps
1.3–2.3×
Anyscale(2026):MI325X 上 Ray + vLLM,同 GPU 预算同 SLA 下的可持续 QPS,最高折算 67% 成本下降
1.4×
Splitwise(ISCA 2024):吞吐提升同时成本降 20%;另一配置为同成本同功耗下 2.35× 吞吐
注意这些数字的口径:全部是 goodput(SLO 约束下),不是 raw throughput 。换成无约束的 token/s,PD 分离基本没有增益——这一点在下一章会被 vLLM 官方文档正面确认。
09 PD 分离(二):具体怎么拆
架构本身只有三个零件:一个会看请求的路由器、两池 GPU、一条传输 KV Cache 的通道。复杂度全在这条通道上。
PD 分离部署全景
客户端
OpenAI API
路由器
按长度 / 前缀亲和
Prefill 池
节点 1(算 KV)
节点 2(算 KV)
节点 3(算 KV)
Decode 池
节点 1(生成)
节点 2(生成)
节点 N
①
②
③ KV Cache 传输
④ token 流式返回(SSE)
计算密集 · 小 EP 度 · 大 batch · 目标:压 TTFT
带宽密集 · 大 EP 度 · 高并发 · 目标:压 TPOT
NIXL / LMCache / Mooncake
短 prompt 可以由路由器直接送 decode 池(跳过 prefill 跳数),这是很多生产部署的默认行为 —— 例如按 4096 token 设阈值。
每请求只搬一次 KV;但长 prompt 下这一次就是 GB 级,网络质量决定成败。
图 11 PD 分离的四个零件。真正需要工程投入的是第 ③ 步——它把一个纯粹的显存管理问题,改造成了一个分布式数据搬运问题。
vLLM 的实现:两个实例 + 一个 connector
vLLM 的 disaggregated prefilling 实现得很直白:跑两个 vLLM 实例 ,一个只做 prefill(kv_producer),一个只做 decode(kv_consumer),中间用 connector 搬运 KV。全部代码在 vllm/distributed/kv_transfer 下,由三个抽象组成:
Connector —— 调度侧决定「发哪些 KV」,worker 侧按层异步存取
LookupBuffer —— 在途 KV 块的暂存区,insert 非阻塞 / drop_select 阻塞
Pipe —— 单向 FIFO,send_tensor / recv_tensor
启动方式(官方示例形态):
# prefill 实例
vllm serve <model> --port 8100 \
--kv-transfer-config '{"kv_connector":"NixlConnector","kv_role":"kv_producer"}'
# decode 实例
vllm serve <model> --port 8200 \
--kv-transfer-config '{"kv_connector":"NixlConnector","kv_role":"kv_consumer","kv_rank":1}'
截至 2026 年,vLLM 提供 9 类 connector ,常用的几个:
Connector 传输 适用场景
NixlConnector RDMA / UCX / GDS 首选:全异步 send/recv,支持 xPyD 与 TP>1;AMD 侧有对等实现 RIXL,接口完全兼容
LMCacheConnectorV1 NIXL 之上 KV 卸载到 CPU 内存、跨实例 KV 池化;也支持独立 lmcache server 的多进程模式
MooncakeConnector RDMA / TCP Kimi 团队的 KVCache 中心化存储池,任意 prefill 可交给任意 decode
OffloadingConnector 本机 CPU 把 KV 卸载到 CPU 内存,可配 block_size 与 cpu_bytes_to_use
MultiConnector 组合 把多个 connector 串成有序列表,例如 RDMA + 本地共享存储
SGLang 的实现:一等公民 + 参考部署
SGLang 把 PD 分离当核心特性做,并公开复现了 DeepSeek 的线上规模部署(2025 年 5 月,LMSYS):
96×H100 上的公开结果
12 节点 96 卡 ,其中 3 节点(24 卡)做 prefill、9 节点(72 卡)做 decode ,跑 DeepSeek-R1/V3:
· 输入 52.3k token/s/节点 ,输出 22.3k token/s/节点 (2k 输入场景)——第一个接近 DeepSeek 官方口径的开源实现
· 相比同等资源的朴素张量并行,输出吞吐最高 5×
· 折算成本约 $0.20 / 1M 输出 token
· 同口径下 GB200 NVL72 上进一步达到 prefill 3.8×、decode 4.8×(2025 年 9 月后续报告)
几个配套的工程细节值得注意:attention 用 DP Attention 消除 KV 重复;MoE 用 DeepEP 的两种 dispatch 模式分别服务两阶段(prefill 走 normal dispatch 追吞吐,decode 走 low-latency dispatch 追延迟且兼容 CUDA Graph);Two-batch Overlap 把通信藏进计算;EPLB 做专家负载均衡。
传输层:三个开源方案的分工
NIXL (NVIDIA):底层高性能传输,UCX/GDS 后端,全异步——它是其他 connector 的地基。
LMCache (Chicago 大学):把 KV 存储从推理引擎里解耦出来,支持 batched 搬运与 I/O 流水,可做 CPU / 多级卸载。
Mooncake (Kimi / Moonshot,FAST'25 最佳论文):以 KVCache 为中心的分离式平台,把闲置的 CPU/DRAM/SSD 汇成集中 KV 池,集群内任意 prefill 可交给任意 decode。
三者今天都已是大规模推理的标准存储后端选项。
10 PD 分离(三):最佳实践
这一章是可以直接照着做的部分。核心原则只有一句:先证明你的瓶颈真的是「两阶段互相干扰」,再动手拆。
第一步:判断该不该上(三个条件必须同时成立)
条件一 · prompt 足够长
经验阈值:平均 8000 token 以上 。短 prompt 下 prefill 本来就不构成干扰,拆开只会白白增加一次网络跳数。
条件二 · 并发足够高
干扰是并发 现象。低负载下两个池各自都很空,分离带来的只有运维复杂度。多数团队在几百 QPS 以下都不需要。
条件三 · 有 RDMA 级网络
InfiniBand / RoCE / NVLink。Anyscale 实测:传输层退回 TCP,吞吐劣化最高 19× ——足以让整个方案变成负收益。
明确的反面情形:这几种情况下不要上
① 只想要更高吞吐 ——vLLM 官方原文:disaggregated prefill 不提升吞吐,它买的是 TTFT/ITL 独立可调和尾部 ITL 可控。
② TTFT 是唯一硬约束、输出很短 ——分离会多一次 KV 搬运跳数,反而抬高 TTFT(有实测从 426 ms 升到 1032 ms 的案例)。
③ 缓存命中率已经很高 ——命中率高意味着 prefill 本来就没什么活干,干扰自然消失,这时共址方案更简单也更快。
④ 流量在数百 QPS 以下 ——一个调好的共址 server + 连续批处理就够了。
第二步:先验算 KV 传输成本,别事后才发现
用第 02 章的公式:传输字节数 ≈ 2 × 层数 × n_kv_heads × head_dim × seq_len × 每参数字节数。Llama-3-70B bf16 下约 0.32 MB/token ;FP8 KV Cache 可以直接砍半。
把 32k 的 KV Cache 搬过去要多久?(Llama-3-70B,bf16,理论带宽上限,未计协议开销)
1 ms
10 ms
100 ms
1 s
10 s
1k
2k
4k
8k
16k
32k
prompt 长度(token)
TTFT 预算 500 ms(示例)
400 Gbps RDMA
100 Gbps RDMA
10 Gbps TCP
读图要点:RDMA 曲线在 32k 处仍远低于 500 ms 预算;TCP 曲线在 2k 处就已经触及预算线 —— 这就是为什么「网络不行时 PD 分离必然亏」。
注:本图为按理论带宽的建模估算(证据强度:建模),实际需叠加协议与软件栈开销,实测会更慢一些。
图 12 KV 传输时间与序列长度、网络带宽的关系(纵轴对数刻度)。砍传输成本的三条路 :FP8 KV 量化(直接减半)、按层流式传输(首层 KV 到达即可开始 decode)、以及把热 KV 放在离 decode 更近的地方(LMCache / Mooncake 的分级存储)。
第三步:定 P:D 配比 —— 这是最容易搞错的一步
配比不是常数,是负载的函数。下面是 Anyscale 在 MI325X 上用 Ray + vLLM 跑 Qwen3-235B / DeepSeek-V3 的实测结论:
最优 P:D 配比随负载形状大幅摆动
条形按 P 占总 GPU 的比例切分;蓝=prefill 池,绿=decode 池
长入短出
ISL 16K / OSL 1K · 命中 0%
Prefill 67%
Decode 33%
2P:1D
长入长出
ISL 16K / OSL 4K · 命中 0%
25%
Decode 75%
1P:3D
多轮 · 高缓存命中
命中率 80%
33%
Decode 67%
1P:2D
多轮 · 中等命中
命中率 30–60% · 混合瓶颈
40%
Decode 60%
1P:1.5D
推理型输出
长思维链 · 输出远长于输入
Decode 97%
1P:32D
规律:边际 GPU 应该给到当前瓶颈那一侧。命中率高 → prefill 变便宜 → 多给 decode;命中率低且输入长 → 多给 prefill。
最危险的做法:照抄别人的配比。配错的 PD 会在每一项指标上都劣于不分离。
来源:Anyscale 2026 实测(前四行,证据强度:受控实验);推理型 1P:32D 为行业经验值(证据强度:建模/经验)。
图 13 Anyscale 在相同 GPU 预算 + 相同 SLA 下的实测最优配比。DeepSeek 线上是 4 节点 prefill : 40 节点 decode(约 1:10)——那反映的是他们 的长输出高并发现实,不是通用答案。
配比怎么落地:从固定值到闭环
可以写死的场景 :批处理流水线、prompt 模板固定的离线任务——量一次 ISL:OSL,定一个值(如 2P:3D),就结束了。
不能写死的场景 :通用聊天 / Agent 平台。ISL:OSL 会随时间段漂移(上午聊天、下午长文档分析),固定配比很快变成闲置产能。这类应该一开始就预算一个弹性控制器:监控 KV Cache 负载与 prefill 队列深度、预测 ISL/OSL 变化、按 TTFT 与 ITL 目标无阻塞地伸缩两个池。NVIDIA Dynamo 的 SLA-based Planner 就是这条思路的产品化实现。
第四步:路由器决定成败
分离之后,「把请求发给谁」变成了一个独立的优化问题。路由器至少要会三件事:
按长度分流 :低于阈值(如 4096 token)的短 prompt 直连 decode 池,跳过 prefill 跳数——这是很多生产部署的默认行为。
前缀亲和路由 :让同一会话、同一批重复 prompt 落到已经持有对应 KV 的节点。实测价值很大:llm-d 的前缀感知路由在 Llama-3.1-70B / 4×MI300X 上给出 3× 输出吞吐、2× 更快 TTFT (相对 round-robin)。
传输 vs 重算的权衡 :当大小为 S 的前缀在节点 i 上、而节点 j 队列最短时,系统至少有四个选择——路由到 i、等 i、从 i 搬到 j、在 j 上重算。判断条件可以简化为比较 T_transfer(S,i→j) + T_queue(j) 与 T_wait(i)、T_recompute(S)。
第五步:上线清单
步骤 动作 验收标准
1 先把共址方案调到位 连续批处理开启、前缀缓存开启、max_model_len 与实际上下文匹配、chunked prefill 生效。这是基线,也是对照组
2 验证传输层 用 ucx_perftest / ib_write_bw 之类的工具确认 RDMA 真的在工作。不要跳过 :TCP 回退会带来最高 19× 的劣化,而它不会报错
3 量自己的 ISL:OSL 分布 从线上日志统计输入/输出长度的 P50/P90/P99,而不是凭感觉。配比和阈值都从这里来
4 从 1:1 起步压测 固定 GPU 总数,逐步调整配比,记录 TTFT / TPOT / goodput。观察哪一项先撞 SLO,就把边际 GPU 加到那一侧
5 接入缓存亲和路由 监控 cached_tokens,确认多副本下命中率没有崩
6 上弹性控制器(如需要) 按 TTFT / ITL 目标自动伸缩两池;流量稳定可跳过
7 固化监控与回滚 保留共址部署作为回滚路径;版本锁死(vLLM 该特性仍标 experimental)
必须上监控的指标
服务质量
TTFT / TPOT / ITL 的 P50、P90、P99 (均值会掩盖尖刺);SLO 达成率;goodput(达标 QPS);每请求 cached_tokens。
资源与链路
两个池各自的 GPU 利用率(计算与带宽分开看)、KV Cache 占用率、prefill 队列深度、KV 传输实际耗时与带宽 、网络重传/降速事件。
11 反模式清单
按「症状 → 修正」排列。这里列的每一条,都是生产环境里真实发生过的。
战略层:方向错了,后面全白做
照抄 P:D 配比
症状 :看到 DeepSeek 用 1:10,或者某个博客说 1:8,直接照搬;结果 PD 部署在每一项指标上都劣于原来的共址部署。
修正 :配比是 ISL:OSL 与命中率的函数。从 1:1 起步压测,看 TTFT 和 TPOT 谁先撞 SLO,把边际 GPU 给那一侧。
用 raw throughput 评估 PD 分离
症状 :拆完之后 token/s 没涨,于是判定「PD 分离没用」——或者反过来,用 token/s 上涨证明方案成功,但用户投诉变多了。
修正 :唯一正确的指标是 goodput (SLO 约束下的达标 QPS)+ P99 ITL。vLLM 官方已经写明:disaggregated prefill 不提升吞吐。
相信没有前提条件的性能倍数
症状 :「SGLang 比 vLLM 快 3 倍」被写进选型 PPT。实际上不同来源给出的方向相反,因为它们测的 batch 大小、命中率、模型都不一样。
修正 :任何对比都先看三个前提——batch 大小、前缀命中率、模型与并行方式。然后用自己的真实流量回放压测。
为了 PD 分离而换引擎
症状 :现有 vLLM 部署跑得好好的,看到 SGLang 的 PD 更成熟就整体迁移,结果在模型兼容、运维配套上付了一大笔学费。
修正 :不要为单个特性换引擎。vLLM 的 disaggregated prefilling 虽然标 experimental,但已经足够做延迟调优;真正需要大规模分离式集群时再评估。
工程层:细节吃掉收益
把变量塞进「共享」的系统提示
症状 :精心设计了 1500 token 的系统提示,监控却显示命中率接近 0。日志里看不出任何异常。
修正 :检查是否混入了时间戳、会话 ID、用户 ID、随机数。把它们移到提示的尾部 (即放到用户消息里),让公共前缀保持纯净。用 cached_tokens 验证。
多副本用 round-robin 负载均衡
症状 :单副本压测命中率 90%,扩到 8 副本后掉到接近系统提示那一层的水平,会话级复用归零。
修正 :上缓存感知路由 / 会话粘滞(SGLang sglang-router、vLLM 侧的 prefix-aware routing)。这是横向扩容时的必做项,不是可选项。
没验证 RDMA 是否真的在工作
症状 :PD 分离上线后 TTFT 暴涨、吞吐暴跌,但系统没有任何报错——传输层静默回退到了 TCP。
修正 :部署前用带宽测试工具实测;把「KV 传输耗时」与「网络带宽」做成常驻监控项。Anyscale 实测 TCP 回退可带来最高 19× 劣化。
max_model_len 直接设成模型支持的上限
症状 :显存被预留吃光,并发数上不去,但 GPU 利用率看起来并不高。
修正 :按业务真实需要的上下文长度设置,并留出 KV Cache 余量。这是最容易被忽略、收益却立竿见影的一项。
约束解码每请求重新编译状态机
症状 :开了 JSON Schema 约束之后吞吐断崖式下跌。
修正 :状态机必须预处理并跨请求复用 。SGLang 论文实测:每请求重做预处理会让吞吐降低 2.4×。
运维层:上线之后才是开始
只看平均延迟
症状 :P50 很漂亮,用户却抱怨「经常卡一下」。
修正 :把 P90 / P99 的 ITL 做成主指标。PD 分离的核心价值恰恰在尾部,不看尾部就无法验收。
没有回滚路径,也没锁版本
症状 :vLLM 升级后 PD 相关参数语义变化,服务直接不可用。
修正 :该特性仍标 experimental —— 锁死版本;保留共址部署作为随时可切的回滚目标。
一次性铺到最大规模
症状 :直接按 1:10 建两个大池,上线后发现配比严重错误,但资源已经切分完毕、改回来成本极高。
修正 :小步试错——先用少量 GPU 验证传输与配比,确认 goodput 确实提升后再扩。
落地成熟度阶梯:每一级都是下一级的前提
L1 静态批处理
显存利用率 20–40%
仅适合离线批量
L2 连续批处理
分页 + 前缀缓存
显存 90%+ · 吞吐 2–4×
大多数团队的终点
L3 分块与调优
chunked prefill
调度策略与参数
结构化输出加速
尾部 ITL 开始可控
L4 亲和路由
多副本 + 会话粘滞
缓存感知调度
监控 cached_tokens
命中率不再被洗掉
L5 PD 分离
RDMA 传输层就位
P:D 配比压测
独立扩缩容
TTFT / TPOT 解耦
或弹性控制器
跳过中间任何一级直接上 L5,几乎必然失败:你会把「本可以用参数解决的问题」误当成「需要改架构才能解决的问题」。
图 14 大多数团队真正需要停在 L2–L3。观点 L4 是横向扩容的必选项(不是可选项),L5 则只在三条件同时成立时才划算。
12 结论与判断
以下明确区分「社区共识」与「本文观点」,请区别对待。
已经形成共识的部分
分页式 KV Cache 管理是标配 ,不是可选项。PagedAttention 之后的引擎基本都采用了「块 + 块表 + 引用计数」这套结构。
连续批处理是吞吐的基础 ,调度粒度必须下沉到 forward step。
前缀复用对 Agent 型负载收益巨大 ,且应当默认开启。维护开销已经被压到可以忽略(vLLM 0% 命中时 <1%,SGLang 树操作 <0.3%)。
PD 分离的价值在于 goodput 与尾部延迟,不在于 raw throughput。 这一点 vLLM 官方文档写得毫不含糊。
传输层质量是 PD 分离的生死线。 RDMA 与 TCP 之间可以差一个数量级以上。
本文的判断(不是共识,供参考)
判断一
引擎之争已经结束,负载之争才刚开始。 vLLM 与 SGLang 的差异是真实的,但它小于「同一个引擎调好与没调好」之间的差异。把预算花在压测与调优上,比花在选型辩论上更划算。
判断二
KV Cache 正在从「显存里的一块临时数据」变成「集群级的一等资源」。 前缀缓存跨请求、分离部署跨节点、LMCache / Mooncake 跨存储介质——调度的基本单位正在从「请求」变成「KV 状态」。谁先把这件事做对,谁的效率就高一个量级。
判断三
PD 分离会在 2026–2027 从「高级选项」变成「默认形态」,但只在大厂与大规模场景。 中小团队真正的收益点仍在 L2–L4:把缓存命中率做上去、把路由做聪明、把参数调对——这些不花钱,收益却常常超过拆架构。
如果只带走一句话
先测,再拆。 推理引擎的所有优化,本质都是在回答三个可测量的问题:显存有没有被浪费、GPU 有没有在空转、同样的东西是不是被算了两遍。把这三个数测出来,你要不要 PD 分离、该用什么配比、该选哪个引擎,答案会自己浮出来。
13 参考来源
按证据强度分组。一手论文与官方文档优先;行业实测报告次之;二手综述仅用于交叉印证。
一手研究(论文)
Kwon et al. Efficient Memory Management for Large Language Model Serving with PagedAttention (SOSP 2023)——PagedAttention 原始论文,显存利用率 20–40% → 90%+、吞吐 2–4× 的出处。一手
Zheng et al. SGLang: Efficient Execution of Structured Language Model Programs (2023,arXiv 2312.07104)——RadixAttention、压缩 FSM、前端 DSL;树操作开销 0.2s/74.3s、压缩 FSM 1.6×、重复预处理 −2.4×。一手
Zhong et al. DistServe: Disaggregating Prefill and Decoding for Goodput-optimized LLM Serving (OSDI 2024,arXiv 2401.09670)——PD 分离的奠基工作;4.48× 请求数 / 10.2× SLO 收紧;13B 单 A100 的 1.6 → 3.3 rps 测算。一手
Patel et al. Splitwise: Efficient Generative LLM Inference Using Phase Splitting (ISCA 2024)——1.4× 吞吐 @ −20% 成本;2.35× 同成本同功耗。一手
Qin et al. Mooncake: A KVCache-centric Disaggregated Architecture for LLM Serving (FAST 2025 最佳论文,arXiv 2407.00079)——KVCache 中心化、分层存储、早期拒载;模拟长上下文最高 +525%、真实负载 +75% 请求量。一手
Yu et al. Orca (OSDI 2022)——连续批处理(iteration-level scheduling)的原始提出者。一手
官方文档
vLLM Docs, Disaggregated Prefilling (experimental) (2026)——「DOES NOT improve throughput」原文;9 类 KV connector 清单与配置示例;Connector / LookupBuffer / Pipe 三抽象。官方
vLLM Docs, vLLM V1 用户指南 (2025–2026)——统一调度器、chunked prefill 与 prefix caching 默认开启、V0 移除时间线。官方
vLLM Blog, Inside vLLM: Anatomy of a High-Throughput LLM Inference System (2025-09-05)——前缀缓存的哈希与引用计数实现细节。官方
vLLM Blog, vLLM V1: A Major Upgrade to vLLM's Core Architecture (2025-01-27)——V1 设计动机与 1.7× 吞吐。官方
SGLang 官方文档(sglang.org)——特性列表、硬件与模型覆盖、PD 分离与并行策略。官方
行业实测与工程报告
LMSYS / SGLang Team, Deploying DeepSeek with PD Disaggregation and Large-Scale Expert Parallelism on 96 H100 GPUs (2025-05)——3 节点 prefill / 9 节点 decode,52.3k 输入 token/s、22.3k 输出 token/s 每节点,5× 于朴素 TP,$0.20/1M 输出 token。实测
Anyscale, Achieving Up to 67% Cost Savings with PD Disaggregation Using Ray + vLLM on AMD MI325X (2026)——Qwen3-235B / DeepSeek-V3,1.3–2.3× QPS;P:D 配比表;RIXL;TCP 回退最高 19× 劣化。实测
Hao AI Lab, Disaggregated Inference: 18 Months Later (2026)——生态综述:LMCache、Mooncake、Dynamo、llm-d 的分层关系;GB200 NVL72 上 3.8×/4.8×。综述
AWS, Disaggregated prefill and decode for LLM inference on SageMaker HyperPod (2026)——按 4096 token 阈值条件路由、前缀感知与会话路由策略。工程
llm-d 项目报告(2026)——前缀感知路由在 Llama-3.1-70B / 4×MI300X 上 3× 输出吞吐、2× TTFT(相对 round-robin)。实测
NVIDIA Dynamo(GTC 2025 发布,2026-03 GA 1.0)——跨引擎的编排层,SLA-based Planner 自动伸缩 P/D 池。工程
二手综述(仅用于交叉印证,不作为唯一依据)
Particula Tech、Packet.ai、Groundy 等 2026 年 PD 分离综述文章——用于交叉核对框架支持矩阵与成熟度判断;其中「8000 token 以上」「几百 QPS 以下不建议」等经验阈值来自这类来源,属于经验值而非实测结论。二手
Sandbase 等 vLLM vs SGLang 对比文章——提供了 p95 延迟与 batch 吞吐的对照数字,但缺少完整测试条件,本文仅将其作为「结论依赖测量条件」的例证,未将其数字用于选型建议。二手
阅读这些资料时的两条提醒
① 区分 goodput 与 throughput :很多令人印象深刻的倍数来自 SLO 约束下的 goodput,换成无约束 token/s 结论会完全不同。 ② 区分厂商宣传与可复现结果 :涉及硬件厂商的端到端倍数通常包含完整优化栈(不只是 PD 分离),应优先看是否给出了可复现的配置与仓库。