并行计算范式:数据并行、模型并行与流水线并行
说到大规模训练,并行计算是绕不开的话题。我刚开始接触分布式训练时,也一度被各种并行方式搞晕。其实说白了,并行计算的核心就一句话:把大任务拆成小任务,分给多个设备一起干。但怎么拆、拆完怎么协调,这里面的门道可不少。
今天咱们就聊聊三种最主流的并行范式——数据并行、模型并行和流水线并行。这三种方式,我在不同项目里都踩过坑,也积累了一些实战经验,分享给你。
数据并行:最直观的并行方式
数据并行,顾名思义,就是把数据切分到多个设备上。每个设备都有一份完整的模型副本,各自处理不同的数据批次。最后再把梯度汇总,更新模型参数。
嗯,这里要注意:数据并行虽然直观,但通信开销是个大问题。每个设备都要把梯度广播出去,设备越多,通信压力越大。
核心公式:梯度更新 = 1/N * Σ(grad_i),其中 N 是设备数量,grad_i 是第 i 个设备的梯度。
我在项目中遇到过这样一个场景:用 64 张 GPU 做数据并行训练一个 BERT 模型。结果发现,随着 GPU 数量增加,加速比并没有线性增长。为什么?因为通信开销占了很大比例。尤其是 AllReduce 操作,每次都要等所有设备算完才能开始通信。
数据并行有几个关键点需要关注:
- 同步 vs 异步:同步模式保证梯度一致性,但慢;异步模式快,但可能收敛不稳定。我个人习惯用同步模式,除非网络带宽特别紧张。
- 梯度累积:当单卡显存放不下大 batch 时,可以用梯度累积模拟大 batch 效果。但要注意,梯度累积会增加训练步数,影响收敛速度。
- 混合精度:数据并行时,混合精度能显著减少通信量。FP16 的梯度只有 FP32 的一半,通信时间直接减半。
避坑指南:我曾经在数据并行时忽略了 batch size 对学习率的影响。batch size 翻倍,学习率也要相应调整。否则模型可能不收敛,或者收敛到次优解。
模型并行:当模型放不下时
模型并行解决的是另一个问题:模型太大,单卡显存放不下。比如 GPT-3 这种千亿参数模型,单卡根本装不下。这时候就需要把模型切分到多个设备上。
模型并行有两种常见方式:
- 层内并行:把一层网络的参数切分到多个设备。比如一个 4096 维的全连接层,可以切成 4 份,每份 1024 维,分布在 4 张卡上。
- 层间并行:把不同层分配到不同设备。比如第 1-10 层放在 GPU0,第 11-20 层放在 GPU1。
你想想看,层内并行的问题是什么?通信太频繁了。每次前向传播和反向传播,设备之间都要交换中间结果。我做过一个实验,层内并行时,通信时间占了总训练时间的 60% 以上。
层间并行相对好一些,但又有新的问题:设备利用率不均衡。前面的设备算完了,后面的设备还在忙,导致大量设备空闲等待。
| 并行方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 层内并行 | 负载均衡好 | 通信开销大 | 单层参数极大 |
| 层间并行 | 通信量小 | 设备利用率低 | 层数多、每层参数适中 |
注意:模型并行对网络带宽要求极高。如果用的是千兆以太网,建议别碰模型并行。NVLink 或 InfiniBand 是基本要求。
流水线并行:让设备忙起来
流水线并行是对模型并行的一种改进。它的思路是把模型分成多个阶段(stage),每个阶段放在一个设备上。数据像流水线一样,依次经过各个阶段。
举个例子:假设模型有 4 层,分成 4 个 stage,每个 stage 放在一张卡上。第一个 batch 进入 stage1 计算,算完后传给 stage2,同时 stage1 开始处理第二个 batch。这样,所有设备都能同时工作,利用率大幅提升。
但流水线并行也有自己的问题:
- 气泡(bubble):流水线启动和结束时,部分设备会空闲。比如第一个 batch 进入 stage4 时,stage1 已经空闲了。气泡大小和 stage 数量成正比。
- 负载不均衡:如果各 stage 的计算量不一样,快的 stage 要等慢的 stage,形成新的气泡。
我记得在训练一个 100 层的 ResNet 时,用了 4 个 stage 的流水线并行。结果发现气泡占了总时间的 15% 左右。后来改用 GPipe 的微批次策略,把每个 batch 再切分成更小的 micro-batch,气泡才降到了 5% 以下。
关键技巧:流水线并行中,micro-batch 的数量一般设为 stage 数量的 4-8 倍。这样能有效减少气泡比例。
三种范式的对比与选择
说了这么多,到底该用哪种?我个人的经验是:
- 模型能放进单卡:优先用数据并行。简单、稳定、效果好。
- 模型太大,单卡放不下:考虑模型并行或流水线并行。如果网络带宽好,用模型并行;如果带宽一般,用流水线并行。
- 超大规模训练:三种方式混合使用。比如数据并行 + 流水线并行,或者数据并行 + 模型并行 + 流水线并行。
下面这张图展示了三种范式的核心逻辑:
最后说一句:没有银弹。每种并行方式都有其适用场景,关键是根据你的模型大小、硬件配置和训练目标来选。我见过不少团队盲目追求大规模并行,结果训练效率反而下降了。记住,并行不是目的,加速才是。
实战建议:刚开始做分布式训练时,先从数据并行入手。等熟悉了通信模式和性能瓶颈,再尝试更复杂的并行策略。一步一个脚印,稳扎稳打。
想要更多资料,联系可可