跳转到主要内容

Attention 架构演化:从多头注意力(MHA)到 GQA、MLA

用 KV 共享、表示压缩、访问稀疏和递推状态四条路线理解现代 LLM Attention

· 约 5 分钟阅读

现代 LLM 没有沿一条路线简单“替代 MHA”。更稳定的理解方式是看四个控制点:存几份 KV、每份表示多大、每步访问多少历史,以及是否仍保存逐 token KV。

30 秒复习
  • 一句话:Attention 演化是在表达能力、KV 容量、历史扫描和硬件效率之间重新分配成本。
  • 三个判断:MQA/GQA 减少 KV 份数;MLA 压缩 KV 表示;稀疏/局部与递推结构分别减少访问范围和逐 token 历史存储。
  • 核心模型KV 共享 → 表示压缩 → 访问稀疏 → 递推状态 是四条正交坐标,可被组合而非互斥替代。
  • 边界:FlashAttention 主要改变精确 attention 的实现;GQA、MLA、稀疏和递推结构改变模型参数化或可见区域,不能都称为“等价加速”。

Attention 从 MHA 到混合架构的演化地图

1. 基线:缩放点积注意力与 MHA

单头缩放点积注意力为:

Attention(Q,K,V)=softmax ⁣(QKdk)V\operatorname{Attention}(Q,K,V) = \operatorname{softmax}\!\left(\frac{QK^\top}{\sqrt{d_k}}\right)V

Query 表示“当前在找什么”,Key 用于匹配,Value 是匹配后取回的内容。MHA 用多组投影并行学习不同表示子空间:

MHA(X)=Concat(head1,,headh)WO\operatorname{MHA}(X) =\operatorname{Concat}(\operatorname{head}_1,\ldots,\operatorname{head}_h)W^O

逻辑上的多个 head 通常由融合 GEMM 一次生成 Q/K/V 后再 reshape;它不意味着物理上执行许多独立小矩阵乘法。W^O 是输出投影,也不是 softmax attention weight。

MHA 的服务成本集中在三处:

阶段主要成本随上下文增长
PrefillQuery 与可见 Key 的交互dense causal attention 约为 O(S2)O(S^2)
Decode每步读取历史 K/V每步约为 O(S)O(S)
常驻资源每层、每 token 的 K/V容量约为 O(S)O(S)

2. 四条演化路线

路线控制点代表结构主要收益主要代价
KV 共享存几份 K/VMQA、GQA降低 cache 容量与读取量约束 KV 参数化
表示压缩每份 KV 多大MLA降低 bytes/token需要专用投影、layout 和 kernel
访问稀疏每步看多少历史Sliding Window、Block/Routed Sparse降低长上下文交互可能漏掉远距离信息
递推状态是否保存逐 token KVLinear/Recurrent Attentiondecode 读写固定状态有限状态会压缩历史细节

这些路线可以混合。例如一套模型可以在多数层使用局部或递推结构,在少数层保留完整 GQA/MLA,并在系统层继续做分页和量化。

3. MQA 与 GQA:减少 KV 份数

设 Query heads 数为 hh,KV heads 数为 gg

架构Query headsKV heads共享方式
MHAhhhh每个 Q head 有独立 K/V
GQAhhgg,且 1<g<h1<g<h一组 Q heads 共享一组 K/V
MQAhh11所有 Q heads 共享一组 K/V

缓存元素数由 KV heads 决定:

KV elements/token/layer=2×nkv-heads×dhead\text{KV elements/token/layer} =2\times n_{\text{kv-heads}}\times d_{\text{head}}

MQA 共享最强,GQA 是 MHA 与 MQA 之间的折中。这里不展开 cache 总量与分页,统一见 KV Cache

4. MLA:压缩表示

MLA 先把 hidden state 压到共享 latent:

ctKV=WDKVhtc_t^{KV}=W_{DKV}h_t

它主要缓存 latent KV 与小型 RoPE 分支,而不是按多个 KV heads 保存完整 K/V。矩阵吸收又让 decode 可以避免显式恢复全部历史向量。因此它与 GQA 的作用点不同:

GQA / MQA:减少独立 KV 的份数
MLA:      压缩 KV 共同依赖的表示

低秩结构、RoPE 解耦、矩阵吸收和 serving 边界见 DeepSeek MLA

5. 局部与稀疏注意力:减少“看谁”

局部或稀疏注意力直接改变访问范围:

  • Sliding Window 只看最近 WW 个 token。
  • Local/Global Hybrid 让多数层看局部、少数层看全局。
  • Block/Routed Sparse 根据 Query 选择少量历史块。

它们减少计算和访存,但选择机制可能漏掉远距离关键信息;优化的是可见区域,不是 KV 表示。CSA/HCA 是一个仍待主来源核验的具体案例,见 CSA/HCA 注意力

6. 递推式注意力:用状态概括历史

递推结构不要求每步读取完整逐 token KV,而是更新有限状态:

St=Update(St1,kt,vt),yt=Read(qt,St)S_t=\operatorname{Update}(S_{t-1},k_t,v_t), \qquad y_t=\operatorname{Read}(q_t,S_t)

这样 decode 成本不再随完整 KV 序列同样增长;代价是历史被压缩进有限状态,prefill 还需要 scan、chunk 或三角矩阵等并行化。真实 kernel 中的 chunk 与 scheduler 的 chunk 不是同一概念,见 GDN 与 Chunked Prefill

7. “精确”必须分层判断

技术是否与完整 MHA 数学等价改变了什么
FlashAttention是,忽略浮点舍入顺序差异tiling、online softmax 与 IO
MQA / GQAK/V 参数化和共享约束
MLA否;可保留完整历史 softmax 访问KV 表示的低秩约束
局部/稀疏注意力一部分 token 对不参与计算
线性/递推式注意力通常否用新算子或有限状态替代完整 softmax

“不与 MHA 数学等价”不等于模型一定更差:这些结构通常从训练开始适应自身约束。系统评估时应分别验证模型质量、可见区域、cache bytes/token 和目标硬件上的 kernel 路径。

8. 如何读混合架构

面对新架构,依次回答四个问题:

  1. 每层保存的是完整 K/V、共享 K/V、latent,还是固定状态?
  2. Query 能访问完整历史、局部窗口,还是选出的块?
  3. Prefill 与 decode 是否走不同 kernel/layout?
  4. 哪些结论来自架构定义,哪些只是某个引擎或版本的实现?

这样可以把模型机制与 serving 实现分开,也能避免只凭名称推断 KV 容量或复杂度。

相关页面

修改历史2 次提交