3.2 分布式训练:并行策略与 DeepSpeed 实践

1 阅读1分钟

基于《大规模语言模型:从理论到实践(第2版)》第4章 分布式模型训练

爆款小标题:数据并行、张量并行、流水并行怎么选?原书第4章+DeepSpeed 落地


为什么这一节重要

当模型参数量达到 7B、70B 甚至更大时,单卡显存无法容纳完整模型与优化器状态,必须依赖分布式训练把计算与显存分摊到多卡或多机。分布式训练有多种并行方式:数据并行、张量并行、流水并行,以及 ZeRO 等显存优化技术。选错策略会导致显存溢出、训练极慢或通信成为瓶颈。本节基于原书第 4 章与 DeepSpeed 实践,把各类并行的适用场景、ZeRO 的分片逻辑与使用顺序讲清,并给出「先跑通再调优」的落地建议。


学习目标

学完本节,你将能够:

  • 区分三种并行:准确说明数据并行(DP)、张量并行(TP)、流水并行(PP)各自如何切分计算与数据、适用什么规模的模型、以及通信特点。
  • 理解 ZeRO:说明 ZeRO-1/2/3 分别对优化器状态、梯度、参数做了哪些分片与通信,以及 ZeRO-3 相比 ZeRO-2 的额外收益与通信开销。
  • 能做初步选型:根据模型规模(如 7B/70B)与单卡显存、卡数,初步选择「DP+ZeRO」或「DP+ZeRO+TP/PP」的组合,并能在 DeepSpeed 配置上跑通一个示例。

一、数据并行(Data Parallelism, DP)(原书第 4 章)

做法:每张卡上各保留一份完整的模型副本,每卡处理不同的数据(batch 的不同分片);前向与反向在各卡本地完成,梯度在卡间做 AllReduce(或等价操作)得到全局梯度,再各自用相同梯度更新参数,从而保证各卡参数一致。

优点:实现简单、与单卡训练逻辑最接近;扩展性好,卡数增加时只需保证数据分片与梯度同步正确。缺点:单卡必须能放下完整模型与一份优化器状态等,因此模型不能超过单卡显存

适用:模型能完整放入单卡(或通过 ZeRO 等优化后能放入)时,优先用数据并行扩规模。原书第 4 章将其作为基础并行方式介绍。

通信:每步反向结束后一次 AllReduce(或 ReduceScatter + AllGather),通信量与模型参数量成正比;卡数多时通信可能成为瓶颈,需结合梯度累积与通信重叠等手段。


二、张量并行(Tensor Parallelism, TP)(原书第 4 章)

做法:把单层的权重与计算切分到多卡。例如把一层 (Y = XW) 的 (W) 按行或列切分,每卡持有一部分 (W),计算时每卡算局部结果,再通过 AllGather 或 ReduceScatter 拼成完整输出。这样单层不再依赖单卡显存,但单层计算过程中需要多卡通信

优点:能训练「单层就很大」的模型(如 70B 的 FFN 层)。缺点:通信频繁(每层都可能通信)、对带宽要求高;实现复杂,通常依赖 Megatron 等框架。

适用:当单卡放不下单层(例如单层参数量超过单卡显存)时,需要用张量并行或流水并行。原书第 4 章对 TP 的切分方式与通信有进一步说明。

工程注意:TP 通常与 DP 组合使用(例如 4 卡 TP × 2 组 = 8 卡),组内做张量并行、组间做数据并行;集群拓扑(如 NVLink、PCIe)会影响通信效率,需结合带宽规划。


三、流水并行(Pipeline Parallelism, PP)(原书第 4 章)

做法:把模型按层切分到多卡,形成「流水线」:第 1 卡算第 1 批的前几层,算完传给第 2 卡算接下来几层,依次类推;当第 1 卡把第 1 批传走后,可以开始算第 2 批的前几层,从而实现多批同时在 pipeline 上流动。

优点:单卡不需要存完整模型,只需存若干层;适合层数多、单层不算特别大的模型。缺点:存在「流水线气泡」——部分卡在等前一批数据时空闲,利用率会下降;需要调 micro batch 等参数平衡效率与显存。

适用:层数多、但单层能放进单卡时,可用 PP 把层摊到多卡。常与 DP、TP 组合成 3D 并行(原书第 4 章)。


四、ZeRO:优化器、梯度与参数的分片(原书 DeepSpeed 实践)

问题:数据并行时,每卡都存完整模型 + 完整优化器状态(如 Adam 的动量与方差)+ 完整梯度,显存占用是单卡训练的「卡数倍」,反而限制了可用的 batch size 或模型规模。

ZeRO-1:只对优化器状态分片。每卡只存 1/N 的优化器状态(N 为 DP 卡数),更新时按需 Gather 再分片,从而把优化器状态占用的显存降到约 1/N。

