第2章 深度学习训练基础:模型训练流程、显存瓶颈、计算瓶颈、分布式训练基本概念
在真正使用 DeepSpeed 之前,必须先理解深度学习训练到底在做什么、瓶颈通常出现在哪里,以及分布式训练为什么能解决这些问题。很多初学者一上来就配置 ZeRO、Offload、混合精度,却说不清每一步在优化什么,结果调参全靠猜。本章把训练流程、显存与计算瓶颈、分布式训练的基本概念串成一条清晰的链路,为后续 DeepSpeed 的各个特性打好地基。
一、模型训练的标准流程
一次完整的训练迭代(iteration)可以拆成四个核心阶段,它们循环往复直到收敛:
- 前向传播(Forward):输入一个 batch 的数据,逐层计算,得到模型输出(logits)。
- 损失计算(Loss):用损失函数比较预测值与真实标签,得到一个标量 loss。
- 反向传播(Backward):从 loss 出发,沿计算图反向求每个参数的梯度。
- 参数更新(Optimizer Step):优化器根据梯度更新权重,例如 SGD 或 Adam。
用伪代码表示,训练循环大致如下:
for batch in dataloader:
outputs = model(batch.inputs) # 前向
loss = criterion(outputs, batch.labels) # 损失
loss.backward() # 反向,梯度写入 param.grad
optimizer.step() # 更新参数
optimizer.zero_grad() # 清空梯度
看似简单,但每一步都伴随着大量的张量运算和显存占用。理解这些占用从何而来,是判断瓶颈类型的关键。
二、显存瓶颈:训练时显存被谁吃掉了
训练显存主要由四部分组成:模型参数、梯度、优化器状态、激活值。以 Adam 为例,每个参数除了本身,还要保存一份梯度、一份一阶动量、一份二阶动量,相当于参数量的 4 倍左右(FP32 下)。激活值则是前向过程中每层输出,反向传播时需要复用,batch 越大、序列越长,激活值越庞大。
下面这张图展示了单卡训练时显存的主要构成与它们随 batch 增长的变化关系:
当显存不足时,训练会直接抛出 CUDA out of memory。此时要么减小 batch,要么引入显存优化技术。DeepSpeed 的 ZeRO 正是针对参数、梯度、优化器状态做分片,把单卡显存压力分摊到多卡上。
三、计算瓶颈:GPU 到底在等什么
显存够用不代表训练就快。计算瓶颈通常表现为 GPU 利用率低、step 时间波动大。常见原因有三类:
- 数据加载慢:CPU 预处理、磁盘 IO 跟不上 GPU,GPU 空转等数据。
- 通信开销大:多卡训练时梯度同步、参数广播占用大量时间。
- 算子效率低:小 batch、小矩阵乘无法打满 Tensor Core。
判断瓶颈类型的一个实用方法是看 GPU 利用率和 step 时间:如果利用率长期低于 50%,多半是数据或通信瓶颈;如果利用率高但 step 时间仍长,则可能是计算本身或显存带宽受限。
四、分布式训练基本概念
分布式训练的核心思想是把计算和存储分摊到多张卡上。需要先分清几个高频术语:
| 术语 | 含义 | 典型作用 |
|---|---|---|
| 数据并行(DP) | 每张卡持有完整模型,输入不同数据 | 提升吞吐,梯度需同步 |
| 模型并行(MP) | 模型切分到多卡,各卡算一部分层 | 放下超大模型 |
| 流水线并行(PP) | 按层分段,micro-batch 流水执行 | 减少气泡,提升利用率 |
| 张量并行(TP) | 单层内矩阵切分到多卡 | 降低单卡参数与激活 |
| All-Reduce | 多卡梯度求平均并广播 | 数据并行的同步核心 |
| 通信组(Process Group) | 参与通信的进程集合 | 决定通信范围与拓扑 |
数据并行是最常用的起点:每张卡跑相同模型、不同数据,反向结束后通过 All-Reduce 把梯度求平均,保证各卡参数一致。它的代价是通信量与参数量成正比,模型越大通信越重。DeepSpeed 的 ZeRO 在数据并行基础上进一步把优化器状态、梯度、参数分片,从而在保持数据并行易用性的同时大幅降低单卡显存。
五、案例复盘:一次显存溢出的排查
假设你在单张 24GB 卡上训练一个 1.3B 参数的模型,batch size 设为 8 时出现 OOM。按下面的顺序排查:
- 先算固定开销:1.3B 参数 FP32 约 5.2GB,梯度约 5.2GB,Adam 状态约 10.4GB,合计已超 20GB。
- 再算激活值:batch=8、序列长度 512 时激活值可能再占数 GB,必然溢出。
- 缓解手段:改用混合精度可把参数与梯度降到约一半;开启梯度检查点可显著降低激活值;若仍不够,则引入 ZeRO-2 或 ZeRO-3 做分片。
这个例子说明:显存瓶颈往往不是单一原因,而是参数、梯度、优化器状态、激活值共同叠加的结果。理解每一部分的量级,才能有针对性地选择优化手段,而不是盲目调小 batch 或换卡。