本文整理自 Avi Chawla 的 X Article《KV Caching in LLMs, Clearly Explained》
你在使用 ChatGPT、Claude 或任何流式大模型时,应该都见过这个现象:第一个 token 往往等得更久,但一旦开始输出,后面的 token 会像流水一样连续冒出来。
这不是魔法,也不是 UI 动画。背后是一个非常关键的推理工程设计:KV Cache。它的目标很直接:减少自回归生成里的重复计算,让 LLM inference 更快。
先看一张直观对比:没有 KV Cache 时,模型每一步都在重复算历史 token;有 KV Cache 后,历史 token 的 Key/Value 会被存起来,新一步只处理最新 token。

有无 KV Cache 的推理路径对比:核心差异是历史 K/V 是否被复用。 (原文为动态演示,可查看原动画。)
下面从第一性原理拆开看。
1. LLM 是怎么一个 token 一个 token 生成的?
Transformer 会处理输入序列里的所有 token,并为每个 token 生成 hidden state。随后 hidden state 被投影到词表空间,得到 logits,也就是"下一个词可能是什么"的分数。
但这里有一个关键点:真正用于采样下一个 token 的,只有最后一个 token 对应的 logits。

Transformer 会为每个位置产生 logits,但生成下一步时只使用最后一个位置。 (原文为动态演示,可查看原动画。)
模型从最后一个位置的 logits 里采样出下一个 token,把它追加到输入序列末尾,然后重复同样过程。

采样、追加、再推理:自回归生成就是这样一步步滚动起来的。 (原文为动态演示,可查看原动画。)
所以第一条关键洞察是:为了生成下一个 token,我们只需要最新位置的 hidden state;其他位置的 hidden state 主要是中间产物。
2. Attention 实际上在算什么?
在 Transformer 的每一层里,每个 token 都会被投影成三组向量:
- Query(Q):我在找什么;
- Key(K):我提供什么索引;
- Value(V):我真正携带的信息。
Attention 会用 Query 和 Key 做相似度计算,得到注意力分数,然后用这些分数去加权 Value。

Attention 的核心:Q 与 K 计算权重,再加权 V 得到输出。 (原文为动态演示,可查看原动画。)
现在只盯住最后一个 token。因为我们只需要最后一个位置的 hidden state,所以在注意力矩阵里,我们真正关心的是最后一行。

最后一个 token 的注意力行:它的 Query 要和所有历史 Key 交互。 (原文为动态演示,可查看原动画。)
最后一行的计算需要:
- 最新 token 的 Query;
- 序列里所有 token 的 Key;
- 序列里所有 token 的 Value。
也就是说:每一层为了算最新 token,都需要"最新 Q + 全量 K/V"。
3. 冗余到底在哪里?
假设正在生成第 50 个 token,模型需要 token 1 到 50 的 K/V。
下一步生成第 51 个 token 时,模型需要 token 1 到 51 的 K/V。
问题来了:**token 1 到 49 的 K/V 早就算过,而且不会变。**同样的输入、同样的权重、同样的输出。没有缓存时,模型每一步却都把它们重新计算一遍。

相邻生成步骤中,大量历史 K/V 完全相同,却会被重复计算。
这就是浪费:每一步都有 O(n) 的重复工作,整段生成累计下来就是 O(n²) 级别的冗余计算。
4. KV Cache 怎么修?
修法很朴素:既然历史 K/V 不变,那就存起来。
每生成一个新 token:
- 只为最新 token 计算 Q、K、V;
- 把新的 K/V 追加进 cache;
- 从 cache 里取出所有历史 K/V;
- 用最新 Q 去 attend 完整的 K/V cache。

KV Cache 的工作流:新 token 只新增一份 K/V,历史 K/V 直接从缓存读取。 (原文为动态演示,可查看原动画。)
这就是 KV Cache:每层、每步只新增一个 token 的 K/V,其余全部从显存里读。
注意,Attention 本身仍然要看完整上下文,因此它依然随序列长度增长;但昂贵的 K/V 投影不再被重复计算。换句话说,KV Cache 不是让上下文"免费",而是消掉了最不该重复的那部分计算。
5. 为什么第一个 token 慢?TTFT 的来源
现在就能解释开头那个现象了。
当你发送 prompt 时,模型要先完整处理整个输入,把每个 prompt token 在每一层里的 K/V 都算出来并写入 cache。这个阶段叫 prefill。
prefill 是一次请求里最重的计算阶段,所以你会感到第一个 token 出来前有明显等待。等 cache 建好后,后续每个 token 只需要处理最新位置,进入 decode 阶段,速度就会快很多。

TTFT 来自 prefill:先构建整段 prompt 的 KV Cache,之后 decode 才能快速流式输出。
这段首 token 延迟就是 Time-to-First-Token(TTFT)。prompt 越长,prefill 越重,TTFT 通常越高。
优化 TTFT 本身又是一大块工程:chunked prefill、speculative decoding、prompt caching 等技术都围绕这个问题展开。但底层动态始终一样:建 cache 贵,读 cache 便宜。
6. 代价:用显存换计算
KV Cache 的交易很清楚:用 GPU memory 换 compute。
每一层都要为每个 token 存 K 和 V。对于大模型和长上下文,这个 cache 会很夸张。原文举了 Qwen 2.5 72B 的例子:80 层、32K context、hidden dim 8192,单个请求的 KV Cache 就可能吃掉数 GB 显存。
如果同时服务几百个请求,KV Cache 的显存占用甚至可能超过模型权重本身。
这也是为什么很多推理优化技术都围绕 KV Cache 展开:
- GQA(Grouped-Query Attention):多个 Query head 共享更少的 Key/Value head;
- MQA(Multi-Query Attention):进一步让多个 Query head 共用同一组 K/V;
- PagedAttention:像操作系统分页一样管理 KV Cache,降低碎片和浪费;
- Prompt caching:复用相同 prompt 前缀对应的 cache,减少重复 prefill。
上下文长度翻倍不是简单把窗口开大。因为窗口越长,单请求 KV Cache 越大,同一张 GPU 上能并发服务的用户就越少。
tl;dr
KV Cache 的本质是:自回归生成中,历史 token 的 K/V 不会改变,所以不要每一步重算;算一次,存起来,后续复用。
每个新 token 只需要自己的 Q/K/V,然后用最新 Q 去 attend 完整的 K/V cache。

KV Cache 的结果:实践中可带来显著加速,但显存成为新的瓶颈。 (原文为动态演示,可查看原动画。)
工程上,KV Cache 是现代 LLM serving 的地基之一。vLLM、TGI、TensorRT-LLM 等推理栈都建立在这类思想之上。
一句话总结:**KV Cache 让 LLM 少做蠢事;但它把"算力瓶颈"换成了"显存瓶颈"。**这就是推理系统设计最经典的 trade-off。
原文链接:x.com/_avichawla/...