Attention 家族
LLM 架构 · 2017–2024

Attention 家族:MHA、MQA、GQA、MLA 如何把 KV cache 压小

因果注意力的 decode 每一步只生成一个 token,却要把历史所有 token 的 K/V 重新读一遍;序列越长、层数和头数越多,这一步越像搬显存而不是做矩阵乘法。 MQA 让所有 query 头共享一套 K/V,GQA 折中成 G 组,MLA 把 K/V 联合压成 latent,再额外缓存一个共享的 decoupled key 来承载 RoPE。 四条路线改的是同一个账本,但质量、训练稳定性和 kernel 复杂度各不相同。

Vaswani 2017 · Shazeer 2019 · Ainslie 2023 · DeepSeek-V2/V3 MHA ↗ MQA ↗ GQA ↗ DeepSeek-V2 ↗ DeepSeek-V3 ↗
TL;DR · 30 秒抓住核心

MHA 给每个 query 头配一套 K/V,decode 每生成一个 token 都要把历史 K/V 重新读一遍。 MQA 论文 §2.4.1 把这件事写成内存访问与算术的比值:Θ(n/d + 1/b);当序列长度接近模型维度 d、batch 又小的时候,比值接近 1,瓶颈从算力转到带宽。

MQA 把所有 query 头压到一套 K/V;GQA 把 query 头分成 G 组,每组一套 K/V;MLA 不共享头,而是把 K 和 V 联合压成 latent cKV,再额外缓存一个共享的 decoupled key kR 来承载 RoPE。

三者的缓存账本分别是 2dhl、2Gdhl、(dc+dhR)l 每 token。前两者省在头数,MLA 省在表示维度;代价分别是质量、uptraining 和 RoPE 与吸收路径的实现复杂度。

下面的数字卡分别取 MQA 的解码延迟、GQA-8 的推理时间与平均分、MLA 在大 MoE 上的 KV cache 占比。它们来自三组不同实验,不能拼成一个端到端结论。

12.1×
MQA 解码 3.8 μs/token,MHA 46 μs/token
WMT14 EN-DE,batch 1024,序列 128
5.4×
GQA-8-XXL 每样本每 TPUv4 芯片 0.28 s,MHA-XXL 1.51 s
平均分 47.1 vs 47.2(T5-XXL,5% uptraining)
4.0%
大 MoE 上 MLA 每 token KV cache 占 MHA 的 4.0%
34.6K / 860.2K elements(DeepSeek-V2 Table 9)
01

decode 的瓶颈是每步重读全部 K/V,不是矩阵乘法

先建立共同账本:一层 attention 缓存多少元素、为什么增量解码会从 compute-bound 变成 memory-bound。

自回归生成时,第 t 步只为新 token 算一次 query,但注意力要看到 0..t 的所有 key 和 value。 这意味着整个模型(所有层)的 KV cache 大小是「已生成 token 数 × 每 token 元素数」;每 token 元素数由头数、每头维度和层数决定。 DeepSeek-V2 的 Table 1 把它写成 2nhdhl:两个矩阵(K 和 V)、nh 个头、每头 dh 维、l 层。

cacheMHA(token) = 2 · nh · dh · l 个元素
每 token 的元素数;字节数再乘以存储精度。公式出自 DeepSeek-V2 Table 1,符号沿用该表。

把 DeepSeek-V2 的配置代进去:60 层、128 个 query 头、每头 128 维。 每 token 每层是 2×128×128 = 32,768 个元素;乘 60 层得到 1,966,080 个元素。按 FP16/BF16 每元素 2 字节算,每 token 是 3,932,160 B,约 3.75 MiB。 4K 上下文就是 15,360 MiB,也就是 15 GiB,还没算 attention 的中间激活。

这只是单请求、单份 KV。serving 时多个请求并发,KV cache 直接决定能同时放多少条序列、序列能开多长。 DeepSeek-V2 §2.1.1 把这一点写成「heavy KV cache is a large bottleneck that limits the maximum batch size and sequence length」。 所以后面所有结构都在做同一件事:在不把质量砍掉太多的前提下,减少每 token 的缓存元素数。

MQA 论文 §2.4.1 给了增量解码的定量解释。假设 m=n、k=v=d/h、n≤d, 跨 n 次调用,算术量是 Θ(bnd²),内存访问量是 Θ(bn²d + nd²), 两者之比是 Θ(n/d + 1/b)。当 n≈d 或 b≈1 时,这个比值接近 1, 而现代 GPU/TPU 的算力可以比带宽高两个数量级,于是 decode 被带宽卡住。

