分布式训练编排实战 - 第4节

4. 混合并行(Hybrid Parallelism):数据并行+模型并行的组合策略

聊到混合并行,我得先说说自己的经历。几年前我接手一个百亿参数模型训练任务,单卡显存根本放不下,数据并行又因为通信开销太大导致效率极低。那时候我就在想,能不能把几种并行方式组合起来用?说白了,这就是混合并行的核心思路——不把鸡蛋放在一个篮子里。

4.1 为什么需要混合并行?

你想想看,数据并行虽然简单,但每个GPU都要存一份完整的模型。模型大到一定程度,比如GPT-3这种1750亿参数的怪兽,单卡显存根本装不下。模型并行呢?虽然能拆分模型,但计算效率往往不如数据并行高。

所以实际工程中,我们通常把两者结合起来。我习惯的做法是:先做模型并行把模型拆开,再做数据并行把数据分片。这样既解决了显存瓶颈,又能充分利用多卡的计算能力。

核心原则:混合并行的目标是在显存约束和计算效率之间找到最佳平衡点。不是简单叠加,而是根据模型结构和硬件拓扑做精细化设计。

4.2 混合并行的典型架构

我在项目中常用的混合并行架构是这样的:

  • 层内并行(张量并行):把单个Transformer层的参数切分到多卡上
  • 层间并行(流水线并行):把不同层分配到不同设备上
  • 数据并行:在以上基础上,复制多份模型副本处理不同数据

举个例子,假设我们有64张GPU,训练一个12层的Transformer模型。我可能会这样分配:

并行策略切分方式GPU数量
张量并行每层切4份4
流水线并行12层分3组3
数据并行复制多份64/(4*3)≈5

嗯,这里要注意:张量并行的通信量最大,所以通常只在单机内使用(NVLink连接)。流水线并行次之,数据并行通信量最小。

3D并行:数据并行+张量并行+流水线并行

3D并行,说白了就是把三种并行方式组合成一个三维网格。我最早接触这个概念是在Megatron-LM项目中,当时觉得这设计真巧妙。

4.3 3D并行的三维视角

你可以把3D并行想象成一个三维坐标系:

  • X轴:数据并行 — 复制模型副本,处理不同数据批次
  • Y轴:张量并行 — 切分单个层的参数
  • Z轴:流水线并行 — 切分模型的层

每个GPU在这个三维网格中都有一个坐标(x, y, z),负责处理特定的数据分片、特定的张量分片和特定的层。

我的经验:3D并行最头疼的是通信拓扑设计。我建议把通信密集的张量并行放在节点内部,流水线并行放在节点之间,数据并行则全局使用。这样能最大化利用带宽。

4.4 3D并行的通信模式

3D并行涉及三种通信模式,每种的开销都不一样:

并行类型通信模式通信量频率
张量并行All-Reduce高(模型参数大小)每个计算步骤
流水线并行P2P Send/Recv中(激活值大小)每个微批次
数据并行All-Reduce低(梯度大小)每个训练步骤

我曾经踩过一个坑:把张量并行的通信域设得太大,导致跨节点通信成了瓶颈。后来我改成只在单机8卡内做张量并行,性能直接翻倍。

ZeRO优化器:内存节省原理

ZeRO(Zero Redundancy Optimizer)是DeepSpeed推出的内存优化技术。我刚开始用的时候,觉得这玩意儿简直就是显存救星。

4.5 ZeRO-1:优化器状态分区

ZeRO-1只分区存储优化器状态(比如Adam的动量和方差)。每个GPU只保存自己那部分优化器状态,而不是完整复制。

内存节省效果:

  • 原始:每个GPU存完整优化器状态(4倍模型参数大小)
  • ZeRO-1:每个GPU只存1/N(N为GPU数量)
  • 节省比例:约75%(假设N=4)

关键点:ZeRO-1不减少模型参数和梯度的内存占用,只优化优化器状态。如果你的模型已经能放进显存,但优化器状态放不下,ZeRO-1是首选。

4.6 ZeRO-2:梯度分区

ZeRO-2在ZeRO-1基础上,进一步分区存储梯度。每个GPU只保存自己那部分梯度,计算完就丢弃其他部分。

内存节省效果:

  • 原始:每个GPU存完整梯度(1倍模型参数大小)
  • ZeRO-2:每个GPU只存1/N
  • 加上ZeRO-1:总共节省约87.5%的优化器相关内存

我记得有次训练一个30亿参数的模型,用ZeRO-2后,原本需要8张A100才能跑的任务,4张就搞定了。嗯,真香。

4.7 ZeRO-3:参数分区

ZeRO-3是终极方案,连模型参数都分区存储。每个GPU只保存自己那部分参数,计算时通过All-Gather通信获取完整参数。

内存节省效果:

  • 原始:每个GPU存完整参数(1倍模型参数大小)
  • ZeRO-3:每个GPU只存1/N
  • 加上ZeRO-1/2:总共节省约95%的内存

注意:ZeRO-3虽然省内存,但通信开销最大。每个前向/反向传播都需要All-Gather参数。我建议只在模型实在放不下时才用ZeRO-3,否则优先用ZeRO-2。

4.8 ZeRO各版本对比

版本分区内容内存节省通信开销适用场景
ZeRO-1优化器状态~75%低优化器状态占大头
ZeRO-2优化器状态+梯度~87.5%中梯度也放不下
ZeRO-3优化器状态+梯度+参数~95%高模型完全放不下

4.9 ZeRO与混合并行的结合

实际工程中,ZeRO经常和混合并行一起用。我常用的组合是:

  • 小模型(<10B):数据并行 + ZeRO-2
  • 中模型(10B-100B):3D并行 + ZeRO-1
  • 大模型(>100B):3D并行 + ZeRO-3

为什么会这样?因为模型越大,参数本身占的内存就越多,ZeRO-3的优势就越明显。但也要权衡通信开销,毕竟All-Gather参数可不是免费的。

避坑指南:我曾经在ZeRO-3下使用流水线并行,结果发现通信重叠做得不好,导致GPU利用率只有40%。后来我调整了微批次大小和流水线深度,才把利用率提到80%以上。记住:ZeRO-3的通信和计算要尽量重叠。

4.10 知识体系图

下面这张图展示了混合并行、3D并行和ZeRO优化器的关系:

分布式训练并行策略体系 混合并行 (Hybrid Parallelism) 数据并行 (DP) 张量并行 (TP) 流水线并行 (PP) 3D并行 = DP + TP + PP ZeRO优化器:内存优化技术 ZeRO-1: 优化器状态 ZeRO-2: +梯度 ZeRO-3: +参数 内存节省: ZeRO-1 (75%) → ZeRO-2 (87.5%) → ZeRO-3 (95%)

这张图清晰地展示了混合并行、3D并行和ZeRO优化器的层级关系。从底层的数据并行、张量并行、流水线并行,到上层的3D并行组合,再到ZeRO优化器的内存优化,每一层都有其独特的作用。

我个人建议,在实际项目中先评估模型大小和硬件资源,再选择合适的并行策略组合。不要一上来就上3D并行+ZeRO-3,有时候简单的数据并行+ZeRO-2反而更高效。

想要更多资料,联系可可