1. 一个请求不是一次调用,而是一段生命周期

服务端收到请求后,先完成鉴权、tokenize、模板展开、可能的图像/音频编码和 prefix lookup。随后将未命中的 prompt token 送入 prefill,产生每一层的 K/V。之后请求进入 decode:每一步读已有 KV、计算下一个 token 分布、采样、追加新 KV,直到 EOS、长度上限、工具调用或取消。Agent 工具调用还会把同一请求暂停、外出 I/O、带着部分 KV 返回。

vLLM PagedAttention 论文的系统总览图
原始/官方结构图:Kwon et al., PagedAttention / vLLM, Figure 4。看 Scheduler 如何同时驱动 KV Cache Manager 与多个 worker;这是 PagedAttention 论文的系统分解,不等于 2026 vLLM 的全部特性或真实物理部署。
NEW → queued → prefix lookup → prefill → ready-to-decode → decode(step 1…N) → [tool wait → resume] → finish / cancel / evict

调度器实际管理的是一组状态机,它们所处阶段、token 预算和 deadline 各不相同。单一固定 batch 往往会浪费 prefill 的并行性,同时拖慢 decode 的交互响应。

2. Prefill:用完整 prompt 换取一次性并行

设一个请求有 T 个新输入 token。prefill 的 Q/K/V 投影和 MLP 都可以按 [T, H] 的大矩阵处理;FlashAttention 类算法以分块方式计算 attention,避免显式写出完整 T×T 注意力矩阵。输入越长、同一轮被拼进来的新 token 越多,GEMM 越接近 GPU 喜欢的形状。

但 prefill 不是“免费并行”。长 prompt 会占用大量计算和 KV 写入带宽。若将一个百万 token 请求和大量短交互请求混在同一时间片,前者可把短请求的首 token 时间(TTFT)拖到不可接受。因此现代服务通常把 token budget、chunked prefill、优先级和 admission control 明确建模。

3. Decode:每步少算一点,却要反复读很多历史

decode 时,单请求每层只有一个新 query。该 query 仍要对所有可见历史 KV 做 attention,随后穿过 MLP/MoE。新 token 的计算量相对小,但权重与 KV 的读入难以通过一个大矩阵完全摊薄。多个请求共同 decode 能增加 batch 维并提高利用率,可是 batch 过大又会延长每一轮的调度周期,使每个用户等待更久。

一次 decode step 的关键路径: 读本层权重 → 当前 token Q/K/V → 读取历史 KV pages → attention → MLP 或 MoE → logits → sampling → 新 KV 写入 重复 L 层,并对所有 active sequences 同步推进。

交互式服务要在两个方向之间取舍:更大的 sequence batch 有利于吞吐,更短的单轮执行有利于 ITL(inter-token latency)。引擎通常用每轮最大 token 数、最大 sequence 数、优先队列和 preemption 动态调节,不存在一个适合所有流量的固定 batch。

4. 三个服务指标必须分开看

TTFT 是从请求到第一个输出 token 的时间,主要包含排队、prefix lookup、预处理和 prefill。ITL 是相邻输出 token 的时间,主要反映 decode 调度、KV 读取、权重带宽和通信。端到端完成时间 还取决于输出长度、工具调用和取消。离线 benchmark 常报告 tokens/s,却可能把长 batch 的良好平均值误当成面向用户的体验。

任何报告都应写清 percentile。平均 TTFT 很好但 P99 很差,通常说明队列或长 prefill 的隔离失败;平均 ITL 很好但尾部抖动,常提示 KV 缺页、专家热点、网络拥塞或 GPU 时间片竞争。

5. 静态 batch 为什么不够

静态 batch 要等待一组请求一起到齐,然后每个成员以相同节奏运行。现实中,有人刚到,有人完成,有人生成 5 token,有人生成 5,000 token,还有人卡在工具调用。固定 batch 会在早完成成员空闲后仍保留槽位,也会让新到短请求等待慢成员。

continuous batching 每个 iteration 都重组活跃集合:已完成的请求离开,新请求进行 prefill 或加入 decode。它提升槽位利用率,但也带来资源会计问题:每个 sequence 的 KV page、长度、采样状态、adapter、工具上下文必须可独立挂起和恢复。

6. Chunked prefill:把长请求切成可以让路的工作

若长 prompt 一次性 prefill,GPU 会长时间服务它,decode 请求只能等待。chunked prefill 把 prompt 按 token chunk 切开,在若干 decode iteration 之间插入一部分 prefill token。它降低队头阻塞,但不是越细越好:chunk 太小会降低 GEMM 效率、增加调度开销;chunk 太大仍会劫持 TTFT。最合理的值依赖模型、GPU、KV 容量和流量分布。

