vLLM 为什么快?PagedAttention、continuous batching 解决什么?

Q6-02推理引擎原理常见vLLMPagedAttentioncontinuous-batchingchunked-prefill推理优化吞吐与延迟

谁在问:算法工程向面试官;自建推理集群的平台组、模型服务团队二面

口语化问法

  • 你们自建用的什么推理引擎?vLLM 为什么比直接用 transformers 快那么多?
  • PagedAttention 和 continuous batching 分别解决什么问题?这两个是一回事吗?
  • 如果让你从零解释一下现代推理引擎的核心优化,你会怎么讲?

考察意图

面试官在判断三件事:

  1. 你是照着文档起了个服务,还是知道它在优化什么。 这道题的答案在网上到处都是,所以真正的区分度不在"能不能说出这两个词",而在能不能说清它们各自消灭的是哪一种浪费
  2. 你报数字的时候有没有意识到口径。 "vLLM 快 24 倍"是一个被引烂了的数字,但它是跟裸 HuggingFace Transformers 比的。张口就报、不问跟谁比的人,等于承认没看过论文正文。
  3. 你的知识停在哪一年。 这是 2026 年这道题最有效的过滤器——continuous batching 和 PagedAttention 早已是所有引擎的地基,只夸这两件事说明知识停在 2023。

参考答案

图 2 · 60 分与 90 分差在哪:代价、演进、怎么验证

60

60 分答案(及格线)

vLLM 快主要靠两个机制。

PagedAttention 借鉴了操作系统的虚拟内存分页。传统实现会给每条请求预留一整块连续显存,而且要按"它最多可能生成多长"来预留,导致大量显存被浪费掉。PagedAttention 把 KV Cache 切成固定大小的 block 按需分配,还能让共享前缀的请求指向同一批 block,大幅提高了显存利用率。显存省下来了,就能放更多并发请求,吞吐自然上去了。

continuous batching(连续批处理)解决的是批处理的等待问题。传统的静态批处理要等一整批请求全部生成完才能开始下一批,先完成的请求会白白占着坑位;连续批处理把调度粒度降到每一次迭代,谁生成完谁就退出,空出的位置立刻给新请求。

论文里说这两个优化加起来能带来最高 24 倍的吞吐提升。

为什么只有 60 分:机制描述是对的,比方也用对了,但有三个明显短板——一是报了 24 倍却没说跟谁比;二是没提这两个优化各自的适用边界(continuous batching 在输出长度整齐的负载上几乎没收益);三是知识停在 2023 年的论文,完全没有 2026 的现状。

90

90 分答案(有生产经验的回答)

我会先把它拆成两种不同的浪费,因为这两个机制解决的根本不是同一件事。

continuous batching 消灭的是"等"的浪费。 静态批处理像跟团游,一车人得等最慢的那位逛完才能一起走;连续批处理像急诊分诊,谁看完谁走,坑位立刻给下一个。它的源头是 Orca 那篇论文,机制是把调度粒度从"一次请求"降到"一次迭代",再配上选择性批处理绕开序列长度不齐的问题。

但这里有个必须说出来的条件:它的收益完全取决于输出长度的方差。经典测评里那个"约 8 倍"是在输出长度上限从 32 到 1536 的极端方差下测出来的;如果你的场景里所有请求输出长度都差不多(比如固定格式的分类任务),静态批处理本来也没浪费多少,换成连续批处理提升有限。

PagedAttention 消灭的是"占"的浪费。 论文测出当时的系统里真正存住 token 状态的显存只占 20% 到 38%,剩下的是三类:为未来生成预留的槽位、按最大长度分配的内部碎片、分配器造成的外部碎片。分页之后官方的说法是浪费降到 4% 以下。

报倍数之前一定要问"跟谁比",这是这道题最容易翻车的地方:跟裸 HuggingFace Transformers 比是最高 24 倍——但对方连 continuous batching 都没有;跟已经有 continuous batching 的 TGI 比是 3.5 倍;论文正文里跟 Orca 比只有 1.7 到 2.7 倍。能主动拆开"内存管理贡献了多少、批处理贡献了多少",比背住任何一个数字都值钱。

然后是 2026 的现状,这部分我觉得更重要。 这两个机制早就不是"优化项"了,是所有主流引擎的地基——vLLM、SGLang、TensorRT-LLM 三家都有。现在真正在动的是后面这几层:

  • chunked prefill:长 prompt 的预填充是个高延迟大算子,会插队打断正在解码的请求,造成尾延迟尖峰。切成固定大小的块跟解码请求混批,正好利用了"预填充卡算力、解码卡带宽"的互补性。代价是单请求的首字延迟会变长max_num_batched_tokens 是个真实的跷跷板:调小首字延迟差、吐字间隔好,调大反过来。
  • 前缀缓存:现在是默认开启的,因为命中率为 0 时吞吐损失也小于 1%。但分布式下真正的杀手是路由——负载均衡器把同前缀的请求打散到不同实例,缓存局部性就没了。
  • 投机解码:官方说得很明确,它只在中低 QPS、内存带宽受限的负载下有效。高 QPS 下解码已经变成卡算力了,多出来的验证开销就是纯亏。
  • 预填充与解码分离:这里有个必须记住的官方原话——它不提升吞吐。它买的是"首字延迟和吐字间隔可以独立调、尾延迟可控",卖的是 KV 跨实例传输带宽、额外一跳、两池资源利用率下降。而且 vLLM 内建的这块至今标着 experimental,真正生产化的是集群编排那一层。

