筹备一场千人宴,主厨眉头紧锁:一张灶台炒不出千人的菜,一口锅放不下整头的牛。他设计了三个妙招——第一,把厨房原样复制到隔壁楼,多间厨房同时开火;第二,把超大锅具切成四块,几位厨师各占一角协作翻炒;第三,把烹制流程拆成“备菜→烹调→装盘”的接力线,每个工位只做一段。看起来是三件事,其实是一张图:一栋三维的中央厨房矩阵。 训练千亿参数的大模型,就像这场千人宴。显卡(GPU)就是灶台,模型权重就是食材,训练数据就是订单。单个灶台装不下整头牛,单双手来不及翻千道菜,单条流水线端不出满汉全席。于是业界把三个并行招数叠在一起——数据并行、张量并行、流水线并行——组成“3D 并行”。本文会用厨房里的故事,把三维切分策略、GPU 分配、通信拓扑和调优配置讲得明明白白。
掌握 3D 并行训练架构,是设计千亿参数大模型训练方案的核心技能。无论做预训练、微调还是推理服务,你都需要靠它把显存、带宽和算力安排得明明白白。
目录
可视化演示
动态演示3D并行训练架构的核心机制,通过架构/数据/状态/性能四种模式展示关键概念与交互流程。
本节配有交互动效(进入视口后自动加载,约 3KB)。
3D并行训练架构:D并行架 3D并行架构与三维切分原理 GPU分配与维度选择策略 核心机制可视化 3D并行训练架构整体架构与关键组件
三种并行模式:一张三维蓝图
筹备千人宴,主厨掰着手指说:一个灶台炒不了千人的菜。他准备了三件法宝——第一,把整个厨房原样复制到隔壁楼里,两间厨房同时开工;第二,把最大的炒锅切成四份,四位厨师各占一角同时翻炒;第三,把炒菜流程拆成“备菜→烹调→装盘”,每个工位各有专人。三件法宝叠在一起,就是一张三维厨房蓝图。
在深度学习训练中,这三件法宝分别对应数据并行、张量并行和流水线并行。数据并行(DP):每张 GPU 持有一份完整模型副本,各吃一批不同的训练数据,最后把梯度汇总。张量并行(TP):把某层的权重矩阵按行或列切开,让多张 GPU 合作完成一次矩阵乘法。流水线并行(PP):把几十上百层网络按层切段,设备 i 只负责其中一段。三者分别从“样本维度、层内计算维度、层间序列维度”分开下刀。
把三种切分组合起来,总 GPU 数量等于三个维度数字之积:
这个公式揭示了 3D 并行的第一原则:三个方向的切分度相乘,正好得到总设备数。实际部署时,通常先在节点内切 TP,再用 PP 连接不同层段,最后用 DP 复制整个链条来提高吞吐——三个数字共同决定集群怎么组织。
主厨把三种切法叠在一起,发现整体是一个“分层大网格”:数据并行沿样本方向复制,张量并行在每层内部横切,流水线并行沿层序列纵切。这就是“3D 并行”名字的由来。
- 符号 $G$(总设备数)所有参与训练的 GPU 总数,相当于整个三维厨房图纸上的灶位总和。
- 符号 $D_p$(数据并行度)把一批数据切成多少份,每个数据并行副本对应一组完整的厨房。
- 符号 $T_p$(张量并行度)把一层权重矩阵切成多少块,块数越多单卡显存越省,但通信越重。
- 符号 $P_p$(流水线并行度)把模型切成多少段,段数越多单卡显存越省,但气泡等待越多。
数据并行详解:多厨房同时开火
主厨在东西两楼各布置一间一模一样的厨房,厨师照着同一本菜谱,只是每间厨房分到不同的食材批次。每天收工后,两间厨房的厨师把各自调出的味道笔记(梯度)拿到中央台面比对,取一个平均值,再统一照着平均值调整明天的火候。第二天,两间厨房继续同步开火。
数据并行是三种并行里最直观的一种:把训练数据集按 batch 维度切成 $D_p$ 份,每张 GPU 拥有完整的模型参数副本。每个训练步,各副本独立完成前向和反向,计算出各自的梯度。为了保持参数一致,需要对所有梯度做一次平均。
梯度平均由集合通信里的 AllReduce 原语完成。设第 $i$ 个副本算出梯度 $g_i$,则最终平均梯度为:
这个公式看起来简单,但每一次 AllReduce 都要把所有梯度的字节从所有卡传到所有卡,通信量随参数量线性增长。因此在 3D 并行中,数据并行通常承担“扩吞吐”角色:它把吞吐扩大 $D_p$ 倍,同时只需在每步结束时花一次通信开销。
数据并行的好处像开分店:厨房越多,批次吞吐越大。但主厨很快意识到,若只有分店而没有店内配合,每间厨房还是放不下一整套锅具——这正是张量并行出场的原因。
- 符号 $\bar{g}$(平均梯度)所有数据并行副本完成一步训练后,大家统一用来更新权重的梯度。
- 符号 $D_p$(副本总数)有多少个数据并行副本,就做多少次独立的前向和反向。
- 求和 $\sum_{i=1}^{D_p} g_i$把每个副本算出的梯度逐元素相加,对应把各间厨房的味道笔记汇总到中央台面。
- 除以 $D_p$让每个副本对最终权重更新有同等话语权,防止某间厨房的数据量偏大而歪曲全局方向。
张量并行详解:切开一口巨锅
千人宴的招牌菜是一张比圆桌还大的千层披萨,一口锅根本烙不下。主厨把披萨面饼切成四等份,四位厨师各拿一个测温计同时烤,出锅后再拼回完整形状上桌。切开的不是“菜谱”,而是“菜本身”。
张量并行切的是模型层的权重矩阵。以最常见的线性层 $Y = XW$ 为例,$X$ 是输入激活,$W$ 是权重。若把 $W$ 按行切成两块 $W_1, W_2$,分别放到两台设备,那么输入也要相应切成 $X_1, X_2$。每台设备先算自己的局部矩阵乘,再通过一次 AllReduce 把两个局部结果相加:
这个公式揭示了张量并行的本质:把一次大矩阵乘法拆成若干个小矩阵乘法,让多卡合作完成。矩阵乘法在每个 Transformer 层中会出现几十次,因此张量并行必须在层与层之间都保持同步,通信频率极高。它要求设备间用最快的互连(如 NVIDIA NVLink)连接——这也是为什么张量并行几乎不会跨机柜。
主厨总算明白:披萨切得越细,灶位越省地方,但拼回完整披萨时需要的“拼盘手势”(通信)越频繁。要是把切披萨的厨师安排在相隔两层的厨房,端菜跑一趟的时间就比做菜还长了。
- 输入切分 $X_1, X_2$把输入激活按列方向切成两份,分别发给两台设备。
- 权重行切分 $W_1, W_2$把权重矩阵按行劈开,各设备保存一半权重。
- 局部矩阵乘 $X_i W_i$每台设备用自己收到的输入与本地权重做乘法,得到部分输出。
- 加法(AllReduce 归并)把两个部分输出逐元素相加,得到与整块权重计算完全等价的结果。
流水线并行详解:后厨接力流水线
主厨把后厨改造成一条流水线:第一站洗菜切菜,第二站热锅翻炒,第三站装盘点缀。一道菜必须依次经过三个工位才能上桌。问题来了:如果一桌有十道菜,第一道菜正在第二站炒着时,第一站已经可以开始洗第二道菜——大家并行起来,出菜速度大幅提升。
流水线并行把一个大模型按层切成 $P_p$ 段,每个设备组只负责其中一段。与数据并行和张量并行不同,PP 让信息“串行流过”各段。为了让各段设备不空等,我们把一个 batch 进一步切成 m 个 micro-batch(微批次),让它们像排队进入流水线一样连续被处理。
流水线并行有不可避免的“气泡”:第一段设备最早开工也最晚收工;最后一段设备则要等前面的微批次送过来。气泡占比可以用利用率公式描述:
当 m 远大于 $P_p$ 时 U 接近 1,但 m 增大会占用更多显存(每个 micro-batch 的中间激活都要缓存)。实践中常用 1F1B(one-forward-one-backward)调度,让前向和反向交替下发,既保持高利用率又限制显存峰值。
主厨发现一个道理:工位砌得越多($P_p$ 越大),每道菜在每个工位上的等待时间越长;把菜切得越碎(m 越大),流水线装得越满,但台面上待处理的食材(显存)也堆得越高。厨师要在“装得满”和“摆得下”之间找平衡。
- $m$(微批次个数)把一个训练 batch 切成的碎块数,m 越大流水线装得越满。
- $P_p - 1$(流水线排空等待数)最后一段设备要等的阶段数,决定了每个周期的“空档”长度。
- $U$(设备利用率)设备真正干活的时间占比,其余时间在等上下游送数据。
GPU分配与通信设计:厨房空间魔法
主厨拿着图纸算水电:切披萨的老师傅必须站在同一间厨房里,隔着一堵墙传锅还能接受,隔两层楼就不行了;楼与楼之间只能用电动餐车送半成品,一趟能拉很多但速度慢;分店之间交换菜谱靠电话也能办,但对话回合太多。厨房的物理布局决定了工序能不能跑得快。
3D 并行里三种并行的通信特征完全不同。张量并行每个计算步骤都要高频交换中间结果,通信量最大,必须放在同一节点内用 NVLink 直连;流水线并行只在段间传递激活值,次数少但单次数据大,适合用 InfiniBand 等高速跨节点网络;数据并行每步收尾只做一轮梯度同步,次数少,以太网即可。
三种通信的耗时大致可以写成:
其中 V 是需要传递的数据量,B 是各层网络的带宽。因此分配 GPU 时有一条铁律:先把张量并行组安置在同一节点内,再按节点安排流水线并行段,最后把数据并行副本铺到不同节点和机架。
主厨最后总结:空间布局就是性能的隐形天花板。把切披萨的厨师放在同一屋檐下,把流水线工位放在同楼层,把分店隔得远一点反而没关系——因为分店之间一周才通一次电话。
- $V_{TP}$(张量通信量)每次矩阵乘前后需要归并的中间结果,与序列长度、隐藏层大小和并行度成正比。
- $B_{NVLink}$(节点内带宽)NVLink 双向带宽可达 900 GB/s,是节点内通信的“厨房传菜窗口”。
- $V_{PP}$、$B_{IB}$流水线阶段间传递每层激活值,单次数据量虽少,但要走 InfiniBand(如 400 Gb/s)跨节点。
- 三部分相加总通信耗时由三个链路各自花费相加,哪一段带宽明显偏低,哪一段就是瓶颈。
3D并行部署调优:三管齐下的总谱
开工前夜,主厨把三项技术全部铺开:两个分店(DP=2)同时做宴席;每间厨房里四位厨师共用一口巨锅(TP=4);后厨分为“蒸、炒、炖”三个工位(PP=3)。主厨需要在纸上验算:显存会不会爆、排队会不会太久、传菜会不会堵。
3D 并行本质上是三维正交切分:样本、层内、层间三个方向同时开刀。配置的目标是在 GPU 总数固定的前提下,让单卡显存放得下、通信时间尽量短、流水线气泡尽量少。通常的启发式是:先确定 TP 匹配节点内的 GPU 数,再为流水线选尽量少的段数,最后把剩余 GPU 全部用于数据并行。
一个常用的效率度量是“实际计算时间占总时间的比例”:
其中 $\eta$ 是端到端训练效率。工程上还会用“计算通信比”来诊断:某一步里算得很快但通信很慢,就考虑调低 TP;气泡占比高,就增加 micro-batch 数或减少 PP 段数。典型例子:64 卡训练 70B 模型,节点内 8 卡 NVLink,可取 TP=4、PP=2、DP=8。
主厨最终把总谱定为 8 分店 × 4 切锅 × 3 工位,既让每口锅都放进一张完整的食材台,又让每一层传送带的压力控制在可控范围。3D 并行的真谛,正是让三种并行在空间上各司其职、在时间上无缝咬合。
- $T_{compute}$(纯计算时间)GPU 真正做矩阵乘的时间,是所有调整试图保住的底线。
- $T_{comm}$(通信时间)AllReduce、段间激活传输等花费的时间,受 GPU 拓扑和并行度配置影响。
- $T_{bubble}$(气泡时间)流水线等待前后段数据造成的空闲时间,与流水线段数近似成正比。
- $\eta$ 接近 1 越高效分母里任何一项膨胀,都会拖累整体效率;调优的任务就是让三项开销互相平衡。
AI 应用场景
千亿参数 LLM 预训练
阶段:训练与优化
解决的问题:训练千亿参数模型时,单卡显存完全装不下模型、优化器状态和中间激活,训练周期长达数月。传统单卡训练无法推进,即便只做数据并行,每张卡也放不下一份完整模型。3D 并行通过三维切分,让上千张 GPU 协同承担存储和计算,以可控通信开销换取近乎线性的扩展。
具体案例:Megatron-LM 训练 175B 参数 GPT-3 时,在 1024 块 A100 上采用 DP=64、TP=8、PP=8 的组合:节点内 8 卡以 NVLink 做张量并行,节点间用 InfiniBand 做流水线并行,数据并行负责扩吞吐,训练数月稳定运行。
大模型微调与 RLHF
阶段:微调与对齐
解决的问题:微调 13B 甚至 70B 模型对小团队也不轻松。直接加载权重经常 OOM,RLHF 的四个模型同时训练更是把显存压力推高数倍。3D 并行的“小号版”——只保留 DP+TP 或 DP+PP——就能在 32 卡集群上从容完成。
具体案例:某团队在 32 卡 A800 上微调 LLaMA-2 13B,使用 DeepSpeed 搭配 DP=8、PP=2、TP=2,并开启激活重计算,batch size 提到 128 后显存稳定在 72GB/卡左右,训练速度比纯 DP 快约 1.6 倍。
在线推理与并发服务
阶段:推理部署
解决的问题:大模型推理时 KV Cache 占显存,请求并发高时单卡放不下。虽然推理与训练侧重不同,但 TP 仍被大量使用:把权重和 KV Cache 切到多卡,从而增加单请求可用的显存和带宽。
具体案例:vLLM 部署 70B 模型时按 TP=4 将模型分到 4 张 A100,配合 PagedAttention 管理 KV Cache,单机即可服务 20 路并发,首 Token 延迟低于 1.5 秒。
Python 演示
import numpy as np np.random.seed(42) def shard(matrix, axis, parts): """把张量沿指定轴平均切成 parts 片""" return np.array_split(matrix, parts, axis=axis) def predict_ref(x, w1, w2): """单卡上的完整前向:两层感知机""" h = np.maximum(x @ w1.T, 0) return h @ w2.T def predict_3d(x, w1, w2, dp=2, tp=2): """模拟 3D 并行前向: - 数据并行:把样本切成 dp 份,分别进入 dp 个副本 - 张量并行:把 w2 的输出维度切成 tp 片,拼回完整输出 - 流水线并行:w1 和 w2 代表两个阶段,串行执行 """ x_parts = shard(x, 0, dp) w2_parts = shard(w2, 0, tp) outs = [] for xp in x_parts: stage1 = np.maximum(xp @ w1.T, 0) # 流水线阶段 1 stage_out = [] for wp in w2_parts: stage_out.append(stage1 @ wp.T) # 每个 TP 设备算局部片 y = np.concatenate(stage_out, axis=1) # 拼回完整输出 outs.append(y) return np.concatenate(outs, axis=0) # DP 副本结果拼回 def main(): x = np.random.randn(16, 32) w1 = np.random.randn(64, 32) w2 = np.random.randn(16, 64) y_ref = predict_ref(x, w1, w2) y_3d = predict_3d(x, w1, w2, dp=2, tp=2) print("两种前向结果的最大误差:", np.max(np.abs(y_ref - y_3d))) assert np.allclose(y_ref, y_3d, atol=1e-12) print("3D 并行切分与原模型完全等价 OK") if __name__ == "__main__": main()
shard(matrix, axis, parts)用np.array_split沿指定轴切分,对应把矩阵按行/列切给不同设备。x_parts = shard(x, 0, dp)把输入样本沿 batch 维切成 dp 份,对应数据并行把订单分给多个分店。w2_parts = shard(w2, 0, tp)把第二层权重沿输出维切成 tp 片,对应张量并行切分权重矩阵。stage1 = np.maximum(xp @ w1.T, 0)先过第一层线性变换加激活,对应流水线阶段 1。stage_out.append(stage1 @ wp.T)每片权重与同一份激活做局部矩阵乘,对应每个 TP 设备的局部计算。np.concatenate(stage_out, axis=1)把多片输出拼回,等价于完整权重一次算完。np.allclose(y_ref, y_3d, atol=1e-12)断言两种路径数值一致,证明切分不改变数学结果。
常见误区
误区我觉得把 512 张卡平均切成 8×8×8 最均匀,三个方向各有 8 份,这样一定最均衡高效。
正解3D 并行不是均匀分蛋糕。TP 需要最贵的 NVLink 通信,PP 每步都有气泡,DP 最灵活。实践上通常按“DP 尽量大、TP 匹配节点拓扑、PP 尽量小”的优先级配置。8×8×8 意味着 64 台节点间要频繁做跨节点张量通信,性能会非常差。
为何常见:把“三维”误解为空间上的等分,忽略了三种并行在通信成本和调度开销上的巨大差异。
误区TP 直接把权重切成 8 片,每张卡只存 1/8,最省显存,所以我优先把 TP 拉满。
正解TP 的通信量最大,每层前向和反向都要多次 AllReduce,对设备间带宽极其敏感。若没有 NVLink 级别的机内高速互连,TP 会让训练速度骤降。当模型能塞进显存时,应优先用 DP 扩吞吐、用 PP 减显存,TP 只作为补充手段。
为何常见:人对显存压力最敏感,但忽略了训练性能的主要矛盾往往是通信而非存储。
误区流水线利用率公式是 m/(m+P−1),m 越大利用率越接近 1,所以我直接把微批次个数设到极大值。
正解m 受总 batch size 和显存双重限制。每个 micro-batch 的中间激活都要缓存,m 过大会直接 OOM;此外改变 m 也改变了有效 batch size,可能影响收敛。实践中用 1F1B 调度时 m 取 4(P−1) 左右就足够填满流水线。
为何常见:在孤立数学模型里结论正确,但忘了显存边界和其他配套约束。
误区训练时配好了 DP×TP×PP,推理时同一份模型、同一个集群,直接沿用配置就能跑得飞快。
正解训练追求吞吐,推理追求低延迟。推理常用 TP 配流水线或仅 TP,且 batch size 小、KV Cache 占用高,配置需要重新评估;甚至可以用量化、权重合并等方式减少并行度。照搬训练配置往往导致延迟过高或显存浪费。
为何常见:以为并行配置只和模型大小有关,忽略了训练和推理的工作负载特征完全不同。
面试题
Q1. 3D 并行中的"D"代表什么?
- A.数据并行度← 正确答案
- B.模型深度
- C.设备时延
- D.显存容量
答案:A。D 代表 Data Parallelism,即数据并行度。它决定把训练数据切成多少份、有多少个完整模型副本同时运行。模型深度、设备时延、显存容量都不是并行的维度。
Q2. 数据并行每轮训练结束后,核心的通信操作是什么?
- A.参数广播
- B.梯度全规约← 正确答案
- C.权重裁剪
- D.模型量化
答案:B。数据并行各副本独立算出梯度后,需要通过 AllReduce 全规约操作对所有梯度求平均并广播给所有节点,保证各副本权重一致。参数广播是 AllReduce 的一部分但不是全部,权重裁剪和量化与同步无关。
Q3. 张量并行最适合依赖哪种设备间互连?
- A.千兆以太网络
- B.PCIe 高速总线
- C.NVLink 互连← 正确答案
- D.SATA 硬盘接口
答案:C。张量并行每层计算都要做高频 AllReduce,通信量最大、频率最高,只有 NVLink 这类超高带宽、超低延迟的机内互连才能扛住。千兆以太网和 PCIe 带宽不足,SATA 是存储接口,与 GPU 间通信无关。
Q4. 流水线并行中的“气泡”指的是什么?
- A.梯度消失现象
- B.设备空转等待← 正确答案
- C.显存碎片化
- D.通信丢包重传
答案:B。气泡指设备因等待前一流水线阶段的数据而空闲的时间。流水线启动和排空阶段都会产生气泡,通常用增大微批次数量来缓解。梯度消失、显存碎片、丢包重传都不是流水线并行的核心矛盾。
Q5. 总 GPU=64,每节点 8 卡 NVLink 互连,以下哪种配置更合理?
- A.TP=8, PP=2, DP=4← 正确答案
- B.TP=4, PP=4, DP=4
- C.TP=2, PP=8, DP=4
- D.TP=64, PP=1, DP=1
答案:A。张量并行必须优先落在节点内,8 卡节点的最佳 TP 是 8。然后 PP 取较小值以减少气泡,DP 用剩余 GPU 扩吞吐,因此 TP=8、PP=2、DP=4 更合理。TP=64 跨全部节点不可行,PP=8 会带来大量气泡,TP=4 浪费了节点内 NVLink 的完整带宽。
Q6. 以下哪些是数据并行的特征?
- A.每卡持有完整权重← 正确答案
- B.每步同步梯度汇总← 正确答案
- C.把权重矩阵切成片
- D.把模型层分给设备
答案:AB。数据并行让每张卡持有完整模型副本,每步用 AllReduce 同步梯度。把权重矩阵切成片是张量并行,把模型层分给设备是流水线并行,它们都不属于数据并行。
Q7. 3D 并行做 rank 分配时,最优先保证什么?
- A.张量并行组落在同一节点内← 正确答案
- B.数据并行组平均分布
- C.流水线阶段跨区域最远
- D.按 GPU 编号随机分配
答案:A。张量并行通信频率最高、数据量最大,必须用 NVLink 级互连,所以 rank 分配时首先把 TP 组放在同一节点内。数据并行平均分布和流水线跨区域没有优先于 TP 的必要,随机分配会毁掉性能。
Q8. 3D 并行能带来哪些收益?
- A.突破单卡显存上限← 正确答案
- B.缩短整体训练耗时← 正确答案
- C.直接提升模型精度
- D.减少通信开销总量
答案:AB。3D 并行通过三维切分让单卡只需存一部分权重和激活,从而突破单卡显存上限;同时利用更多设备并行计算,缩短训练耗时。并行方式不改变模型结构和超参数,不会直接提升精度;相反,并行通常会增加通信开销,不会减少通信总量。
Q9. 张量并行主要切分的是什么?
- A.训练数据集分片
- B.层内权重矩阵切片← 正确答案
- C.优化器状态分块
- D.日志记录与监控
答案:B。张量并行把每个网络层内部的权重矩阵按行或列切开,让多卡合作完成同一次矩阵乘法。训练数据集分片属于数据并行,优化器状态分块属于 ZeRO 优化器,日志监控与并行切分无关。
Q10. 关于流水线并行 micro-batch,下列说法正确的有?
- A.微批越多气泡越低← 正确答案
- B.1F1B 能省显存← 正确答案
- C.批越大收敛越好
- D.微批受显存约束← 正确答案
答案:ABD。利用率公式 m/(m+P−1) 表明微批越多气泡占比越低;1F1B 调度让前向与反向交替执行,减少同时缓存的激活数量从而节省显存;但微批数量受显存限制,不能无限增大。微批大小与模型收敛质量没有单调关系,所以 C 错误。