经典 Transformer 到今天的大模型,关节上换了几把刀:KV Cache、GQA、RoPE、SwiGLU、Flash Attention、MoE。 教学性模拟--所有图示为确定性示意,用以理解原理,非真实模型实现。
2017 的配方 vs 今天 Llama 系的配方。改了哪几样。
| 部位 | 2017 经典 | 现代 LLM (Llama 系) |
|---|---|---|
| 归一化 | LayerNorm | RMSNorm(更快) |
| 位置编码 | 正余弦绝对 | RoPE(旋转,外推好) |
| 激活 | ReLU / GELU | SwiGLU(带门控) |
| 归一化位置 | post-norm | pre-norm |
| 注意力头 | 标准 MHA | GQA(省 KV cache) |
| 推理 | 逐 token 重算 | KV Cache + Flash Attention |
| FFN | 稠密 | 可换 MoE(稀疏) |
生成时,已算过的 K/V 别重算,存起来直接复用。点 STEP 逐词生成。
今天 天气 很
没 KV Cache:每生成一个新词,要对前面所有词重算一遍 K/V--长度 N 就 O(N²) 累加。
有 KV Cache:旧 K/V 存着,新词只需算自己那一份,接到 cache 末尾。生成复杂度从 O(N²) 降到 O(N)。这就是为什么长文本生成能跑得动。
KV cache 太占显存。让多个 Q 头共享同一份 K/V。点 tab 看三种。
每个 Q 头有自己专属的 K/V 头。效果最好,但 KV cache = 头数 × 维度,最占显存。
所有 Q 头共享同一份 K/V。cache 直接砍到 1 份,但效果掉得明显。
折中:把 Q 头分成几组,组内共享一份 K/V。质量接近 MHA,cache 省好几倍。现代大模型几乎都选它。
不另加位置向量,而是按位置旋转 Q/K。(第 1 篇有直觉,这里讲为什么强)
Q·K 的点积,两个向量旋转后再点积,结果只取决于它们的旋转角差 = 相对位置。于是相对位置直接写进了注意力打分里。三个好处:① 不占额外参数(不是查表);② 外推好(训练没见过的长度也能用,配合长度扩展技巧可到百万 token);③ 易扩展(调旋转基底就能拉长上下文)。
两个小改动,省算力、提效果。
FFN 升维后多一条门控分支:SwiGLU(x) = Swish(xW) ⊙ (xV)。一半算值、一半当开关决定放多少。比 GELU 表达力更强,代价是多一组权重(所以 d_ff 常配 8/3·d_model 平衡参数)。
LayerNorm 要算均值和方差;RMSNorm 只用均方根去缩放,不算均值。少一步运算、效果几乎一样,大模型里这点算力×万亿次就省大了。Llama 全系用 RMSNorm。
数学完全一样,快的是「搬数据」的方式。
注意力要把 N×N 的矩阵算出来,N 大了显存扛不住,得分块算(tiling)。普通做法在慢速显存(HBM)和快速缓存(SRAM)间反复搬运,搬运本身就慢。Flash Attention 重排计算顺序,让数据进一次 SRAM 就把该算的算完再写回,IO 次数大降。
关键点:算出来的结果和标准注意力数学上等价,不是近似。它是「同样的算法、更聪明的实现」,长上下文必备。现在成了主流训练/推理后端的默认选择。
把一个大 FFN 换成多个小 FFN(专家),每个 token 只激活其中几个。点 RUN 路由。
"猫"
普通模型:每个 token 过同一个大 FFN,算力 = 参数量。
MoE:有 N 个「专家」(小 FFN),一个路由器(gate)把 token 送到 top-2/top-k 个专家,其余不激活。结果:参数量很大(知识多),但单次计算量小(省算力)。这就是 DeepSeek/Mixtral 等能做超大又跑得动的原因。
| 术语 | 一句话 |
|---|---|
KV Cache | 缓存已算 K/V,生成时复用,复杂度 O(N²)->O(N) |
MQA | 所有 Q 头共享一份 K/V,省显存但掉点 |
GQA | Q 分组、组内共享 K/V,质量与省兼顾,主流 |
RoPE | 按位置旋转 Q/K,注入相对位置,外推好 |
SwiGLU | 带门控的激活,替代 GELU,表达力更强 |
RMSNorm | 只去方根缩放不算均值,比 LayerNorm 快 |
Flash Attention | 数学等价、IO 重排,长上下文快 2-4× |
MoE | 多专家稀疏激活,参数大而计算省 |
从「文字变向量」到「现代稀疏大模型」,六篇走完 Transformer 的骨肉关节。建议回头动手写一个 mini 版--把零件自己拼一遍,刀法才真在手里。