关键区分

同一个结构,训练和推理的瓶颈不是同一个

训练时整条序列可以并行,MQA 论文 §2.3.1 给出的内存/算术比是 O(1/k + 1/(bn)),可以做到远小于 1, 所以训练通常是 compute-bound 推断(由 §2.3.1 的内存/算术比 O(1/k + 1/(bn)) 远小于 1 推出,论文未直接下此结论);增量解码不能并行,比值里的 n/d 随序列长度增长。 这也解释了为什么 MQA Table 2 里训练成本几乎不变(13.2 → 13.0 μs),而解码成本从 46 μs 降到 3.8 μs。

于是问题被拆成三个可调的量:能不能少存几个 K/V 头(MQA/GQA),能不能把 K/V 压成更短的表示(MLA), 以及这些改动会不会破坏位置编码、训练稳定性和 kernel 的矩阵乘形状。下一节先看 MHA 的质量基线,以及直接砍头的代价。

02

MHA 是质量基线,直接砍头会把质量一起砍掉

看清两条已有路线:减少 KV 头数(MQA/GQA)与压缩 KV 表示(MLA);先看 naive 砍头的代价,再决定每种结构在什么条件下值得用。

MHA 的做法是给每个 query 头配一套独立的 K/V。Transformer 论文的 base 模型取 h=8、dk=dv=dmodel/h=64、dmodel=512(h 与 dk/dv 见 Transformer §3.2.2;dmodel=512 见 Transformer §3.1)。 每个头单独做 scaled dot-product attention,输出拼接后再过一次 WO。 论文 Transformer Table 1 里,self-attention 每层复杂度是 O(n²·d),顺序操作是 O(1);训练时可以沿序列并行,decode 时不行。

质量基线在 Transformer Table 3(本节仅引用 base 与 single-head 两行,未逐行转录):base 模型 6 层、512 维、8 头、65M 参数,dev BLEU 25.8。 把 8 头换成 1 头、每头维度放到 512,参数量不变,BLEU 掉到 24.9,差 0.9 分;论文 Transformer §6.2 也直接写了「single-head attention is 0.9 BLEU worse than the best setting」。 这说明多头不是装饰:不同头在不同表示子空间里做注意力,把 K/V 头砍掉会损失容量。

MQA 论文 Table 1 把「砍头」和「砍维度」放在同一张参数对齐的表里。multi-head 系列(含 local)的 FFN 是 4096,multi-query 系列(含 local)是 5440;只有 h=1、2、4、8 这四个砍头/砍维度变体才把 FFN 加宽到 6784,以保持总参数量与 baseline 持平; 在这个条件下,h=1、2、4、8(对应 dk,dv=128、64、32、16)的 dev BLEU 都低于 8 头 128 维的 baseline。 唯独 multi-query 把 K/V 头压到 1 个、但保留每头 128 维时,dev BLEU 只低 0.2 分,test beam-4 反而高 0.1 分。这是 MQA 的核心经验:共享整套 K/V 比把每个头的 K/V 做小更划算。

表 1 · 直接减少 KV 头数或维度:参数对齐,WMT14 EN-DE(MQA 论文 Table 1;local 变体也一并转录)

表 1 · WMT14 EN-DE 上的注意力变体(MQA 论文 Table 1,全部 8 行转录)
结构hdk,dvdffln(PPL) devBLEU devBLEU test beam 1 / 4
multi-head812840961.42426.727.7 / 28.4
multi-query812854401.43926.527.5 / 28.5
multi-head local812840961.42726.627.5 / 28.3
multi-query local812854401.43726.527.6 / 28.2
multi-head112867841.51825.8—
multi-head26467841.48026.226.8 / 27.9
multi-head43267841.48826.1—
multi-head81667841.51325.8—
路线 A · 共享 K/V 头

MQA 与 GQA:改头数,不改表示

MQA 把所有 query 头指向一套 K/V;GQA 把 query 头分成 G 组,每组一套 K/V。 两者都不改变每头维度,也不改变 Q 的头数,因此 kernel 只需要把同一份 K/V 广播给多个 query 头。

代价:K/V 的容量随头数下降;GQA 论文 Appendix A 还报告 MQA 在长输入任务上训练不稳定。

