分布式训练基础:数据并行、模型并行、张量并行的基本概念

聊分布式训练之前,我先问个问题:
你手头有一张A100,显存80G,但模型参数有200G。怎么办?
答案很简单——用多张卡。但怎么用,这里头门道就多了。

我个人习惯把分布式训练分成三大流派:数据并行模型并行张量并行
说白了,就是三种切分思路。你想想看,一个模型无非就是数据和参数,怎么分?

1. 数据并行:最直观的思路

数据并行,我估计你最早接触的就是它。
每张卡上都放一份完整的模型副本,然后把训练数据切成多份,每张卡处理一份。

举个例子:
你有4张卡,一个batch有64条数据。每张卡分到16条,各自算梯度。
算完之后,大家把梯度汇总一下,更新模型参数。

嗯,这里要注意:
数据并行最大的坑是通信开销。每张卡算完梯度后,得把所有梯度同步一遍。
我在项目中遇到过,模型参数特别大时,梯度同步的时间比计算时间还长。

核心公式:
总吞吐 ≈ 单卡吞吐 × 卡数 / (1 + 通信开销占比)

说白了,卡越多,通信越频繁。如果通信带宽跟不上,加卡反而没收益。

2. 模型并行:把模型拆开

模型并行,就是模型太大,一张卡放不下。
把模型的不同层放到不同卡上。比如,前几层在卡0,中间层在卡1,后几层在卡2。

这样做的好处是:每张卡只存一部分参数,显存压力小。
但坏处也很明显:计算是串行的。卡0算完才能传给卡1,卡1算完才能传给卡2。
你想想看,这就像流水线,只要有一张卡慢,整条线都等着。

我的经验:
模型并行适合那种层数特别深的模型,比如Transformer的几十层。
但要注意,层与层之间的通信量很大,尤其是激活值传递。

我曾经踩过一个坑:
把模型并行和数据并行混着用,结果通信拓扑搞得太复杂,调试了三天才跑通。
后来我建议,能不用模型并行就别用,除非模型真的放不下。

3. 张量并行:更细粒度的切分

张量并行,比模型并行更细。
它不是按层切,而是把一个层内部的矩阵运算拆开。

比如一个全连接层,权重矩阵是 [4096, 4096]。
我可以把它切成两块 [4096, 2048] 和 [4096, 2048],分别放在两张卡上。
输入数据也切成两半,各自算一部分,最后拼起来。

这样做的好处是:
每张卡只算一半的矩阵乘法,计算量减半,显存也减半。
但坏处是:通信更频繁。每次矩阵乘法前后都要做 all-reduce 或 all-gather。

注意:
张量并行对通信带宽要求极高。我建议只在单机多卡场景下使用,跨机器的延迟太高,得不偿失。

三种并行方式的对比

并行方式 切分对象 通信频率 适用场景
数据并行 训练数据 每个batch一次 模型能放进单卡
模型并行 模型层 每层一次 模型层数极深
张量并行 层内矩阵 每次矩阵运算 单机多卡,大模型

它们怎么配合?

实际训练大模型时,这三种方式经常混着用。
比如训练GPT-3,用了数据并行 + 张量并行 + 模型并行三层嵌套。

我画了一张图,帮你理解它们的关系:

三种并行方式的关系 数据并行(Data Parallelism) 每张卡一份完整模型,数据切分 通信:梯度 all-reduce 模型并行(Model Parallelism) 按层切分,每张卡负责若干层 通信:层间激活值传递 张量并行(Tensor Parallelism) 按矩阵切分,每张卡算一部分 通信:矩阵运算前后 all-reduce / all-gather

从这张图你能看出来:
数据并行在最外层,负责数据分发和梯度汇总。
模型并行在中间层,负责把模型按层切分。
张量并行在最内层,负责把每一层的计算拆得更细。

我的建议:
刚开始做分布式训练,先从数据并行入手。
等遇到显存瓶颈了,再考虑加张量并行。
模型并行,我建议最后再碰,调试成本太高。

嗯,这三种并行方式,说白了就是空间换时间时间换空间的权衡。
数据并行用多份模型换训练速度,模型并行和张量并行用通信换显存。
怎么选,取决于你的硬件条件和模型大小。

我个人习惯,先算一笔账:
模型参数多大?单卡显存多少?通信带宽多少?
算清楚了,再决定用哪种并行方式,或者怎么组合。

最后说一句:
分布式训练不是银弹。有时候加卡反而更慢,就是因为通信开销超过了计算收益。
这个平衡点,就是我们下一节要聊的——通信与计算的权衡


公众号:蓝海资料掘金营,微信deep3321