每生成一个字都要把全部权重读一遍:从 vLLM 看 LLM 推理提速
生成一个字为何这么慢?先把「慢」拆成三层
你有没有好奇过:同样是大模型,训练时一跑好几天没人嫌慢,部署上线后用户却在等每一句话的第一个字。这口气慢在哪,正是本专题的出发点。要回答它,得先看清生成这件事的形态。
大模型写回答是自回归的:一次只吐一个 token(可以粗略理解成一个词或半个词),而且后一个 token 的生成依赖前面已经生成的全部内容,没法并行。传统 serving 系统把一次请求切成两段:prefill 阶段一次吃进整个 prompt,算出所有位置的 key 和 value,这一段是纯粹的计算密集型;之后进入 decode 阶段,逐个生成新 token。麻烦就在 decode 这一段。
GPU 上有两种资源永远在抢时间:算力(每秒能算多少次乘加)和显存带宽(每秒能从显存搬多少字节)。现代 GPU 的算力超出显存带宽约两个数量级,也就是说,只要一个任务「搬运多、计算少」,它就根本喂不饱算力。decode 正是这种任务。每生成一个新 token,网络只对这个 token 做前向计算,计算量很小,却必须把模型的全部权重从显存里过一遍。权重是模型参数,也就是一张巨大的查找表,13B 参数按 FP16 存就是 26GB。你可以想象成每次要查一个字,就得把整本字典从头翻到尾,翻书的时间远大于认字的时间。PagedAttention 论文把这一点说得很直接:逐 token 串行生成使负载变成 memory-bound,GPU 算力被大量闲置,吞吐被显存带宽卡死PagedAttention。
有心的读者会问:每步都要重新算一遍前面所有 token 的 K/V 吗?2019 年 Shazeer 的论文给出了最早的解法:把上一步算好的 key、value 缓存下来,下一步直接拼接复用,这就是 KV Cache 的雏形。论文还做了带宽分析:增量解码时每生成一个 token 都要把已算好的 K/V 张量重载一遍,内存访问与运算的比值接近 1,解码受带宽而非算力限制。作为对策,multi-query attention(MQA,所有头共享同一套 K/V)压缩写头维度来省带宽,这是带宽优化的早期形态;后来的 grouped-query attention(GQA,若干头共享一组 K/V)是它的折中,Llama 系模型多采用MQA。
缓存换来了时间,却把显存推成了新的瓶颈。KV Cache 的大小随序列长度和 batch 线性增长,论文给出一个直观的算例:OPT-13B 每个 token 的 KV cache 要占 800KB(2×5120 隐藏维×40 层×2 字节 FP16),一个最长 2048 token 的请求就是 1.6GB,即便把整块显存都给 KV cache,也只装得下几十个请求PagedAttention。
到这里,「慢」已经被拆成了三本独立的账:
| 账本 | 症状 | 根因 |
|---|---|---|
| 计算利用率 | 算力闲置,GPU 用不满 | decode 每步只算一个 token,并行度低 |
| 显存带宽 | 每步都像「翻整本字典」 | 权重与 KV 都要从显存搬一遍,搬运时间主导 |
| 显存占用 | 请求一多就装不下、要排队 | KV Cache 随序列与并发线性膨胀 |
这三本账最终汇成两个互相打架的指标:吞吐(单位时间完成多少请求)和延迟(单个请求从发出到收完要等多久)。后面每一章的技术,本质上都是在问同一个问题:它治的是哪一本账,代价又是什么。
对症下药:哪项优化技术治哪一层瓶颈?
三本账各有一味药,而且它们互相兼容、不互斥。先把对照关系摆出来:KV Cache 免掉重复计算,治的是「算力浪费在重算上」;连续批处理喂饱 GPU,治的是「算力闲置」;投机解码压掉串行步数,治的是「每步都要等一次前向」的延迟。
先看连续批处理,它是批处理维度的解药。传统 serving 按请求粒度调度:一批请求同时进来、整批跑完才放下一批,批内先完成的请求只能干等,新到的请求也要排长队。Orca 在 2022 年把调度粒度从「请求」下沉到「单次迭代」:调度器每一轮只做三件事,从请求池里挑下一轮要跑的请求集合,让执行引擎对它们各跑一次模型前向,再接收本轮新增的输出 token 并更新进度。粒度一下沉,早完成的请求当轮就能返回,新请求也能搭上正在运行那批的顺风车Orca。
为什么不能干脆把进度各异的请求强行塞进同一个 batch?Orca 给出了 selective batching 的论证:Attention 的 K/V 张量形状随已处理 token 数变化,进度不同的请求拼不成同形状的张量;而且注意力算子不关联任何模型参数,对它做 batch 并不能靠「复用加载进来的权重」省显存读取。所以做法是只对 Transformer 其余算子(QKV 投影、输出投影等)保持批处理,Attention 逐个请求独立执行。示意图如下:
图注:按 Orca 论文 Figure 4 的组件与流程重绘的迭代级调度工作流。注意 Scheduler 到 Execution Engine 的调度发生在每一次迭代,而不是每完成一个请求,这正是「连续批处理」与静态批处理的本质区别。示意重绘图。
再来看延迟维度的解药:投机解码。它治的是串行本身。思路很反直觉:与其让大模型老老实实一次生成一个 token,不如先让一个又小又快的草稿模型一口气猜出接下来 γ 个 token,再让大模型并行校验这些猜测。大模型只串行跑一次前向,就能同时验证 γ+1 个位置,猜中的 token 直接白赚Speculative Decoding。

