跳到正文
阿里雲開發者社區 AI·· 51 分鐘前AI 評分57

把 Llama 2 7B 一塊一塊拆開:6.74B 參數、13.5 GFLOPs 的由來

把 Llama 2 7B 一块一块拆开:6.74B 参数、13.5 GFLOPs的来历

AI 導讀

這篇教程逐層拆解 Llama 2 7B,計算其約 6.74B 參數及單 token 前向約 13.5 GFLOPs 的由來。文中將模型拆為 Embedding、32 個 Transformer Block 和 LM Head,指出約 96% 參數位於 Block,並推導 FFN 中間維度 11008 的由來。

正文

2026-11-06 4

版权

版权声明:

本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《 阿里云开发者社区用户服务协议》和 《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写 侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

简介: 本课以Llama 2 7B为标本,逐层拆解大模型:从Embedding查表、32层Transformer Block结构(含Attention与SwiGLU FFN)、到LM Head输出,手算每块参数与计算量,揭示96%参数在Block、FFN占主导等关键事实。免费在线可读,含完整源码(MIT许可)。

前四篇讲了 Self-Attention、Transformer 骨架、现代结构改造、Tokenization。这一篇把它们装回一个真实模型——以 Llama 2 7B 为标本,从 Embedding 到 LM Head 逐层拆开,每个数字都自己乘一遍。内容来自我做的一套 34 课大模型课程的第 5 课。

问题 1:拆开一个 7B 模型,里面到底有几层?每层在干什么?

Llama 2 7B 只有三部分:一个 Embedding 层、32 个完全相同的 Transformer Block、一个 LM Head(把隐藏向量投影成词表概率的输出层)。每个 Block 里再分 Attention 和 FFN 两个子层,每个子层前各有一个 RMSNorm。

可以把结构想成一条装配线:首尾各一个工位,中间几十个工位做一模一样的加工——这些重复的工位就是 Block。

组件 包含什么 参数 占比
Token Embedding 32000 × 4096 查表矩阵 131.1M 1.95%
32 × Transformer Block 每层 Attention + FFN + 2×RMSNorm 32 × 202.4M = 6,476M 96.1%
LM Head + Final RMSNorm 独立输出矩阵 + 最后归一化 131.1M + 0.27M 1.95%

三者相加 6,738.4M ≈ 6.74B,这就是「7B」的由来。一个 Block 内部:

子层 操作 参数
Input RMSNorm 归一化 4096(只有缩放参数 γ)
Attention QKV 三个投影 + O 投影,各 4096×4096 4 × 16.78M = 67.1M
Post-Attention RMSNorm 归一化 4096
FFN(SwiGLU) gate / up / down 三个矩阵 3 × 45.09M = 135.3M

一个结论值得记住:模型 96% 的参数在 Block 里,而 Block 里 FFN 又占 67%(135.3 / 202.4)。FFN 比 Attention 大两倍,不是设计失误——它才是「知识存储」的主体。

问题 2:从「你好」到一堆 4096 维向量,Embedding 做了什么运算?

答案是:只做查表,没有乘加。

有一个 32000 × 4096 的矩阵 W_embed,token ID 是 t,输出就是第 t 行。所以:

字 Token ID(示意) 参数来源
你 12845 词表第 12845 行
好 6721 词表第 6721 行

输入 tensor 形状 [1, 2](batch=1,seq_len=2),查表后变成 [1, 2, 4096]。

项目 计算 结果
参数数量 32000 × 4096 131,072,000(131M)
fp16 显存 131M × 2 bytes 262 MB(250 MiB)
fp32 显存 131M × 4 bytes 524 MB(500 MiB)

262 MB 常驻显存,对 24 GB 显卡约占 1%——看着不多,但它和 LM Head 是两张一样大的表。

这里有个容易混的点:Llama 2 没有做 weight tying(权重绑定,让输入查表和输出投影共用同一份矩阵)。GPT-2 做了,能省一半;Llama 2 的 LM Head 是独立的 [4096, 32000] 矩阵,所以 6.74B 里这两块各算了一次 131M。

