4. 分布式训练基础:数据并行、模型并行、流水线并行、张量并行概念解析

分布式训练,说白了就是让多个GPU一起干活。你想想看,单卡训练大模型,显存不够、速度太慢,怎么办?那就把活分出去,大家一起干。

我刚开始接触分布式训练时,也搞不清这些并行策略到底有啥区别。后来在项目中踩了不少坑,才慢慢摸清楚门道。今天咱们就把这四种并行方式掰开揉碎了讲清楚。

4.1 数据并行——最常用的并行方式

数据并行,顾名思义,就是把数据切分到多个GPU上。每个GPU都有一份完整的模型副本,但只处理一部分数据。

举个例子:假设你有4张卡,每张卡上都放着一个一模一样的模型。训练数据有1024条,那就每张卡分256条。每张卡各自算梯度,然后汇总求平均,再更新所有卡的模型参数。

核心流程:

  1. 将batch数据切分到各GPU
  2. 每个GPU独立前向传播、计算损失
  3. 每个GPU独立反向传播,得到梯度
  4. AllReduce操作汇总梯度
  5. 每个GPU用平均后的梯度更新参数

我在项目中遇到过一个问题:当模型大到一张卡放不下时,数据并行就失效了。因为每张卡都需要完整的模型副本,显存不够就是不够。这时候就得考虑其他并行方式了。

我的经验:数据并行适合模型能塞进单卡的情况。如果模型太大,别硬撑,换别的方案。

4.2 模型并行——把模型拆开

模型并行,就是把模型本身切分成多个部分,分别放到不同的GPU上。每个GPU只负责模型的一部分计算。

比如一个12层的Transformer,你可以把前6层放在GPU0上,后6层放在GPU1上。数据先经过GPU0,算完再把中间结果传给GPU1继续算。

嗯,这里要注意:模型并行有个天然的问题——计算串行化。GPU0算完之前,GPU1只能干等着。这会导致GPU利用率不高。

避坑指南:我曾经在一个项目中把模型切成4块放在4张卡上,结果发现大部分时间都在等待数据传输,实际加速比远低于预期。后来才意识到,模型并行要尽量让各部分的计算量均衡,否则会出现「木桶效应」。

4.3 流水线并行——让GPU忙起来

流水线并行,说白了就是模型并行的升级版。它解决了模型并行中GPU空闲等待的问题。

怎么解决的?把数据也切成小份,像流水线一样送进去。GPU0算完第一个小份,就把结果传给GPU1,同时GPU0开始算第二个小份。这样所有GPU都能同时工作。

举个例子:

# 传统模型并行(串行)
GPU0: [batch1] → GPU1: [batch1] → GPU2: [batch1] → GPU3: [batch1]
GPU0: [batch2] → GPU1: [batch2] → GPU2: [batch2] → GPU3: [batch2]

# 流水线并行
GPU0: [batch1] → GPU1: [batch1] → GPU2: [batch1] → GPU3: [batch1]
      [batch2] → [batch2] → [batch2] → [batch2]
      [batch3] → [batch3] → [batch3] → [batch3]

你看,流水线并行让所有GPU几乎同时在工作,利用率高多了。

我个人习惯把流水线并行想象成工厂的流水线。每个GPU就是一个工位,数据就是待加工的产品。产品依次经过每个工位,所有工位同时开工,效率自然高。

小技巧:流水线并行中,micro-batch的大小很关键。太小了通信开销大,太大了又会导致GPU空闲。我一般会调成让每个micro-batch的计算时间刚好覆盖通信延迟。

4.4 张量并行——最细粒度的并行

张量并行,是在单个算子层面做切分。比如一个矩阵乘法,可以拆成多个小矩阵乘法,分别在不同GPU上算,最后再拼起来。

这跟模型并行不一样。模型并行是按层切分,张量并行是按张量(矩阵)切分。说白了,张量并行更「微观」。

举个例子,一个全连接层 y = xW,其中W是一个大矩阵。我们可以把W按列切成两块:

W = [W1, W2]  # 按列切分
y = x * [W1, W2] = [x*W1, x*W2]  # 两个GPU分别计算
y = concat([y1, y2])  # 最后拼起来

张量并行在Megatron-LM、DeepSpeed等框架中广泛使用。它能把超大模型塞进多卡,但通信量也很大,因为每次计算都要同步中间结果。

四种并行方式对比:

并行方式 切分对象 通信频率 适用场景
数据并行 数据 每个batch一次 模型能塞进单卡
模型并行 模型层 每层一次 模型太大,单卡放不下
流水线并行 模型层+数据 每个micro-batch一次 需要提高GPU利用率
张量并行 张量/矩阵 每个算子一次 超大模型,单层都放不下

4.5 知识体系总览

下面这张图,是我自己总结的分布式训练并行策略全景图。你看一眼就能明白它们之间的关系:

分布式训练并行策略全景图 分布式训练 数据并行 模型并行 流水线并行 张量并行 切分数据 每卡完整模型 AllReduce梯度 适合小模型 切分层 每卡部分层 串行计算 适合大模型 切分层+数据 流水线调度 高利用率 适合大模型 切分张量 算子级并行 通信密集 适合超大模型 实际应用中,通常组合使用多种并行策略 例如:3D并行 = 数据并行 + 流水线并行 + 张量并行

4.6 实际项目中的选择建议

说了这么多,到底该用哪种?我个人的经验是:

  • 模型能塞进单卡:直接用数据并行,简单高效
  • 模型稍大,单卡放不下:试试流水线并行,利用率高
  • 模型超大,单层都放不下:必须上张量并行
  • 追求极致性能:组合使用,比如3D并行

我曾经踩过的坑:一开始做分布式训练时,我总想着把所有并行方式都用上,结果通信开销巨大,反而比单卡还慢。后来才明白,并行不是越多越好,要根据模型大小和硬件条件来选。记住一个原则:能不并行就不并行,能少并行就少并行。

好了,这四种并行方式就讲到这里。你想想看,其实核心就一句话:数据并行分数据,模型并行分层,流水线并行分流水,张量并行分矩阵。搞清楚了切分对象,剩下的就是调参和踩坑了。

可可精品资料库