路线 B · 压缩 K/V 表示

MLA:改维度,不改头数

MLA 保留全部 query 头,把 K 和 V 联合投影到一个低秩 latent cKV, 再额外缓存一个所有头共享的 decoupled key kR 来承载 RoPE。

代价:RoPE 不能直接作用在压缩后的 key 上,否则上投影矩阵无法吸收进 query 侧;需要 decoupled 分支和对应的 kernel。

两条路线的共同约束是:缓存减少必须用质量或工程复杂度来换。MQA 论文摘要写的是 "incur only minor quality degradation from the baseline", GQA 论文 §5 的结论是 "achieves quality close to multi-head at comparable speed to multi-query attention",DeepSeek-V2 §1 写的是 "MLA achieves superior performance compared with MHA, and meanwhile significantly reduces the KV cache during inference"。 这些结论都有各自的模型配置和基准,不能直接外推;下一节拆开机制,后面再用表格对齐数字。

03

MQA 共享一套 K/V,GQA 按组共享,MLA 把 K/V 压成 latent 再拼回 RoPE

记住三个机制:MQA 去掉 K/V 的头维度;GQA 用 G 个 KV 头;MLA 缓存 cKV 与 kR,并在推理时把上投影吸收进 Q/O。

MQA:K/V 只剩一套,Q 头数不变

MQA 论文 §3 的定义很直接:multi-head attention 有 h 组不同的 K/V 线性投影; multi-query attention 保留 h 个 query 头,但所有头共享同一组 K/V 投影。 用代码的话说,就是把 Pk、Pv 里的 h 维去掉(MQA §3)。 缓存公式因此从 2nhdhl 变成 2dhl。

MQA:cache(token) = 2 · dh · l
GQA:cache(token) = 2 · G · dh · l
MQA 是 GQA 在 G=1 时的特例;GQA 在 G=nh 时退回 MHA(GQA 论文 §2.2)。

收益来自 decode 的内存访问项。MQA 论文 §3.1 把每步的内存/算术比从 Θ(n/d + 1/b) 改写为 Θ(1/d + n/(dh) + 1/b):原来的 n/d 被头数 h 除了一次。 batch 足够大时,1/b 项可以压小,剩下的 n/(dh) 仍然随序列增长,但斜率低了 h 倍。

GQA:把 query 头分组,G 个 KV 头做插值

GQA 论文 §2.2 把 H 个 query 头分成 G 组,每组共享一个 key head 和一个 value head。 GQA-1 就是 MQA,GQA-H 就是 MHA;中间任意 G 给出一个缓存与质量的插值点。 从已有 MHA checkpoint 转换时,组内原来的多个 K/V 头做 mean pooling,而不是只选第一个头或随机初始化(GQA §2.1); 转换后再用原始预训练配方的 α 比例做 uptraining。

GQA 论文 §2.2 还给了一个大模型视角:模型变大时头数通常也变大,MQA 把 K/V 头固定为 1,等于随规模增长做越来越激进的裁剪; GQA 让 KV 头数随总头数按比例缩减。另一个工程点是标准张量并行会把单个 KV 头复制到每个分区,GQA 减少了这份复制开销。

MLA:低秩联合压缩 + decoupled RoPE

MLA 不共享头,而是把 K 和 V 联合压到一个低秩 latent。DeepSeek-V2 §2.1.2 的式 9–11 是:

ctKV = WDKV ht
ktC = WUK ctKV,   vtC = WUV ctKV
ctKV ∈ Rdc,dc ≪ dhnh;推理只缓存 ctKV,所以每层每 token 是 dc 个元素(DeepSeek-V2 §2.1.2)。

但 RoPE 和低秩压缩不兼容。若把 RoPE 直接作用在 ktC 上, WUK 会和一个与当前位置相关的 RoPE 矩阵耦合;推理时这个矩阵夹在 WQ 和 WUK 之间, 矩阵乘法不满足交换律,WUK 就不能再吸收进 query 侧,只能对全部前缀重算 key(DeepSeek-V2 §2.1.3)。 这就是 decoupled RoPE 要解决的问题:另外用一组 query 和一个所有头共享的 key 来承载位置信息。