问题 3:一个 Attention Head 里,Q、K、V 是怎么从输入一步步算出来的?

输入 [1, 2, 4096] 进来,经过 QKV 投影 → 拆头 → 算分数 → 加权求和 → 合并 → O 投影,出去还是 [1, 2, 4096]。

用借书打比方:Q 是你手里的索书号,K 是书脊上的分类标签,V 是书页里的正文——拿 Q 和每张 K 比,谁最像就借走谁的 V。

第 1 步,三个投影,每个都是一次矩阵乘法:

操作 计算 输出形状 参数
Q = X × W_Q [1,2,4096] × [4096,4096] [1, 2, 4096] 16.78M
K = X × W_K 同上 [1, 2, 4096] 16.78M
V = X × W_V 同上 [1, 2, 4096] 16.78M

第 2 步,把 4096 维拆成 32 个头,每头 128 维:[1, 2, 4096] → [1, 32, 2, 128]。

第 3 步,每个头单独算 Q·Kᵀ/√128,得到 2×2 的注意力分数(示意值):

对「你」 对「好」
「你」这一行 0.43 0.18
「好」这一行 0.15 0.52

√128 ≈ 11.31,作用是压住点积的量级,防止 softmax 变成 one-hot、梯度消失。

第 4 步,按行做 softmax:

  • 「你」:[0.43, 0.18] → [0.562, 0.438]
  • 「好」:[0.15, 0.52] → [0.409, 0.591]

再用这两个权重去加权 V,得到每个位置的输出。

第 5 步,32 个头拼回 [1, 2, 4096],乘 W_O 再变一次维度不变的映射。整个 Attention 层参数 = QKV 50.3M + O 16.78M = 67.1M。

为什么是 32 个头而不是 1 个?如果只有一个 4096 维的头,主谓关系、修饰关系、位置相邻这些模式会全混在一个注意力分布里;32 个头等于 32 个视角同时看同一句话,各自学一种关系。

问题 4:一个 token 走完 32 层,到底要算多少次浮点运算?

只需要一条规则:一次前向里,每个权重恰好做一次「乘 + 加」,也就是 2 FLOPs。所以前向 FLOPs ≈ 2 × 参数量。

先把三种口径说清,避免和论文对不上:

口径 数什么 Llama 2 7B
只数乘法 乘一次算 1 ≈ 1N = 6.7 GFLOPs
只计前向,乘加都数 每权重 2 FLOPs ≈ 2N = 13.5 GFLOPs
前向 + 反向 反向约是前向 2 倍 ≈ 6N = 40.4 GFLOPs

套进具体数字(N = 6.74B):

阶段 计算 结果
单 token 前向 2 × 6.74e9 13.5 GFLOPs
单 token 反向 4 × 6.74e9 27.0 GFLOPs
单 token 训练 6 × 6.74e9 40.4 GFLOPs

注意 2N 里的 N 已经是全部 32 层的参数总和,所以不需要再乘 32。

训练总算力就是把这个式子乘以 token 数 D:C = 6ND。

训练规模 计算 结果
1T token 6 × 6.74e9 × 1e12 4.04 × 10²² FLOPs
2T token 6 × 6.74e9 × 2e12 8.09 × 10²² FLOPs

换成推理场景:prefill 1000 个 token ≈ 1000 × 2 × 6.74e9 = 13.5 TFLOPs;生成 100 个 token ≈ 1.35 TFLOPs。这里只算 2N,忽略了 attention 的 O(L²) 项——几百 token 的短上下文下它很小,上下文极长时才会盖过 2N。

问题 5:FFN 的中间维是 11008——这个怪数字怎么定出来的?

不是随手取的整数,是「参数量守恒」倒推出来的。

标准 FFN 用两个矩阵,中间维惯例取 4d,参数量 = 2 × d × 4d = 8d²。d = 4096 时是 134.2M。