整段 prefill

长 prompt 吞吐高,短交互可能被阻塞;适合离线或严格按批处理的场景。

分块 prefill

给 decode 留出节奏,TTFT 更可控;需要更精细 token budget 和公平性策略。

7. Prefix cache 改变的是“未命中 token 数”

多个请求若共享 system prompt、长文档前缀、代码仓库或 agent 的已知轨迹,服务端可以直接复用已有 KV,省去对应的 prefill。cache key 至少要包含模型版本、token 序列、位置/rope 配置、adapter、会影响 hidden state 的配置,以及多模态输入处理参数。命中后只计算最长有效前缀之后的部分。

prefix cache 并不减少 decode 的每步工作,也不是文本字符串缓存。tokenizer 版本、模板空格、图像预处理、LoRA 和 KV 精度不同都可能使“看起来相同”的请求不能安全共用。KV cache 页会展开 page table、引用计数和多层缓存。

8. 调度器究竟在决定什么

每个 iteration,调度器要选择:哪些 decode sequence 继续;给哪些请求分配 prefill token;是否抢占/换出某个低优先级 KV;是否将命中 cache 的请求路由到持有该 cache 的 worker;是否拒绝一个无法在 deadline 内完成的超长请求;以及 MoE/多模态模型的特殊资源是否可用。它的资源单位通常是 token 和 KV block,而非传统 Web 服务里的“一个连接”。

可观测的输入应包括队列年龄、剩余输出上限、已占 KV blocks、prefix 命中长度、模型/adapter、GPU/网络域、用户或租户优先级、取消概率和 deadline。没有这些字段,所谓“智能调度”只是在对请求数做粗糙排队。

9. 为什么要把 prefill 和 decode 分开部署

prefill 偏向大算子和长输入吞吐;decode 偏向低 ITL、较多活跃 KV 和稳定的小步进度。PD disaggregation 用不同 worker group 分别承担两段,再将生成的 KV 从 prefill worker 转交给 decode worker。好处是可以分别扩缩容、隔离长 prompt 干扰,并为不同硬件选择不同最优点。

KV 传输也可能很大。远端 transfer 较慢、协议不支持分块流式、缓存亲和性被破坏或调度器频繁迁移时,PD 分离只是把算力瓶颈换成了网络尾延迟。是否采用它要按负载和链路条件计算,详见 08 数据中心 KV 与 PD

10. Speculative decoding 与 MTP 如何进入生命周期

speculative decoding 让 draft model 或多 token prediction(MTP)先提出一段 token,target model 一次验证多个候选;被接受的 token 才写入最终状态。若接受率高,target 的关键路径可一次推进多 token,缓解逐 token decode 的串行性。接受率低时,额外 draft/验证工作可能吞掉收益。

它不取消 KV 的存在,反而要求更严格的临时状态管理:候选 token 的 KV 何时提交、何时回滚?不同 sequence 长度如何被连续 batch 容纳?MoE 模型的 draft 与 target 是否共享 tokenizer、rope、量化语义?GLM-5.2 与 Gemma 4 等 2026 公开资料中出现的 MTP 机制,应放在这个生命周期内理解,而不是只记一个“加速倍数”。

11. 一个混合流量的决策例子

假设队列里有:A,8K 文档问答;B,128K RAG 输入;C,持续输出的代码 agent;D,命中 120K prefix 的多轮客服;E,一张图和 1K 文本。五个请求不应平均分配资源。D 应路由到持有其 prefix blocks 的 worker,C 需要稳定的低 ITL decode 份额,B 可以拆成 chunks,E 要先经过视觉 encoder 并按实际视觉 token 计费,A 则可利用空档完成 prefill。调度目标还要计入尾延迟与 cache locality,不能只看 GPU 利用率。

12. 常见的错误归因

  • “GPU 利用率不高,所以加大 batch。”可能会压坏 ITL;先区分是 decode 带宽受限、通信受限还是调度没有填满 token budget。
  • “TTFT 高,所以模型慢。”也可能是排队、tokenize、多模态 encoder、prefix miss 或长 prefill 队头阻塞。
  • “cache 命中率高,所以成本低。”还要看命中 KV 是否在本地 HBM、是否因占用挤出更有价值的会话。
  • “PD 分离可扩展。”只有 KV transfer 与路由策略一起成立时才可扩展。

13. 来源与进一步阅读