9.5 性能建模与分析
在大模型的研发和部署过程中,"这个模型有多大?训练需要多少显存?推理一张卡能不能放下?"是工程师每天都要面对的问题。回答这些问题不需要实际跑一遍实验——只要掌握几组关键公式,拿出纸笔就能算出相当准确的估计。本节将系统地建立 Decoder-Only Transformer 的性能模型,涵盖参数量、计算量、训练显存和推理显存四个维度,并以 LLaMA-7B 为案例进行完整的手算验证。
9.5.1 浮点运算量(FLOPs)与 6PD 法则
FLOPs 与 FLOPS 的区别。 在深度学习语境中,这两个术语经常被混用,但含义截然不同:
- FLOPs(Floating-point Operations,注意小写 s):指完成某个计算任务所需的浮点运算总次数,是一个无量纲的计数值。例如"训练 GPT-3 大约需要
FLOPs"。 - FLOPS(Floating-point Operations Per Second,大写 S):指硬件每秒能执行的浮点运算次数,是衡量计算速率的指标。例如"H100 的 BF16 理论峰值约为 989 TFLOPS"。
矩阵乘法的 FLOPs。 Transformer 中绝大多数计算量来自矩阵乘法。对于矩阵
这个公式是所有后续推导的基石。
6PD 法则。 对于拥有
其推导逻辑如下:
- 前向传播:模型中的计算以线性层为主,每个线性层本质上是一次矩阵乘法。对于参数量为
的模型,每个 token 经过前向传播大约需要 次浮点运算(矩阵乘法中的乘与加)。处理 个 token,前向传播总量为 。 - 反向传播:反向传播需要计算损失对每个参数的梯度,涉及两次矩阵乘法(分别对输入和权重求导),计算量约为前向传播的 2 倍,即
。 - 总计:
。
这个公式忽略了 LayerNorm、Softmax、激活函数等非矩阵乘法操作,因为在大模型中它们的计算量相比于大规模矩阵乘法可以忽略不计。
实例:LLaMA-7B 在 1T token 上的训练计算量。 将
即大约
9.5.2 模型浮点利用率(MFU)
有了计算量的估算,下一个自然的问题是:我的 GPU 到底跑了多少"有用的"计算?MFU(Model FLOPs Utilization) 正是回答这个问题的指标:
其中分子的计算方式为:
分母则是硬件规格书上标注的理论最大值,取决于芯片型号和所使用的数据精度(BF16、FP8 等)。
MFU 的典型范围。 一般认为 MFU 超过 50% 即为良好。实际训练中,MFU 低于预期通常源于以下瓶颈:
| 瓶颈类型 | 典型表现 |
|---|---|
| 数据加载(I/O) | GPU 利用率间歇性降为 0,数据预处理 CPU 占满 |
| 通信开销 | 多卡/多节点训练时,AllReduce 等集合通信占比高 |
| Kernel 启动开销 | batch size 过小或模型过小,GPU 频繁启停 |
| 内存带宽受限 | 算子访存密集(如 LayerNorm、Softmax),计算单元空转 |
优化 MFU 的常见手段包括:增大 batch size 以提高计算密集度、使用 torch.compile 进行算子融合、采用混合精度训练利用 Tensor Core 加速、优化数据加载流水线等。MFU 是大规模训练中最重要的效率指标之一——同样的硬件,MFU 从 30% 提升到 50%,训练时间直接缩短近 40%。
9.5.3 参数量精确公式
掌握参数量公式是进行所有后续显存和计算量估算的前提。以下以标准的 Decoder-Only Transformer(GPT / LLaMA 架构)为对象,逐模块推导。
记号约定:
单层 Transformer Block
每层由自注意力(Self-Attention)模块和前馈网络(FFN)模块组成,各配一个 LayerNorm。
(1)自注意力模块。 包含 Q、K、V 三个投影矩阵和一个输出投影矩阵,每个都是
注意:多头注意力只是将
(2)前馈网络模块。 标准设计是两层线性变换
对于采用 SwiGLU 激活的架构(如 LLaMA),FFN 包含三个投影 gate_proj、up_proj(均为
(3)LayerNorm / RMSNorm。 每层有 2 个归一化层。标准 LayerNorm 每个有
单层总计:
当
嵌入层与输出层
- 词嵌入(Token Embedding):查找表
,参数量 。 - 位置编码:若使用 RoPE 等旋转位置编码,不引入可学习参数;若使用可学习位置编码,参数量为
。 - 输出投影(LM Head):
,参数量 。若与词嵌入共享权重(weight tying),则不额外计入。
总参数量公式
其中第一项是
9.5.4 手算案例:LLaMA-7B 参数量验证
LLaMA-7B 的核心配置为:
逐项计算:
| 模块 | 公式 | 计算过程 | 参数量 |
|---|---|---|---|
| 词嵌入 | |||
| 每层注意力 | |||
| 每层 FFN | |||
| 每层 RMSNorm | |||
| 单层小计 | — | ||
| 32 层合计 | |||
| 输出投影 |
总参数量:
与官方标注的"7B"基本一致(命名中的 7B 为取整值)。
速算验证: 直接用简化公式
9.5.5 训练显存公式推导
训练阶段的显存占用远超推理,因为除了模型参数本身,还需要存储梯度和优化器状态。以当前主流的 Adam + 混合精度训练为基准进行分析。
静态显存:参数 + 梯度 + 优化器
设模型有
(1)模型参数。 混合精度训练中,前向和反向传播使用 FP16/BF16 格式存储参数,每个参数 2 字节:
(2)梯度。 每个参数对应一个梯度值,与参数同精度(FP16/BF16):
(3)优化器状态。 Adam 优化器为每个参数维护两个状态量:
- 一阶动量
(梯度的指数移动平均):FP32 存储, bytes - 二阶动量
(梯度平方的指数移动平均):FP32 存储, bytes
(4)主参数副本(Master Weights)。 混合精度训练中,优化器更新在 FP32 精度下进行,因此需要维护一份 FP32 的参数副本:
静态显存合计:
即每个参数平均占用 16 字节。如果不保留 master weights(某些实现中梯度也用 FP32),具体数值在 12-20 之间浮动,但 16 bytes/param 是最常用的经验值。
动态显存:激活值
前向传播中产生的中间结果(激活值)需要保留到反向传播时用于计算梯度。激活值的显存占用取决于 batch size
对于标准 Transformer 的单层,详细分析表明激活值显存约为:
其中
在实际工程中,可以使用激活重计算(Activation Checkpointing) 以时间换空间:不保存全部激活值,而是在反向传播时重新计算部分中间结果。这可以将激活显存降低到原来的
训练显存经验公式
综合静态和动态部分,训练显存的工程估算公式为:
其中 16-20 的范围取决于具体实现(是否保留 master weights、梯度精度等),激活值部分与
手算案例:LLaMA-7B 训练显存。 取
加上激活值后,7B 模型的全量微调通常需要 120-160 GB 显存,对应 2 张 80GB 的 A100 或 H100。这也解释了为什么 LoRA 等参数高效微调方法如此流行——它们大幅减少了需要存储梯度和优化器状态的参数数量。
9.5.6 推理显存公式推导
推理阶段没有梯度和优化器状态,显存占用相比训练大幅降低。但随着序列长度的增长,KV Cache 会成为不容忽视的"内存刺客"。
模型参数
推理时只需加载模型权重,FP16 精度下:
KV Cache
自回归生成的核心优化是 KV Cache:在生成每个新 token 时,将当前 token 对应的 Key 和 Value 向量缓存起来,避免对历史 token 重复计算。
逐步推导 KV Cache 大小:
- 单头、单层、单 token:需要缓存 K 和 V 各一个向量,每个向量维度为
。FP16 下单个向量占 字节,K 和 V 合计 字节。 - 所有头:
个头的 K、V 拼接后等价于维度 的完整向量。单层、单 token 的 KV Cache 为 字节。 - 所有层:
层叠加,单 token 总计 字节。 - 整个序列:序列长度为
(含 prompt 和已生成的 token),总计 字节。 - 考虑 batch:batch size 为
时,总计 字节。
更一般地写成
推理总显存
KV Cache 为何是"内存刺客"
KV Cache 的显存占用与序列长度
手算案例:LLaMA-7B 推理显存。 取
模型参数:
KV Cache(S = 2048):
KV Cache(S = 32768,即 32K):
KV Cache(S = 131072,即 128K):
可以看到:
| 序列长度 | 参数显存 | KV Cache | 总计 | KV Cache 占比 |
|---|---|---|---|---|
| 2K | 14 GB | 1 GB | 15 GB | 6.7% |
| 32K | 14 GB | 16 GB | 30 GB | 53% |
| 128K | 14 GB | 64 GB | 78 GB | 82% |
当序列长度达到 128K 时,KV Cache 占据了总显存的 82%,是名副其实的"内存刺客"。这正是 GQA(Grouped-Query Attention)、MQA(Multi-Query Attention)、量化 KV Cache 等技术的驱动力——它们通过减少 K/V 头的数量或降低精度来压缩 KV Cache。
9.5.7 Transformer 拆解建模实践
将上述公式汇总,可以建立一套完整的 Transformer 性能建模方法论:
第一步:确定模型配置。 从模型的 config.json 中读取
第二步:估算参数量。 用
第三步:估算训练成本。
- 显存:
bytes 起步,加激活值。据此决定需要多少张卡、是否需要模型并行。 - 计算量:
,除以硬件峰值 FLOPS 再除以预期 MFU,得到训练时间。
第四步:估算推理资源。
快速参考表:
| 模型 | 参数量 | 推理显存(FP16) | 训练显存(粗估) | ||
|---|---|---|---|---|---|
| LLaMA-7B | 32 | 4096 | ~6.7B | ~14 GB + KV | ~120 GB |
| LLaMA-13B | 40 | 5120 | ~13B | ~26 GB + KV | ~220 GB |
| LLaMA-70B | 80 | 8192 | ~65B | ~130 GB + KV | ~1.1 TB |
9.5.8 本节小结
本节建立了一套围绕 Decoder-Only Transformer 的完整性能建模框架,核心结论可以浓缩为四组公式:
- 参数量:
,其中单层 (注意力 + FFN )。 - 训练计算量:
,前向 + 反向 。 - 训练显存:参数
+ 梯度 + 优化器 + master weights = bytes/param,再加激活值。 - 推理显存:参数
+ KV Cache ,长序列下 KV Cache 主导显存。
这些公式的价值在于:它们让工程师在项目启动前就能完成资源规划——需要多少卡、训练多长时间、推理能支持多大的 batch 和上下文长度——而不必依赖昂贵的试错。理解这些公式背后的推导过程比记住数字更重要,因为当模型架构发生变化时(例如 MoE、GQA、线性注意力等),只有理解了原理才能灵活地调整估算。