图注:投机解码一次迭代的完整过程。每行是一次迭代:绿色 token 是被大模型接受的草稿建议,红色是被拒绝的建议,蓝色是拒绝后重新采样出的纠正 token。第一行里大模型只跑了一次前向,却产出了 5 个 token。Speculative Decoding
这套框架能用多快,取决于两个数:接受率 α,即草稿 token 被大模型接受的平均概率;成本比 c,即草稿模型跑一步相对大模型跑一步的时间。在 i.i.d. 假设下,理论加速比是
$$\frac{1-\alpha^{\gamma+1}}{(1-\alpha)(\gamma c+1)}$$
直觉是 α 越大(猜得越准)加速越多,c 越小(草稿越便宜)加速越多。更妙的是投机采样保证输出分布与直接跑大模型完全一致,草稿猜错不改变结果质量,只是少赚几步,这正是它与蒸馏、量化这类近似加速的本质区别。论文在 T5-XXL 上实测加速约 2 到 3 倍(论文自报)。
这个框架到今天已经进化出很强的现代实现。EAGLE-3 是目前 vLLM、SGLang 等引擎集成的主要投机解码方案之一:它不再复用目标模型顶层特征做预测(那会限制草稿模型的表达力),改为直接预测 token,并把目标模型低、中、高三个层次的特征拼接降维成融合特征来指导草稿EAGLE-3。

图注:EAGLE-3 草稿模型的推理管线示意图。l、m、h 分别代表目标模型的低、中、高层特征,e 是 embedding,三者融合后指导草稿模型逐 token 生成候选。图只画机制,不含加速数值。EAGLE-3
到这里三味药都认领了自己的瓶颈。但细心的人会发现一处伏笔:连续批处理想让 batch 越大越好,可 batch 一加大,KV Cache 的显存占用就线性爆炸,批处理被显存挡住。能不能把显存这层浪费也连根拔掉?这就引出了全篇最深的那个杠杆。
KV Cache 又大又碎,为何不用操作系统分页的思路管它?
先看显存怎么被浪费。主流系统把每个请求的 KV Cache 当成一整块连续张量,按最大可能输出长度一次性预留,至少产生三类浪费:reserved,为最坏情况预留却用不完;internal fragmentation(内部碎片),块内分配了却没填满;external fragmentation(外部碎片),零散空洞凑不成连续显存给新请求。PagedAttention 论文的 profiling 显示,只有 20.4% 到 38.2% 的 KV cache 显存真正用于存放 token 状态,约六到八成被浪费(论文自报)PagedAttention。
这个问题的形状,操作系统早就遇到过。进程的地址空间也是「按最大可能长度预留一大块连续内存」,代价是同样的碎片化。虚拟内存的解法是分页:把内存切成固定大小的页,进程看到的是连续的虚拟地址,背后由页表映射到物理内存中任意位置、按需分配的物理页。PagedAttention 把同一套思想搬进了 KV Cache 管理:把每个序列的 KV cache 切成定长块(每个 block 装固定数量 token 的 K/V),允许这些块散落在物理显存的任意位置。下面的插画先把整套机制的三步走画给你看:

