直觉:三本不同的账
谈大模型动辄"7B"“70B”“千亿参数”,但参数量只是其中一本账。工程上真正要算清的是三件事:
- 参数量:模型有多大,决定权重占多少存储。
- FLOPs:跑一次要多少计算,决定训练成本和推理延迟。
- 显存:能不能塞进卡里,决定你需要几张 GPU。
这三本账互相关联但不等价。一个能"装下"模型权重的显卡,未必能训练它,甚至未必能高效推理它。下面把每本账拆开算。
第一本账:参数量从哪来
Transformer 的参数绝大部分集中在两类线性层。设隐藏维度为 ,层数为 。
注意力部分:每层有 Q、K、V 三个投影加一个输出投影,各是 的矩阵,合计约 。
FFN 部分:标准 FFN 先升维到 再降回,两个矩阵合计约 。
所以每层约 个参数,整个模型主干约:
(这里忽略了 embedding、LayerNorm、bias 等小项。)以一个 、 的模型粗算:,约 6.4B——和常见 7B 模型量级吻合。这个公式让你看到一个关键事实:参数量对 是平方增长的。 宽度翻倍,参数翻四倍。
第二本账:FLOPs 与那个 6N 法则
有一条广为人知的经验估算:训练一个 参数的模型,处理 个 token,总计算量约
这个 6 从哪来?前向传播每个参数对每个 token 大致做一次乘加(2 FLOPs),即 ;反向传播要算输入梯度和权重梯度两部分,约是前向的两倍,即 。加起来每 token 约 。乘以 token 数 就是总量。
推理只有前向,所以推理时每生成一个 token 约 FLOPs。这条法则的实用价值在于快速估算:给定算力预算,能立刻反推能训多大模型、喂多少数据。
注意这是主干矩阵乘法的估算,没算注意力里 那块对序列长度 的依赖。当序列很长时,注意力的 项会变得不可忽略——这也是长上下文成本高的根源。
第三本账:显存,最容易爆的一本
显存账要分推理和训练两种场景,差别巨大。
推理显存
主要两块:
- 权重: 个参数 × 每参数字节数。fp16 是 2 byte,int8 是 1 byte,int4 是 0.5 byte。70B 模型 fp16 就要约 140 GB,单卡放不下;量化到 int4 约 35 GB,单张大显存卡可行。
- KV Cache:自回归生成时缓存历史 token 的 K、V,避免重复计算。这块常被低估。它的大小约为:
其中 2 是 K 和 V, 是序列长度, 是 KV 的总维度, 是 batch size。KV Cache 随序列长度和 batch 线性增长,长上下文、高并发场景下它甚至会超过权重本身的占用。这正是 GQA(分组查询注意力)、MQA(多查询注意力)这类技术的动机——通过让多个 query 头共享 K、V 来压缩 ,大幅缩小 KV Cache。
训练显存
训练贵得多,因为要存:
1 | 权重 参数 |
前三项在微调篇里算过——用 Adam 混合精度训练,每个参数训练态要占十几个 byte。但训练显存里最"软"、也最容易爆的是激活值:前向算出的中间结果要留着给反向用,它的量级正比于 batch × 序列长度 × 层数 × 隐藏维度。
1 | # 极简的训练显存估算(单位 GB,仅主干,量级参考) |
省激活值有几招:梯度检查点(gradient checkpointing) 只保存部分激活、反向时重算其余,用计算换显存;ZeRO/张量并行 把状态切到多卡。
把三本账连起来看
理解了三本账,很多工程现象就解释得通了:
- 为什么推理能跑、训练却 OOM? 因为训练多了梯度、优化器状态和激活值,是推理显存的好几倍。
- 为什么量化首先救的是推理? 量化主要压权重和 KV Cache,对推理立竿见影;但训练时反量化和数值稳定性更复杂。
- 为什么长上下文这么贵? 注意力 FLOPs 的 项和 KV Cache 的 增长同时发力,一个吃算力,一个吃显存。
- 为什么更宽的模型涨得快? 参数量 ,FLOPs ,连锁放大。
踩坑
1. 别用参数量直接估显存需求。 "70B 模型需要 70GB"是错的——推理 fp16 要约两倍参数量的字节,训练还要再翻几倍。
2. 忘了 KV Cache 是高并发部署的头号杀手。 算推理容量时,权重是固定开销,KV Cache 才决定你能同时服务多少长对话。
3. 6ND 是数量级估算,不是精确值。 它忽略了注意力对序列长度的依赖、激活函数、归一化等,用来做能力规划够用,别拿去对账。
4. MoE 打破了"参数量=计算量"的直觉。 混合专家模型总参数量很大,但每个 token 只激活一部分专家,FLOPs 远小于按总参数算的值——这正是 MoE 的卖点:用激活稀疏性把参数量和计算量解耦。
小结
千亿模型的账不是一本而是三本:参数量 决定模型多大, 决定训练算多久,而显存要分推理(权重 + KV Cache)和训练(再加梯度、优化器、激活值)两套来算。 真正卡住部署的往往不是参数量本身,而是被忽视的 KV Cache 和训练激活值。会算这三本账,你才能在拿到一个模型规格时,立刻判断它要几张卡、跑多快、能不能微调。