qtR = RoPE(WQR ctQ),   ktR = RoPE(WKR ht)
qt,i = [qt,iC; qt,iR],   kt,i = [kt,iC; ktR]
ot,i = Σj≤t softmaxj(qt,iTkj,i / √(dh+dhR)) vj,iC
式 14–18。ktR 没有 head 下标,所有 query 头共用;这是 MLA 只增加 dhR(而不是 nhdhR)缓存的原因。

有了 decoupled key,WUK 可以吸收进 query 的上投影,WUV 可以吸收进 WO; 推理时不需要把 K 和 V 显式算出来(DeepSeek-V2 Appendix C)。缓存里只留两样东西: ctKV(dc 维)和 ktR(dhR 维), 每 token 每层共 dc+dhR 个元素。

DeepSeek-V2 取 dc=512、dhR=64、dh=128, 所以 dc=4dh、dhR=dh/2, 每层每 token 是 576 个元素,约 4.5dh(由 Table 1 的 2.25 组派生)。 同头数 MHA 是 32,768 个元素(2×128×128),MLA 是它的 1.76%;换算成 GQA,等于 2.25 个组。

表 2 · 每 token KV cache 的元素数(DeepSeek-V2 Table 1,四行完整转录;Capability 是论文的定性列)

表 2 · 不同 attention 的 KV cache 公式(DeepSeek-V2 Table 1)
Attention 机制每 token 元素数论文 Capability备注
MHA2nhdhlStrong每个 query 头一套 K/V
GQA2ngdhlModerateng 为组数
MQA2dhlWeakG=1 的 GQA
MLA(dc+dhR)l ≈ 9dhl/2Strongerdc=4dh,dhR=dh/2

这张表只比较「元素数」,不比较精度、kernel 实现或质量。MHA 的 2nhdhl 和 MLA 的 (dc+dhR)l 都是每 token 的元素数(公式已含 l 层);实际显存还要乘序列长度和每元素字节数,下一节的计算器就是把这几个量乘起来。

04

同一组超参下,四种结构的每 token 缓存相差 128 倍;MLA 相当于 2.25 个 GQA 组

把公式变成字节账本:拖参数看每 token 与整段 cache;手算两组配置与 JS 逐位对齐。

公式本身很小,难的是把「每 token 元素数」换算成「整段序列的字节数」。需要乘三个量:层数 L、序列长度 S、每元素字节数 b。 其中 b 由存储精度决定:FP16/BF16 是 2 B,FP8 是 1 B,DeepSeek-V2 §3.2.3 部署时还把 KV cache 量化到平均 6 bit,即 0.75 B。 下面的计算器默认取 DeepSeek-V2 的 MLA 尺寸:60 层、128 个 query 头、每头 128 维、dc=512、dhR=64;GQA 对照取 8 组(GQA 论文选的中间点),序列 4096、2 B。

KV cache · 当前配置

MHA:每层每 token 32,768 elements;每 token 1,966,080 elements = 3,932,160 B;S=4,096 时整段 16,106,127,360 B = 15,360.0 MiB。

MLA latent = d_c + d_h^R = 576 elements/token/layer,相当于 GQA 2.25 组(DeepSeek-V2 Table 1)。

表 3 · 同一组超参下的 KV cache(页面按 DeepSeek-V2 Table 1 的公式计算)
结构每层每 token 元素每 token 元素每 token 字节整段字节(S)整段 MiB
MHA 32,768 1,966,080 3,932,160 16,106,127,360 15,360.0
MQA 256 15,360 30,720 125,829,120 120.0
GQA-8 2,048 122,880 245,760 1,006,632,960 960.0
MLA 576 34,560 69,120 283,115,520 270.0

计算器是容量计算:元素数按 DeepSeek-V2 Table 1 的公式,字节数按所选精度,整段字节 = 每 token 字节 × 序列长度。它不模拟 attention 计算、块对齐、prefix caching 或量化误差。

手算对账:两组配置,JS 与手算逐位一致默认 V2 配置 + V2-Lite 配置

口径:每层每 token 元素数 = 2×H×dh(MHA)、2×dh(MQA)、2×G×dh(GQA)、dc+dhR(MLA);每 token 元素 = 每层 × L;字节 = 元素 × 每元素字节数;整段 = 每 token 字节 × S。下面两组都用 2 B。

