人人都会AI编程

9.4 流水线并行(PP):模型纵向切分的原理与气泡问题

更新时间:2026-07-09

在 9.3 节张量并行(TP)中,我们把单层内的矩阵乘法和注意力计算横向切分到多张卡上,依靠机内高速 NVLink 做 AllReduce 聚合。TP 的瓶颈在于:它对通信带宽极度贪婪,且当模型进一步加深时,即使“一层”也足以撑爆单卡显存——此时横向切分已走到尽头。于是我们需要第二种切法:纵向切分,把模型的不同层(Layer)像切香肠一样分段,分配到不同 GPU 上。这就是流水线并行(Pipeline Parallelism, PP)


一、核心原理:按层切分,流水执行

假设你有一个 48 层的 Transformer Decoder,你有 4 张 GPU。最直观的切法是:

  • GPU 0:Layer 1–12
  • GPU 1:Layer 13–24
  • GPU 2:Layer 25–36
  • GPU 3:Layer 37–48

每一张卡只负责模型深度方向的一个阶段(Stage)。数据的前向传播像水流一样依次经过 GPU 0 → GPU 1 → GPU 2 → GPU 3,在最后一阶段计算 loss;反向传播则逆流而上,从 GPU 3 把梯度逐层传回 GPU 0。

相邻 GPU 之间只需点对点(P2P)通信传递激活值(Forward)和梯度(Backward),不需要全局集合通信。这听起来比 TP 的 AllReduce 轻量得多,但引入了一个 TP 不存在的新问题——顺序依赖


二、朴素流水线的致命伤:气泡(Bubble)

如果你采用最朴素的实现(Naive Pipeline):等一个完整 batch 的前向走完所有 4 个 stage,再开始反向。那么在时间轴上,任何一刻都只有一张 GPU 在计算,其余三张都在空转。

这种空转在 timeline 上表现为一段段空白,形似管道里的空气,因此被称为流水线气泡(Pipeline Bubble)

气泡的占比可以用一个简化公式刻画:

Bubble Ratio ≈ (N − 1) / (N − 1 + M)

其中:

  • N = 流水线阶段数(Stage 数,即 GPU 数)
  • M = 一个 batch 被切成的 micro-batch 数量

这个公式揭示了一个残酷现实:如果 M=1(不拆分 micro-batch),4 张卡的气泡比例高达 (4−1)/(4−1+1) = 75%——意味着 75% 的 GPU 时间在干等。这是无法接受的浪费。


三、缓解气泡的三大工程流派

为了把气泡挤出去,业界发展出三类方案,理解它们的取舍,是你选型 PP 框架的关键。

1. GPipe:用 micro-batch 填满管道

Google 提出的 GPipe 核心思想很直接:把一个 mini-batch 切成 M 个 micro-batch,让它们像波浪一样接连涌入流水线。

  • 过程:M 个 micro-batch 的前向依次进入 GPU 0,然后 GPU 1……直到 GPU 3;等最后一个 micro-batch 的前向结束后,再统一开始所有 micro-batch 的反向传播。
  • 效果:当 M 足够大时,流水线基本被填满,气泡被稀释到可接受范围。
  • 代价显存爆炸。因为在最后一个 micro-batch 完成前向、第一个 micro-batch 开始反向之前,每个 stage 都必须缓存 M 份中间激活值。显存占用与 M 成正比,这在 GPT-3 级别的大模型上是致命的。

2. PipeDream:异步前向,敢为人先

微软提出的 PipeDream 走了另一条路:不等梯度回传更新权重,就敢用旧权重继续跑下一个 batch 的前向

  • 机制:每个 micro-batch 前向时,系统保存一份当时的权重快照(Weight Stashing);等反向梯度回来时,再按快照版本更新。
  • 效果:流水线几乎 100% 满负荷,气泡极小。
  • 代价权重版本不一致。同一个 batch 的前向和反向可能使用不同版本的参数,导致优化过程理论性质变,收敛曲线可能出现抖动甚至发散。工程维护复杂度极高,目前在超大规模预训练中已较少作为首选。

3. 1F1B(One Forward One Backward):业界的黄金标准

当前最主流的方案(Megatron-LM、DeepSpeed Pipeline 均采用)是 1F1B。它的核心思想是让前向和反向像齿轮一样咬合,而不是等所有前向跑完再统一反向。

具体流程:

  • 当 GPU 0 完成 micro-batch 1 的前向,并将其推给 GPU 1 后,它不立即开始 micro-batch 2 的前向,而是等待;
  • 当 micro-batch 1 的反向梯度从 GPU 1 传回 GPU 0 时,GPU 0 立即做 micro-batch 1 的反向;
  • 反向一做完,激活值即可释放,然后马上开始 micro-batch 2 的前向。