ZeRO-2:在 ZeRO-1 基础上再对梯度分片。每卡只存 1/N 的梯度,AllReduce 时用 ReduceScatter 等操作直接得到分片结果,梯度显存也降到约 1/N。

ZeRO-3:在 ZeRO-2 基础上再对参数分片。每卡只存 1/N 的模型参数,前向与反向时按需 Gather 完整参数(或分层 Gather),计算完再释放。这样单卡显存不再需要存完整模型,可训练远大于单卡显存的模型;代价是前向与反向中多了参数 AllGather 等通信,通信量比 ZeRO-2 大。

选型建议:模型能放进单卡时,ZeRO-2 即可显著降低显存并加速(因梯度与优化器状态分片);模型放不进单卡时,需要 ZeRO-3 或 ZeRO-3 + TP/PP。原书配套的 DeepSpeed 实践部分给出了 ZeRO-2/3 的配置示例,建议先跑通再按显存与速度调 batch size 与并行度。


五、工程实战要点

1. 从小规模组合开始

不要一上来就 3D 并行(DP+TP+PP)。建议顺序:先数据并行 + ZeRO-2(或 ZeRO-3 若模型大);若单卡仍放不下(例如单层就很大),再考虑加 TP;若层数多、单层能放下,可考虑 PP。先在小规模(如 2 卡、4 卡)跑通配置与数据管线,再放大。3D 并行的配置复杂(如 TP 与 PP 的组划分、通信拓扑),调试成本高,只有在「必须」时才上。

2. 梯度累积与有效 batch

当单卡 batch size 受显存限制较小时,可通过梯度累积扩大有效 batch:多步前向—反向,累积梯度后再做一次 AllReduce 与优化器更新。有效 batch = 每卡 batch × 梯度累积步数 × DP 卡数。预训练时常用较大有效 batch(如数百万 token/step),需合理设置梯度累积步数以平衡显存与吞吐。

3. 使用 DeepSpeed 时先跑通再调参

用官方或原书给出的 ZeRO 配置文件(如 ds_config.json)先跑通一个 epoch;再根据显存占用与速度调整 train_batch_sizegradient_accumulation_steps、以及 ZeRO 的 stage。遇到 OOM 时优先考虑增大梯度累积、减小 batch、或开 ZeRO-3。

DeepSpeed ZeRO-2 配置示例

{
  "zero_optimization": {
    "stage": 2,
    "offload_optimizer": {"device": "none"},
    "allgather_partitions": true
  },
  "train_batch_size": 32,
  "train_micro_batch_size_per_gpu": 4,
  "gradient_accumulation_steps": 2
}
  • stage: 2 表示 ZeRO-2(优化器状态 + 梯度分片);stage: 3 则加上参数分片。
  • 有效 batch = 4 × 2 × 卡数;若 4 卡则 4×2×4=32。OOM 时减小 train_micro_batch_size_per_gpu 或增大 gradient_accumulation_steps

4. 通信带宽与拓扑

张量并行与 ZeRO-3 的 AllGather 都依赖卡间带宽。多机时要注意网络带宽;单机多卡时 NVLink 比 PCIe 快很多。集群规划时把「通信量」与「带宽」一起考虑,避免通信成为瓶颈。


六、常见误区与避坑指南

误区一:一上来就 3D 并行

3D 并行配置复杂、调试成本高,且未必需要。避坑:先评估「单卡能放多少」「模型多大」,从 DP+ZeRO 开始,再按需加 TP/PP。

误区二:忽视通信带宽

TP 与梯度同步都依赖带宽;带宽不足时加卡数可能反而变慢。避坑:做扩展实验时监控步时与通信占比;多机时优先保证网络带宽与拓扑。

误区三:ZeRO-3 一定比 ZeRO-2 慢

ZeRO-3 多了参数通信,在模型不大、单卡能放下时,ZeRO-2 往往更快。避坑:在「能放下」的前提下优先 ZeRO-2;只有显存不够时才上 ZeRO-3。


七、小结与衔接

本节结合原书第 4 章与 DeepSpeed,梳理了数据并行、张量并行、流水并行的适用场景与通信特点,以及 ZeRO-1/2/3 对优化器状态、梯度、参数的分片与对应显存与通信权衡;并给出了「先 DP+ZeRO,再按需 TP/PP」的选型顺序与工程要点。下一节将进入指令微调:如何构建指令数据、如何用 LoRA 做参数高效微调,以及长上下文扩展的常见做法(原书第 5 章)。


课后思考题

  1. 在 8 张 A100 上训练 70B 模型,单卡显存不足以放下完整模型时,你会优先考虑哪种并行组合?简要说明理由。
  2. ZeRO-3 相比 ZeRO-2 多做了哪类分片?带来的好处与额外通信开销是什么?