图注:PagedAttention 三步机制的教学插画。第一步「分块」,把请求不断增长的 KV cache 切成定长 KV blocks 而非一整块连续张量;第二步「映射」,经 block table 把逻辑块翻译到 GPU 显存池中任意位置的物理块;第三步「计算」,注意力 kernel 逐块读取非连续的 K/V 完成计算。
那逻辑块怎么找到自己的物理块?靠一张表。每个请求维护一张 block table,从左到右记录它的逻辑块序列,每个条目登记对应的物理块编号和块内已填充的位置数。这和操作系统的页表是同一个套路:把 blocks 看成 pages、tokens 看成 bytes、requests 看成 processes,逻辑上连续,物理上随意。

图注:vLLM 中的 block table 翻译过程。一个请求的逻辑 KV block 序列经 block table 映射到 GPU 物理内存中互不相邻的物理块,每个条目记录物理块编号与已填充位置数,无需为整条序列预留连续显存。PagedAttention
分块带来的第一层好处是按需分配:序列长到哪,块就分配到哪,reserved 浪费消失;最后一块填不满的部分只浪费在一个块内,内部碎片被限制在块粒度。第二层好处是共处:既然逻辑与物理解耦,多个请求完全可以各用各的逻辑块,却在同一片物理显存里错落排布,外部碎片随之消失,同样的显存能装下更多请求,batch 容量直接受益。
下面这张图把「两个请求在物理显存里共处」画了出来。两个序列的块同住一片物理空间,逻辑相邻的块在物理上完全不必相邻,这正是外部碎片被消除的样子:

图注:两个请求的 KV cache 同时存放在 vLLM 中。两个序列各自的逻辑块映射到共享物理空间里的不同物理块,逻辑相邻的块在物理内存中无需连续,物理空间被两个序列有效利用。此图展示的是共存与消碎片,不是共享同一物理块。PagedAttention
分块粒度怎么定是个权衡。块内多放几个 token,注意力 kernel 就能跨更多位置并行,硬件利用率更高、延迟更低;但块越大,内部碎片越多,两个请求共享同一物理块的概率也越小。论文的经验结论是 block size 取 16 左右,在多数负载下已经足够高效又不会造成明显碎片(论文自报)PagedAttention。
块式注意力本身也很好懂。query 到来时,kernel 不再假设 K/V 在内存里挨着,而是逐块取出 K_j、V_j 分块计算,公式上等价于把各物理块的内容按逻辑顺序拼起来再做注意力:
$$s_j = \frac{q^{\top} K_j}{\sqrt{d_k}}, \qquad o = \sum_j \text{softmax}(s)_j , V_j$$

