大模型推理:为什么只缓存 KV,不缓存 Q?

作者:

做过大模型推理优化的同学,应该都听过 KV Cache 这个概念。这里有一个问题:Attention 计算明明涉及 Q、K、V 三个矩阵,为什么只有 KV 需要缓存,Q 却被”抛弃”了?

这不是设计上的偷懒,而是由自回归生成的本质决定的。


自回归生成的时序特性

大模型生成文本的过程是一个 Token 接一个 Token 往外蹦的,这叫自回归(Autoregressive)。当大模型生成第 t 个 Token 时,需要”回头看”前面所有 0 到 t-1 个 Token,和它们做 Attention 计算。

自回归生成过程
自回归生成过程

这个过程中,Q 和 KV 承担的角色截然不同:

KV 是历史的累积。 前面每个 Token 的 Key 和 Value 在它出现的那一刻就算好了,而且数值永远不会变。到了第 t 步,这些历史 KV 还要被反复读取。如果不存起来,每生成一个新 Token 就得把前面所有 Token 的 KV 重算一遍——复杂度直接从 O(N) 爆炸到 O(N²)。

Q 是当下的查询。 生成第 t 个 Token 时,只有当前这个 Q 参与计算。算完这一步,Q 的使命就结束了。下一步生成 t+1 时,会产生一个全新的 Q,旧的 Q 完全不会再被用到。


从公式看数据流向

Attention 的核心公式:

$$\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d}}\right)V$$

Attention 计算数据流
Attention 计算数据流

在第 t 步推理时:

  • Q_t 的形状是 (1, d),只有一个向量——当前 Token
  • K_{0:t} 和 V_{0:t} 的形状是 (t, d),包含了从开头到当前的所有历史 Token

K 和 V 是”被查阅的资料库”,会随着序列变长不断膨胀,必须持久化存储;Q 是”查阅者”,用完即弃,缓存它对后续计算没有任何帮助。


如果强行缓存 Q 会怎样?

两个字:浪费。

KV Cache vs QKV Cache 显存对比
KV Cache vs QKV Cache 显存对比

显存白白多占 50%。 本来存 KV 两份,现在变成存 QKV 三份,但没有任何计算收益。

旧 Q 是”死数据”。 Attention 机制里不存在 Q × Q 或 K × Q_old 这样的运算,历史的 Q 缓存下来也无人问津。

可以打个比方:去图书馆查资料,每次都要带上自己的问题(Q),但图书馆的藏书(KV)是一直在那里、不断累积的。每次问的是新问题,上一次的问题留不留着都无所谓。


哪些场景会涉及 Q 的”缓存”?

虽然标准自回归解码不缓存 Q,但有些场景确实会暂存 Q:

不同场景下的缓存策略
不同场景下的缓存策略

Prefill(预填充)阶段。 处理用户输入的 Prompt 时,所有 Token 是并行计算的,Q、K、V 都是批量生成的中间激活值。有些框架为了内存布局优化可能会短暂暂存 Q,但这属于计算过程中的临时状态,不是跨步复用的 Cache。

非自回归 / Encoder 模型。 像 BERT 这类双向模型,所有 Token 同时参与注意力计算,不存在”历史 vs 当前”的区别,不涉及 KV Cache 的概念。

Speculative Decoding(投机采样)。 验证阶段可能同时评估多个候选 Token,会有多个 Q 并存,但本质是为当前验证步骤服务,而非持久化的历史记忆。

Linear Attention / RNN-like 架构。 Mamba、RWKV 这类新架构把历史信息压缩成固定大小的 State,传统的 KV Cache 概念本身就在被重构,这属于另一套范式了。


DeepSeek 的”缓存命中率”是什么?

聊完 KV Cache,再延伸一个实际问题:DeepSeek API 返回的”缓存命中率”,指的是什么?

答案是:就是 KV Cache 的命中。

Prefix Caching 工作原理
Prefix Caching 工作原理

更准确地说,它指的是 Prefix Caching(前缀缓存) 技术中对 KV Cache 的复用程度。当 API 报告”缓存命中 800 tokens”时,意味着这 800 个 Token 对应的 KV Cache 已经存在于显存中,系统直接加载复用,跳过了这些 Token 的 Prefill 计算。

需要注意,这里的”缓存”不是简单的文本字符串匹配,而是张量级别的 KV 状态复用。即使两段文本内容相同,如果分词结果或位置编码不同,KV Cache 也无法命中。

这也解释了为什么 DeepSeek 的定价里,缓存命中的 Token 价格只有未命中的 1/4 到 1/10——因为命中意味着省去了 Prefill 的算力开销。


总结

Q vs KV 核心差异
Q vs KV 核心差异
特性Query (Q)Key-Value (KV)
角色当前的提问者历史的资料库
生命周期单步有效,用完即弃全程有效,逐步累积
是否被后续复用❌ 否✅ 是
缓存价值极高(避免 O(N²) 重算)

一句话:KV Cache 缓存的是”过去”,因为过去会被反复回顾;Q 代表的是”现在”,而现在转瞬即逝,无需为未来保存。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注