还有一个反转值得一提(截至 2026-08):vLLM 在今年 7 月的一个版本里把自己那份 PagedAttention 的 CUDA 内核删掉了,因为 FlashAttention/FlashInfer 生态里的分页变体更快。但分块 KV 管理机制完全健在——block pool、KV cache manager、block table 全都在,只是改由上游注意力库消费 block table。准确的说法是:概念赢了并成了行业地基,那份专用内核输给了上游生态。 说"vLLM 不用 PagedAttention 了"是错的。

追问链

图 1 · 五层追问树:面试官会往哪儿挖
三家引擎功能已趋同 —— 追问全在问「这项优化的边界在哪」

  1. 对方已经用了 TGI 或 SGLang,换 vLLM 还有多少收益?

    期望直接答没有通用答案 —— 2026 年三家功能集已高度趋同,相对性能只取决于你自己的输入输出长度分布、并发度与 SLO。有区分度的是结构差异:SGLang 调度器按最长共享前缀重排请求,agent 多轮、长 system prompt 这类负载结构性占优
    信号拒绝报倍数、改成「得在你自己的负载上实测」并说得出三家结构性差异 → 真做过;直接给一个百分比 → 在编
  2. chunked prefill 的块大小你会怎么调?

    期望它是跷跷板max_num_batched_tokens 调小(如 2048)吐字间隔更平滑但首字延迟变差,调大(超 8192)反过来。调法是先定 SLO 再调参:对话类往大调、长文流式阅读往小调,并配合 goodput 测 —— 单看吞吐或单看延迟都会调偏
    信号说出「先定 SLO 再调参」并把它和 goodput 挂钩 → 调过;只说「官方推荐 8192」→ 抄配置
  3. 什么情况下你会考虑上 P/D 分离?什么情况明确不上?

    期望核心是那句官方原话 —— P/D 分离不提升吞吐。上:首字延迟与吐字间隔各有独立 SLO 且互相打架、长输入短输出、两阶段要选不同并行策略。不上:集群小(两池空转盖过收益)、无高速互联(KV 跨实例传输成新瓶颈)、团队维护不了 P/D 路由
    信号把 P/D 分离说成「提升吞吐的优化」→ 没读过官方文档;说得出「先把 chunked prefill 调明白再考虑 P/D」→ 有判断
  4. 投机解码你们上了吗?为什么?

    期望判据只有一条 —— 负载是不是中低 QPS、是不是内存带宽受限。解码的算术强度约等于并发数,低并发下远低于临界值;并发一高解码变回卡算力,验证开销纯亏。代价还有两条:draft 模型或 EAGLE 头挤占 KV Cache 显存、接受率低即负收益 —— 要在真实流量上量接受率
    信号把「投机解码的边界」追溯到「解码算术强度约等于并发数」→ 真懂;只说「能加速解码所以上了」→ 听说过
  5. 首字延迟达标但 P99 吐字间隔忽高忽低,只许改配置,怎么定位?

    期望先按输入长度分桶 —— 只有和长请求同时段的受影响 = 长 prompt 预填充插队 → ② preemption 警告一出是显存不够,与调度参数无关 → ③ 第一刀调小 max_num_batched_tokens拿首字延迟换吐字平滑,先确认它的 SLO 有余量 → ④ 长文灰度 FP8 KV 腾并发 → ⑤ 超长请求单开队列(有用户可见代价)
    信号第一动作是「按输入长度分桶」而不是「调参数试试」→ 真排过障;把抢占警告和调度参数分开处理 → 知道显存瓶颈与调度瓶颈是两回事
只夸 PagedAttentioncontinuous batching 的,五层一层都接不住 —— 它们在 2026 已是地基。分水岭在第 3、4 层:P/D 分离与投机解码考的都是「什么情况明确不上」。

评分要点

  1. 把两个机制拆成**"等"的浪费和"占"的浪费**,而不是并列复述
  2. 报任何倍数时主动说明跟谁比(24× 对裸 transformers / 3.5× 对 TGI / 1.7–2.7× 对 Orca)
  3. 说得出 continuous batching 的适用边界:收益取决于输出长度方差
  4. 知道这两件事在 2026 已是地基,能往下讲至少两项后续进展
  5. 知道 P/D 分离不提升吞吐,它买的是延迟可独立调节
  6. 知道投机解码只在中低 QPS 有效,并能追溯到算术强度这个原因
  7. 知道 chunked prefill 的 max_num_batched_tokens首字延迟与吐字间隔的跷跷板
  8. (加分)知道 2026 年 vLLM 删掉了自己的 PagedAttention 内核,但分块 KV 机制仍在
  9. 谈引擎选型时拒绝报倍数,改成"取决于你的长度分布,得实测"

常见错误

"vLLM 比 transformers 快 24 倍"——不问跟谁比。这是这道题最标志性的纸面回答。
把 PagedAttention 和 continuous batching 说成一回事,或者说"PagedAttention 就是把请求批起来"。
只夸这两个机制,讲不出任何 2023 年之后的进展。2026 年这等于宣布知识过期。
把 P/D 分离说成"提升吞吐的优化"——官方文档写的是它提升吞吐。
"TensorRT-LLM 的缺点是得提前 build engine、换模型要重编译"——这是 2023–2024 的认知,截至 2026-08 官方主推 PyTorch-native 路径。
含糊表述:"vLLM 做了很多显存和调度层面的优化,所以吞吐更高"——听着都对,问不出任何一个具体机制。
认为前缀缓存要按场景决定开不开。它在 vLLM V1 是默认开启的,命中率为 0 时吞吐损失也小于 1%;真正要操心的是分布式下的路由把缓存局部性打散。
把"引擎快"等同于"服务快"。用户感受到的延迟里还有网关缓冲、排队、检索——参见 T6-2 里 Pipeline TTFT 与 Model TTFT 的拆分。

关联学习