图注:PagedAttention 块式注意力示意。query token 与散落在多个非连续物理块中的 key/value 做分块计算,每块先算注意力分数,再汇总得最终输出,物理存储位置不影响结果。PagedAttention
分页还有第三层更妙的好处,发生在解码算法想要「分叉」的时候。并行采样时多个输出序列共享同一个 prompt,beam search 时若干分支共享同一段前缀。没分页之前,每个序列都得把自己的 KV cache 完整拷一份,显存翻倍地烧。分页之后,一个物理块可以被多个逻辑块同时映射,于是给物理块加一个引用计数,多个序列要写同一个共享块时,才在块粒度触发 copy-on-write:拷贝旧块内容、把计数降回 1、再写入新值。只有真正分叉的那一个块需要拷贝。论文报告并行采样时 prompt 的 KV cache 占单请求总 KV 的约 12% 可以完全共享,beam search 场景最高能省约 55% 显存(论文自报)PagedAttention。
这套设计让 vLLM 相对 FasterTransformer、Orca 等系统把吞吐提升了 2 到 4 倍(论文自报)。但要诚实交代一句:这 2 到 4 倍来自系统整体的调度与显存收益,PagedAttention 的 kernel 本身相对高度优化的实现延迟还要高 20% 到 26%,是端到端的收益盖过了 kernel 的局部代价PagedAttention
不过,分页说到底只是一套算法。它如何被编排成一台真实引擎,让调度器知道每轮该放哪些请求、给谁分块,是下一章的问题。
分页只是算法:vLLM 如何把它编排成引擎?
vLLM 就是 PagedAttention 论文团队做出来的开源推理引擎,如今已经迭代到 V1 架构。这里必须先破除一个版本陷阱:你在很多旧教程里看到的 V0 机制,比如 prefill 与 decode 严格拆分的旧调度分工、GPU 与 CPU 之间的 KV cache 交换(swap)预占,在 V1 里都已弃用或移除;注意 max_num_batched_tokens 与 max_num_seqs 这两个参数在 V1 里仍然存在并继续使用——前者作为统一的 token 预算主控,后者作为并发序列数上限——真正被移弃的是 V0 把 prefill 与 decode 严格分开的那套旧分工语义,以及 GPU 与 CPU 间的 KV swap,并非这两个参数本身。本文按 V1 现状讲,这也是 vLLM 官方文档当前的状态vLLM 文档。
V1 调度器最核心的设计是统一 token 预算。旧调度器把 prefill 和 decode 严格分开,V1 则把 prompt token 与输出 token 一视同仁,用简单的字典 {request_id: num_tokens} 记录每个请求当轮分到的 token 数。调度器的 schedule() 每轮把可执行的请求排进队列,按预算分额度,再决定哪些请求被预占或完成。
图注:V1 请求生命周期与调度循环示意。请求经 API server 进入 engine core,调度器每轮按 token 预算决定执行集合,KV Cache Manager 负责分配物理块,GPU worker 执行前向并把新 token 回写;请求完成即返回,空间不足时请求被预占。
token 预算这套机制,让几个高级功能都变成默认行为。其一是 chunked prefill(分块 prefill):prefill 计算量大、decode 带宽受限,两者混在同一个 batch 里本来会互相拖累。V1 的调度策略是 decode 优先,先把所有待处理的 decode 排进去,剩下在预算内的空位才塞 prefill;排不进的 prefill 自动切成块,塞进后续轮次的空隙。这样 prefill 不再独占 GPU。其二是自动前缀缓存:如果新请求与已处理请求共享同一段前缀(比如反复查询同一篇长文档、多轮对话复用聊天历史),直接复用已缓存的 KV、跳过共享部分的 prefill 计算。注意前缀缓存只省 prefill,不省 decode,答案很长时收益有限vLLM 文档。
其三是预占规则的版本演进。显存不足时调度器要把某些请求的 KV 空间腾出来,等有空间了再恢复。V1 默认的预占方式是 RECOMPUTE,即之后重新计算被丢弃的 KV,而不是 V0 时代的 SWAP(把 KV 换到 CPU 内存再换回来)。V1 架构下重算比交换更便宜,所以 swap 功能被整体移除了vLLM 文档。
这套引擎跑在多进程架构上:API Server 处理 HTTP 与输入预处理;Engine Core 跑调度器、管 KV cache,每个数据并行 rank 一个;GPU Worker 每张 GPU 一个;数据并行时再加一个 DP Coordinator 做跨 rank 负载均衡。进程总数满足 A + DP + N,数据并行时加 1。单机 -tp=4 即 1 个 API server、1 个 engine core、4 个 GPU worker,共 6 个进程:
图注:vLLM V1 在张量并行 TP=4 单节点下的进程拓扑示意(进程数为文档文字事实)。API server 与 engine core 之间、engine core 与各 GPU worker 之间通过 ZMQ 通信。
CPU 核数是这里常被忽视的稀缺资源:最少需要 2 + N 个物理核(API server 1 个、engine core 1 个、每张 GPU 的 worker 1 个),engine core 是忙循环,特别怕 CPU 饥饿。核数欠配会直接拉低输入处理吞吐和调度延迟vLLM 文档。
机制讲完,落到代码上只有两个入口值得记住。调度器在 vllm/v1/core/sched/scheduler.py,主类是 Scheduler,核心方法就是 schedule(),配套的 _preempt_request、_select_waiting_queue_for_scheduling 一眼能看出职责;KV cache 的分配在 vllm/v1/core/kv_cache_manager.py,其中 KVCacheBlocks 数据结构正是调度器与 KV Cache Manager 之间的接口,把物理块的内部结构对调度器隐藏起来。上一章讲的 block table,在这里就是 KV Cache Manager 的职责底座vLLM 仓库。类名和路径会随版本演进,读代码时先 git pull 再按目录找,别把路径当永久契约。
机制都装进引擎了,那么部署时那些 --gpu-memory-utilization 之类的启动参数,到底在拧系统的哪个部位?
部署压测时那些参数旋钮,各自在拧系统的哪个部位?
调参不是玄学。vLLM 的启动参数几乎都能对回前几章的机制层,弄清每个旋钮连到哪根杆,压测就有章法。三个最常被动的参数如下(默认值来自当刻源码字段,以你 clone 的版本为准):
| 参数 | 控制的机制层 | 源码默认值 | 拧动的影响 |
|---|---|---|---|
gpu_memory_utilization | 第三章的分页池大小 | 0.92(CacheConfig) | 决定预留给 KV cache 的显存比例,其余留给权重与激活。调高减少预占,但会压榨模型权重的空间 |
max_num_batched_tokens | 第四章的 token 预算闸门 | 2048(SchedulerConfig) | 单次迭代最多处理的 token 数。调小 ITL 更好(prefill 少拖累 decode),调大 TTFT 更好(单批能吞更多 prefill),追求吞吐建议大于 8192 |
max_num_seqs | 同批序列数上限 | 128(SchedulerConfig) | 限制单次迭代最多几个序列并发,约束显存与调度的并发度 |
gpu_memory_utilization 管的是 KV cache 的预留:vLLM 按这个比例从整卡显存切出一块预分配给 KV cache 池,第三章的物理块都从池里取。调高它,池变大、预占变少,但如果模型权重加激活已经逼近显存上限,反而可能连模型都装不下,服务起不来。max_num_batched_tokens 是第四章 token 预算的闸门,取舍在延迟内部还有分工:调小让每个 decode token 的间隔(ITL,inter-token latency)更稳,因为 prefill 分块更碎、拖慢 decode 更少;调大让首 token 延迟(TTFT)更好,因为 prefill 不用等太多轮。想同时讨好两者,只能在负载上做取舍实验vLLM 文档。
这里要再强调一次版本差异:V0 里 max_num_seqs 和 max_num_batched_tokens 有严格分工,V0 弃用后,V1 用统一的 token 预算调度,max_num_batched_tokens 是主闸门。照抄旧教程的语义会调出错误结论。另外有两个约束校验值得知道:max_num_batched_tokens 小于 max_num_seqs 会直接报错;如果手动关掉 chunked prefill,max_num_batched_tokens 必须大于 max_model_len,否则启动崩溃vLLM 仓库。
压测入口也换了代。仓库里 benchmarks/benchmark_throughput.py 这些旧脚本如今都只是提示迁移的占位文件,官方主入口是 vllm bench 命令族:
vllm bench throughput --model <模型路径> # 纯吞吐:灌固定数量请求,测每秒完成数
vllm bench serve --model <模型路径> # 模拟服务:按请求率发流式请求,测 TTFT/ITL 等
vllm bench latency --model <模型路径> # 单请求延迟剖析
具体子命令的参数以 vllm bench --help 和当刻 stable 文档为准。前缀缓存对比则保留了独立脚本 benchmarks/benchmark_prefix_caching.py(可配 --enable-prefix-caching 开关)vLLM 仓库。
设计对照实验就一句话:固定模型和负载,一次只动一个参数,分别记录吞吐、TTFT 与 ITL,再对比。比如先跑基线 vllm bench serve,然后把 max_num_batched_tokens 从 2048 翻到 8192,看 TTFT 是否下降、ITL 是否变差;再把 gpu_memory_utilization 从 0.90 提到 0.95,观察预占计数(Prometheus 里有 total_cumulative_preemption_cnt 指标)是否减少。所有结论都要来自你机器上的实测,不同 GPU、不同模型的最优点差异很大,网上任何「通用最优参数」都只配当起点。
到这里,你已经能独立部署、压测、解释每个旋钮了。不妨退后一步问:学了这么多单点技术,它们在整个领域的地图上站在哪?前面又往哪走?
学完这些单点技术,它们在地图上站在哪里、前沿又往哪走?
2026 年 7 月,一篇系统视角的 KV cache 优化综述把整个领域收拢成了一张三维坐标系。它定义的研究范畴叫 sKis(system-aware KV infrastructure for serving LLMs):在推理期运行、以 KV cache 为主要优化目标、不重训权重也不改架构。全部 serve 期 KV 优化按系统行为的三个维度归位:执行与调度(temporal,时间维,解决何时访问与计算 KV)、放置与迁移(spatial,空间维,解决 KV 放到哪级存储、怎么搬)、表征与保留(structural,结构维,解决 KV 如何压缩表示、如何管理生命周期)KV Survey。

