07. vLLM 为什么快?PagedAttention 的核心思路是什么?

整理 vLLM 的性能优势与 PagedAttention 的核心思路。

简单回答

vLLM 快的核心原因是 PagedAttention——借鉴操作系统虚拟内存分页管理的思想来管理 KV Cache。传统实现预分配连续显存给每个请求的最大可能序列长度,导致大量显存碎片和浪费。PagedAttention 把 KV Cache 分成固定大小的"页",按需分配、不必连续,大幅减少了显存浪费,使得同样的 GPU 能同时服务更多请求,直接提升吞吐量。结合 Continuous Batching,vLLM 的吞吐量比 HuggingFace Transformers 高 10~24 倍。

详细解释

传统 KV Cache 管理的问题

在传统的推理实现中,每来一个请求,系统需要为它预分配一块连续的显存来存放 KV Cache。问题是:在请求开始时,系统不知道这个请求最终会生成多少 token。为了保险,通常按最大序列长度(比如 4096 token)预分配。

这带来两个问题。内部碎片——如果实际生成只用了 200 token,剩下 3896 个 token 位置的显存全被浪费了。外部碎片——即使总剩余显存够,但因为被已分配的请求切割成不连续的小块,无法给新请求分配足够大的连续空间。

这两种碎片在实际部署中导致 KV Cache 的显存利用率通常只有 20%~40%。大量显存被浪费意味着能同时服务的请求数更少,吞吐量下降。

PagedAttention 怎么做

PagedAttention 的思路直接来自操作系统的虚拟内存管理。在操作系统中,进程看到的是连续的虚拟地址空间,但实际的物理内存是按固定大小的"页"(通常 4KB)分配的,虚拟页到物理页的映射由页表维护。

PagedAttention 对 KV Cache 做了同样的事情。KV Cache 被分成固定大小的"块"(block),每块存放固定数量 token 的 KV(比如 16 个 token 的 KV 为一块)。每个请求有一个"块表"(block table)记录它的 KV Cache 用了哪些块以及顺序。

新请求到来时不预分配最大长度的空间,而是生成一块就分配一块。一个请求如果生成了 200 个 token,只占用 个块。这些块在显存中不需要连续——通过块表记录逻辑顺序到物理位置的映射。

请求完成后释放其占用的块,这些块可以立刻被新请求复用。没有外部碎片(因为分配单位是固定大小的块),内部碎片也很小(最多浪费一个块中剩余的位置)。

KV Cache 共享

PagedAttention 的分页机制还天然支持 KV Cache 共享。如果多个请求共享相同的前缀(比如相同的 System Prompt),它们的 KV Cache 前缀部分可以共享同一组物理块,通过类似"写时复制"(Copy-on-Write)的机制——只有当某个请求的生成开始产生分化时,才为它分配新的块。

这对于 Beam Search 和 Parallel Sampling(同一个 Prompt 生成多个候选)特别有价值——多个候选共享 Prompt 的 KV Cache,只为各自不同的生成部分分配独立块。

vLLM 的其他优化

除了 PagedAttention,vLLM 还集成了 Continuous Batching(前面讲过的动态批处理)、高效的 CUDA kernel(优化的 Attention 计算、量化推理 kernel)、以及完善的调度器(管理请求优先级、抢占和恢复等)。

vLLM 的调度器在显存不足时会做抢占(preemption)——暂停低优先级请求、释放其 KV Cache 块、让高优先级请求先处理。被抢占的请求后续可以从检查点恢复或重新计算。

实际效果

根据 vLLM 的论文和实测,在相同硬件上 vLLM 的吞吐量比 HuggingFace Transformers 高 10~24 倍,比 TGI 高 2 ~ 4 倍。主要收益来自于 KV Cache 利用率的提升——同样的显存能同时服务更多请求。

面试时可以这样答

vLLM 快的核心在 PagedAttention。传统做法为每个请求预分配最大长度的连续显存放 KV Cache,导致大量内部碎片(实际用不了那么多)和外部碎片(空间不连续无法利用),显存利用率只有百分之二三十。

PagedAttention 借鉴操作系统的虚拟内存分页——把 KV Cache 分成固定大小的块,按需分配不必连续,通过块表维护逻辑到物理的映射。生成多少就分配多少块,请求结束立刻释放。内部碎片最多一个块,外部碎片几乎为零。KV Cache 利用率从二三十提升到九十以上。

这直接意味着同样的 GPU 能同时跑更多请求,吞吐量大幅提升。再加上 Continuous Batching 和高效 CUDA kernel,vLLM 比原生 HuggingFace 快十到二十多倍。

PagedAttention 还天然支持 KV Cache 共享——多个请求如果有相同的 Prompt 前缀,可以共享同一组物理块,进一步节省显存。这对 System Prompt 很长的场景特别有用。

常见追问

  1. PagedAttention 的块大小怎么选?对性能有什么影响?
  2. vLLM 的抢占机制具体怎么工作?
  3. PagedAttention 对 Attention 计算本身有性能开销吗?