组 A(默认,DeepSeek-V2):L=60,H=128,dh=128,G=8,dc=512,dhR=64,S=4,096,2 B

  1. MHA:每层 2×128×128 = 32,768;每 token 32,768×60 = 1,966,080;字节 1,966,080×2 = 3,932,160;整段 3,932,160×4,096 = 16,106,127,360 B = 15,360.0 MiB。
  2. GQA-8:每层 2×8×128 = 2,048;每 token 2,048×60 = 122,880;字节 122,880×2 = 245,760;整段 245,760×4,096 = 1,006,632,960 B = 960.0 MiB。
  3. MQA:每层 2×1×128 = 256;每 token 256×60 = 15,360;字节 15,360×2 = 30,720;整段 30,720×4,096 = 125,829,120 B = 120.0 MiB。
  4. MLA:每层 512+64 = 576;每 token 576×60 = 34,560;字节 34,560×2 = 69,120;整段 69,120×4,096 = 283,115,520 B = 270.0 MiB。
  5. 比例:GQA-8 / MHA = 2,048 / 32,768 = 6.25%;MQA / MHA = 256 / 32,768 = 0.78125%;MLA / MHA = 576 / 32,768 = 1.7578125%;MLA / GQA-8 = 576 / 2,048 = 28.125%。

组 B(DeepSeek-V2-Lite):L=27,H=16,dh=128,G=8,dc=512,dhR=64,S=32,768,2 B

  1. MHA:每层 2×16×128 = 4,096;每 token 4,096×27 = 110,592;字节 110,592×2 = 221,184;整段 221,184×32,768 = 7,247,757,312 B = 6,912.0 MiB。
  2. GQA-8:每层 2×8×128 = 2,048;每 token 2,048×27 = 55,296;字节 55,296×2 = 110,592;整段 110,592×32,768 = 3,623,878,656 B = 3,456.0 MiB。
  3. MQA:每层 2×1×128 = 256;每 token 256×27 = 6,912;字节 6,912×2 = 13,824;整段 13,824×32,768 = 452,984,832 B = 432.0 MiB。
  4. MLA:每层 512+64 = 576;每 token 576×27 = 15,552;字节 15,552×2 = 31,104;整段 31,104×32,768 = 1,019,215,872 B = 972.0 MiB。
  5. 比例:MLA / MHA = 576 / 4,096 = 14.0625%;这与 DeepSeek-V2 Table 9 对小 MoE 报的 14% 同一量级,但 DeepSeek-V2 Table 9 是实测模型对,不是本页的同头数换算。

JS 只做整数乘法和除以 1,048,576,没有随机数或取整到整 MiB;上面两组参数在页面上切换后,显示的字节数与手算逐位一致。 组 B 的 L=27 来自 DeepSeek-V2-Lite 的 27 层(DeepSeek-V2 Appendix B),H=16 也来自 DeepSeek-V2 Appendix B;组 A 的 60/128/128/512/64 来自 DeepSeek-V2 §3.1.2。

计算器覆盖了什么、没覆盖什么公式边界

覆盖:DeepSeek-V2 Table 1 的每 token 元素数公式(MHA 2nhdhl、MQA 2dhl、GQA 2ngdhl、MLA (dc+dhR)l); 按所选精度换算字节;整段 = 每 token 字节 × 序列长度。

未覆盖:KV cache 的块对齐与块内碎片;attention 本身的 FLOPs;MLA 的 WUK/WUV 吸收在具体 kernel 中的实现; 张量并行下 KV 头的复制;6-bit 量化的打包开销与误差;prefix caching、beam search 等跨请求共享;训练激活内存与优化器状态。 因此它是缓存容量计算器,不是端到端吞吐模型。

把计算器放回论文的语境,三种结构的工程取舍并不一样。MQA 的训练成本几乎不变(MQA Table 2 里 13.2 → 13.0 μs), 因为训练本来就是把整条序列并行地做矩阵乘;GQA 需要一次 uptraining,GQA 论文 §3.1 取 α=0.05, T5-XXL 上大约 600 TPUv3 chip-days;MLA 的低秩 query 压缩是为了降低训练激活内存(DeepSeek-V2 §2.1.2), 它本身不减少 KV cache,真正减少 cache 的是 cKV 与 kR 这条推理路径。

MLA 的推理路径还有一个实现前提:吸收之后,WUK 和 WUV 不再单独出现在 attention 里, attention kernel 直接消费 cKV。这不是「把 K/V 算出来再存」的等价写法,而是改变矩阵乘顺序后的实现(DeepSeek-V2 Appendix C); 如果 kernel 不支持这种吸收,MLA 的缓存优势还在,但每步会多出恢复 K/V 的计算。