图注:综述的三维 taxonomy 示意图,把 serve 期 KV 优化组织为执行与调度(时间维)、放置与迁移(空间维)、表征与保留(结构维)三个维度,并标注各维子类与代表方法。分类示意图,不含性能数据。KV Survey
在这张坐标系里回望前文,会有种「原来如此」的感觉。PagedAttention 与 vLLM 的分页和块表落在「表征与保留」维度下的分配与复用,和 RadixAttention、vTensor 共享同一个格子;连续批处理(Orca)站在「执行与调度」维度;投机解码不直接改 KV 管理,而是靠减少串行前向次数来减少 KV 读写,属于旁路手段。你学到的不是孤立的 trick,而是一条技术线的不同截面。
坐标系也标出了两个活跃的前沿方向,正好对应 2026 年两个有代表性的工作。
第一个方向是调度还能怎么改进,代表是 LMetric。它研究的问题在单机之上:LLM 服务通常是一个集群、多个 serving 实例加一个全局路由,请求到达时路由到哪个实例。好路由要同时讨好两个目标:路由到 KV cache 命中率高的实例(省 prefill 计算),以及各实例负载均衡。这两个目标互相牵制,过度追命中会让请求扎堆到热点实例。既有方案都有各自的痛点:
| 组合方式 | 机制 | 痛点 |
|---|---|---|
| 线性加权和 | KV 指标与负载指标加权求和打分 | 最优权重随工作负载漂移,需要反复试参 |
| 过滤式 | 先按阈值滤掉过载实例,再挑 KV 命中最高者 | 阈值依赖负载,一旦失衡就完全放弃 KV 感知 |
| 仿真式 | 用模拟器预测各实例 TTFT 再选择 | 每个模型加硬件都要造并调准一个模拟器 |
| 乘法 | 两个指标直接相乘,路由到乘积最小的实例 | 论文认为没有明显缺点,极端热点有检测兜底 |
LMetric 的观察是:把精心挑选的两个指标相乘,比较实例时线性组合里的超参数会自然消去,于是不需要调参。两个指标一个是 P-token,即把请求路由到某实例所需的新增 prefill token 数,它把排队中的 prefill 也算了进去;另一个是 BS,即该实例当前的 batch size,正好反映 decode 负载。打分就是
$$\text{score}(i) = \text{P-token}(i) \times \text{BS}(i)$$
路由到乘积最小的实例。论文报告相对 vLLM-v1 的负载均衡基线,真实负载下 TTFT 减少 92%、TPOT 减少 24%,对比阿里 Bailian 生产调度分别减少 39% 和 51%(均为论文自报)LMetric。
第二个方向是 KV 还能放在哪,代表是 ContiguousKV。它把战场从 GPU 显存内部挪到了存储层级:当大量请求共享同一段长前缀(RAG、多轮对话、长文档问答),系统可以把前缀的 KV cache 预先算好存进 CPU 内存甚至 SSD,新请求只需把它读回来再做注意力、生成首 token。这段「读回 + 计算首 token」的阶段论文称为 Re-Prefill,它同时是计算密集和 I/O 密集的:每一层的 KV 必须完整加载完才能开始该层计算,形成层内串行依赖,I/O 与计算交替空转。更糟的是粒度错配:语义级剪枝算法按细粒度挑重要 token,offloading 系统却按粗粒度定长块管理 I/O,结果为了几 KB 有用的 KV 要读整个几 MB 的块,多数请求遭遇约 12 倍的读放大,极端情况高达 25 到 56 倍(论文自报)ContiguousKV。
ContiguousKV 的解法是把重要性打分、存储组织、缓存管理、I/O 预取的粒度全部统一到同一个单元 ContiguousChunk,再用相邻层的「重要块索引」高度相似这一观察做两级异步预取,让 I/O 与逐层计算流水重叠:

图注:ContiguousKV 系统架构总览。KV cache 分三层存放于 GPU Cache、CPU Cache 与 SSDs/Disks,三个设计组件(Contiguous Chunking 统一粒度、Reuse-aware Prefetching 两级异步预取、Attention-guided Cache 缓存管理)协同工作。黑白线框图,不含量化数值。ContiguousKV
论文在 5% KV budget 下相对当时的 offloading 系统 IMPRESS 平均把 TTFT 加速 3.85 倍(论文自报,baseline 为作者按论文重实现)ContiguousKV
这两个 2026 年的工作正好是综述开放挑战里两条可动手的路:LMetric 属于集群级调度打分,对应「执行与调度」维度的改进;ContiguousKV 属于离屏存储与 I/O 流水,对应「放置与迁移」维度。想做科研,可以从综述的开放挑战里挑一条,比如把 SLO 违规归因到具体 KV 行为,或给 KV 逐出加可信性约束。训练侧显存优化与更大规模集群调度是这条学习路径地图上的相邻区块,本专题不展开,坐标系已给你指了方向:先吃透单机引擎的调度与 KV 管理,再沿两个维度向外走。
回望全篇:推理慢是三本账,KV Cache、连续批处理、投机解码各治一层;PagedAttention 用分页把显存浪费连根拔起;vLLM V1 用统一 token 预算把它编排成引擎;压测时每个参数都对应一个机制层;最后,一张 2026 年的坐标系告诉你这一切站在哪里、路往哪走。下一次再有人问你「vLLM 为什么快」,你可以从那一句开始回答:因为每生成一个字都要把全部权重读一遍,而它想办法让每一次读取都物尽其用。
参考文献
本专题引用的核心资料如下,建议深入学习时阅读原文:
- Efficient Memory Management for Large Language Model Serving with PagedAttention — arXiv:2309.06180
- Orca: A Distributed Serving System for Transformer-Based Generative Models — USENIX OSDI '22
- Towards Efficient Large Language Model Serving: A Survey on System-Aware KV Cache Optimization — arXiv:2607.08057
- EAGLE-3: Scaling up Inference Acceleration of Large Language Models via Training-Time Test — arXiv:2503.01840
- Fast Transformer Decoding: One Write-Head is All You Need — arXiv:1911.02150
- vLLM Official Documentation(Architecture Overview / V1 Scheduler / Paged Attention / Optimization and Tuning) — https://docs.vllm.ai/en/stable/
- vLLM GitHub Repository(scheduler / KV cache manager / benchmarks) — https://github.com/vllm-project/vllm
- LMetric: Simple is Better: Multiplication May Be All You Need for LLM Request Scheduling — arXiv:2603.15202
- Fast Inference from Transformers via Speculative Decoding — arXiv:2211.17192
- ContiguousKV: Accelerating LLM Prefill with Granularity-Aligned KV Cache Management — arXiv:2601.13631