这样一来,每个 GPU 在大多数时刻都在交替执行前向和反向,流水线处于准满负荷状态。更重要的是,显存占用与 stage 数近似线性关系,不再像 GPipe 那样随 M 膨胀。

1F1B 的 Bubble 特征:气泡时间 ≈ (N − 1) × t_stage,总时间 ≈ 2M × t_stage + (N − 1) × t_stage。只要 M >> N,气泡占比就能压到很低。实践中,N 通常取 4–8(一个机架内的节点数),M 取 16–64,气泡可控制在 10% 以内。


四、再进一步:交错流水线(Interleaved PP)

Megatron-LM 还提供了一种交错切分(Interleaved Pipeline):每个 GPU 不持有连续的层,而是持有多个交错的层块(Chunk)

例如,原本 48 层 4 路 PP 是每人 12 层;交错后,GPU 0 持有 Layer 1–3、13–15、25–27、37–39。相当于在更细的粒度上增加了流水线的段数,让波浪更平缓,进一步降低气泡。

代价:层间激活值的通信点变多了,P2P 通信次数上升。因此它更适合层数极多、通信带宽充裕的场景,否则通信延迟会吃掉计算收益。


五、PP 的通信特征与工程权衡

与 TP、DP 相比,PP 有自己独特的“性格”:

| 维度 | 数据并行(DP) | 张量并行(TP) | 流水线并行(PP) |
|------|---------------|---------------|----------------|
| 切分对象 | 样本(Batch) | 单层内的张量 | 层(Stage) |
| 通信内容 | 梯度(AllReduce) | 部分结果(AllReduce) | 激活值/梯度(P2P) |
| 通信量 | 与参数量成正比 | 极大(每层多次 AllReduce) | 较小(仅层间边界) |
| 通信模式 | 全局集合通信 | 机内高频集合通信 | 顺序点对点通信 |
| 扩展瓶颈 | 受 batch size 限制 | 受机内带宽/卡数限制 | 受气泡和顺序延迟限制 |
| 典型规模 | 几十到几千卡 | 2–8 卡(机内) | 2–16 阶段(机架内) |

关键洞察:PP 的通信量虽小,但延迟敏感。因为 stage k 必须等 stage k−1 的前向结果到达才能开工,这种强顺序依赖意味着 PP 很难像 DP 那样无限横向扩展。在工程实践中,PP 维度通常不超过 8 或 16。


六、实用认知:PP 落地的四条铁律

  1. PP 与 TP 是绝配,不是替代

标准做法是:机内用 TP(NVLink 扛住 AllReduce),机间用 PP(IB 扛住 P2P)。两者结合再加上 DP,就构成了 9.6 节将讲的 3D 并行。不要试图只用 PP 解决一切问题。

  1. 激活值重计算(Activation Checkpointing)是必选项

在 PP 中,为了塞入更多 micro-batch 来稀释气泡,你必须用“重计算”换显存:只保存边界层的激活值,中间层在反向时重新计算。这是 DeepSpeed 和 Megatron 的默认配置。

  1. Bubble 无法消灭,只能稀释

不要幻想存在一个“零气泡”的完美方案(PipeDream 近似但代价过高)。工程上的务实选择是:在显存允许范围内,尽可能增大 micro-batch 数量 M,这是降低气泡性价比最高的手段。

  1. 调试 PP 比调试 TP 痛苦一个数量级

PP 的 bug 往往表现为卡死(Hang):某个 stage 永远等不到上游的激活张量,或者下游的梯度丢了。排查时需要用 nsys 抓取 P2P 通信时间线,检查 NCCL P2P 是否因 PCIe/NVLink 拓扑问题 fallback 到了慢速路径。


七、小结

流水线并行(PP)通过纵向切分模型层数,解决了“模型太深、单卡连一层完整参数都装不下”的困境。它的核心矛盾不是通信带宽,而是顺序执行带来的流水线气泡

  • GPipe 用显存换气泡减少;
  • PipeDream 用收敛风险换利用率;
  • 1F1B 在显存、气泡和实现复杂度之间取得了最佳平衡,成为今天的事实标准。

在 9.5 节中,我们将转向另一种更激进的显存优化思路——ZeRO(零冗余优化器),它不从切分模型入手,而是从“每张卡都存一份完整优化器状态”这一冗余现状开刀,让数据并行也能训练百亿级模型。