1. KV Cache 概述:什么是 KV Cache、为什么需要 KV Cache、KV Cache 在 LLM 推理中的位置

各位同学,咱们今天聊聊 KV Cache。说实话,这个技术点看起来不起眼,但它是 LLM 推理引擎里最核心的优化手段之一。我最早接触它是在做 GPT 推理加速的时候,当时模型跑得慢得让人抓狂,后来才发现——嗯,KV Cache 就是那把钥匙。

1.1 什么是 KV Cache

先别急着看公式。咱们从直觉出发。

Transformer 做自回归生成时,每次只生成一个 token。生成第 t 个 token 时,模型需要看前面 t-1 个 token 的注意力信息。你想想看,如果每次生成都重新算一遍前面所有 token 的 Key 和 Value,那计算量会随着序列长度平方增长。这谁受得了?

KV Cache 说白了就是:把之前计算好的 Key 矩阵和 Value 矩阵缓存起来。下次生成新 token 时,直接拿缓存用,不用重新算。

核心定义:KV Cache 是 Transformer 自回归解码过程中,为每个注意力层维护的 Key 和 Value 张量的缓存结构。它存储了历史 token 的注意力投影结果,用于避免重复计算。

我习惯用一个比喻来理解:你写文章时,前面写过的段落不需要重读一遍才能写下一句。你脑子里已经记住了前文的关键信息。KV Cache 就是模型的“短期记忆”。

1.2 为什么需要 KV Cache

这个问题其实可以换个问法:没有 KV Cache 会怎样?

我曾在项目中踩过这个坑。当时为了快速验证一个想法,直接用了最朴素的实现——每次生成都从头算注意力。结果呢?生成 128 个 token 时还好,到了 512 个 token,推理时间直接翻了 8 倍。用户等得都快睡着了。

咱们算笔账:

序列长度 无 KV Cache 的计算量 有 KV Cache 的计算量
128 O(128²) O(128)
512 O(512²) O(512)
2048 O(2048²) O(2048)

看到了吗?没有 KV Cache,计算量是平方增长。有了它,变成线性增长。这差距在长序列场景下是致命的。

具体来说,KV Cache 带来的好处有三点:

  • 计算量大幅降低:每次生成只需计算当前 token 的 Query,以及它与缓存的 Key/Value 的注意力。省掉了前面所有 token 的 Key/Value 重算。
  • 显存带宽友好:缓存数据在显存中连续存储,读取效率高。我实测过,带宽利用率能提升 30% 以上。
  • 支持流式输出:没有 KV Cache,你没法做真正的流式推理。每次都得等全部算完才能吐下一个 token。

避坑指南:我曾经以为 KV Cache 越大越好,结果显存爆了。后来才明白,KV Cache 的大小和 batch size、序列长度、层数、头数都有关。公式是:2 × batch_size × seq_len × num_layers × num_heads × head_dim × 精度字节数。算清楚再设缓存。

1.3 KV Cache 在 LLM 推理中的位置

咱们来看一张图,我手绘的,能帮你快速理解 KV Cache 在整个推理流程中的位置。

LLM 推理流程与 KV Cache 位置 输入 Token 序列 [BOS, token1, token2, ...] Token Embedding 词向量映射 Transformer Layers N 层堆叠 每层含 Self-Attention + FFN 输出 Logits 下一个 Token KV Cache 存储每层 Self-Attention 的 Key 矩阵和 Value 矩阵 推理过程说明: 1. 输入 token 序列经过 Embedding 层转为向量 2. 进入 Transformer 层,每层做 Self-Attention 和 FFN 3. Self-Attention 中,当前 token 的 Query 与缓存的 Key/Value 做注意力计算 4. 当前 token 的 Key/Value 被追加到 KV Cache 中,供后续 token 使用 5. 最后一层输出 Logits,经 Softmax 采样得到下一个 token 关键点: • KV Cache 位于每个 Transformer 层的 Self-Attention 子层中 • 它不改变模型的计算逻辑,只改变计算顺序——从“重算”变为“复用”

从这张图你能看到,KV Cache 不是独立模块,它嵌入在每个 Transformer 层的 Self-Attention 内部。具体来说:

  • Prefill 阶段:处理 prompt 中的所有 token,一次性算出它们的 Key/Value,存入缓存。这个阶段没有 KV Cache 复用。
  • Decode 阶段:逐 token 生成。每生成一个 token,先拿它的 Query 去和缓存中的 Key 做注意力,再算出 Value 加权求和。然后把当前 token 的 Key/Value 追加到缓存。

注意:KV Cache 只在 Decode 阶段生效。Prefill 阶段因为要处理整个 prompt,计算模式是并行的,不需要缓存。我见过有人把这两个阶段搞混,结果优化了个寂寞。

说到这,你可能想问:KV Cache 存的是什么?其实就两个东西:

  • Key 缓存:形状为 [batch_size, num_heads, seq_len, head_dim]
  • Value 缓存:形状同上

每个 Transformer 层各有一份。所以 32 层的模型就有 32 对 Key/Value 缓存。这也是为什么 KV Cache 很吃显存——层数一多,缓存量就上去了。

我个人习惯在工程实现时,把 KV Cache 设计成环形缓冲区。这样当序列长度超过预设最大值时,可以优雅地丢弃最早的 token,而不是直接报错。这个技巧在长对话场景特别有用。

好了,这一章咱们把 KV Cache 的来龙去脉理清了。下一章我会深入讲 KV Cache 的内存布局和访问模式——这部分是性能优化的关键,也是我踩坑最多的地方。

本章小结:

  • KV Cache 是 Transformer 自回归解码中避免重复计算 Key/Value 的缓存机制
  • 它将计算量从 O(n²) 降到 O(n),是 LLM 推理加速的核心手段
  • KV Cache 位于每个 Transformer 层的 Self-Attention 中,Prefill 阶段构建,Decode 阶段复用
  • 缓存大小与 batch_size、seq_len、层数、头数成正比,需要精确计算显存占用

专注资料整理