这一页是 Transformer 架构 的动手版:公式和推导在那边,这里只做一件事——让每个机制都能拖、能点、能看到数字怎么变。图里的数字都在浏览器里实时计算;模型家族的具体配置变化很快,以文末的论文和公开 config 为准。

这次要拆什么一张会变形的结构图,和六个改变了它的优化
需要先会attention 公式 · residual · causal LM
真正的主角KV cache · GQA / MLA · sliding window · RoPE · MoE · FlashAttention
最后要能证明每个优化省的是显存、访存还是计算,代价又是什么

图例贯穿全页:蓝色是 query 和 attention 相关的东西,橙色是 key、FFN 和 expert,绿色是 value 和 embedding。

结构图:一个 block,很多家族

先看最常见的自回归 Transformer:把 token 变成向量,经过多层 block,预测下一个 token。这里的“重复”指结构相似,不是每层共用同一组参数。标准 block 里,attention 在 token 之间传递信息,FFN 对每个 token 单独做变换,两条分支都有残差连接(residual connection)。混合架构也可能把部分 attention 换成循环状态更新,不能把这张图当成所有 LLM 的统一结构。

先比较几处最容易看见的差别:norm 放在哪、位置怎么编码、K/V head 怎么共享、FFN 是 dense 还是 MoE。选一个家族,看哪里动了;右侧带圆点的行,就是相对上一个选择发生变化的地方。数据、训练目标和推理配置不在这张结构图里,却同样影响效果。

图解 结构图:选一个模型家族,看哪里变了

这张交互图需要启用 JavaScript。

最值得对比的三步:Transformer ’17 → GPT-2 / 3(去掉 encoder 和 cross-attention,norm 移进残差分支)、GPT-2 / 3 → Llama 3(LayerNorm → RMSNorm,绝对位置 → RoPE,GELU → SwiGLU,MHA → GQA)、Llama 3 → DeepSeek-V3(GQA → MLA,dense FFN → MoE)。

Self-attention:一步一步算

每个 token 产生三个向量:query(我在找什么)、key(我能提供什么)和 value(我要传递什么)。分数是点积(inner product) $q\cdot k$,除以 $\sqrt{d_k}$,加上 mask 保证看不到未来,再过 softmax;输出是 value 的加权平均,也就是 $\operatorname{softmax}(QK^\top/\sqrt{d_k})\,V$。

图解 Self-attention 一步一步算(6 个 token 的玩具例子)

这张交互图需要启用 JavaScript。

这是一个玩具例子:6 个 token、$d_k=4$,权重是手工设定的(不是训练出来的),方便逐步核对。把鼠标放到某一行,可以跟着这个 token 走完整个计算;关掉 causal mask,就能看到双向 attention,但这还不是完整的 BERT:训练目标和其他层也不同。为什么要除以 $\sqrt{d_k}$、三个投影矩阵各自的含义,见 Transformer 架构。

为什么解码离不开 KV cache

生成是一个 token 一个 token 来的。如果每次都完整重算长度为 $t$ 的前缀,单层每个 head 要重算 $t$ 个 key、$t$ 个 value,以及 $t(t+1)/2$ 个有效 causal 分数。模型权重、前缀和位置配置不变,且关闭 dropout 时,过去的 K/V 可以复用;每步只需算新 token 的 K/V 和一行 attention 分数。修改前缀、权重或位置处理后,旧 cache 不一定还能用。

图解 解码 10 个 token:每一步到底算了什么

这张交互图需要启用 JavaScript。

切到“没有 cache”再看一遍,注意两条累计柱的差距。在层数和维度固定时,attention 的单步工作量从 $O(t^2)$ 降到 $O(t)$,代价是 cache 随长度增长。小 batch 解码常受读取权重和 KV 的带宽限制(batch 变大后怎样变化,见推理性能);大 batch、不同 kernel 或硬件下,瓶颈可能不同。下一节只比较 KV 存储,不据此保证吞吐量。

压缩 cache:MHA → GQA → MQA → MLA

每层每个 token 的 cache 大小是

$$ 2 \times n_{\text{kv heads}} \times d_{\text{head}} $$

个数值,假设 K/V 维度相同、每层配置一致。再乘层数、token 数和每个数的字节数,才是存储字节数。固定 KV head 数和维度后,query head 数不会额外进入这个公式:

  • MQA(2019):所有 query head 共享一个 K/V head。相同维度下,它在这类 head 共享方案中缓存最小;质量是否下降要看训练和任务。
  • GQA(2023):一组 query head 共享一个 K/V head,在存储和表达能力之间折中。下表中的 Llama 3、Mistral、Qwen3 和 Gemma 3 都采用了它。
  • MLA(DeepSeek-V2,2024):缓存压缩后的 KV latent,再单独存 RoPE key。每层每 token 是 $d_c+d_r$ 个数值,不是通用的 $4.5\,d_{\text{head}}$。DeepSeek-V3 的配置是 $512+64=576$;矩阵吸收(weight absorption)还能避免在解码时显式还原全部 K/V,细节见 MLA 推导。
图解 每个 token 要缓存多少个 K/V head

这张交互图需要启用 JavaScript。

