Attention→K3 三十天课 · Day 17 / 30 课程首页 面试视角 自测题
Day 17 · 推理性能核心瓶颈

KV Cache:为什么大模型推理最缺的不是算力而是显存?

很多读者以为:大模型跑得慢,是因为 GPU 算力(FLOPS)不够用。但在真实部署中,大模型在逐 token 生成(Decode)时,GPU 的算力往往大量闲置、利用率低得可怜!真正的死穴是显存带宽(Memory Bandwidth)与显存容量被疯狂吃爆。今天拆解大模型推理的命根子——KV Cache(键值缓存)。

学完你能回答
为什么自回归推理必须把历史 KV 存起来?
学完你能回答
Prefill 与 Decode 两个阶段有什么本质不同?
学完你能回答
为什么说推理是典型的 Memory-bound(访存受限)?

1起点:这些你早就会了

KV Cache 的逻辑,本质就是日常办公里的「草稿纸暂存」:

你已经会的AI 世界里对应的东西
写长篇小说:每写一个新段落,不需要把前面的内容全部重抄一遍KV Cache 机制:把历史 token 的 K 和 V 存在显存里,每次只算最新 1 个 token 的 Q
读题与作答:先花 5 秒通读上千 token 的题目,再用 1 秒写出一个答案Prefill vs Decode:Prefill(预填充,并行算完全文)与 Decode(逐 token 解码)
办公桌堆积:每个人桌上都堆着厚厚的历史档案,桌子不够放了KV 显存膨胀:序列长度 × 并发用户数,显存占用比模型权重还大
卡车运货:发动机马力极大(算力强),但路口太窄每次只能过一辆(带宽小)Memory-bound(内存墙):算力在摸鱼,时间全花在从 HBM 搬运 KV 数据上
查资料时把常用页折角,下次直接翻到那一页缓存复用:算过的 K/V 留在显存里随取随用,不用重算
旺季快递仓库爆仓:货太多堆不下,只能排队等仓位高并发挤爆显存:并发一多 KV Cache 装不下,请求就得排队等显存

2为什么需要 KV Cache?(空间换时间)

回忆 Day 9 的公式:生成第 t 个 token 时,我们需要当前 token 的 q_t 去和历史所有位置的 k_1, k_2, …, k_t 做点积,并加权混合 v_1, v_2, …, v_t。

两种推理策略对比
• 没有 KV Cache(傻子模式):
为了吐出第 100 个 token,把前 99 个 token 从头完整过一遍模型,重新算一遍它们的 K 和 V;吐出第 101 个 token 时,再把前 100 个 token 从头算一遍……
生成 N 个 token 的总计算量是 1 + 2 + … + N,即 O(N²),越往后越慢得令人发指!

• 有了 KV Cache(聪明模式):
前 99 个 token 算好的 K 和 V 直接缓存在 GPU 显存里。生成第 100 个 token 时,模型只需要输入这 1 个 token,算出它的 q₁₀₀、k₁₀₀、v₁₀₀;
把 k₁₀₀、v₁₀₀ 追加写入缓存,拿 q₁₀₀ 和缓存里所有 K 做一次点积即可!每步需要「新算」的只有这 1 个 token——从「重算全部历史」变成「读一遍缓存」。

严格来说(类比的边界):Decode 每步除了要读 KV Cache,还要把整套模型权重从显存搬进计算核心——上下文短时,权重搬运才是大头;KV Cache 的搬运量随历史变长线性增长,长上下文下才反超成为主角。
KV Cache 推理流程:历史 KV 驻留显存,新 token 仅算单个 Q 进行点积 左侧为显存中积累的历史 K 和 V,右侧为新输入的 token t 仅生成单行 Qt 进行注意力计算 KV Cache 工作原理:仅计算当前最新 1 个 Token 的 Q GPU 显存中的 KV Cache 静态缓存池(已生成 t-1 步) Keys: [k₁, k₂, k₃, ..., k_t₋₁] (保留历史) Values: [v₁, v₂, v₃, ..., v_t₋₁] (保留历史) 当前第 t 步计算 输入: token_t → q_t 打分: q_t · [K_cache, k_t]ᵀ
图 17.1:KV Cache 推理流向。空间换时间,避免了历史序列的无休止重复前向计算。

3两段截然不同的人生:Prefill 与 Decode

你每次在聊天窗口发送一段长文本并等待回答时,模型内部会经历两个性格完全相反的阶段:

4显存杀手现形:长序列下的显存海啸

为什么长上下文和大并发这么贵?我们来算一笔震撼的显存账:

KV Cache 显存占用公式 KV Cache 显存 = 2 × 层数(L) × 隐藏维度(d) × 序列长度(S) × 并发批次(B) × 精度字节
以一个常见 70B 模型(80层,8192维,FP16=2字节)为例:
• 处理 1 个 128K 长度的请求,仅 KV Cache 就要霸占 320 GB 显存(示意,按 MHA 假设估算:80 层 × 8192 维 × 128K × 2 字节 × 2(K 和 V)——相当于 4 张 A100 80G 显卡,光存上下文就满了,连模型权重都放不下!);
• 如果要并发服务 100 个用户,显存需求直接奔着几万 GB 去了!

