MLA 的 KV 压缩为什么省显存
一句话定位:MLA(多头潜在注意力)是 DeepSeek 提出的 KV 压缩方案——推理时不缓存完整的 K、V,只缓存一个低秩「潜向量」,用的时候靠矩阵吸收把注意力分数原样算出来。前置:推理优化——KV Cache 的显存账公式在那篇建立;Attention 与 Transformer——GQA 的分组共享是 MLA 要对比的谱系起点;位置编码:RoPE——解耦位置键是本篇的关键配角。
先看一个两难:共用够省,但够好吗
推理优化篇算过:KV Cache 是推理时必须吃的显存,长上下文下能吃掉几十 GiB(长上下文篇的「键值显存墙」)。压缩的第一招是让头与头共用 K、V——MQA 让所有头共用一份(省得最狠、质量损失大),GQA 让分组共用(折中,多数开源模型用它)。
但「共用」的天花板很明显:不管怎么分组,每个头看到的 K、V 都是别人的副本——模型越大、头越多,共用的信息损失越容易被放大。DeepSeek 做 V2 时面临的选择:继续加大共享力度,还是换一条根本不同的路?
能不能既不共用、又不逐头全量存,把缓存压到 MQA 的量级而质量不掉?
他们选了后者:MLA 不共用、也不每个头单独存,而是把所有头的 K、V 压缩成一个低秩潜向量(用一个更小的向量装下所有头的公共信息)存进缓存——用时再把注意力分数原样算出来。论文口径:相比其前代 DeepSeek 67B(GQA 架构),KV 缓存减少 93.3%、最大生成吞吐提升 5.76 倍。
先给两个口径注记:93.3% 是对 67B 整模型的实测;本篇后面的教学账会用「128 头全量 MHA」做假想基线逐层对比——多头注意力(MHA,每头各存一份 K、V)是压缩前的起点,两者基准不同,数字不可互相换算。先看全景:
图:MLA 全景——缓存侧只存潜向量与位置键共 576 个数,计算侧走吸收路线连完整 K 都不用恢复;代价是位置键单独缓存与专用内核
渐进拆解:压缩、吸收、让路
低秩联合压缩:一个潜向量装下所有头
MLA 的第一步是给每个 token 的 K、V 拍一卷「微缩胶片」:用一个向下的投影矩阵(一次压缩变换),把这一层所有头要用的键值信息压进一个 512 维的潜向量(DeepSeek-V2 配置口径,下同)。每个注意力头不再有自己的 K、V——需要时用一个向上的投影矩阵从潜向量「恢复」出头专属的那份。
数学上这就是低秩分解:与其存 128 个头各一份完整 K、V,不如存它们共同的那份低维「底稿」——好比 128 个人要看的资料各不相同,但全部源自同一卷微缩胶片,档案室只存胶片,谁的资料都能投影出来。「低秩为什么敢信」也在这:不同头的 K、V 高度相关(大家都在看同一段上下文,只是视角不同),信息天然冗余——这正是低秩压缩的用武之地,潜向量装的是「公共内容」,各头的「视角差异」由恢复矩阵承载。
这条「压进去——按头恢复」的通路画成图:
图:低秩联合压缩——128 个头的 K、V 经向下投影压进一份潜向量,缓存只存底稿;各头用向上投影矩阵恢复自己的那份
缓存侧的账立刻变小,具体账本(每 token 每层压到 576 个数)见下面谱系图与动手实算;其中 64 个是位置键,来历见下文。
权重吸收:解压这一步可以省掉
如果 MLA 只是「存压缩包、用时解压」,那省了显存却多算了账。真正的妙处是:恢复矩阵可以吸收进查询那一侧——「用恢复矩阵把潜向量升维成 K,再与查询点积」在数学上完全等价于「先用恢复矩阵的转置把查询变换一下,再直接与潜向量点积」。变换后的查询直接吃压缩形式,完整 K 从头到尾不必算出来(本篇动手段用具体数字实算了这条等式)。代价是恢复后的 K 形状不规则,标准注意力内核(GPU 上执行注意力计算的优化程序)不认,需要专门优化的内核——DeepSeek 为此开源了 FlashMLA。
「先恢复再打分」与「先变换查询再打分」为什么完全等价?把两条通路画成图:
图:权重吸收——先恢复完整 K 再打分,与把 Wᵀ 折进查询后直接用潜向量打分,是同一条等式;推理走路线 B,完整 K 不必算出
RoPE 让路:位置信息要单独存放
吸收有一个例外:RoPE(旋转位置编码,负责告诉模型词序)与具体 token 的位置有关,而吸收矩阵是静态权重——「位置相关的旋转」没法折进「位置无关的矩阵」里。MLA 的解法是解耦:把位置信息拆出来,用额外的 64 维小键单独承载并单独缓存;潜向量主体保持位置无关,安心被吸收。这就是全景图里那 64 维「位置键」的来历——它是吸收路线为 RoPE 让出的通道。
MHA → MQA → GQA → MLA 的谱系
四种方案是「缓存怎么省」的四级演化,各方案的缓存数、质量与代表模型的完整对照见下图。以 128 头 ×128 维的模型为例(GQA 取 8 组的教学假设,Llama 70B 级配置;注意力篇里 Qwen2-7B 的 28 头 4 组是另一个常见档位,组数不同比例不同)把账排在一张图里:
图:四代方案对照——缓存从 MHA 的 32768 个数/层压到 MLA 的 576 个,MLA 与 MQA 同档压缩但质量不输基准;GQA 靠分组拿到了「接近基准」的折中位
这个排序有个数学背书:TransMLA 论文证明 GQA 能表达的注意力结构是 MLA 的真子集(MLA 表达力覆盖 GQA)——任何 GQA 模型都能转换成同等 KV 缓存开销的 MLA,转换只需加一个投影矩阵,但要少量微调恢复性能,反向转换则不总是可行。
代价层面 MLA 也不是免费:潜向量在计算侧要被每个头反复使用,计算路径比 GQA 绕,通用内核跑不快,需要 FlashMLA 这类专用实现——「省显存、费内核」是 MLA 与 GQA 分工的分水岭。
大白话:GQA 是「一个办公室四个人合用一台打印机」——省是省了,打印要排队,且只能打共享的那几种格式;MLA 是「把所有人的文档做成一卷微缩胶片」——档案架(显存)只放胶片,谁的资料都能从胶片投影出来(吸收),只是投影仪(内核)得特制。
技术定义:MLA(Multi-Head Latent Attention,多头潜在注意力)将每层每个 token 的键值经向下投影压缩为低秩潜向量(DeepSeek-V2 为 512 维)缓存,各头以向上投影矩阵从潜向量恢复键值;由于恢复矩阵可与查询侧及输出投影静态合并(权重吸收),推理时无需显式恢复完整 K、V。RoPE 因依赖 token 位置而不可吸收,由 64 维解耦位置键单独承载与缓存;表达力覆盖 GQA(TransMLA 证明的真子集关系)。
动手:亲手验证「吸收」是一条等式
吸收不是近似,是精确的数学等式。用随机小矩阵实算两条路线(完整代码可复跑):
import numpy as np
rng = np.random.default_rng(0)
c = rng.normal(size=8) # 缓存里的潜向量(示意 8 维)
W_UK = rng.normal(size=(16, 8)) # 某头的恢复矩阵(8 维 → 16 维)
q = rng.normal(size=16) # 查询向量
score_a = q @ (W_UK @ c) # 路线 A:恢复完整 K,再打分
q_absorbed = W_UK.T @ q # 吸收:把恢复矩阵折进查询侧
score_b = q_absorbed @ c # 路线 B:直接与潜向量点积
print(f"{score_a:.10f} vs {score_b:.10f}") # 实算:8.4495273986 vs 8.4495273986
两次打分打印出的 10 位小数完全一致(浮点内部差仅约 1e-15)——这就是「推理时不用恢复完整 K」的全部依据:等式 q·(W·c) = (Wᵀq)·c 对任意矩阵 W 成立,MLA 把每个头的恢复矩阵都折进了查询侧。再算缓存账(DeepSeek-V2 维度口径):
mha = 2 * 128 * 128 # MHA:K、V 各 128 头 ×128 维
mla = 512 + 64 # MLA:潜向量 512 + 解耦 RoPE 键 64
print(f"每 token 每层:{mha} 个数 → {mla} 个数(约 {mla/mha:.1%})")
# 实算输出:每 token 每层:32768 个数 → 576 个数(约 1.8%)
账本读法:缓存压到约 1.8%、吸收保分数不变——「省显存不省质量」的机制基础就在这两行实算里。注意这条路对 RoPE 走不通:旋转矩阵随位置变,折不进静态权重,所以才有那 64 维单独缓存的位置键——把这段代码里加一个「随位置变化的旋转」再试吸收,等式立刻不成立,这也是理解解耦设计的最快方式。
边界与取舍
什么时候 MLA 是对的选择? 判据是「显存瓶颈有多硬、内核生态有多深」。长上下文、大并发、自建推理栈(内核可控、能吃 FlashMLA 的优化)→ MLA 的显存收益直接变成并发与成本优势;模型不大、上下文不长、依赖通用推理框架的成熟路径 → GQA 的兼容性与简单性仍然占优。V2 论文自己也给了旁证:5.76 倍的生成吞吐提升——显存省下来直接兑换成了服务能力。
MLA 的代价清单。 三笔代价:
- 内核门槛:吸收后的计算形状非标准,通用注意力内核吃不到优化,专用内核(FlashMLA 等)成为必需品——这是「省显存、费内核」。
- 位置编码绑死解耦设计:模型从设计起就要按 MLA 组织注意力,存量 GQA 模型只能靠转换工具迁移。
- 潜向量维度是超参:压得越狠显存越省、表达力越受限,512 是 V2 选定的工程值(论文未公布该维度的消融)。
坏味道预警:把 MLA 与 GQA 的对比说成「有损 vs 无损」。 GQA 的共用是信息的硬共享(组内头看到的完全相同),MLA 的压缩在信息论意义上也有损(512 维装不下 32768 维的一切)——它的优势是「有损得更聪明」,实测质量不掉。真实的对比口径是「同压缩率下谁的质量高」与「同质量下谁更省」,而不是「谁无损」。
自测
合上文章先自己答,再展开对照:
MLA 推理时怎么把压缩的 KV「吸收」回来?代价是什么?
吸收的机制:注意力分数只需要「查询点乘键」,而 MLA 的键是「恢复矩阵 × 潜向量」——代入后就是「(恢复矩阵转置 × 查询)点乘潜向量」,即把恢复矩阵预先折进查询侧(静态权重可以合并),之后每步直接用潜向量打分,完整 K 从头到尾不必恢复。本篇动手段的实算验证了两条路线打分 10 位小数完全一致(等式 q·(W·c) = (Wᵀq)·c 对任意 W 成立,差值仅浮点误差)。代价有三:① RoPE 位置旋转依赖具体位置,静态矩阵吸收不了——位置信息拆成 64 维解耦键单独承载与缓存;② 吸收后的计算形状非标准,通用内核不认,必须配 FlashMLA 这类专用内核(省显存、费内核);③ 潜向量维度(512)是压缩率与表达力的平衡超参,模型设计期就要定死。
MQA、GQA、MLA 三代压缩方案的本质区别是什么?
区别在「怎么省」:MQA 是所有头共用同一份 K、V(硬共享,缓存最小、质量损失最大);GQA 是分组共用(组内头看完全相同的 K、V,折中方案,Llama 2 后多数开源模型采用);MLA 是低秩压缩——不是谁跟谁共用,而是把所有头的键值信息压进一个 512 维潜向量,各头用各自的恢复矩阵从潜向量取信息,且吸收机制让推理时连恢复都不用做。质量排序上 MLA 不输 MHA,缓存接近 MQA 量级;数学背书是 TransMLA 证明 GQA 能表达的结构是 MLA 的真子集(MLA 表达力覆盖 GQA)。四代演化的主线:从「共用的艺术」走到「压缩的科学」。
参考与延伸
- DeepSeek-AI《DeepSeek-V2: A Strong, Economical, and Efficient Mixture-of-Experts Language Model》(2024):MLA 的提出处(93.3% 缓存削减与 5.76 倍吞吐口径出处) — arxiv.org/abs/2405.04434
- Meng 等《TransMLA: Multi-Head Latent Attention Is All You Need》(2025):GQA 表达力是 MLA 真子集的证明与 GQA→MLA 转换 — arxiv.org/abs/2502.07864
- DeepSeek《FlashMLA》(开源仓库,2025):MLA 专用推理内核 — github.com/deepseek-ai/FlashMLA
- 《Understanding Multi-Head Latent Attention》(2025):吸收机制与 RoPE 冲突的逐步推导 — planetbanatt.net/articles/mla.html
- Ji 等《Towards Economical Inference: Enabling DeepSeek’s Multi-Head Latent Attention in Any Transformer-based LLMs》(MHA2MLA,ACL 2025):存量 MHA 模型迁移 MLA 的微调方法 — aclanthology.org/2025.acl-long.1597
下一站:并行训练:DP / ZeRO / FSDP / TP / PP——MLA 省的是推理显存;训练侧显存更挤,答案是另一族技术:把模型切开分给一群显卡。