两种并行方式#
一般有三种并行方式:数据并行、模型并行、通道并行。而通道并行可以认为是前两者的组合,故这里只介绍前两者。而其中又以数据并行使用得最多。
数据并行#
训练的时候,首先将模型权重克隆到所有 n 个 workers(worker 之后会讲)上。
然后,对于每一个 batch,将其平均分为 n 份(不能整除的话会有细微调整),发送到 n 个 workers 上。
对于每个 worker,它会对自己得到的那部分 batch 计算 forward,得到 loss 值,再计算 backward,得到模型所有参数的 grad.
等到所有 worker 都计算完自己的 grad,会通过 all_reduce 将所有的 grad 直接加起来(或者取平均)并重新分配给每个 worker,每个 worker 拿到统一的 grad 更新自己的参数。
这样保证了计算任务均摊到每个 worker,但又保证 workers 里面的模型始终都是相同的。
但这样的问题是:
- 在 all_reduce 的时候,workers 需要输出自己的 grad,再拿回汇总后的 grad,通信开销大。
- 分 batch 之后,每个 worker 拿到的数据变少,可能无法发挥全部计算性能;计算时间变短,一旦快于 batch 分配、grad 汇总等通信速率,就会导致 worker 等待,性能浪费。
对应的解决办法就是:
- 加大带宽(比如 NVLink)
- 加大 batch_size,但可能会影响模型训练效果(比如 num_epoch 相同时,更大的 batch_size 表示更少的 step 数,模型收敛变慢;如果调大 learning_rate,又会导致其他问题,比如震荡)
综上可知,并行不是加快训练的 elixir!只有模型够复杂、数据集够大、计算是瓶颈的时候才更适合做并行。并行有时需要相应调大 batch_size 和 learning_rate,而因此可能还需要切换到适合更大 batch_size 和 learning_rate 的优化方法。
丹方:对于图片分类模型,最佳的 batch_size 一般是类别数的 10 倍到 100 倍之间,一般来说建议选择和 10 倍或者 20 倍接近的 2 的幂次(例如对于 CIFAR-10,可选 128)。——沐神
模型并行#
朴素的模型并行就是把一个深层模型按层拆分,然后将不同的层分配给不同 workers 来串流计算,即一个 worker 接受上一个 worker 的输入,算完了再传给下一个 worker,backward 时反过来。
这样可以实现流水线计算,但相比数据并行,并行度仍然较低,并且对通信要求更高。
一般只用于模型过大,单个 worker 无法装下的情况。
不同级别的并行#
前文所述的 worker,可以是单台机器里的多个 GPU 等计算硬件,也可以是多台相互联网的机器。在多台机器之间的并行,叫作分布式。
分布式训练——额外的细节#
分布式训练由于存在多台机器进行计算,因此其数据集的提供、网络参数的更新最好都由专门的机器组织。
提供数据集的是分布式文件系统(知名的有 hdfs)。
组织网络参数更新的机器叫做 Parameter Server(知名的有 BytePS)。每次所有 workers 从这个 PS 获取参数,然后从分布式文件系统获取自己的 batch,计算好梯度之后,回传到 PS. PS 会累加所有 workers 得到的梯度,据此更新权重,然后进入下一次计算。
参考#
34 多GPU训练实现【动手学深度学习v2】 - Bilibili ↗ pytorch多GPU并行训练教程 - Bilibili ↗ torchrun (弹性启动) — PyTorch 2.9 文档 ↗ DistributedDataParallel — PyTorch 2.9 文档 ↗ DataParallel — PyTorch 2.9 文档 ↗