一、分布式训练概述:为什么需要多卡训练、数据并行 vs 模型并行 vs 流水线并行、同步训练 vs 异步训练
大家好,我是你们的讲师。今天咱们聊聊分布式训练。说实话,我刚入行那会儿,觉得单卡训练挺香的——代码简单,调试方便,跑个ResNet-50也就一两天的事。但后来模型越做越大,单卡根本扛不住。我记得第一次尝试训练一个GPT-2规模的模型,单张V100显存32G,模型参数加载完就爆了。嗯,从那天起,我就开始认真研究分布式训练了。
1.1 为什么需要多卡训练?
说白了,就两个原因:显存不够和时间太长。
你想想看,现在主流的LLaMA-70B模型,光参数就要140GB的显存(FP16精度)。单张A100才80GB,根本塞不下。就算你用FP8压缩,也得70GB左右,加上优化器状态、梯度,单卡完全没戏。
另一个痛点就是训练时间。我有个项目要训练一个3B参数的视觉模型,单卡A100得跑两周。后来上了8卡分布式,两天就搞定了。这不仅仅是快,关键是迭代速度上来了,调参、实验都能更快推进。
1.2 数据并行 vs 模型并行 vs 流水线并行
这三种并行策略,我习惯用一个比喻来理解:数据并行是“分数据”,模型并行是“分模型”,流水线并行是“分阶段”。
数据并行(Data Parallelism)
这是最常用、最容易上手的方式。每张卡都复制一份完整的模型,但只处理一部分数据。比如你有8张卡,一个batch是64张图,每张卡分到8张图。每张卡独立计算梯度,然后通过AllReduce操作把梯度汇总,更新模型参数。
我在项目中遇到过一个问题:当模型太大时,数据并行也救不了你——因为每张卡都要完整加载模型。所以数据并行适合模型能塞进单卡显存的情况。
模型并行(Model Parallelism)
当模型太大,单卡放不下时,就得把模型拆开。比如一个Transformer有48层,你可以把前24层放在卡0,后24层放在卡1。数据从卡0流入,经过前24层,再把中间结果传到卡1,继续算后24层。
这种方式的缺点是:卡与卡之间有依赖。卡1必须等卡0算完才能开始,所以存在“空闲等待”的问题。我早期做BERT训练时就踩过这个坑——模型并行虽然解决了显存问题,但GPU利用率只有60%左右,因为总有一半的卡在干等。
流水线并行(Pipeline Parallelism)
流水线并行是模型并行的升级版。它把数据也切成多个微批次(micro-batch),让不同卡同时处理不同微批次的不同阶段。比如卡0在处理微批次1的前24层时,卡1可以处理微批次0的后24层。这样流水线就填满了,GPU利用率能提到80%以上。
嗯,这里要注意:流水线并行虽然效率高,但实现起来比模型并行复杂。PyTorch提供了torch.distributed.pipeline.sync.Pipe接口,但我个人习惯用Megatron-LM或DeepSpeed,它们封装得更成熟。
| 并行策略 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 数据并行 | 模型能放进单卡 | 实现简单,扩展性好 | 模型太大时无效 |
| 模型并行 | 模型超大,单卡放不下 | 解决显存瓶颈 | GPU利用率低,有等待 |
| 流水线并行 | 模型超大,且需要高吞吐 | 利用率高,吞吐量大 | 实现复杂,调试困难 |
1.3 同步训练 vs 异步训练
这个选择,说白了就是“等不等”的问题。
同步训练(Synchronous Training)
所有卡算完一个batch后,统一做一次梯度同步,然后一起更新参数。这样每张卡的模型参数始终一致,训练过程稳定,收敛曲线平滑。
我大部分项目都用同步训练。PyTorch DDP默认就是同步模式,用起来很省心。但缺点也很明显:慢卡拖累全队。如果某张卡因为散热问题降频了,或者网络延迟高了,所有卡都得等它。
异步训练(Asynchronous Training)
每张卡算完自己的梯度后,直接更新参数,不用等别人。这样快卡不会被慢卡拖累,整体吞吐量更高。但问题来了:参数不一致。卡0更新参数时,卡1可能还在用旧参数算梯度,这就导致了“梯度滞后”问题,训练可能不稳定甚至发散。
异步训练在工业界用得比较多,尤其是大规模推荐系统。我记得在广告点击率预估模型上,团队用异步训练把吞吐量提升了3倍,但需要仔细调学习率和梯度裁剪策略,否则模型容易震荡。
| 训练方式 | 优点 | 缺点 | 推荐场景 |
|---|---|---|---|
| 同步训练 | 稳定,收敛快,易调试 | 受慢卡拖累 | CV、NLP等标准任务 |
| 异步训练 | 吞吐量高,硬件利用率好 | 不稳定,调参复杂 | 推荐系统、大规模稀疏模型 |
1.4 知识体系总览
为了让你更直观地理解这些概念之间的关系,我画了一张图。你可以看到,分布式训练的核心就是“分”——分数据、分模型、分阶段,以及“合”——同步或异步地合并梯度。
1.5 小结
这一章我们聊了分布式训练的三个核心问题:为什么需要多卡(显存和时间)、怎么分(数据并行、模型并行、流水线并行)、怎么合(同步 vs 异步)。
我个人建议:如果你是新手,先从数据并行+同步训练入手。PyTorch的DDP封装得很好,代码改动量小,效果稳定。等你对分布式有了手感,再尝试模型并行和流水线并行。异步训练嘛,除非你搞大规模推荐系统,否则暂时不用碰。
嗯,下一章我们会手把手搭建一个多卡训练环境,包括NCCL配置、启动方式、常见报错排查。到时候我会分享一些我当年踩过的坑,保证让你少走弯路。