05

从 MHA 到 MLA:共享、分组、压缩三次改写,Q 头数始终不变

沿一条演化线看每种结构改了什么、没改什么;MLA 多出的是 decoupled key 和吸收路径。

MHA、MQA、GQA 与 MLA 的 KV cache 结构对比 MHA 为每个 query 头缓存一套 K/V;MQA 所有 query 头共享一套 K/V;GQA 把 query 头分组,每组共享一套 K/V;MLA 缓存低秩 latent c_KV 与共享的 decoupled key k_R。 同一组超参:Q 头数不变,变的是被缓存的 K/V MHA H 个 Q 头 H 个 K/V 头 2·H·d_h·L MQA H 个 Q 头,1 个 K/V 头 2·d_h·L 所有 Q 头读同一份 K/V GQA-G H 个 Q 头,G 个 K/V 头 2·G·d_h·L 每组 Q 头共享一套 K/V MLA H 个 Q 头;缓存 c_KV [d_c] + k_R [d_h^R] (d_c + d_h^R)·L W_UK 吸收进 Q,W_UV 吸收进 O 三类改动都不改变 Q 头数:MQA/GQA 共享 K/V 头,MLA 压缩 K/V 表示并额外缓存共享的 decoupled key。
图 1 · 四种 attention 的 KV cache 结构示意。公式与 DeepSeek-V2 Table 1 一致;图中用 H、G、d_h、d_c、d_h^R、L 表示头数、组数、每头维度、latent 维度、decoupled key 维度和层数。
  1. MHA:每个 query 头有独立的 K/V;训练沿序列并行,decode 每步重读全部历史 K/V。缓存 2HdhL,质量基线最高,但显存随头数线性增长。
  2. MQA:K/V 头数压到 1,Q 头数保持 H。MQA 论文在 WMT14 EN-DE 上从零训练,dev BLEU 26.5 对 MHA 26.7,test beam-4 28.5 对 28.4;decoder 每 token 从 46 μs 降到 3.8 μs。代价是质量略低,GQA 论文 Appendix A 还报告了训练不稳定。
  3. GQA:K/V 头数取 G,Q 头分成 G 组。从 MHA checkpoint 转换时对组内 K/V 做 mean pooling,再 uptraining α;G=1 是 MQA,G=H 是 MHA。论文选 8 组作为中间点(GQA Figure 6)。
  4. MLA:K/V 压成 cKV,RoPE 放到共享的 kR 上;缓存 (dc+dhR)L。推理时 WUK 吸收进 Q 侧、WUV 吸收进 WO,不必显式恢复 K/V(DeepSeek-V2 Appendix C)。DeepSeek-V2 取 60 层、128 头、dh=128、dc=512、dhR=64。

DeepSeek-V3(arXiv 2412.19437)在 DeepSeek-V3 §2.1.1 继续采用 MLA,只缓存 cKV 和 kR; DeepSeek-V3 §4.2 给出的配置是 61 层、128 个 query 头、每头 128 维、 dc=512、dhR=64。 按同一公式,每 token 的 latent cache 是 35,136 个元素(576×61),BF16 下 70,272 B,4K 上下文 274.5 MiB。 推断(由 DeepSeek-V3 §4.2 的层数与维度乘出;V3 没有在正文里单独报这个数)。

06

MQA 把 decode 从 46 μs 压到 3.8 μs;GQA-8 用 0.28 s 换回 47.1 分;大 MoE 上 MLA 只留 4% 的 KV

分三组读数字:MQA 的延迟与质量、GQA 的 uptraining 权衡、MLA 的缓存与基准;不要跨模型配置直接比较。

MQA:训练时间几乎不变,解码时间少一个数量级

MQA 论文 Table 2 是 6 层 encoder-decoder Transformer(dmodel=1024、dff=4096、h=8、211M 参数)在 TPUv2 上的摊销成本:训练每 token 从 13.2 μs 变成 13.0 μs,几乎不动; decoder 增量推理从 46 μs/token 降到 3.8 μs/token, 相对 MHA 快 12.1 倍;beam-4 从 203 降到 32,约 6.3 倍。 这组数字的条件是 batch 1024、源/目标长度 128、WMT14 EN-DE(WMT14 实验见 MQA §4.1;batch 与长度见 MQA §4.3)。

