
🧠 记忆锚点:KV Cache 用显存保存历史 K/V,换掉重复前缀计算;生成越长、并发越高,缓存越大。
💡 答案要点
KV Cache = 缓存 Attention 计算的中间结果
为什么需要 KV Cache?
没有 KV Cache(重复计算):
生成 token1:"今"
计算 Attention(prompt)
生成 token2:"天"
计算 Attention(prompt + "今") ← 重复计算了 prompt
生成 token3:"气"
计算 Attention(prompt + "今天") ← 又重复了
...
问题:每生成一个 token,都要重新计算所有历史的 Attention
时间复杂度:O(n²),n 是生成长度有 KV Cache(缓存复用):
生成 token1:"今"
计算 Attention(prompt),缓存 KV
生成 token2:"天"
只计算 "今" 的 KV,复用 prompt 的 KV Cache
生成 token3:"气"
只计算 "天" 的 KV,复用之前的 KV Cache
...
优化:每个 token 只计算一次
时间复杂度:O(n)数学原理:
Attention(Q, K, V) = softmax(QK^T / √d) V
生成第 t 个 token:
Q_t:当前 token 的 Query
K_{1:t-1}:历史所有 token 的 Key(从 Cache 读取)
V_{1:t-1}:历史所有 token 的 Value(从 Cache 读取)
只需计算:
K_t, V_t:当前 token 的 KV(新计算)
然后拼接到 Cache性能对比(生成 100 tokens):
| 方案 | 总计算量 | 延迟 |
|---|---|---|
| 无 Cache | 5050 次 Attention | 25s |
| 有 Cache | 100 次 Attention | 5s |
| 加速比 | 50x | 5x |
KV Cache 显存占用:
单个 token 的 KV 大小:
K: [num_layers, num_heads, head_dim]
V: [num_layers, num_heads, head_dim]
示例(Llama 7B):
层数:32
头数:32
头维度:128
精度:FP16(2 bytes)
单 token KV = 2 × 32 × 32 × 128 × 2 = 524KB
4K 上下文 = 524KB × 4096 = 2GB
128K 上下文 = 524KB × 131072 = 64GB面试话术:
"KV Cache 是用空间换时间的经典案例。不用 Cache,每个 token 要重新计算所有历史,O(n²) 复杂度。用了 Cache,复用历史结果,降到 O(n)。代价是显存占用大,长上下文会炸显存。"