这就是为什么近十年所有架构师都在绞尽脑汁压缩 KV Cache(催生了 MQA、GQA 和 MLA,下节揭秘)!
小结:KV Cache 用显存换时间,消除了历史 K/V 的重复计算,却带来两张新账单——显存容量随「层数 × 维度 × 长度 × 并发」线性膨胀;Decode 每步还要把整块缓存从 HBM 搬进计算核心。怎么把这块缓存压小?明天 Day 18 的 MQA/GQA/MLA 就是干这个的。

5面试视角

面试视角 · 高频考点
面试官可能会问:「大模型推理时的 Prefill 和 Decode 阶段有什么区别?为什么说 Decode 阶段是 Memory-bound(访存受限)的?」
八股答「Prefill 是处理 Prompt,可以并行算,是计算密集型;Decode 是逐 token 生成,每次只算一个 token,受限于显存带宽,是访存密集型。」——背得很熟,若能结合计算访存比(Arithmetic Intensity)解释则更硬核。
本课答「核心是算力与访存的失衡:① Prefill 阶段:输入整个 Prompt 序列 S,进行的是 (S × d) × (d × d) 的 GEMM 矩阵乘法,计算量为 O(S²·d),计算访存比高,能充分打满 GPU Tensor Core;② Decode 阶段:每次输入单个 token,执行的是 (1 × d) × (d × d) 的 GEMV 向量矩阵乘法。每计算一次注意力,必须将显存(HBM)中堆积的所有历史层 KV Cache 全量搬运到芯片 SRAM 缓存中。由于显存读写带宽(如 A100 仅约 2TB/s)远落后于 GPU 浮点算力(312 TFLOPS),算力核心大部分时间处于等待数据传输的饥饿状态,计算瓶颈彻底由算力转向了显存带宽。」

6映射到原文:K3 报告 §5.1

技术报告原文对照 · 《Kimi K3 技术报告》§5.1 KDA 的算法-系统协同设计
「KDA 用固定大小的循环状态 S(维度 d_k × d_v,见 §2.1.1)取代 softmax 注意力中不断增长的键值缓存:其串行更新给并行执行带来挑战,但换来的是一个传输与复用代价都很低的固定大小状态。」

逐词翻译:

  • 「不断增长的键值缓存」:就是今天讲的 KV Cache——softmax 注意力每多生成 1 个 token,缓存就多一条 K/V,显存占用和每步搬运量都随长度线性上涨。
  • 「固定大小的循环状态」:KDA(线性注意力的一种,Day 19 讲)干脆不存逐 token 的 K/V,只维护一个尺寸固定的状态 S——序列再长,它也不变大。
  • 「传输与复用代价都很低」:状态小,搬起来便宜,还能跨请求复用——这正是对今天「Decode 瓶颈在搬运」这条主线的直接回应。

注意 K3 并没有完全抛弃 KV Cache:它的架构是 3 层 KDA 配 1 层 Gated MLA(Day 18/19 讲),MLA 层的缓存还在,只是被压缩过。所以今天学的这笔 KV Cache 账,到 K3 里依然管用。

O(L)
解码每步需从显存读出的历史 KV 量(L=历史长度)
10-20%
未优化解码阶段 GPU 算力利用率(示意)
320 GB
70B 模型单条 128K 序列 KV 显存开销(示意,按 MHA 假设估算)
~2 TB/s
A100 HBM 显存带宽(硬件公开规格)

7自测题(先自己答,再点开看解析)

Q1 什么是 KV Cache?它解决了什么痛点?
解析:KV Cache 在自回归生成过程中,将历史所有 token 的 Key 和 Value 向量保存在显存中。每次生成新 token 时,无需重复计算历史前缀的 K/V——每步要「新算」的从 O(N) 降为 1 个 token 的量(但注意力打分仍需读取全部缓存,是 O(L) 的访存量)。
Q2 为什么 Query(Q)不需要存进 Cache 里?
解析:因为每次生成下一个 token 时,只需要用当前最新 token 的单个 Query 去查询所有历史 Key;历史位置的 Query 在过去的时间步已经用完了,未来再也不会被访问,所以无需缓存。
Q3 为什么大模型生成第 1 个 token(首 token 延迟)通常比后续生成慢?
解析:首 token 生成处于 Prefill 阶段,需要一口气计算并填充整篇长 Prompt 的全部上下文,计算量最大;首 token 吐出后进入 Decode 阶段,每次只处理 1 个 token。
Q4 为什么说 Decode 阶段是 Memory-bound(访存密集型)?
解析:单步计算只有 1 个 token(向量乘矩阵),浮点计算量极小;但为了计算注意力,必须从 GPU 显存里读取全部历史的 KV Cache,时间全消耗在显存搬运带宽上。
Q5 KV Cache 的显存大小与哪些参数成正比?
解析:与层数 L、模型维度 d、序列长度 S、并发批次 B 均呈严格线性正比(显存 ∝ 2·L·d·S·B)。
《从 Attention 到 K3 · 大模型近十年设计演进》30 天课 · Day 17 / 30 · 返回课程首页