表 4 · 摊销训练与推理成本(TPUv2 微秒/输出 token,序列长度 128;表注称 per output token,MQA §4.3 正文称训练为 per (input-token + target-token);MQA 论文 Table 2,四行完整转录)

表 4 · 训练与推理成本(MQA 论文 Table 2)
Attention 类型TrainingInference enc. + dec.Beam-4 enc. + dec.
multi-head13.21.7 + 462.0 + 203
multi-query13.01.5 + 3.81.6 + 32
multi-head local13.21.7 + 231.9 + 47
multi-query local13.01.5 + 3.31.6 + 16

质量侧,MQA 论文 Table 1 的 dev 指标是「slightly worse」:ln(PPL) 1.439 对 1.424,BLEU 26.5 对 26.7; 但 test beam-4 是 28.5 对 28.4,MQA 反而高 0.1。论文没有把这两组结果合成一个结论, 只写了 "the multi-query attention model seems to be slightly worse than the baseline" 以及 "actually had the highest BLEU score (28.5) with beam-4 decoding"(MQA §4.2)。 所以读 MQA 的质量要同时看 dev 和 test、看解码方式,不能只取一个数。

GQA:0.28 s 接近 MQA 的 0.24 s,平均分回到 47.1

GQA 论文 Table 1 比较的是 T5 Large/XXL 与 5% uptraining 的 XXL 变体。MHA-XXL 每样本每 TPUv4 芯片 1.51 s、平均分 47.2; MQA-XXL 0.24 s、46.6;GQA-8-XXL 0.28 s、47.1。 换成相对 MHA-XXL 的口径:GQA-8 快 5.4 倍,平均分低 0.1 分;MQA 快 6.3 倍,平均分低 0.6 分。

表 5 · T5 Large/XXL 的推理时间(s/样本/TPUv4 芯片)与各数据集 dev 分数(GQA 论文 Table 1,全部列转录)

表 5 · 推理时间(每 TPUv4 芯片、每样本)与平均分(GQA 论文 Table 1;R1 为 Rouge-1,WMT 为 BLEU,TriviaQA 为 F1)
模型Tinfer (s)AverageCNNarXivPubMedMediaSumMultiNewsWMTTriviaQA
MHA-Large0.3746.042.944.646.235.546.627.778.2
MHA-XXL1.5147.243.845.647.536.446.928.481.9
MQA-XXL0.2446.643.045.046.936.146.528.581.3
GQA-8-XXL0.2847.143.545.447.736.347.228.481.6

这组数字的条件是 T5.1.1、5% uptraining(α=0.05)、T5-XXL 基座;GQA-8 的 8 组是论文在 GQA Figure 6 里选的中间点。 GQA 论文 §3.2 的结论是 "achieving performance close to MHA-XXL with speed close to MQA";GQA Table 1 的 47.1 对 47.2 支持这一判断, 但不能读成「GQA 在所有任务上都等于 MHA」——表里 CNN、arXiv、MediaSum、MultiNews 的分项仍有零点几分的差。

DeepSeek-V2:MLA 的缓存优势与质量对照

先看同规模的头数消融。DeepSeek-V2 Appendix D.1 的 Table 8 是三个 7B dense 模型,除 attention 外架构相同,训练 1.33T token。 四组基准上 MHA 都高于 GQA-8,GQA-8 都高于 MQA:MMLU 45.2 / 41.2 / 37.9,C-Eval 42.9 / 37.7 / 30.0。 这两组结果的条件不同:MQA 论文是 WMT14 EN-DE 上 6 层、8 头、211M 参数的翻译模型(不是 Transformer 论文的 65M base 模型),DeepSeek-V2 Table 8 是 7B dense 的四个 hard benchmark。 DeepSeek-V2 Table 8 的论文结论是「MHA demonstrates significant advantages over GQA and MQA」,本页照录,不把它外推到 MQA 论文的翻译实验。

表 6 · 7B dense 的 MHA / GQA-8 / MQA(DeepSeek-V2 Appendix D.1 Table 8,全部行转录)

表 6 · 7B dense attention 消融(DeepSeek-V2 Table 8)
Benchmark(Metric)# ShotsMQA 7.1BGQA-8 6.9BMHA 6.9B
BBH (EM)3-shot33.235.637.0
MMLU (Acc.)5-shot37.941.245.2
C-Eval (Acc.)5-shot30.037.742.9
CMMLU (Acc.)5-shot34.638.443.5

