vLLM 0.25.0 解读:PagedAttention 退场,MRv2 接管

从 PagedAttention 论文、MRv2 默认化、Transformers backend 提速和 TLI speculative decoding,看 vLLM 0.25.0 为什么是一次执行路径收口。

vLLM 0.25.0 解读:PagedAttention 退场,MRv2 接管

vLLM v0.25.0 最值得读的不是某个新模型,而是一个工程转折:

早期核心卖点:PagedAttention 把 KV cache 当成分页内存来管理
现在核心主线:V1/MRv2 统一执行路径,后端按模型、硬件和场景选择更合适的 kernel

所以 release notes 里最有象征意味的两件事是:Model Runner V2 成为所有 dense models 的默认路径;PagedAttention legacy attention implementation 被删除。

这不是说 PagedAttention 的思想失败了。更准确地说:PagedAttention 作为 vLLM 早期论文和系统的关键突破,已经被吸收到更大的调度、KV cache、CUDA graph、speculative decoding、distributed serving 体系里;而早期自带的 paged_attention_v1/v2 kernel 和 Python wrapper,已经不再适合作为主执行路径。

1. 先回到 2023:PagedAttention 当初解决什么

LLM 推理不是一次性算完整段话。自回归生成每一步都会把历史 token 的 key/value 保存下来,后续 token 再拿这些 KV cache 做 attention。

KV cache 有三个麻烦:

  1. 大。vLLM 早期博客举过 LLaMA-13B 单序列 KV cache 可到 1.7GB 的例子。
  2. 动态。不同请求长度不同,生成过程还会继续增长。
  3. 会重复。parallel sampling、beam search、共享 prefix 的请求,前面一大段 KV 本来可以复用。

传统做法容易预留过多连续显存,或者因为碎片化浪费显存。vLLM 论文把这个问题换成操作系统的内存管理问题:把每个序列的逻辑 KV block 映射到不连续的物理 block。这样连续的 token 逻辑上连续,显存里可以不连续。

这就是 PagedAttention 的核心直觉:

sequence 像进程
token 像字节
KV block 像 page
block table 像页表

这带来两个收益:

  1. 只在需要时分配 block,减少碎片和预留浪费。
  2. 多个输出共享同一段 prompt KV,必要时 copy-on-write。

论文报告 vLLM 在同等延迟下相对 FasterTransformer、Orca 有 2-4 倍吞吐提升;官方早期博客也展示过相对 HuggingFace Transformers 最高 24 倍吞吐的服务基准。这就是 vLLM 成名的地方。

2. 那为什么 0.25.0 要删 PagedAttention

这里要分清两个东西:

PagedAttention 思想:分页式 KV cache 管理、block table、共享和复用
PagedAttention 旧实现:vLLM 早期自带的 paged_attention_v1/v2 attention kernel

v0.25.0 删除的是后者。PR #47361 的文件清单显示,它移除了:

  1. csrc/libtorch_stable/attention/paged_attention_v1.cu
  2. csrc/libtorch_stable/attention/paged_attention_v2.cu
  3. attention_kernels.cuh
  4. _custom_ops.py 里的 paged_attention_v1/v2 wrapper
  5. _C.paged_attention_v1/v2 的 torch binding

同时,测试和 benchmark 还保留并收窄到 ROCm paged attention kernel。这说明删除动作针对的是 CUDA/libtorch stable 旧 attention 路径,而不是把“分页管理 KV cache”这套系统设计从 vLLM 里抹掉。

我的理解是:vLLM 的性能中心已经从“一个通用 PagedAttention kernel”变成“统一执行框架调度多种后端”。release 里同时出现 FlashAttention、FlashInfer、MLA sparse、XQA、DFlash、CUDA graph、KV offloading、PD disaggregation,这些都不是 2023 年那条单线故事能容纳的复杂度。

3. 之前是什么样子

v0.25.0 之前,vLLM 正在迁移,但还没有完全收口。

