← 返回题目列表

PagedAttention 的原理是什么?它如何降低 KV Cache 的内存浪费?

高频 中等 第 6 / 25 题 更新于 2026/07/25
PagedAttentionKV CachevLLM内存管理

简化版

PagedAttention(vLLM 提出) 借鉴操作系统的虚拟内存分页思想来管理 KV Cache:把每个请求的 KV Cache 切成固定大小的逻辑块,通过块表映射到不连续的物理显存块,按需分配、请求结束即回收。它消除了传统「为最大长度预留连续显存」造成的巨大浪费和外部碎片,还能让相同前缀的请求共享物理块。但它只解决分配和寻址问题,不压缩每个 token 本身的 KV 数据量——长上下文的 KV 总量该多大还是多大。

详细版

传统做法要求一个序列的 KV Cache 位于连续显存,但生成前不知道最终多长,只能按最大长度预留——短请求也占着大块空间,造成内部浪费;不同寿命的请求反复分配释放又产生外部碎片

PagedAttention 借鉴分页:逻辑上连续的 token 块,可以散布在物理块中,注意力内核通过块表找到对应的 K、V。生成新 token 时,只在当前块满了才申请下一个物理块。请求结束后归还物理块,其他请求立即复用。

代价:最后一个块可能有内部空闲(内部碎片),所以块大小是「元数据开销、内核效率、内部碎片」之间的取舍。分页解决的是分配和寻址;若上下文本身很长,KV Cache 仍按 token 数增长,要结合 GQA/MQA、量化、淘汰等。

完整版教学

一、传统连续分配浪费在哪:一个例子

问题的根源是「生成前不知道要多长,只能按最大预留」。假设最大上下文 2048,实际一个请求只生成了 100 token:

连续预留(传统):
  为该请求预留 2048 token 的连续显存
  实际只用 100 token → 浪费 1948 token 的空间(95% 空着!)
  且这块必须连续,找不到足够大的连续空闲就无法分配(外部碎片)

服务里有大量长短不一、寿命不同的请求,反复分配/释放会把显存切得七零八落,即使总空闲够、也凑不出一大块连续空间——这就是外部碎片,直接压低了能并发的请求数。

二、逻辑块与物理块:借鉴操作系统分页

PagedAttention 的解法和操作系统管理内存一模一样——分页

逻辑视角(连续):  [块0][块1][块2][块3] ← 一个请求的 KV,逻辑上连续
                      ↓ 块表映射 ↓
物理视角(分散):  物理块 #7, #2, #15, #9 ← 实际散落在显存各处
  • 每个逻辑块存固定数量 token(如 16 个)的 K、V;
  • 块表记录「逻辑块 → 物理块编号」的映射,物理块无需相邻
  • 生成新 token 时,只在当前块满了才申请下一个物理块(按需分配,不预留);
  • 请求结束,归还它的物理块,别的请求立即复用。

这样内部碎片只剩最后一个不满的块(最多浪费块大小-1 个 token),外部碎片被彻底消除——因为分配的单位是固定大小的块,永远能拼上。

三、注意力内核怎么读分散的 KV

传统注意力默认 K、V 连续存储、顺序读取。PagedAttention 的 K、V 散在不同物理块,所以内核要根据块表分段寻址、逐块读取再算注意力。这带来额外的寻址复杂度,所以收益依赖专门优化的 kernel——不是简单把张量切成一个 list 就行,而是要有配套的高效分页注意力内核(vLLM 提供)。这也是为什么它是一整套系统方案,而非一个小技巧。

四、块级共享与 Copy-on-Write

分页还带来一个额外红利——共享。相同 prompt、并行采样、Beam Search 的多个序列,前缀完全相同,它们的 KV 也相同,于是可以共享同一批只读物理块

请求A、B 有相同的 512-token 前缀:
  共享同样的 32 个物理块(只存一份,引用计数=2)
当某个分支要在共享块上继续写入时:
  触发 Copy-on-Write:复制出一个独立块再写,避免互相覆盖

这和操作系统进程 fork 的 COW 一模一样,能大幅节省重复前缀的显存(也是 Prefix Caching 的实现基础)。共享成立的前提:前缀 token 和所有影响 KV 的模型条件完全相同

五、它没有解决什么(重要边界)

必须清楚 PagedAttention 的能力边界,这是高频追问:

  • 不压缩 KV 数值:每个 token 的 K、V 数据量一点没变,它只是把「怎么分配和寻址」做好了。
  • 不改变注意力的数学结果:输出和连续存储完全一致。
  • 不降低长上下文的 KV 总量:模型层数、KV 头数、head_dim、数据类型、token 数仍然决定 KV Cache 的实际大小。

所以它主要提升的是内存利用率和并发数(把浪费的显存省出来装更多请求),而长上下文本身的 KV 压力要靠 GQA/MQA(减 KV 头)、KV 量化(减字节)、淘汰/换出等其他手段。

记忆钩子:PagedAttention 把 KV Cache 从”每个请求一整段连续显存、按最大预留”改成”逻辑连续、物理分页、按需分配、可共享”——它省的是浪费和碎片,不是 KV 数据本身。

六、和其他技术的配合

PagedAttention 是现代推理引擎(vLLM 等)的地基,和多项技术协同:

  • 连续批处理:变长 KV 的动态进出,靠分页高效分配;
  • Prefix Caching:跨请求共享前缀块,就是分页共享 + COW 的应用;
  • GQA/MQA、KV 量化:正交——它们减小每 token 的 KV,PagedAttention 管好这些 KV 的分配。

七、加强记忆

PagedAttention 记「KV 分页、按需分配、可共享」:借鉴操作系统虚拟内存,把 KV Cache 切成固定大小逻辑块、经块表映射到不连续物理块、用时才分配、完则回收、相同前缀块可 COW 共享,消灭了「按最大长度预留」的内部浪费和外部碎片,大幅提升内存利用率和并发。它只解决分配和寻址、不压缩 KV 数值、不改变注意力结果、不降低长上下文的 KV 总量——真实 KV 压力仍要靠 GQA/MQA、量化等。它是 vLLM 连续批处理和 Prefix Caching 的底层地基。