MLA 的对照在 DeepSeek-V2 Appendix D.2 的 Table 9:两对小/大 MoE 模型,分别只改 attention。小 MoE 的 KV cache 从 110.6K 降到 15.6K elements/token, 比值 14.1%;大 MoE 从 860.2K 降到 34.6K,比值 4.0%。 质量侧,大 MoE 的四项基准 MLA 都更高:BBH 50.7 对 46.6、MMLU 59.0 对 57.5、C-Eval 59.2 对 57.9、CMMLU 62.5 对 60.7。 小 MoE 的四项里,BBH 39.0 对 37.9、MMLU 50.0 对 48.7、CMMLU 53.4 对 52.3,C-Eval 是 50.9 对 51.6,MLA 低 0.7 分。

表 7 · MHA 与 MLA 的 KV cache 与四项基准(DeepSeek-V2 Appendix D.2 Table 9,全部行转录)

表 7 · MoE 上的 MHA 与 MLA(DeepSeek-V2 Table 9;KV cache 单位为 elements/token)
配置ActivatedTotalKV cache/tokenBBHMMLUC-EvalCMMLU
Small MoE · MHA2.5B15.8B110.6K37.948.751.652.3
Small MoE · MLA2.4B15.7B15.6K39.050.050.953.4
Large MoE · MHA25.0B250.8B860.2K46.657.557.960.7
Large MoE · MLA21.5B247.4B34.6K50.759.059.262.5

这两个比值容易和 DeepSeek-V2 §3.1.2 的同头数换算混在一起。DeepSeek-V2 Table 9 的 MHA 是独立的消融模型,表里没有列它的层数和头数; 用 V2 自己的 128 头、128 维去套 MHA,得到的是每 token 1,966,080 个元素,和 DeepSeek-V2 Table 9 的 860.2K 不是同一个配置 推断(依据:DeepSeek-V2 Table 9 未列该 MHA 的层数与头数,且 1,966,080 与 860.2K 两个数并不相等)。 因此 4.0% 只能作为「DeepSeek-V2 Table 9 这两组模型」的读数,不能当成 MLA 对任意 MHA 的固定比例。

部署侧,DeepSeek-V2 §3.2.3 还把参数转成 FP8,并对 KV cache 做平均 6 bit 的量化;论文报告单节点 8×H800 上生成吞吐超过 50K tokens/s, 是 DeepSeek 67B 最大生成吞吐的 5.76 倍,prompt 输入吞吐超过 100K tokens/s。 DeepSeek-V2 §1 给出的整体对比是:KV cache 相对 DeepSeek 67B 降低 93.3%,训练成本也相对 DeepSeek 67B 节省 42.5%(300.6K 对 172.8K GPU hours / 每万亿 token)。 这些数字的分母都是 DeepSeek 67B,不是 DeepSeek-V2 Table 9 的 MHA 消融模型。

07

四种结构都不是免费午餐:共享伤质量,压缩加复杂度,缓存仍随序列线性增长

把不适用场景写清楚:MQA 的训练稳定性、GQA 的 uptraining 依赖、MLA 的 RoPE 与 kernel 代价。

选择判据

按瓶颈选,而不是按「新旧」选

质量优先、缓存不是瓶颈:MHA 仍然是最直接的基线;短序列、训练为主、或显存充足时,没有必须换结构的理由。

decode 带宽受限、能接受小幅质量差:MQA 的收益最直接,但要先验证长输入微调的稳定性;GQA 用 uptraining 换更平滑的质量/速度折中,G=8 是论文选的中间点。

既要 MHA 级质量、又要小 cache:MLA 是候选,但要准备 decoupled RoPE、吸收路径和对应 kernel;DeepSeek-V2 Table 9 的 4.0% 只适用于该表的大 MoE 配置。 推断(由 DeepSeek-V2 Table 1 的公式与 DeepSeek-V2 Table 8/9 的质量对照得出,不是论文给出的选型规则)。

最后回到版本:本页引用的是 Vaswani et al. 2017(1706.03762)、Shazeer 2019(1911.02150)、Ainslie et al. 2023(2305.13245)、 DeepSeek-V2(2405.04434)与 DeepSeek-V3(2412.19437)的 arXiv 正文与 ar5iv 构建;链接不带 vN,图表编号以各文当前 ar5iv 构建为准。 不同版本的章节号可能移动,读表时以表题和数字为准。