迁移 issue #41286 写得很清楚:从 Model Runner v1 到 Model Runner v2 是分阶段推进的,先从 dense model 开始,例如 Qwen3-0.6B、OPT-125M,再到 MoE,例如 DeepSeek-V2-lite,最后覆盖更流行的大模型。

v0.24.0 已经让 MRv2 在 quantized models 上默认启用,但 v0.25.0 才把 dense models 作为整体切到 MRv2。PR #44443 的改动也能看出边界:

  1. runner_type != "generate" 不走默认 MRv2。
  2. hybrid model 不走默认 MRv2。
  3. attention-free model 不走默认 MRv2。
  4. dense generate model 默认可以走 MRv2。

所以“all dense models”不是“所有模型无条件切换”。它的意思是:在 dense causal generation 这条主力路径上,MRv2 不再是实验分支,而是默认路径。

以前的形态大概是这样:

flowchart LR
  A[Request] --> B[Scheduler]
  B --> C[ModelRunner v1]
  B --> D[ModelRunner v2 opt-in or partial default]
  C --> E[Legacy paged_attention_v1/v2]
  D --> F[V1/MRv2 backends]
  C --> G[Native vLLM model implementations]

v0.25.0 之后,主线更像这样:

flowchart LR
  A[Request] --> B[V1 Engine]
  B --> C[Model Runner V2]
  C --> D[Attention and hardware backends]
  C --> E[Speculative decoding]
  C --> F[KV cache and distributed serving]
  C --> G[Transformers modeling backend]

这就是“收口”:不是功能少了,而是默认路径少了。

4. 为什么必须这么做

如果 vLLM 只服务少数 LLaMA-like dense models,保留多套路径也许还能忍。但 v0.25.0 的 release notes 说明现实已经不是这样:

  1. 新模型包括 LLaVA-OneVision-2、Unlimited OCR、MOSS-Transcribe-Diarize、privacy-filter、Hy3。
  2. GLM-5 / DeepSeek-V3.2、MiniMax-M3、Gemma、Voxtral、Mamba、Whisper 都有专项修复。
  3. 硬件上覆盖 NVIDIA/Blackwell、AMD/ROCm、Intel XPU、CPU、RISC-V、POWER。
  4. 服务侧有 Rust frontend、DP supervisor、PD disaggregation、KV offloading、OpenAI compatibility、tool calling、reasoning parser。

这种复杂度下,旧路径的代价不只是多几行代码,而是:

  1. 每个 feature 都要问:v1 怎么办,v2 怎么办,legacy attention 怎么办,Transformers backend 怎么办。
  2. 每个硬件后端都要补 kernel、binding、benchmark、opcheck。
  3. 每个模型新增都可能重复写 native implementation。
  4. CUDA graph、async scheduling、speculative decoding、prefix caching 这些全局优化,很难在碎片化路径里保持一致。

PR #47187 很能说明后半段策略:Transformers modeling backend 通过 torch.fx 检测模型图,再用 AST 在实例上做原地编辑,把 q/k/v projection 融合成 QKVParallelLinear,把 MoE 接进 MoERunner,让 Transformers backend 在 dense、sliding attention、MoE 场景里达到 native vLLM 同级速度。PR 的 future work 也直接说,低中使用量模型可以迁到 Transformers backend,减少 vLLM 维护负担。

这背后的工程判断是:

高频核心路径:MRv2 + 深度优化 backend
长尾模型路径:Transformers backend 承接,少写 native 代码
旧 attention 路径:删除,降低分叉成本

5. TLI:这次 release 里真正“论文味”最重的一块

v0.25.0 还合入了 universal speculative decoding for heterogeneous vocabularies,也就是 PR #38174 里的 TLI。

先用人话说 speculative decoding:

小模型先草拟几个 token
大模型一次性验证这些 token
验证通过就多吐几个
验证不通过就回退到大模型分布

它的关键约束是“无损”:加速不能改变 target model 本来应该采样出的分布。

