KV Cache 完全解析:大模型推理提速的第一功臣

KV Cache 完全解析:大模型推理提速的第一功臣 KV Cache 完全解析大模型推理提速的第一功臣上一篇《一次 LLM 推理的完整旅程》里反复出现一个词KV Cache。Prefill 阶段产出它Decode 阶段每一步都要读它显存被它吃掉大半PagedAttention、GQA、前缀缓存全都围着它转。这一篇就把它彻底讲透它缓存的到底是什么为什么只缓存 K 和 V、不缓存 Q它凭什么把推理速度提升一个数量级又为什么成了显存的头号杀手一、问题的起点自回归生成的重复计算Transformer 大模型生成文字是逐字预测的输入一句话 → 输出第 1 个 token把原文 刚输出的第 1 个 token 再喂进去 → 输出第 2 个 token循环直到结束。每一轮都要执行自注意力Self-Attention对所有历史 token 生成 Query、Key、Value 三组向量用 Q 和所有 K 做点积打分再用分数加权 V 得到输出。问题来了每生成一个新字都要把全部历史 token 的 K、V 从头重算一遍。生成第 100 个 token 时重算前 99 个的 K/V生成第 500 个时重算前 499 个——而这些值和上一轮算出来的一模一样。纯粹的重复劳动越往后越卡整段生成的注意力计算量随长度平方级增长。KV Cache 的思路简单到近乎理所当然算过的就存下来别再算了。每个新 token 只计算自己的 K、V追加进显存里的缓存历史 token 的 K、V 直接复用。一次乘法终身受益。就这一个改动推理速度提升几倍到十几倍成为所有线上大模型服务的必备优化——聊天机器人、代码补全、本地部署 LLM只要是自回归生成无一例外。二、先补底层Q、K、V 到底是什么要理解为什么只缓存 K 和 V得先弄清这三个向量各自的分工。从文字到向量每个 token 先被转换成固定维度的词嵌入向量embedding——一个代表语义的数字数组。模型内置三组独立的可训练权重矩阵WQW_QWQ​、WKW_KWK​、WVW_VWV​把嵌入矩阵XXX全部历史 token 打包分别投影成三套向量QXWQ,KXWK,VXWV Q X W_Q,\quad K X W_K,\quad V X W_VQXWQ​,KXWK​,VXWV​一次矩阵乘法每个 token 就有了自己的一组 (Q, K, V)。三者的分工一次数据库检索最直观的类比是数据库查询QQuery查询向量你的搜索关键词——代表当前正在计算的 token“我是谁我要找什么样的上下文”;KKey键向量数据库里每条记录的索引标签——每个历史 token 的特征摘要专门用来被 Q 匹配VValue值向量每条记录的完整正文——历史 token 携带的实际内容信息。检索流程拿关键词Q和所有索引K做内积打分 → 分数过 softmax 归一化成权重 → 按权重加权求和所有正文V→ 得到当前 token 的输出特征。一个具体例子上下文是「猫咪在窗边睡觉」当前要处理的词是它。它的 Q 和猫咪的 K 点积分数最高softmax 后猫咪的 V 占最大权重——模型由此知道它指代猫。K 负责打分匹配V 负责提供内容缺一不可、分工明确。走一遍完整流程上下文[我, 今天, 吃, 了, 草莓]预测下一个字5 个 token 转成嵌入矩阵 XX 分别乘WQW_QWQ​、WKW_KWK​、WVW_VWV​→ 各得 5 行 Q、K、V 向量取最后一个token「草莓」的 Q和 5 个 K 逐一算相似度相似度加权融合 5 个 V → 输出特征 → 采样出下一个字比如「很甜」。注意第 3 步真正被用到的 Q 只有最后一个 token 的。这是全文最关键的伏笔。三、为什么只缓存 K、V不缓存 Q自回归生成时我们只需要预测下一个token。查询的主体永远是最新的那一个 token——它的 Q 去匹配全部历史的 K 和 V。而历史 token 的 Q 呢它们在各自当过一次新 token时用过一次之后再也不会被任何计算引用。缓存它们没有任何意义。反观 K 和 V每个历史 token 的 K/V 在之后的每一步都要被新 token 的 Q 匹配、加权——它们才是被反复读取的资产。一句话Q 是一次性的查询请求K/V 是被反复查询的数据库。所以缓存叫 KV Cache而不是 QKV Cache。四、KV Cache 的工作流程把缓存机制套进生成过程对比一下没有 KV Cache以「我今天吃了草莓」→ 续写「很甜」为例生成「很」把 5 个历史 token 全部重新过一遍WKW_KWK​、WVW_VWV​再算注意力生成「甜」把 6 个 token含刚生成的「很」又全部重算一遍K/V每一步都从头来上下文越长每步越慢。有 KV CachePrefill 阶段5 个输入 token 一次并行算出 5 组 K/V存入显存缓存生成「很」只算「很」自己的 1 组 K/V追加进缓存注意力直接用缓存里的 6 组 K/V生成「甜」只算「甜」的 1 组复用前面 7 组历史 token 的 K/V 全程零重算。每一步的计算量从正比于上下文长度降到一个 token 的常数量整段生成的注意力计算从平方级降回线性级。补充多头注意力下也一样实际大模型用的是多头注意力Multi-Head Attention把WQ/WK/WVW_Q/W_K/W_VWQ​/WK​/WV​拆成多组独立的头每头各自生成一套 QKV、单独做匹配最后拼接融合——相当于多路并行检索捕捉更细粒度的语义关联。KV Cache 的逻辑完全不变只是每层要为每个头都存一份 K/V。这个每层 × 每头的乘法正是下一节显存账单的来源。五、天下没有免费的午餐显存账单KV Cache 的本质是用显存换算力。省下的计算实实在在付出的显存也实实在在。算一笔账每个 token 需要缓存的字节数 2×层数×KV头数×每头维度×每元素字节数 2 \times \text{层数} \times \text{KV头数} \times \text{每头维度} \times \text{每元素字节数}2×层数×KV头数×每头维度×每元素字节数开头的 2 K 和 V 各一份。以 Llama-3-70B 为例80 层 × 8 个 KV 头 × 128 维 × 2 字节FP16乘上 K 和 V 两份2×80×8×128×2≈327,680 字节≈320KB / token 2 \times 80 \times 8 \times 128 \times 2 \approx 327{,}680 \text{ 字节} \approx 320\text{KB / token}2×80×8×128×2≈327,680字节≈320KB / token一条 8K token 的对话 →约 2.6 GB显存只为这一条请求的缓存128K 长上下文 →约 40 GB——比很多整卡显存还大线上服务同时挂几十条并发KV Cache 轻松超过模型权重本身的占用。由此得出 KV Cache 的两大缺点显存占用随长度线性暴涨万字长文、超长对话很容易把显存顶爆OOM并发量直接受限于缓存能塞下多少越长越慢decode 每一步都要把整个缓存从显存读出来参与注意力计算上下文越长每步搬运的数据越多——这正是上一篇说的 memory-bound 瓶颈的一部分长对话越聊越慢的直接原因。六、围绕 KV Cache 的优化生态正因为 KV Cache 同时是速度的功臣和显存的杀手围绕它长出了一整套优化技术。按思路分四类1. 管得更好PagedAttention传统做法为每条请求预留一整段连续显存按最大长度预留实际用不满碎片浪费惊人。PagedAttention借鉴操作系统的内存分页把 KV Cache 切成固定大小的小块block按需分配、离散存放用页表记录逻辑顺序。显存碎片几乎归零同一张卡能塞下数倍的并发请求。这是 vLLM 的成名作如今 SGLang、TensorRT-LLM 等主流框架均已标配。2. 存得更小量化与结构压缩KV Cache 量化INT8/INT4K/V 张量从 FP16 降到低精度存储显存减半甚至减至 1/4精度损失轻微MQA / GQA / MLA从模型结构上砍 KV 头数——MQA 所有头共用一组 K/VGQA 分组共用Llama 系的选择70B 从 64 个 Q 头压到 8 个 KV 头缓存直接缩到 1/8DeepSeek 的 MLA 更进一步把 K/V 压成低秩隐向量。头数少了上面公式里的乘数就小了。3. 丢得聪明滑动窗口超长对话只保留最近 N 个 token的 K/V久远历史直接丢弃把显存占用钉在一个固定上限内Mistral 等模型采用。代价是模型记不住窗口之外的内容适合只依赖近期上下文的场景。4. 用得更值前缀缓存与投机解码Prefix Caching前缀缓存请求结束后不立即释放缓存相同前缀system prompt、多轮对话历史的下一条请求直接复用跳过大部分 prefill——API 厂商缓存命中的输入便宜 10 倍就是它投机解码Speculative Decoding小模型先猜几个 token、大模型一次并行验证验证过程同样离不开 KV Cache 的支撑进一步压低单 token 的生成耗时。七、总结把整篇压缩成五句话自回归生成会反复重算历史 token 的 K/VKV Cache 用算过就存把平方级计算降回线性只缓存 K/V 不缓存 Q因为 Q 是一次性的查询、K/V 是被每一步反复读取的数据库代价是显存随上下文线性暴涨70B 级模型约每 token 数百 KB长对话越聊越慢、越聊越占PagedAttention 管碎片、量化和 GQA/MLA 压体积、滑动窗口设上限、前缀缓存复用成果——现代推理引擎的半壁江山都在伺候这块缓存理解了 KV Cache就理解了大模型推理为什么快、为什么贵、以及优化的主战场在哪里。它可能是整个大模型推理栈里性价比最高的一个 idea一行存下来别重算的朴素直觉撑起了今天所有线上 LLM 服务的可用性。