# 注意力 · 从 MHA 到 MQA、GQA、MLA

> KV 缓存是推理时的显存杀手。MHA→MQA→GQA→MLA 这一串缩写，其实是同一个问题越来越聪明的答案——共享键值头，还是干脆把键值压缩掉？看 Llama/Qwen 的 GQA 与 DeepSeek 的 MLA 各自的取舍。

- 作者：David（道雾轩）
- 专栏：AI 大模型解构（https://daiw.org/manual/llm-anatomy.md）
- 最后更新：2026-07-13
- 原文：https://daiw.org/manual/llm-anatomy/attention-mha-gqa-mla
- 转载与引用：请注明出处并附原文链接（https://daiw.org/about/copyright）

# 注意力 · 从 MHA 到 MQA、GQA、MLA

第一个、也是最重要的战场。你大概听过 MHA、MQA、GQA、MLA 这一串缩写，觉得高深。其实它们是**同一个问题的一串答案**，而那个问题特别具体：

> **推理时，注意力的「KV 缓存」太占显存了。怎么把它压下去，又不让模型变笨？**

把这句话嚼透，这一串缩写就全通了。

## 先搞懂：KV 缓存为什么是显存杀手

回忆 [nanoGPT 的注意力](https://daiw.org/manual/nanogpt/attention)：每个位置算出自己的 Query、Key、Value，然后用 Q 和前面所有位置的 K 比对、去汇总它们的 V。

生成文本时是**一个 token 一个 token 吐**的。生成第 100 个 token 时，要用它的 Q 去和前面 99 个的 K、V 做注意力。难道每一步都把前面所有 token 的 K、V 重算一遍？太浪费了。于是有了 **KV 缓存**：算过的 K、V 存下来，后面直接取用。

这个缓存有多大？粗算一下每个 token 要缓存的字节：

$$
\text{cache/token} \approx 2 \times n_{\text{layer}} \times n_{\text{kv-head}} \times d_{\text{head}} \times \text{bytes}
$$

- 那个 `2`，是 K 和 V 各一份；
- 要乘 `n_layer`，因为**每一层都有自己的一份 KV**；
- 关键在 `n_kv-head`：**有多少个「键值头」，缓存就翻多少倍。**

再乘上下文长度和 batch。于是问题来了：上下文一长（几万 token）、batch 一大，**KV 缓存能吃掉比模型权重还多的显存**。它，而不是算力，常常是长上下文推理的第一瓶颈。

**MHA、MQA、GQA、MLA 的全部动机，就是压这个缓存里的 `n_kv-head × d_head` 那一项。** 下面这一路，你会看到它越压越狠。

## MHA：人手一份，最费（基准线）

**Multi-Head Attention** 就是 nanoGPT 里那种标准做法，也是原版 Transformer 的做法：有多少个 Query 头，就有多少个**配套的** Key 头、Value 头。8 个头，就缓存 8 份 K、8 份 V。

- **优点**：每个头都有完整的、专属的 K/V，表达力最足。
- **缺点**：缓存最大。头越多越费。
- **谁还在用**：大多数新模型已经不用了，但 **OLMo 2** 偏要用回 MHA（它更在意「透明、标准、好复现」，不追极致省显存）。

MHA 是**基准线**。接下来三种，都是在「怎么让 Key/Value 头变少或变小」上做文章。

## MQA：全体共用一份，最省也最糙

**Multi-Query Attention** 走了极端：**所有 Query 头，共用同一份 K 和 V。** 8 个 Query 头，却只有 1 份 Key、1 份 Value。

- **缓存立刻小 8 倍**（`n_kv-head` 从 8 变 1）。
- **代价**：所有头被迫「看同一套钥匙」，表达力受限，大模型上质量会掉。

MQA 像是「省过头了」。于是有了折中——

## GQA：分组共享，行业甜点

**Grouped-Query Attention** 是 MHA 和 MQA 之间的**折中**，也是当下**绝大多数模型的默认选择**：把 Query 头**分组**，**每组共享一份 K/V**。

举个具体的：Llama 3 70B 有 **64 个 Query 头**，却只有 **8 个 KV 头**——等于每 8 个 Query 头共享一份 K/V，分成 8 组。

```
MHA (人手一份)      Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8
                     |  |  |  |  |  |  |  |
                    K1 K2 K3 K4 K5 K6 K7 K8   ← 8 份 KV,最费

GQA (分组共享)      Q1 Q2 Q3 Q4   Q5 Q6 Q7 Q8
                      \ | | /       \ | | /
                       K1(组1)        K2(组2)     ← 2 份 KV,省 4 倍

MQA (全体共用)      Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8
                      \  \  \ | | /  /  /
                            K1             ← 1 份 KV,最省也最糙
```

- **缓存省了**（上例省 4 倍），质量却**几乎不掉**——这就是它成为甜点的原因。
- **谁在用**：**Llama、Qwen、Mistral、Gemma、GLM、GPT-OSS……** 一大片。可以说，GQA 是这一代的「注意力出厂设置」。

到这儿，故事本该结束了——直到 DeepSeek 说：**共享不是唯一的路，压缩才是。**

## MLA：不共享，而是「压缩」——DeepSeek 的杀手锏

GQA 的思路是「**让 KV 头变少**」。**Multi-head Latent Attention** 换了个思路：**KV 头不减，但把每份 K/V 压成一个低维的「潜向量」再缓存。**

打个比方：

- **GQA** 像是「几个人合看一张地图」——地图数量少了，但每个人能看的还是那张完整地图，只是不再人手一张。
- **MLA** 像是「每个人还是有自己的地图，但地图先**压缩成一个二维码**存起来；真要用时，再把二维码**解压**回完整地图」。缓存里躺着的是小小的二维码，不是大地图。

具体说：MLA 把每个 token 的 K、V 通过一个降维矩阵压成一个**低维潜向量(latent)**，**只缓存这个潜向量**；推理时，再用升维矩阵把它**还原**回各个头要用的 K、V。缓存的大小，从「`n_kv-head × d_head`」变成了「一个小小的 `d_latent`」——**比 GQA 还省**。

最反直觉的是**质量**。DeepSeek-V2 论文里做了消融对比，结论很干脆：

> **在建模质量上：GQA < MHA < MLA。**

也就是说，GQA 是「省显存、但质量比 MHA 略降」的折中；而 MLA 做到了**又省显存、质量还反超 MHA**——鱼和熊掌兼得。这就是 DeepSeek（以及把它放大到 1T 的 Kimi K2）宁可承担 MLA 那份实现复杂度，也要用它的原因。

<Callout type="info">
  **一个绕不开的小麻烦：RoPE 怎么办？** MLA 把 K/V 压成了潜向量，可 RoPE 位置编码是要直接作用在 K 上的，压缩后就没法干净地加了。DeepSeek 的解法是「**解耦 RoPE**」：让 Key 分成两截，一小截专门携带 RoPE 位置信息（不压缩）、其余走压缩通道。细节我们放到位置编码那章再展开，这里你只需记住：**MLA 为了兼容 RoPE，做了一点额外的手术。**
</Callout>

## 一张表看全这一路

| 方案 | KV 头怎么处理 | KV 缓存 | 建模质量 | 代表模型 |
| --- | --- | --- | --- | --- |
| **MHA** | 人手一份 | 最大（基准） | 好 | OLMo 2 |
| **MQA** | 全体共用一份 | 最小 | 明显下降 | 早期一些模型 |
| **GQA** | 分组共享 | 小（省数倍） | 几乎不掉 | Llama、Qwen、Mistral、Gemma、GLM、GPT-OSS |
| **MLA** | 不减头，压成潜向量 | 比 GQA 更小 | **反超 MHA** | DeepSeek-V3、Kimi K2 |

这条线读下来，你会发现一个特别清晰的**取舍谱**：从 MHA 到 MQA 是「用质量换显存，换过头了」；GQA 找回了平衡，成了默认；MLA 则用更高的实现复杂度，换来了「显存和质量双赢」。**一个模型在这一格里的选择，基本就暴露了它的性格：是求稳求标准(MHA)，是随大流(GQA)，还是愿意为极致效率钻研复杂方案(MLA)。**

## 还没完：省 KV 缓存的另一条路

MHA→GQA→MLA 这一路，压的是「**每个 token 缓存多大**」。但还有一条正交的路：**干脆别缓存那么多 token**——反正注意力不一定要看全部历史，盯着**附近一个窗口**就够用了。这就是 Gemma、GPT-OSS 用的**滑动窗口注意力**，也是下一章的主角。👉 [滑动窗口：Gemma 与 GPT-OSS 的局部注意力](https://daiw.org/manual/llm-anatomy/sliding-window)

## 参考文献

- [1] Vaswani et al. “Attention Is All You Need.” NeurIPS 2017. arXiv:1706.03762. —— 原始 Transformer 与标准 MHA。
- [2] Shazeer. “Fast Transformer Decoding: One Write-Head is All You Need.” 2019. arXiv:1911.02150. —— 提出 MQA。
- [3] Ainslie et al. “GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints.” EMNLP 2023. arXiv:2305.13245. —— 提出 GQA。
- [4] DeepSeek-AI. “DeepSeek-V2: A Strong, Economical, and Efficient Mixture-of-Experts Language Model.” 2024. arXiv:2405.04434. —— 提出 MLA，并给出「MLA > MHA > GQA」的建模质量消融。
- [5] DeepSeek-AI. “DeepSeek-V3 Technical Report.” 2024. arXiv:2412.19437. —— MLA 的大规模应用。
- [6] Su et al. “RoFormer: Enhanced Transformer with Rotary Position Embedding.” 2021. arXiv:2104.09864. —— RoPE，与 MLA 解耦 RoPE 相关。