分组查询注意力一览:MHA 有 H 个 query、key、value 头;MQA 让所有 query 头共用一组 key/value;GQA 让每组 query 头共用一组 key/value,介于两者之间。
原文图分组查询注意力一览:MHA 有 H 个 query、key、value 头;MQA 让所有 query 头共用一组 key/value;GQA 让每组 query 头共用一组 key/value,介于两者之间。图源:Ainslie et al., 2023 · GQA · Figure 2 · CC BY 4.0 · 缩小尺寸并转为 WebP

下半部分是控制变量计算器,不是实际部署配置:固定层数、长度与存储精度,再替换 attention 方案。MLA 行固定使用 512 维 latent + 64 维 RoPE key。它不包含权重、临时激活、KV 分页碎片或跨卡副本,也不表示每个模型原生支持这四种方案。

不是每个 token 都要看到所有 token

完整的 causal attention 是 $O(n^2)$。Sliding-window attention 让每个 token 只看最近的 $w$ 个 token:计算量变成 $O(n\,w)$,cache 也封顶在 $w$。信息仍然能传得更远,因为每多一层,可达范围就再多一个窗口——$L$ 层之后大约是 $L\,(w-1)+1$ 个 token。

图解 谁能看到谁:attention pattern

这张交互图需要启用 JavaScript。

StreamingLLM 和已有做法对比:(a) 全量注意力,缓存越来越大,超出预训练长度后效果下降;(b) 只缓存最近 L 个 token 的窗口注意力,开头 token 的 KV 被挤掉后效果骤降;(c) 每步用最近 L 个 token 重算的滑动窗口,效果好但很慢;(d) StreamingLLM 保留开头几个 token(attention sink)再加最近的 token,又快又稳。
原文图StreamingLLM 和已有做法对比:(a) 全量注意力,缓存越来越大,超出预训练长度后效果下降;(b) 只缓存最近 L 个 token 的窗口注意力,开头 token 的 KV 被挤掉后效果骤降;(c) 每步用最近 L 个 token 重算的滑动窗口,效果好但很慢;(d) StreamingLLM 保留开头几个 token(attention sink)再加最近的 token,又快又稳。图源:Xiao et al., 2023 · StreamingLLM · Figure 1 · CC BY 4.0 · 转为 WebP
滑动窗口注意力:每个 token 最多看前一层的 W 个 token(图中 W = 3)。窗口外的 token 仍会影响预测:每过一层,信息最多往前传 W 个 token,k 层之后最多 k × W 个。
原文图滑动窗口注意力:每个 token 最多看前一层的 W 个 token(图中 W = 3)。窗口外的 token 仍会影响预测:每过一层,信息最多往前传 W 个 token,k 层之后最多 k × W 个。图源:Jiang et al., 2023 · Mistral 7B · Figure 1 · CC BY 4.0 · 缩小尺寸并转为 WebP

拖动“堆叠层数”看浅色区域怎么扩张。这里的范围是信息可能经过的路径,不保证远处内容一定被记住。Gemma 3 采用 5 层 local 配 1 层 global;gpt-oss 交替使用窗口层与全局层。StreamingLLM 则保留开头的 sink token 和最近窗口,减少直接丢掉开头 KV 带来的失稳;已经移出窗口的细节并不会因此完整保留。

RoPE:把位置变成旋转

RoPE 不往 embedding 上加位置向量,而是旋转 $q$ 和 $k$ 的成对维度,每对使用不同频率。固定内容向量后,位置对点积的影响取决于相对距离 $m-n$;真实 attention 分数仍然依赖内容,不是只看距离。

图解 RoPE:位置就是旋转

这张交互图需要启用 JavaScript。

点播放:同时移动两个位置,分数不变。再拖动距离 $\Delta$,会看到曲线起伏,不是逐点单调下降。单个旋转平面就能说明:把两个内容向量都设为 $(1,0)$,点积随相位差是 $\cos\Delta$;从 $\pi$ 到 $2\pi$,它反而从 -1 升到 1。调大 base 会减慢部分维度的旋转,但仅改这个数不保证长上下文好用,还要结合训练和评估。推导见 Transformer 架构 · RoPE。

MoE:参数更多,不必每次都算完

MoE 把一个 FFN 换成多个 expert,再由 router 为每个 token 选其中 $k$ 个。固定每个 expert 的大小和 $k$ 时,增加 expert 总数不增加被选中 FFN 的算术量。但 router、通信和负载不均仍有成本;选 2 个同样大的 expert,也不能说和原来 1 个 dense FFN 一样便宜。

图解 MoE:一次一个 token 经过 FFN

这张交互图需要启用 JavaScript。

MoE 层:router 把每个输入向量分给 8 个专家中的 2 个,输出是这两个专家输出的加权和。Mixtral 里每个专家就是普通 Transformer 的 FFN 块。
原文图MoE 层:router 把每个输入向量分给 8 个专家中的 2 个,输出是这两个专家输出的加权和。Mixtral 里每个专家就是普通 Transformer 的 FFN 块。图源:Jiang et al., 2024 · Mixtral · Figure 1 · CC BY 4.0 · 缩小尺寸并转为 WebP

