多卡训练大模型时,除了按数据分、按层内矩阵分,还有一种按层分段的分法:把模型的前几层放一张卡,中间几层放另一张卡,数据像工厂流水线一样从第一段流到最后一段。这就是流水线并行。本文按机制层思路,讲清它怎么分段、怎么排队、气泡是怎么来的。
切段:按层分到各卡
第一步是按层切段。进来的是一个完整模型和若干张卡,按层数均分成 P 段,第 1 到第 k 层放第一张卡,第 k+1 层到第 2k 层放第二张卡,以此类推。出去的是一串「段」,每段自带完整的前后向逻辑。切段位置有讲究:要按显存占用均摊,残差连接和归一化层的位置也会影响切点选择。
微批:数据分批流过管道
第二步是把数据批切成微批。进来的还是一个 global batch,不切成 N 份分给各卡,而是切成 M 个小微批依次流过。每个微批都要走完所有段的前向,再逆序走完所有段的反向。出去的是一串微批的前向激活和反向梯度,靠它们在段间接力。可以把它想象成同时让 Kimi 和讯飞星火分阶段加工同一份材料:Kimi 出初稿,讯飞星火润色,材料在两者之间来回流动,谁手头都不能断活。
排程:别让卡闲着
第三步是排程,也就是「排队」的核心。最朴素的排程是同步式:一个微批完整走完全部段,下一个微批才能进第一段,这样大部分卡在大部分时间都是闲的。改进后的排程让多个微批同时在管道里,第一张卡算完微批 1 的第一段,马上开始微批 2 的第一段,不等微批 1 走完全程,各段的等待被大幅压缩。
气泡:省不掉的等待
第四步是处理气泡。即使排程优化过,管道里仍有空隙:每个微批开始时,最后一段要等前面几段依次算完;每个微批结束时,前面几段要等最后一段反向传回。这些空闲就是所谓的气泡。微批数量 M 越大,气泡占比越小,但激活值要缓存的微批也越多,显存压力上升,这就是流水线并行最经典的权衡。实践中常按显存余量定微批数:先按段数翻倍起步,观察气泡占比和显存占用,哪头紧就往回撤一点。气泡比例是可以估算的,把管道填满和排空的时间除以总时间,心里有数再调。
它和数据并行、张量并行的分工很清晰:数据并行解决「训得慢」,张量并行解决「一层放不下」,流水线并行解决「整个模型放不下且层间有天然先后」。三者常叠加使用:机内张量并行,机间流水线加数据并行,是当前训练超大模型的常见组合。
| 手段 | 解决什么问题 | 落点 |
|---|---|---|
| 数据并行 | 训得慢 | 机间,与流水线叠加使用 |
| 张量并行 | 一层放不下 | 机内,按层内矩阵切分 |
| 流水线并行 | 整个模型放不下且层间有天然先后 | 机间,按层分段接力 |
| ZeRO | 省显存 | 分片存放参数、梯度与优化器状态 |
省显存的思路还有一条完全不同的路。ZeRO 是怎么省显存的讲把参数、梯度、优化器状态分片存放,不动模型结构;而训练时数据的喂入顺序,训练数据的顺序有影响吗会告诉你为什么流水线也不能省掉打乱这一步。
- 切段:按层均分到各卡,切点按显存占用和结构定
- 微批:global batch 拆成多个微批,依次流过所有段
- 排程:多个微批同时在管道里,别等前一个走完全程
- 气泡:管道首尾必然有空闲,微批越多气泡占比越小
- 代价:激活缓存随微批数上升,显存和等待反复权衡
关于流水线并行的三个常问问题
- 微批切多少个合适?:通常取段数的数倍起步,看气泡占比和显存占用两头调,没有万能数。
- 它和把模型分段手动跑有什么区别?:手动分段每段等前一段,气泡占掉一半时间;流水线并行靠排程让多个微批重叠,空闲被压到很小。
- 段数越多越快吗?:不是,段数越多气泡越难填,且段间接力通信变多,一般按卡数和模型深度折中取。