过去标准 speculative decoding 有一个很硬的前提:draft model 和 target model 要共用同一个 vocabulary。否则小模型吐出的 token id,在大模型词表里未必是同一个东西。结果就是 drafter 池子被限制在同一家族、同词表的小模型里,很多时候还得专门训练 drafter。

TLI 论文要解决的正是这个约束。它的做法很朴素,但工程价值很大:

  1. 启动时构建 draft 和 target 的 token 交集。
  2. draft model 只允许采样交集里的 token。
  3. 把 draft token id 映射成 target token id。
  4. 后面的 rejection sampling 仍按标准 speculative decoding 走。

这样做保留了 target 分布,因此是 lossless。论文里说异构词表方法最高能相对自回归解码达到 2.8 倍加速,其中 TLI 这条 token-level 方法最高到 1.7 倍。vLLM PR #38174 的功能测试也给了一个直观数字:Qwen2.5-1.5B 和 Qwen2.5-0.5B 的词表交集是 151665 / 151936,约 99.8%,平均接收长度 2.83 / 3。

这对 vLLM 的意义不是“又多一个算法”,而是扩大 speculative decoding 的可用面:

以前:最好找同词表、同家族 drafter
现在:只要词表交集足够好,更多 off-the-shelf 小模型都可能当 drafter

边界也很清楚:TLI 无损不等于必然更快。词表交集低、drafter 质量差、映射成本高、接受率低时,加速收益会被吃掉。

6. Streaming Parser Engine:前端也在收口

release 里还有一个容易被低估的点:New Streaming Parser Engine。

工具调用和 reasoning parser 看起来像 API 层功能,但在服务系统里它们已经不是简单字符串后处理。模型会一边流式输出,一边吐 reasoning token、tool name、JSON arguments、特殊结束标记。不同模型的格式又不一样,Kimi、DeepSeek、seed_oss、gpt-oss/Harmony 都有自己的边界情况。

如果每个 parser 都各写一套状态机,问题会越来越像早期 model runner:

功能重复
流式状态难复用
错误恢复不一致
OpenAI compatibility 难保持

所以 0.25.0 把 Kimi k2.5/k2.6/k2.7 parser、seed_oss、DeepSeek V4 等都往统一 streaming parser framework 里收。这和 MRv2 的逻辑相同:模型越来越多,格式越来越多,主框架必须减少分叉。

7. 我的结论

vLLM v0.25.0 可以读成一句话:

vLLM 开始删除自己的早期成名实现,把系统复杂度收束到 MRv2、Transformers backend 和统一前端解析框架上。

PagedAttention 仍然是 vLLM 历史上最重要的 idea。它解决了 LLM serving 早期最要命的 KV cache 显存浪费问题,也让“把 OS 内存管理思想搬进推理系统”成为大家都能理解的范式。

但成熟的工程项目不能永远围着第一篇论文转。2026 年的 vLLM 面对的是 MoE、MLA、Mamba/hybrid、multimodal、speculative decoding、CUDA graph、PD disaggregation、ROCm/XPU/CPU/RISC-V,以及越来越接近 OpenAI API 的前端语义。这个阶段最重要的能力不是守住单个 kernel,而是把执行路径统一到能承载这些变化的框架里。

所以这次“删除 PagedAttention”真正说明的是:

一个好 idea 的终点,不一定是它的原始实现永远留下。
更好的结局是:它改变了系统架构,然后原始实现可以被删除。

8. 继续追踪的点

  1. MRv2 对 MoE、hybrid、attention-free 模型的默认化进度。
  2. Transformers backend 是否真的能承接低中频模型,减少 native vLLM implementation 数量。
  3. TLI 在非同家族模型上的接受率、吞吐和映射开销。
  4. PagedAttention 删除后,各 attention backend 在长上下文、prefix cache、KV offloading 组合场景下的表现。
  5. Rust frontend 和 Python frontend 的功能边界会不会继续收口。

References