SwiGLU 用三个矩阵(gate / up / down),参数量 = 3 × d × d_ff。要让两者持平:

3 · d · d_ff = 8d²  →  d_ff = 8d/3 = 8 × 4096 / 3 ≈ 10922.7

再向上对齐到 256 的整数倍:10922.7 / 256 ≈ 42.67 → 43 × 256 = 11008。

于是每层 FFN = 3 × 4096 × 11008 = 135.3M,正好接近标准的 134.2M。换个取值会怎样:

方案 每层 FFN 参数 与 11008 之差 32 层合计
3 矩阵 × 11008(实际) 135.3M 基准 4.33B
3 矩阵 × 16384(若按 4d) 201.3M +66.0M 6.44B
2 矩阵 × 11008(少一个矩阵) 90.2M −45.1M 2.89B

按 4d 取会让 32 层多花 2.11B 参数;少一个矩阵则每层少 45.1M、参数量不再守恒。11008 正好卡在「3 个矩阵 × 2/3 中间维」这一点上。

这套账换个模型照样能算:Llama 3 8B 就把中间维放到 14336,比 8d/3 更大,用参数换表达力。

问题 6:「7B」这个数字,是怎么一块一块加出来的?

把每一块矩阵乘出来,再加总。Llama 2 7B 的超参:d = 4096、32 层、32 个注意力头、FFN 中间维 11008、词表 32000。

每层 Attention,4 个 4096×4096:

矩阵 参数
W_q 16.78M
W_k 16.78M
W_v 16.78M
W_o 16.78M
合计 67.11M

每层 FFN,SwiGLU 的 3 个矩阵:

矩阵 形状 参数
gate_proj 4096 × 11008 45.09M
up_proj 4096 × 11008 45.09M
down_proj 11008 × 4096 45.09M
合计 3 × 45.09M 135.27M

每层 67.11 + 135.27 = 202.38M,乘 32 层 = 6,476.01M。

最后加上首尾:

账目 计算 参数
32 层 Block 202.38M × 32 6,476.01M
Embedding 32000 × 4096 131.07M
LM Head 32000 × 4096 131.07M
RMSNorm 32×2×4096 + 4096 0.27M
总计 相加 6,738.42M ≈ 6.74B

两张表合计占 262.14M / 6,738.42M ≈ 3.9%;如果做 weight tying,能省下其中一张、约 1.9%。这也解释了工程上为什么要权衡词表大小:词表越大,首尾两张表越贵。

小结

问题 结论 一个数字
里面有几层 Embedding + 32 Block + LM Head 96% 参数在 Block 里
Embedding 做什么 纯查表,无乘加 131M 参数 = 262 MB
Q/K/V 怎么来 三次投影 → 拆 32 头 → 分数 → 加权 → 合并 每层 67.1M
多少浮点运算 前向 2N,训练 6ND 单 token 前向 13.5 GFLOPs
11008 怎么来 8d/3 向上对齐 256 3 × 4096 × 11008 = 135.3M
7B 怎么加出来 逐块乘加 6,738.42M ≈ 6.74B

参考与说明

文中所有数字(Embedding 参数量、每层 Attention/FFN 参数、32 层合计、fp16 显存、11008 的推导、2N/6ND、softmax 结果)我都用 Python 独立复算过。"示意值"标明的是为演示取的数字,不是模型真实输出。

说明:这套课程由 AI 在我设计的规则下生成,再经过脚本检查和独立审查;审查发现过不少问题,都写在仓库 README 里。如果你发现错误,欢迎在仓库提 Issue,写清位置,我会逐条核实。

继续学

上一篇是第 4 课「Tokenization 机制」,讲 BPE 怎么合并、中文为什么更费 token。这一课之后是第 6 课「从 Transformer 到 LLM 全景图」。每张卡片后面还有 AI 助教,可以接着追问(每人每天有次数限制)。

來源:阿里雲開發者社區 AI · developer.aliyun.com