一句话定义:PagedAttention(分页注意力)是一种把大模型推理时的 AI 词典:KV Cache">KV Cache(Key-Value Cache,键值缓存)切成固定大小的"块"、按需分配、逻辑上连续而物理上可以不连续的注意力计算方法,由 vLLM 项目提出并开源实现。
它要解决什么问题
大模型是逐字生成文本的:每吐出一个新 token,都要回头"看"一遍前面所有 token。如果每次都重算,代价随长度平方增长,所以工程上会把历史 token 的 Key 和 Value 张量缓存下来,这就是 KV Cache。它随序列变长线性膨胀,在长上下文场景里往往比模型权重本身更吃显存。
麻烦在于:一个请求最终会生成多长,事前没人知道。传统实现只能按模型支持的最大长度,为每个请求预留一整块连续显存。这就像请客不知道来几个人,餐厅却要求你先订一张一百人的连排大桌——人没来,桌子也不能给别人用。
由此产生三类浪费:订了没坐满的(内部碎片);请求长短不一,结束后留下大小不一的空洞,拼不回大块连续区域(外部碎片);多个请求明明有相同的开头(同一段系统提示词),却各存一份缓存。
它怎么解决
思路直接借鉴操作系统的虚拟内存分页。操作系统不让进程直接占用连续物理内存,而是把物理内存切成固定大小的页框,用页表把进程看到的"逻辑页"映射到散落各处的物理页框。
PagedAttention 做的是同一件事:把 KV Cache 按固定长度切块(例如每块装若干 token 的 K/V),每个序列维护一张 block table(块表),记录"我的第 3 个逻辑块,实际放在物理块 17 上"。生成新 token 时才申请新块,序列结束时块立刻归还。于是碎片被压缩到每个序列最后一个没填满的块里,浪费量级从"最大长度的倍数"降到"一个块以内"。
额外的好处是共享:并行采样、beam search,或者一批请求用了同一段系统提示词,它们的块表可以直接指向同一批物理块,配合引用计数与写时复制,相同前缀只存一份、只算一次。
代价是 attention 的计算内核要按块表去"收集"不连续的 K/V,实现更复杂。这也是为什么分页注意力通常需要专门优化的 kernel。
| 概念 | 主要省什么 | 与 PagedAttention 的关系 |
|---|---|---|
| KV Cache 量化 | 每个缓存元素占几个字节 | 正交,可叠加:一个省"单块大小",一个省"布局浪费" |
| FlashAttention | 计算时不落地巨大的注意力分数矩阵,减少显存读写 | 优化计算内核,不改变缓存的分配方式 |
| 连续批处理 continuous batching | 每一步让哪些序列参与计算 | 调度层优化,与分页的显存层互补 |
| 前缀缓存 prefix caching | 相同前缀只计算、只存储一次 | 通常建立在分页之上,靠块共享实现 |
对实际工作的意义
对做推理服务的人,这是一次"内存管理思维"的引入:显存不再是一块块要提前切好的蛋糕,而是可以按需分发回收的池子。同样一张卡能同时容纳的并发序列变多,GPU 算力更容易被喂饱,吞吐随之提升;长上下文请求也变得更实用。调服务参数时遇到的"最大并发序列数""显存占用比例"之类选项,背后往往就是分页这套账。具体某个框架支持到什么程度、参数怎么命名,以官方文档为准。
对普通职场人,可以把它理解成"共享单车代替一人一辆自行车":资源不预留给某个人,谁用谁扫码,用完就还,整体能服务的人自然多得多。你感受到的是 AI 应用响应更快、长文档处理更顺,而账单结构的变化发生在看不见的显存层。