格子按真实数量画(8、128 或 256 个 expert),所以你看到的稀疏度就是真实的稀疏度。DeepSeek-V3 多了一个所有 token 都会经过的 shared expert。图里的 router 是随机的,只为演示负载分布;真实的 router 是一个学出来的线性层,负载均衡要靠辅助 loss 或 bias 项来维持。完整的一组笔记见 MoE 系列。

FlashAttention:数学不变,少搬显存

朴素 attention 会把完整的 $n\times n$ 分数和概率矩阵写到 HBM,来回读写可能很贵。FlashAttention 用分块和 online softmax 累积输出,不需要把这两张完整矩阵存到 HBM。它不靠稀疏化来近似 attention,但浮点计算顺序不同,结果不保证逐位相同(bitwise identical)。省下多少时间仍取决于形状、硬件和 kernel,不能一概说 attention 总是访存瓶颈。

图解 FlashAttention:attention 矩阵放在哪里

这张交互图需要启用 JavaScript。

切到“标准 attention”,看 S 和 P 两个 $n\times n$ 矩阵怎样被完整写进 HBM;再切回来,注意右上角整块被 causal mask 直接跳过的 block。

模型家族速览

下面保留的是这些具体历史版本,不是各家最新型号的排行榜。数字来自对应报告和 config;后续版本见模型家族精读。

家族 整体结构 Norm 位置编码(positional encoding) Attention FFN 上下文 规模
Transformer(2017,base) Encoder–decoder,6 + 6 层 Post-LN · LayerNorm 正弦,加在 embedding 上 MHA · 8 head,另有 cross-attention Dense · ReLU · $d_{ff}$ 2,048 句子对(机器翻译) 65M · $d_{model}$ 512
GPT-2 / GPT-3(2019–20) Decoder-only Pre-LN · LayerNorm,末尾再加一层 可学习的绝对位置 MHA · 25 head(GPT-2 XL)· 96 head(GPT-3,稠密与局部带状稀疏注意力逐层交替) Dense · GELU · 4× 1,024 · 2,048 1.5B:48 层 · 175B:96 层
Llama 3(2024,8B) Decoder-only Pre-norm · RMSNorm RoPE · $\theta$ = 500,000 GQA · 32 query / 8 KV head Dense · SwiGLU · $d_{ff}$ 14,336 8K → 128K(Llama 3.1) 8B:32 层,$d$ 4,096
Mistral 7B(2023) Decoder-only Pre-norm · RMSNorm RoPE GQA · 32 / 8 · sliding window 4,096 Dense · SwiGLU · $d_{ff}$ 14,336 8K,每层窗口 4,096 7B:32 层,$d$ 4,096
Mixtral 8x7B(2023) Decoder-only Pre-norm · RMSNorm RoPE GQA · 32 / 8 · 完整 32K attention MoE · 8 个 SwiGLU expert,选 2 个 32K 总参数约 47B · 激活约 13B
Gemma 3(2025,27B) Decoder-only Pre-norm + post-norm · RMSNorm RoPE · local 层 10k,global 层 1M GQA · 32 / 16 · QK-norm · 5 local(窗口 1,024): 1 global Dense · GeGLU 128K 27B:62 层,$d$ 5,376
Qwen3(2025,235B-A22B) Decoder-only Pre-norm · RMSNorm RoPE · 长上下文用 YaRN GQA · 64 / 4 · QK-norm MoE · 128 个 expert,选 8 个,无 shared expert 原生 32K · YaRN 到 131K 总参数 235B · 激活 22B · 94 层
DeepSeek-V3(2024) Decoder-only Pre-norm · RMSNorm RoPE 作用在单独的 64 维 key 上 MLA · 128 head · 缓存 latent 512 + 64 MoE · 1 shared + 256 routed,选 8 个 128K 总参数 671B · 激活 37B · 61 层
gpt-oss-120b(2025) Decoder-only Pre-norm · RMSNorm RoPE · YaRN 到 131K GQA · 64 / 8 · 隔层 128 窗口 · learned sinks MoE · 128 个 expert,选 4 个 131K 总参数 117B · 激活 5.1B · 36 层

自检

完成这一页后,至少要能解释六个问题:
  1. 从原版 Transformer 到 Llama 3,block 里改了哪四处?各自解决什么问题?
  2. KV cache 在什么条件下可以复用?为什么减少计算后,仍可能卡在内存带宽?
  3. GQA、MQA、MLA 各自缓存的是什么?MLA 的 cache 为什么和 head 数无关?
  4. Sliding window 每层只看 $w$ 个 token,信息是怎么传到更远的地方的?
  5. FlashAttention 为什么是精确的?它省掉的是哪一类开销?
  6. MoE 的总参数量和激活参数量,分别随什么增长?

继续阅读

参考论文

本页术语 4
残差连接 residual connection
x + f(x),让梯度有一条不经过 f 的通路
点积 inner product
两个向量对应分量相乘再求和,双塔的打分方式
逐位相同 bitwise identical
每一个二进制位都一致,比数值近似相等更严格
位置编码 positional encoding
把「第几个 token」的信息注入表示