vLLM 为什么快?PagedAttention、continuous batching 解决什么?
谁在问:算法工程向面试官;自建推理集群的平台组、模型服务团队二面
口语化问法
- 你们自建用的什么推理引擎?vLLM 为什么比直接用 transformers 快那么多?
- PagedAttention 和 continuous batching 分别解决什么问题?这两个是一回事吗?
- 如果让你从零解释一下现代推理引擎的核心优化,你会怎么讲?
考察意图
面试官在判断三件事:
- 你是照着文档起了个服务,还是知道它在优化什么。 这道题的答案在网上到处都是,所以真正的区分度不在"能不能说出这两个词",而在能不能说清它们各自消灭的是哪一种浪费。
- 你报数字的时候有没有意识到口径。 "vLLM 快 24 倍"是一个被引烂了的数字,但它是跟裸 HuggingFace Transformers 比的。张口就报、不问跟谁比的人,等于承认没看过论文正文。
- 你的知识停在哪一年。 这是 2026 年这道题最有效的过滤器——continuous batching 和 PagedAttention 早已是所有引擎的地基,只夸这两件事说明知识停在 2023。
参考答案
60 分答案(及格线)
vLLM 快主要靠两个机制。
PagedAttention 借鉴了操作系统的虚拟内存分页。传统实现会给每条请求预留一整块连续显存,而且要按"它最多可能生成多长"来预留,导致大量显存被浪费掉。PagedAttention 把 KV Cache 切成固定大小的 block 按需分配,还能让共享前缀的请求指向同一批 block,大幅提高了显存利用率。显存省下来了,就能放更多并发请求,吞吐自然上去了。
continuous batching(连续批处理)解决的是批处理的等待问题。传统的静态批处理要等一整批请求全部生成完才能开始下一批,先完成的请求会白白占着坑位;连续批处理把调度粒度降到每一次迭代,谁生成完谁就退出,空出的位置立刻给新请求。
论文里说这两个优化加起来能带来最高 24 倍的吞吐提升。
为什么只有 60 分:机制描述是对的,比方也用对了,但有三个明显短板——一是报了 24 倍却没说跟谁比;二是没提这两个优化各自的适用边界(continuous batching 在输出长度整齐的负载上几乎没收益);三是知识停在 2023 年的论文,完全没有 2026 的现状。
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 了"是错的。
追问链
对方已经用了 TGI 或 SGLang,换 vLLM 还有多少收益?
期望直接答没有通用答案 —— 2026 年三家功能集已高度趋同,相对性能只取决于你自己的输入输出长度分布、并发度与 SLO。有区分度的是结构差异:SGLang 调度器按最长共享前缀重排请求,agent 多轮、长 system prompt 这类负载结构性占优信号拒绝报倍数、改成「得在你自己的负载上实测」并说得出三家结构性差异 → 真做过;直接给一个百分比 → 在编chunked prefill 的块大小你会怎么调?
期望它是跷跷板:max_num_batched_tokens调小(如 2048)吐字间隔更平滑但首字延迟变差,调大(超 8192)反过来。调法是先定 SLO 再调参:对话类往大调、长文流式阅读往小调,并配合 goodput 测 —— 单看吞吐或单看延迟都会调偏信号说出「先定 SLO 再调参」并把它和 goodput 挂钩 → 调过;只说「官方推荐 8192」→ 抄配置什么情况下你会考虑上 P/D 分离?什么情况明确不上?
期望核心是那句官方原话 —— P/D 分离不提升吞吐。上:首字延迟与吐字间隔各有独立 SLO 且互相打架、长输入短输出、两阶段要选不同并行策略。不上:集群小(两池空转盖过收益)、无高速互联(KV 跨实例传输成新瓶颈)、团队维护不了 P/D 路由信号把 P/D 分离说成「提升吞吐的优化」→ 没读过官方文档;说得出「先把 chunked prefill 调明白再考虑 P/D」→ 有判断投机解码你们上了吗?为什么?
期望判据只有一条 —— 负载是不是中低 QPS、是不是内存带宽受限。解码的算术强度约等于并发数,低并发下远低于临界值;并发一高解码变回卡算力,验证开销纯亏。代价还有两条:draft 模型或 EAGLE 头挤占 KV Cache 显存、接受率低即负收益 —— 要在真实流量上量接受率信号把「投机解码的边界」追溯到「解码算术强度约等于并发数」→ 真懂;只说「能加速解码所以上了」→ 听说过首字延迟达标但 P99 吐字间隔忽高忽低,只许改配置,怎么定位?
期望① 先按输入长度分桶 —— 只有和长请求同时段的受影响 = 长 prompt 预填充插队 → ② preemption 警告一出是显存不够,与调度参数无关 → ③ 第一刀调小max_num_batched_tokens:拿首字延迟换吐字平滑,先确认它的 SLO 有余量 → ④ 长文灰度 FP8 KV 腾并发 → ⑤ 超长请求单开队列(有用户可见代价)信号第一动作是「按输入长度分桶」而不是「调参数试试」→ 真排过障;把抢占警告和调度参数分开处理 → 知道显存瓶颈与调度瓶颈是两回事
PagedAttention 和 continuous batching 的,五层一层都接不住 —— 它们在 2026 已是地基。分水岭在第 3、4 层:P/D 分离与投机解码考的都是「什么情况明确不上」。评分要点
- 把两个机制拆成**"等"的浪费和"占"的浪费**,而不是并列复述
- 报任何倍数时主动说明跟谁比(24× 对裸 transformers / 3.5× 对 TGI / 1.7–2.7× 对 Orca)
- 说得出 continuous batching 的适用边界:收益取决于输出长度方差
- 知道这两件事在 2026 已是地基,能往下讲至少两项后续进展
- 知道 P/D 分离不提升吞吐,它买的是延迟可独立调节
- 知道投机解码只在中低 QPS 有效,并能追溯到算术强度这个原因
- 知道 chunked prefill 的
max_num_batched_tokens是首字延迟与吐字间隔的跷跷板 - (加分)知道 2026 年 vLLM 删掉了自己的 PagedAttention 内核,但分块 KV 机制仍在
- 谈引擎选型时拒绝报倍数,改成"取决于你的长度分布,得实测"