Attention Architecture Evolution
结论
先给出最重要的判断:
- Full/MHA、MQA、GQA、MLA 是同一 dense softmax 家族中的不同 KV 组织方式。后三者主要减少 KV cache 或带宽,并不自动把全部 token 两两交互变成线性复杂度。
- GDN 与 KDA 属于递归状态路线。历史不再以逐 token K/V 保存,而是写入固定大小矩阵状态;KDA 把 GDN 的 head-wise 标量遗忘细化为 key-channel-wise 对角遗忘。
- DSA 属于 token 稀疏路线。Lightning Indexer 仍扫描历史并产生 top-k,主 MLA 才只读取选中位置,所以“主注意力稀疏”不等于整个模块没有历史扫描成本。
- 公开时间并不等于概念顺序。DSA 于 2025 年 9 月公开,KDA 于 2025 年 10 月公开;本文按真实时间线排列,而不是按缩写的相似度排列。
时间线
| 首次公开 | 结构 | 首个一手来源 | 主要变化 | 历史表示 |
|---|---|---|---|---|
| 2017-06-12 | Full Attention / MHA | Attention Is All You Need[^mha-paper] | 每个 Query head 拥有独立 K/V,读取全部历史 | 完整 K/V cache |
| 2019-11-06 | MQA | Fast Transformer Decoding: One Write-Head is All You Need[^mqa-paper] | 多个 Q head 共享一组 K/V | 单组 K/V cache |
| 2023-05-22 | GQA | GQA: Training Generalized Multi-Query Transformer Models[^gqa-paper] | Q head 分组共享 K/V | 多组 K/V cache |
| 2024-05-07 | MLA | DeepSeek-V2[^mla-paper] | K/V 联合低秩压缩,解耦 RoPE | cKV + kR |
| 2024-12-09 | GDN | Gated Delta Networks[^gdn-paper] | head-wise 衰减的 delta-rule 固定状态 | S ∈ R^(K×V) |
| 2025-09-29 | DSA | DeepSeek-V3.2-Exp[^dsa-release] | Indexer 选 top-k,主 MLA 稀疏读取 | MLA cache + Indexer K |
| 2025-10-30 | KDA | Kimi Linear[^kda-paper] | key-channel-wise 对角衰减的 delta-rule | S ∈ R^(K×V) |
三条演进路线
定义:序列长度为 T,Query head 数为 Hq,KV head 数为 Hkv,head 维度为 d,MLA 的 KV latent 维度为 r,DSA 选出的历史位置数为 k。
| 结构 | Token 连通性 | 随 T 增长的主要缓存 |
单步 decode 主计算 | 优化焦点 |
|---|---|---|---|---|
| Full/MHA | Dense | 2 × T × Hq × d |
O(T × Hq × d) |
基线 |
| MQA | Dense | 2 × T × d |
O(T × Hq × d) |
KV cache 与带宽 |
| GQA | Dense | 2 × T × Hkv × d |
O(T × Hq × d) |
质量与 KV 成本折中 |
| MLA | Dense | T × (r + d_rope) |
仍扫描全部历史 latent | 低秩 KV cache |
| GDN | Recurrent | 与 T 无关的 H × K × V 状态 |
O(H × K × V) |
固定状态 |
| KDA | Recurrent | 与 T 无关的 Hv × K × V 状态 |
O(Hv × K × V) |
更细粒度遗忘 |
| DSA | 主注意力 top-k | MLA cache + Indexer K | Indexer 扫描 T,主 MLA 读取 k |
长上下文主计算稀疏化 |
这张表解释了一个常见误区:KV cache 更小、token 连通性更稀疏、算法复杂度更低是三个不同命题。MQA/GQA 改第一个,DSA 改第二个,GDN/KDA 改第三个所依赖的历史表示。
Dense Softmax 家族
Full Attention
对输入 X,每个 head 独立计算:
1 | Qh = X WQh, Kh = X WKh, Vh = X WVh |
Hugging Face 的 Llama eager 实现把投影、score、softmax 和 value 聚合完整暴露出来:[^llama-code]
1 | query_states = self.q_proj(hidden_states).view(hidden_shape).transpose(1, 2) |
瓶颈有两层:prefill 需要形成 T × T score;decode 虽然每步只有一个新 Query,却要读取越来越长的 K/V cache,常被显存带宽限制。
MQA
MQA 保留 Hq 个 Query head,但只生成一组 K/V:
1 | Qi = X WQi, K = X WK, V = X WV |
Llama 的同一个实现通过 num_key_value_heads 表达 MHA、GQA 与 MQA。MQA 的配置边界是 num_key_value_heads = 1;repeat_kv 只创建与 Query head 对齐的计算视图,不代表 cache 中保存了 Hq 份 K/V:[^llama-code]
1 | self.num_key_value_groups = ( |
MQA 的优势集中在 decode cache 和内存读取。代价是所有 Query head 只能从同一份 K/V 表示读取信息,可能损失 head 多样性。
GQA
GQA 在 MHA 与 MQA 之间引入 Hkv 组 K/V,每组服务 Hq / Hkv 个 Query head:
1 | group(i) = floor(i / (Hq / Hkv)) |
对应的开源边界仍是 Llama 的两行投影和 repeat_kv:[^llama-code]
1 | self.k_proj = nn.Linear(hidden_size, num_key_value_heads * head_dim) |
因此 GQA 的准确理解是:用一部分 head 多样性换取一部分 KV cache 和带宽收益。它仍然是对全部历史 token 的 dense attention。
MLA
MLA 不再以“减少 KV head 数”压缩 cache,而是把所有 head 的 K/V 联合投影到低维 latent:
1 | cKV = WDKV h |
DeepSeek-V2 的兼容实现直接展示了联合降投影和位置分量拆分:[^deepseek-v2-code]
1 | compressed_kv = self.kv_a_proj_with_mqa(hidden_states) |
真正体现 memory-optimal decode 的是 DeepSeek 原生推理代码:cache 只分配 kv_lora_rank 和 qk_rope_head_dim;decode 时把 WUKV 的 K 部分吸收到 Query,把 V 部分吸收到输出路径:[^deepseek-v32-mla-code]
1 | self.kv_cache = torch.zeros(max_batch, max_seq, self.kv_lora_rank) |
MLA 压缩的是 每个 token 的历史表示,并没有选择更少的历史 token。没有 DSA 时,score 仍覆盖全部可见位置。
递归状态家族
GDN
GDN 仍产生 Q/K/V,但 K/V 不进入按 token 增长的 cache。它先经过短卷积与归一化,再把当前 token 写入固定状态 S:
1 | S_bar_t = exp(g_t) S_(t-1) |
其中 g_t 在 GDN 参考实现中是 [B,T,H],即每个 head 一个标量衰减;beta_t 控制 delta 写入强度。FLA 层代码展示 Q/K/V 的短卷积和 gate 输入:[^gdn-layer-code]
1 | q = self.q_conv1d(x=self.q_proj(hidden_states), ...)[0] |
Naive recurrence 则把状态更新写得最清楚:[^gdn-naive-code]
1 | b_q = q[:, :, i] |
固定状态不是无损 KV 压缩。多个历史 token 会竞争同一矩阵容量,模型需要学习何时遗忘、何时覆盖。训练时可用 chunk/parallel 算法加速,但语义上仍是按时间递推。
KDA
KDA 延续 delta-rule,却把 g_t 从 [H] 扩展为 [Hv,K]。于是每个 value head 的每个 key channel 都有独立衰减:
1 | S_bar_t = Diag(exp(g_t)) S_(t-1) |
Kimi Linear 模型实现先投影并短卷积 Q/K/V,再从两层低秩投影产生 per-dimension gate:[^kimi-model-code]
1 | q = self.q_conv1d(x=self.q_proj(hidden_states), ...)[0] |
FLA naive KDA 明确记录 g: [B,T,HV,K],并在 key channel 维衰减状态:[^kda-naive-code]
1 | # g: [B, T, HV, K], S: [B, HV, K, V] |
更细粒度 gate 提高了状态表达能力,也增加 gate 生成和状态更新的复杂度。Kimi Linear 因此采用 KDA 与 MLA 混合层,而不是宣称固定状态可以完全替代 softmax attention。
Token 稀疏家族
DSA
DSA 建立在 MLA 上。Lightning Indexer 为 Query 生成多 head 索引向量,为每个历史 token 生成共享 Indexer K 和按 head 权重,再选择 top-k:
1 | s_tj = sum_h w_th <qI_th, kI_j> |
DeepSeek-V3.2-Exp 的开源 Indexer 使用 FP8 Q/K、独立权重和 topk:[^deepseek-v32-code]
1 | q = self.wq_b(qr).view(bsz, seqlen, self.n_heads, self.head_dim) |
主 MLA 用这些 indices 构造稀疏 mask;decode 仍从压缩 cKV cache gather,而不是回到完整 K/V:[^deepseek-v32-code]
1 | topk_indices = self.indexer(x, qr, start_pos, freqs_cis, mask) |
混合架构
长上下文模型越来越少押注单一 Attention。线性或递归状态层负责大部分低成本历史传播,周期性 Full/MLA 层补充精确 token 检索,是更现实的质量—效率折中。
这种混合思想也适用于其他组合:GQA 降低 cache,DSA 降低主 attention 的 token 数,二者解决不同维度;MLA 与 DSA 更是明确的基座和索引关系。
选择框架
| 主要瓶颈 | 优先考察 | 原因 | 必验风险 |
|---|---|---|---|
| Decode KV cache / 带宽 | GQA、MQA、MLA | 直接减少每 token 历史表示 | 质量回退、kernel 与 cache layout |
| 极长上下文的固定内存 | GDN、KDA | recurrent state 不随 T 增长 |
状态容量、训练 kernel、跨序列边界 |
| 极长上下文主 attention FLOPs | DSA | 主 MLA 只读取 top-k | Indexer recall、top-k 通信、稀疏 kernel |
| 质量优先、上下文适中 | Full/MHA、GQA | 精确 dense retrieval,生态成熟 | cache 和带宽上限 |
| 质量与极长上下文同时要求 | Hybrid | 递归层传播、周期性 softmax 检索 | 层型比例、状态/cache 双系统 |
工程选型时至少测四件事:
- Prefill 与 decode 分开:二者的算力、带宽和并行特性完全不同。
- 峰值 cache 与实际吞吐同时测:更小的理论 cache 可能被不合适的 layout、dequant 或 gather 抵消。
- 固定准确率条件下比较:MQA/GQA group 数、MLA rank、DSA top-k、GDN/KDA state 维度都属于质量—成本旋钮。
- 按实现边界比较:FlashAttention、FlashMLA、chunk recurrence 与稀疏 gather 的 kernel 成熟度往往比大 O 公式更决定真实速度。
常见误区
- “MQA/GQA 是稀疏 attention”:错误。它们共享 K/V head,但仍读取所有历史 token。
- “MLA 把 attention 变成线性复杂度”:错误。MLA 压缩每个 token 的 K/V 表示,没有压缩 token 数。
- “GDN/KDA 只是更激进的 KV cache 压缩”:不准确。它们改变了历史记忆算法,用固定状态递推替代逐 token softmax 检索。
- “DSA 只算 top-k,所以模块没有全历史成本”:不完整。主 MLA 是 top-k,Indexer 仍扫描历史。
- “后出现的结构必然取代前者”:错误。真实模型广泛使用混合层,不同方法解决的是 cache、状态容量、token 连通性或 kernel 效率中的不同问题。
总结
Attention 的发展路径可以压缩成一句话:先共享 K/V,再联合压缩 K/V;另一条路线把历史写入固定状态;最新的稀疏路线先检索,再让昂贵的主注意力读取少数 token。
理解这些结构时,不要只背缩写。顺着代码追四个对象就足够:
Q/K/V如何投影、按多少 head 组织;- cache 保存完整 K/V、latent、Indexer K,还是固定状态;
- score 是对全部历史、top-k,还是根本不存在显式
T×T矩阵; - 被省掉的成本是否转移到了低秩重建、状态更新、索引器或稀疏 gather。
本文七张计算图均依据版本固定源码自绘,SVG 源文件与 1920×1080 PNG 同时保留,并通过结构、箭头、碰撞、语义几何与版式校验。
参考文献
[^mha-paper]: Vaswani et al., Attention Is All You Need, first submitted 2017-06-12.
[^mqa-paper]: Shazeer, Fast Transformer Decoding: One Write-Head is All You Need, first submitted 2019-11-06.
[^gqa-paper]: Ainslie et al., GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints, first submitted 2023-05-22.
[^mla-paper]: DeepSeek-AI, DeepSeek-V2: A Strong, Economical, and Efficient Mixture-of-Experts Language Model, first submitted 2024-05-07.
[^gdn-paper]: Yang et al., Gated Delta Networks: Improving Mamba2 with Delta Rule, first submitted 2024-12-09.
[^dsa-release]: DeepSeek-AI, DeepSeek-V3.2-Exp release, 2025-09-29; model and paper repository.
[^kda-paper]: Zhang et al., Kimi Linear: An Expressive, Efficient Attention Architecture, first submitted 2025-10-30.
[^llama-code]: Hugging Face Transformers, modeling_llama.py, commit 29985e67.
[^deepseek-v2-code]: DeepSeek-AI, modeling_deepseek.py, revision 604d5664.
[^deepseek-v32-mla-code]: DeepSeek-AI, inference/model.py MLA, commit 87e509a2.
[^deepseek-v32-code]: DeepSeek-AI, inference/model.py, commit 87e509a2.
[^gdn-layer-code]: FLA, fla/layers/gated_deltanet.py, commit c70f11c5.
[^gdn-naive-code]: FLA, fla/ops/gated_delta_rule/naive.py, commit c70f11c5.
[^kimi-model-code]: Moonshot AI, modeling_kimi.py, revision e1df551a.
[^kda-naive-code]: FLA, fla/ops/kda/naive.py, commit c70f11c5.
Attention Architecture Evolution