第2章 KV Cache:模型内部的显存复用 章节摘要:本章跟着一条"成本回收"的线走。第 1 章算过,重复 Prefill 是推理里最贵的浪费——同样一段提示词被反复搬进算力流水线。本章往下钻一层,看模型怎么在显存里把已经付过的算力"存"回来。我们会从自回归生成天生的重复计算讲起,推导出 KV Cache 把单请求内的注意力从平方复杂度压成线性;再翻开显存账本,看清这笔缓存到底占多大地方;然后看 PagedAttention 把操作系统的页表思路搬进显存、把复用从单请求扩到请求之间,看 RadixAttention 用基数树把多轮对话的前缀组织成可命中的缓存;最后在显存见底时,走压缩三路把更多缓存塞进预算。
章节摘要:本章跟着一条"成本回收"的线走。第 1 章算过,重复 Prefill 是推理里最贵的浪费——同样一段提示词被反复搬进算力流水线。本章往下钻一层,看模型怎么在显存里把已经付过的算力"存"回来。我们会从自回归生成天生的重复计算讲起,推导出 KV Cache 把单请求内的注意力从平方复杂度压成线性;再翻开显存账本,看清这笔缓存到底占多大地方;然后看 PagedAttention 把操作系统的页表思路搬进显存、把复用从单请求扩到请求之间,看 RadixAttention 用基数树把多轮对话的前缀组织成可命中的缓存;最后在显存见底时,走压缩三路把更多缓存塞进预算。读完这一章,你手里就有一把算缓存账的尺子,能估算任意模型在任意上下文下的 KV 显存,也能判断一个服务该用哪种复用策略。
把全章串起来的是一句话:显存是缓存最大的成本项,复用是回收这笔成本的唯一手段。
第 1 章站在请求边界上看问题——同一个提示词被两个请求各算一遍,是边界外的浪费。本章把镜头推进到模型内部:即便只有一个请求,自回归生成本身也在反复重算已经算过的东西。KV Cache 的出现,本质上是用一块显存把"算过的注意力中间结果"钉住,下次直接取用。
这条线从最朴素的单请求内复用出发,逐步把复用的边界向外推:
每个站点都在回答同一个问题:怎么用更少的算力预付,回收更多的推理成本。
按推进顺序,本章五站各往前推一步:
| 站点 | 解决了什么 | 关键产出 |
|---|---|---|
| 2.1 自回归困境与 KV Cache 诞生 | 单请求内为什么要缓存、省了多少 | 注意力复杂度从平方到线性的推导,乘加次数模拟 |
| 2.2 KV Cache 显存账 | 这笔缓存到底占多大显存 | 显存公式与 7B/70B 在 4K/32K/128K 下的占用表 |
| 2.3 PagedAttention | 连续显存分配为什么浪费、怎么改 | 逻辑块/物理块/块表设计,碎片率量化 |
| 2.4 RadixAttention 与多轮命中 | 请求间前缀怎么组织才能命中 | 基数树管理 + 五轮对话命中轨迹复盘 |
| 2.5 KV Cache 压缩三路 | 显存不够时怎么减料 | GQA/MQA、量化、稀疏滑窗三路对比 |
全章的推进关系用一张图收一下:
从 B 到 E 都是模型和服务内部的显存复用,F 是下一章把这套机制搬出单机、做成按命中计费的平台能力。
全章最关键的认知转折发生在 2.2 末尾:上下文越长,KV Cache 比权重更容易成为显存瓶颈。
这个结论反直觉。多数人以为推理服务的显存主要被模型权重吃掉——毕竟 70B 的权重就要 140GB。但把公式摊开算,一个 7B 模型在 32K 上下文、FP16 精度下,KV Cache 已经和权重大致持平;推到 128K,KV Cache 是权重的近五倍。权重只随模型大小固定,KV Cache 却随上下文长度、并发数线性甚至超线性膨胀。所以"加显存为了跑更大的模型"这句话,在长上下文时代要改口成"加显存为了缓存更长的对话"。
这个拐点是后面所有设计的动机:PagedAttention 是为了让膨胀的缓存不浪费碎片,RadixAttention 是为了让膨胀的缓存能被更多请求分摊,压缩三路是为了让预算卡死时还能多装。
本章把复用锁死在单机显存里:缓存跟着进程走,进程一重启就没了,跨用户、跨时间、跨机器的复用都做不到。第 3 章要做的,是把这套"算力预付、缓存回收"的机制云化——变成平台级的、按命中计费的、跨请求持久的那一层。你可以把本章的 KV Cache 想象成"本地内存缓存",第 3 章把它升级成"分布式缓存服务"。理解本章的账本和碎片,才能看懂平台级缓存为什么值得做成一门生意。