深蓝黑背景封面。左侧一个立方体:正面青色描边、顶面紫色描边、侧面灰色描边,从顶点引出三根坐标轴箭头——水平轴「DP 数据并行 · 切数据」、纵深轴「TP 张量并行 · 切单层内部」、垂直轴「PP 流水线并行 · 按层分段」。顶部注「一个训练集群 = 三种切分的组合」。下方卡片写「总卡数 = DP × TP × PP,例:8 × 8 × 8 = 512 卡,每一维解决不同瓶颈」。右侧大标题「数据、张量、流水线并行,怎么组合成 3D 并行」,副标题「三种维度各切一刀,拼满千卡集群」。左上标注「面试经典 · 分布式训练」,右上胶囊标注「Day 04 · 11-21」。 图 1:三种并行是三个正交的切分维度,乘起来就是集群规模。

先说明属性:这是一篇经典题解析,题目出自本地历史面试资料整理,与任何公司的当前招聘无关。训练千亿参数级模型,单卡既装不下也算不动,「3D 并行怎么组合」因此成了分布式训练面试的必问题。答好它的关键不是背三个名词,而是讲清每种并行各切哪个维度、各自的通信脾气,以及组合时谁先谁后。

第一种:数据并行(DP),切数据。

每张卡保存一份完整的模型副本,各算自己分到的不同 batch,反向传播后做一次梯度 all-reduce,保证所有副本的参数同步。实现最简单、扩展近乎线性,但显存效率最低——参数、梯度、优化器状态在每卡上完整冗余一份。通信发生在每步一次、量级是参数规模,频率低。

第二种:张量并行(TP),切单层内部。

2019 年的 Megatron-LM 论文系统化了这个方向:把一层里的矩阵乘按行或列拆到多卡,各卡算自己那一块,再在层内做 all-reduce 拼回结果。它是减少单层激活显存的手段,显存随并行度成比例下降;代价是通信最频繁——每一层都要通信,对带宽极度敏感,因此通常只敢放在同一台机器内部的高速互联上跑,跨机做 TP 利用率会掉到没法看。

第三种:流水线并行(PP),按层分段。

把模型按层切成几段,每段放一组卡,前一段的输出激活传给下一段。段间通信是点对点、每微批次只传一次激活值,通信量最小;代价是流水线有气泡——头尾阶段总有卡空等,靠把 batch 切成多个微批次流水填充来压气泡。

一句话对比:DP 通信最少但显存最浪费,TP 显存最省但通信最凶,PP 通信最省但调度最复杂。三者切的维度正交,所以可以叠加。

3D 并行:三个维度相乘,拼满整个集群。

总卡数 = DP × TP × PP。比如 512 卡的集群切成 DP 8 × PP 8 × TP 8:先按数据切成 8 个数据并行组,每组 64 卡各持完整模型;每组内再按层分 8 段流水线,每段 8 卡;每段内 8 卡做张量并行,各持有矩阵的 1/8。2021 年的 Megatron-LM 后续论文(arXiv:2104.04473)系统研究了三种并行的组合配比,在 3072 卡上把万亿参数模型训到每卡 52% 的峰值算力利用率,证明了这套组合能扩展到千卡规模。

用一段小脚本把切分账算清楚,Node.js 22.15.0 运行(node parallel3d.js):

function plan(total, dp, pp, tp, hidden, layers) {
  if (dp * pp * tp !== total) throw new Error('维度乘积必须等于总卡数');
  console.log(`${total} 卡 = DP ${dp} × PP ${pp} × TP ${tp}`);
  console.log(`第一层切数据:${dp} 个数据并行组,每组 ${total / dp} 卡`);
  console.log(`第二层切层数:每条流水线 ${pp} 段,每段 ${layers / pp} 层、${total / dp / pp} 卡`);
  console.log(`第三层切张量:每卡持有矩阵的 1/${tp}(隐藏维 ${hidden} → 每卡 ${hidden / tp})`);
}
plan(512, 8, 8, 8, 8192, 64);

输出:

512 卡 = DP 8 × PP 8 × TP 8
第一层切数据:8 个数据并行组,每组 64 卡
第二层切层数:每条流水线 8 段,每段 8 层、8 卡
第三层切张量:每卡持有矩阵的 1/8(隐藏维 8192 → 每卡 1024)

部署口诀:通信越频繁的维度越靠内。

组合时的排布不是随意的:TP 每层都要 all-reduce,必须放在机内高速互联;PP 段间只传激活、量小,可以跨机;DP 每步才同步一次梯度,放最外层跨机也扛得住。口诀就是「通信越频繁的维度越靠内」。另外要提一句互补关系:ZeRO 系列解决的是「优化器状态、梯度、参数的冗余存储」,与 3D 并行的计算维度切分正交,实际大训练往往是 3D 并行加 ZeRO 一起上——ZeRO 的分阶段细节是另一道题,这里不展开。

深蓝黑背景概念图。左侧一条自上而下的层级分解链:顶层「512 卡集群」经标注「÷ DP 8」的箭头到「8 个数据并行组,每组 64 卡」,再经「÷ PP 8」到「每条流水线 8 个阶段,每段 8 卡」,最后经「÷ TP 8」到青色高亮的「每卡持有 1/8 张量切片」。右侧三张卡片解释三个维度:数据并行 DP——每组一份完整模型副本,各算不同 batch,反向后 all-reduce 梯度,通信最少、放最外层;流水线并行 PP——模型按层分段,段间只传激活值,用微批次填气泡;张量并行 TP——把矩阵乘按行列拆到多卡,层内 all-reduce 最频繁,通信量最大、放机内高速互联。底部总结条:部署口诀 —— 通信越频繁的维度越靠内,TP 走机内高速互联,PP 与 DP 跨机。 图 2:512 卡按 DP→PP→TP 逐层切分,每层各解决一个瓶颈。

面试答题骨架:先讲单卡装不下、算不动这两个动机,再按「切什么、通信特点、代价」三栏过一遍 DP/TP/PP,然后给出总卡数公式和一个具体切分例子,最后落到「通信越频繁越靠内」的部署口诀和与 ZeRO 的互补关系。能把「为什么 TP 不能跨机」讲清楚,基本就站稳了。你在实际训练里调过并行配比吗?气泡和通信哪个更头疼?欢迎聊聊。