30 秒快速回答

KV Cache(键值缓存)是大模型推理时,把已计算过的注意力 Key 和 Value 矩阵暂存在显存里、避免重复计算的加速技术。 它是所有主流推理引擎(vLLM、SGLang、TensorRT-LLM)和云端 API 加速的基石——没有它,每生成一个新 token 都要把前面整段对话重新算一遍,成本暴涨数十倍。同时它也是推理时显存占用的「头号大户」,直接决定了服务能开多大并发。

核心价值一句话:看懂 KV Cache,你就看懂了大模型推理的提速与降本逻辑。


一、为什么需要 KV Cache?——重复计算的浪费

先看大模型是怎么「写」字的。LLM 采用自回归解码:一次只生成一个 token,然后把新 token 拼回输入继续生成。假设输入 100 个 token、要生成 200 个 token:

  • 生成第 101 个 token 时,需要计算前 100 个 token 的注意力
  • 生成第 102 个 token 时,又需要重新计算前 101 个 token 的注意力
  • ……

如果不做任何缓存,总计算量是 100+101+102+…+300,其中绝大部分是重复劳动——第 1 个 token 的注意力被白算了 200 次。

KV Cache 的做法:每个 token 的 K、V 矩阵算过一次后就存进显存,后续新 token 只需与缓存里的 K、V 做注意力计算,不再重算历史前缀。

方式 生成 200 token 的计算量 相对开销
无 KV Cache 反复重算全部前缀 高 10-100 倍
有 KV Cache 只算新 token 的增量 1x(基准)

二、KV Cache 到底存了什么?

Transformer 的每一层自注意力,都会为每个 token 计算三组向量:Query(Q)、Key(K)、Value(V)。其中 Q 只服务于当前 token 的查询,用完即弃;而 K、V 需要被之后所有 token 复用,因此被缓存下来。

简单说,缓存的就是:每一层、每个 token、每个注意力头的 K 和 V 张量。

# 伪代码:带缓存的自注意力(单层)
def attention_with_cache(q, k, v, cache):
    # cache 里存着之前所有 token 的 K、V
    k = torch.cat([cache.k, k], dim=1)  # 拼上新 token 的 K
    v = torch.cat([cache.v, v], dim=1)  # 拼上新 token 的 V
    scores = q @ k.transpose(-2, -1) / math.sqrt(d_k)
    attn = torch.softmax(scores, dim=-1)
    return attn @ v, (k, v)  # 返回更新后的缓存

关键洞察:KV Cache 不改变任何计算结果,只是用显存换时间——典型的空间换时间策略,这也是它能在不损失质量的前提下加速的原因。


三、KV Cache 有多吃显存?——一个公式算清楚

KV Cache 的大小由四个因素决定:

KV Cache 大小 = 2 × 层数 × 头数 × 头维度 × 序列长度 × 精度字节

以 Llama-2-70B(80 层、64 头、头维度 128、FP16)生成 4096 token 为例:

2 × 80 × 64 × 128 × 4096 × 2 字节 ≈ 10.7 GB

对比:模型权重本身约 140GB(FP16),KV Cache 可占权重的 7%-10%,且随序列长度线性增长。这也是为什么 128K 长上下文部署成本急剧上升——KV Cache 成了真正的显存瓶颈。

模型 上下文 4K 的 KV Cache 上下文 128K 的 KV Cache
7B(32层、32头) ~1.3 GB ~42 GB
70B(80层、64头) ~10.7 GB ~340 GB

四、主流优化技术:怎么给 KV Cache 瘦身?

4.1 GQA / MQA / MLA:共享 KV 头

标准多头注意力(MHA)每个头都有独立的 K、V。GQA(分组查询注意力)让多个 Q 头共享一组 K、V 头,MQA 则让所有 Q 头共享同一组 K、V,参数量几乎不变,KV Cache 却显著缩小:

技术 KV 头数 KV Cache 相对大小 代表模型
MHA 64 1x(基准) GPT-3
GQA 8 ~1/8 Llama 2/3、Qwen
MQA 1 ~1/64 Falcon、PaLM
MLA 低秩压缩 ~1/12 且不降质量 DeepSeek-V2/V3

MLA(多头潜在注意力)是 DeepSeek 的招牌创新:把 K、V 压缩成低秩潜向量,缓存的是压缩结果,显存占用大幅下降——这也是 DeepSeek 能维持超低推理成本的关键之一。

4.2 KV Cache 量化:从 FP16 到 FP8/INT8

KV Cache 本身也能量化,把缓存张量从 FP16 压到 FP8/INT8,显存直接减半,精度损失通常很小。vLLM 一行命令开启:

vllm serve Qwen/Qwen2.5-7B-Instruct --kv-cache-dtype fp8

4.3 滑动窗口注意力(SWA)

只缓存最近 N 个 token 的 KV,丢弃更早的。显存占用从「随序列线性增长」变为「封顶」,非常适合流式对话与长文档场景,Mistral 系列即采用此方案。

4.4 PagedAttention 与 KV 复用

  • PagedAttention(vLLM 核心):把 KV Cache 切成固定大小块,按需分配、零碎片、支持跨请求共享,单卡吞吐可提升数十倍
  • 前缀缓存 / Prompt Caching:多轮对话或大量请求共享相同前缀时,直接复用已算好的 KV,首 token 延迟大幅下降

五、代码示例:一键开关看差距

用 HuggingFace Transformers 可以直观感受 KV Cache 的影响:

from transformers import AutoModelForCausalLM, AutoTokenizer

model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-7B-Instruct")
tok = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-7B-Instruct")
inputs = tok("请写一段关于人工智能的简介:", return_tensors="pt")

# 关闭 KV Cache:每个新 token 都重算整段前缀
out_off = model.generate(**inputs, max_new_tokens=512, use_cache=False)

# 开启 KV Cache(默认):增量计算,速度快数倍
out_on = model.generate(**inputs, max_new_tokens=512, use_cache=True)

在 7B 模型、输出 512 token 的场景下,开启 KV Cache 通常快 5-10 倍以上。生产环境(vLLM/SGLang)则进一步叠加 PagedAttention、GQA、KV 量化等手段,把推理成本压到极致。


总结

KV Cache 是大模型推理最核心的「空间换时间」机制:

  1. 作用:缓存 K、V 矩阵,避免自回归解码重复计算,加速数倍
  2. 代价:显存随层数 × 头数 × 序列长度线性增长,是并发瓶颈
  3. 优化:GQA/MQA/MLA 减少 KV 头、KV 量化降精度、滑动窗口限制长度、PagedAttention 消除碎片
  4. 趋势:2026 年推理成本持续下降,MLA、FP8 量化、前缀复用等 KV Cache 优化正是最大功臣

延伸阅读