模型并行原理:模型并行 vs 数据并行、张量并行、流水线并行、序列并行

大家好,我是你们的老朋友。今天咱们聊聊模型并行。

说实话,我刚入行那会儿,觉得分布式训练就是多卡跑数据并行。后来模型越来越大,发现光靠数据并行根本喂不进去。你想想看,一个1750亿参数的模型,单卡显存才80G,怎么塞?

嗯,这时候就需要模型并行登场了。

数据并行 vs 模型并行:本质区别

先搞清楚一个基本问题:数据并行和模型并行,到底差在哪?

数据并行,说白了就是每张卡上都放一份完整的模型副本。数据被切成多份,每张卡处理一份。梯度算完后,大家同步一下参数。

我遇到过不少新手,觉得数据并行是万能的。直到模型大到单卡放不下,才意识到问题。

模型并行就不一样了。模型被切成多块,每张卡只负责其中一块。数据呢?要么每张卡都有一份完整数据,要么数据也被切分。

这里有个关键点:模型并行是为了解决「模型太大,单卡装不下」的问题。数据并行是为了解决「数据太多,单卡算太慢」的问题。

核心区别一句话:

  • 数据并行:模型复制,数据切分
  • 模型并行:模型切分,数据复制(或切分)

我个人习惯把模型并行再细分成三类:张量并行、流水线并行、序列并行。下面一个一个说。

张量并行:把一层拆开

张量并行,英文叫 Tensor Parallelism,简称 TP。

它的思路很直接:把一层网络的计算,拆到多张卡上做。比如一个矩阵乘法,本来是一张大矩阵,现在切成两块,每张卡算一半。

我在项目中遇到过这种情况:一个Transformer的FFN层,参数太大,单卡放不下。用张量并行,把权重矩阵按列切开,每张卡存一半。前向传播时,输入复制到每张卡,各自算完,再拼起来。

避坑指南:

我曾经在8卡上做张量并行,结果通信开销比计算还大。后来发现,张量并行适合卡间通信带宽高的场景,比如NVLink。如果用的是千兆以太网,还是别折腾了。

张量并行的通信模式是「all-reduce」或「all-gather」。每层计算完,都需要同步一次。所以层数越多,通信越频繁。

流水线并行:按层切分

流水线并行,Pipeline Parallelism,简称 PP。

这个思路更直观:把模型按层切成几段,每张卡负责一段。比如一个12层的Transformer,切成4段,每段3层,分给4张卡。

数据呢?像流水线一样,一批数据先过卡1,再过卡2,依次往后传。

你想想看,这样有个问题:卡1在算第1批数据时,卡2在闲着。等卡1算完传给卡2,卡2才开始算,卡1又闲了。这就是经典的「气泡」问题。

方案 气泡比例 适用场景
朴素流水线 约 50% 简单实验
GPipe(微批次) 约 20-30% 小规模部署
1F1B(交错调度) 约 10-15% 大规模训练

我记得第一次用GPipe时,气泡占了将近一半时间。后来换成1F1B调度,效率才提上来。

注意:

流水线并行的通信量比张量并行小得多。它只在卡与卡之间传激活值和梯度,不传权重。所以对带宽要求没那么高。

序列并行:把序列长度拆开

序列并行,Sequence Parallelism,简称 SP。这个比较新,是最近两年才火起来的。

它的思路是:把输入序列的长度切分。比如一个序列有2048个token,切成4段,每段512个token,分给4张卡。

为什么要这么做?因为Transformer的自注意力机制,计算复杂度是O(n²)。序列越长,显存消耗越大。我见过一个场景:序列长度从2048涨到8192,显存直接翻了4倍。

序列并行通常和张量并行配合使用。张量并行切分隐藏维度,序列并行切分序列维度。两者互补,效果更好。

嗯,这里要注意:序列并行需要修改注意力计算的实现。不是简单地把数据切分就完事了。每个token需要和其他所有token做注意力,跨卡通信是少不了的。

四种并行方式对比

说了这么多,咱们用一张表总结一下:

并行方式 切分对象 通信模式 通信量 适用场景
数据并行 数据批次 all-reduce 中等 模型能装下,数据量大
张量并行 层内计算 all-reduce/all-gather 高 单层太大,高带宽环境
流水线并行 层间切分 点对点通信 低 模型层数多,带宽有限
序列并行 序列长度 all-gather 中等 长序列训练

核心逻辑框架图

下面这张图,是我自己画的。它展示了四种并行方式的关系和适用边界:

模型并行核心逻辑框架 模型并行 数据并行 模型复制,数据切分 张量并行 层内计算切分 流水线并行 层间切分 序列并行 序列长度切分 关键选择指标 模型能否装下单卡? → 能:数据并行优先 → 不能:模型并行 卡间带宽是否充足? → 高带宽:张量并行 → 低带宽:流水线并行 序列长度是否很长? → 是:配合序列并行 → 否:只用TP+PP即可 实际训练中,通常组合使用:DP + TP + PP + SP

实际训练中的组合策略

说实话,实际训练很少只用一种并行方式。我参与过的项目,基本都是混合使用。

举个例子:一个千亿参数模型,怎么部署?

  1. 先做流水线并行:按层切成8段,每段分给一组卡
  2. 每组内做张量并行:每段内部的FFN和Attention,再切成4份
  3. 最后做数据并行:多组之间复制模型,切分数据批次
  4. 如果序列长:再加上序列并行

这样算下来,8×4=32张卡,再加上数据并行的副本数,轻松上百卡。

我的经验:

我个人习惯先确定流水线并行的段数,再决定张量并行的切分粒度。因为流水线并行的通信开销最小,适合跨节点。张量并行通信量大,适合节点内。

嗯,今天就聊到这。模型并行这块,内容不少,但核心就是这几类。搞清楚了它们的区别和适用场景,后面讲具体实现时,你会觉得轻松很多。

想要更多资料,联系可可