想象你是一家大酒楼的老板,突然接到一笔大单:三天后要办一场 1000 人的宴席,每桌 12 道菜。你的厨房(一张 GPU)只有两口锅,食材仓库(显存)也已塞得满满当当——而这份菜单(模型参数)本身就大到连仓库都放不下。换一个更大的厨房?市面上最大的「单锅厨房」也装不下全部食材。唯一的路,就是把宴席拆解成许多小任务,在多个厨房同时开火。大型语言模型的训练困境正是如此:GPT-3 级别的 1750 亿参数模型,单张 80GB 显存的 A100 连权重都装不下。 NVIDIA 开源了 Megatron-LM,一套「多厨房协作手册」。它的看家本领是张量并行:把神经网络的权重矩阵想象成一块巨大的五花肉,按行或按列切成小块,分给多个 GPU 同时「揉面」,最后再拼回完整结果。本文就用大白话,把这场「分菜艺术」从头到尾讲清楚——你会看到一张二维矩阵如何被拆解、如何被多卡协同消化、如何在通信与计算之间找到平衡。
对 AI 从业者而言,张量并行是驾驭千亿参数大模型的底气。理解它的拆分原理与工程取舍,你才能在真实集群上把每一张 GPU 的算力都榨干。
可视化演示
展示查询优化器对多种执行计划的代价估算过程,对比I/O代价和CPU代价,自动选择总代价最小的最优执行计划。
本节配有交互动效(进入视口后自动加载,约 3KB)。
执行计划代价对比 优化器枚举所有可行执行计划并估算总代价 Cost = α×IO + β×CPU 选择总代价最小的计划作为最优方案
框架背景
在 Megatron 出现之前,训练大模型靠的基本是「大力出奇迹」——疯狂堆数据并行。就像一家酒楼让多个厨房各做各的一整桌菜,菜单完全一样,只是客人不同。可当模型大到单个厨房连菜单都背不下来时,数据并行就崩溃了:每张卡都要存一份完整的模型副本,显存直接爆掉。
Megatron-LM 是 NVIDIA 在 2019 年提出的开源框架,它真正实现了「模型并行」——不再把数据分给不同 GPU,而是把模型本身切成片,让不同 GPU 各持有一部分权重,共同完成一次前向与反向计算。核心思想就是张量并行:把一个线性层的权重矩阵 W 进行切分,多卡协作完成矩阵乘法。
为什么必须这么做?因为现代大模型的体量太惊人了。以 GPT-3 175B 为例,仅权重就要约 350GB(FP16),远超单卡 80GB。估算 Transformer 每层参数有一个快速公式:
每个 Transformer 层就像一道菜需要的四种调料包。当配方本身大到一张卡片记不下时,就必须请多位厨师(GPU)各保管几个调料包、协作完成烹饪——这正是 Megatron 存在的理由。
- 注意力 QKV 矩阵每层有 Q、K、V 三个投影矩阵,每个尺寸为 H×H,合计贡献 3H²
- 注意力输出投影将注意力结果映射回 H 维,一个 H×H 矩阵,贡献 H²
- MLP 第一层把 H 维映射到 4H 维,矩阵尺寸 H×4H,贡献 4H²
- MLP 第二层把 4H 维映射回 H 维,矩阵尺寸 4H×H,贡献 4H²
- 四者相加3H² + H² + 4H² + 4H²,即每层参数量约 12H²
切分原理
既然单卡放不下,最朴素的想法就是「切食材」。假设一整块五花肉(权重矩阵 W)要下锅,你把肉从中间一分为二:厨师 A 拿左半边,厨师 B 拿右半边,各自在自己的案板上处理。数学上,这对应张量并行里最基础的「列切分」。
设输入 X 的形状为(batch, H),权重 W 的形状为(H, H_out),输出 Y = X·W。如果沿 W 的列方向把它分成两半 W₁ 和 W₂,那么:
列并行之后,每个 GPU 只需存储 W 的一半,显存直接减半,计算也被分摊到两张卡。更重要的是,这一步没有 GPU 间通信——两块 GPU 只需要各自拿到完整的输入 X,输出保持「切碎状态」交给下一层继续处理。这种「先本地处理,再统一汇合」的节拍,正是张量并行贯穿整个网络的基本节奏。
- 原始线性层Y = X×W,W 的每一列对应输出的一维特征
- 按列切分 W将 W 切成两块,每块形状为(H, H_out/2)
- 分头计算GPU0 算 X×W₁ 得 Y₁,GPU1 算 X×W₂ 得 Y₂
- 拼接结果把 Y₁ 和 Y₂ 横向拼接,得到与整块计算完全相同的 Y
行列并行
做红烧肉要两步:先切肉,再下锅炒。MLP 块同样有两个线性层:第一层把 H 维映射到 4H 维(升维),第二层把 4H 维映射回 H 维(降维)。问题来了:如果第一层用列切分,第二层还能用列切分吗?不行!因为第一层的输出已经「切碎」成两段,第二层的输入形状是拼接前的维度,对不上。所以第二层必须换一种玩法——行切分。
MLP 的计算公式为:
其中 f 是激活函数(如 GELU)。W₁ 的尺寸为(H, 4H),W₂ 的尺寸为(4H, H)。
第一层用列并行:
得到的中间激活 Z 被切成 Z₁ 和 Z₂,分别落在 GPU0 和 GPU1 上。第二层用行并行:
这种「列并行 → 行并行」的组合是 Megatron 的核心模式。它保证了每个 GPU 只存 W₁ 的一块和 W₂ 的一块(显存减半),且只有在一层结束时才做一次 All-Reduce。同样的原理也适用于多头注意力:Q、K、V 投影矩阵沿列切分,输出投影沿行切分——整个 Transformer 块就是这样被张量并行化的。
一道菜的节奏是「切→各做→合炒」:切肉师傅把肉分成两半,炒菜师傅必须两半都收进锅里一起翻炒。Megatron 的全部精妙,就是把每个 Transformer 层的这场「合炒」安排在最少通信的位置上。
- MLP 两层结构第一层线性变换加激活,第二层再做线性变换
- 第一层列切分W₁ 按列切成 W₁a 和 W₁b,激活后得到 Z₁、Z₂
- 第二层行切分W₂ 按行切成上下两块,与 Z₁、Z₂ 分别相乘
- All-Reduce 合并两个部分积相加恢复完整输出,这一步需要一次全局通信
通信优化
当两个厨房各炒完半锅菜,需要把两半倒进同一个大盘子时,主厨就不得不干等。在大规模训练中,这种「倒菜」就是 All-Reduce 通信。它的代价有多高?张量并行每次 All-Reduce 的通信量近似为:
其中 B 是 batch size,H 是隐藏维度,N_layers 是层数。每层前后各有若干次 All-Reduce,如果通信时间不加以隐藏,训练效率可能直接腰斩。
Megatron 的通信优化非常务实,核心是「f-b 融合」:把相邻模块的 All-Reduce 与下一层的计算重叠起来,让通信在后台「偷偷」进行。前向时,上一层算完立即启动输出同步,同时 GPU 进入下一层计算;反向时同理,梯度 All-Reduce 与下一层反向计算并行。这样,通信时间被彻底「隐藏」在计算背后。
就像大厨在掂锅翻炒的同时,助手已经悄悄把下一道菜的食材端到了灶台边。Megatron 优化通信的本质,就是让「等待传菜」的时间不再被看见。
- 前向通信每个 Transformer 层在 attention 输出处和 MLP 输出处各需要一次 All-Reduce
- 反向通信反向传播同样需要在两处各做一次梯度同步
- 每层总次数前后向加起来共 4 次,乘以层数 N
- 合并估算每次 All-Reduce 传 B×H 的数据,所以总通信量约 2×N×B×H
组合扩展
当餐厅从 2 个厨房扩展到 32 个厨房时,只靠张量并行远远不够。真正的千人宴席需要三种协作:每一个分店各做各的一整桌菜(数据并行);同一桌菜按工序接力完成(流水线并行);一道菜本身由多个厨师合作(张量并行)。Megatron 擅长把三者编织成一张大网:
以训练 175B 参数模型为例:T=8(一个 8 卡节点内部协同),P=4(把 96 层网络切 4 段),D=64(每组流水线复制 64 份吃不同数据)。总 GPU 数 = 8×4×64 = 2048 张,每张卡只需承担 175B/8≈22B 参数的权重和计算,显存压力大大缓解。这就是 Megatron 能驯服千亿级模型的底气。
三种并行策略就像不同层级的团队协作:同一家分店的厨房里多位厨师合作一道菜(张量并行);厨房之间按工序接力(流水线并行);同一道工序又有多家分店同时开工(数据并行)。Megatron 的伟大之处,就是把这三种协作统一进一张「总调度表」,让千人宴席井然有序。
- T 张量并行度一层网络被多少张卡共同完成,对应权重矩阵的切分数
- P 流水线并行度网络按层切成多少段,段与段之间接力计算
- D 数据并行度整套流水线被复制多少份,各自吃不同的 batch
- 乘积关系三个维度正交互不冲突,总 GPU 数就是三者乘积
工程实践
理论再漂亮,落到真实的训练集群上,还有一堆「后厨细节」要处理。开一家大酒楼,光会做菜还不够,还要管冷库容量(显存)、食材新鲜度(精度)、排班表(调度)。大模型训练的显存开销不只是权重本身,还包括梯度、优化器状态和中间激活值。
以 Adam 优化器 + 混合精度训练为例,一个包含 P 个参数的模型,显存需求量大约为:
所以在实践中,光靠张量并行还不够,还要配合其他手段:混合精度(BF16/FP16 降低存储与通信开销)、序列并行(把序列维度也切分以压缩激活值显存)、激活值重计算(不保存中间结果,反向时重新计算,用算力换显存)、以及 ZeRO 优化器(把优化器状态也切碎分到多卡)。Megatron 提供了 --tensor-model-parallel-size 这样的命令行参数,直接将控制权交给使用者。
酒楼老板不仅要会设计菜单,还得算清冷库容量、进货频率和员工排班。「显存管理」「混合精度」「序列并行」正是后厨的这些细节——缺一不可,搭配得当才能让千人宴席准时开席。
- FP16 权重模型参数用半精度存储,占 2P 字节
- FP16 梯度反向计算的梯度同样半精度存储,占 2P 字节
- Adam 一阶动量优化器用 FP32 保存动量 m,占 4P 字节
- Adam 二阶动量用 FP32 保存方差 v,再占 4P 字节
- 合计2P+2P+4P+4P = 12P 字节,即每 10 亿参数要吃掉约 12GB 显存
性能调优
当训练集群跑起来之后,如何判断系统效率?是看 GPU 是不是一直在满负荷运转,还是看训练任务何时收敛?业界有一个通用指标叫 MFU(Model FLOPs Utilization,模型浮点利用率),度量理论算力中有多少真正用在了刀刃上:
在 Megatron 场景下,提升 MFU 的关键有三条:T 的选择——张量并行度通常取单节点 GPU 数(如 8),超过后跨节点 All-Reduce 会拖垮通信;微批大小——流水线并行时,微批越大,各段之间的空闲「气泡」越少;计算与通信重叠——把梯度 All-Reduce 和下一层计算同时进行,彻底隐藏通信延迟。
调优的本质就是给团队排班:每个厨师切多大块的肉(切分粒度),如何让所有人同时开工不互相等待(负载均衡),以及什么时机上菜(通信调度)。把这套「排班表」打磨到极致,MFU 就是那张打分卷。
- 分子训练全程实际完成的运算量,约为 6×P×D(P 为参数量,D 为处理的总 token 数)
- 分母理论峰值 = 单卡峰值算力 × GPU 总数 × 训练秒数
- 利用率两者相除得到一个 0 到 1 之间的比值,越接近 1 说明算力用得越充分
AI 应用场景
用 Megatron 训练千亿参数大模型
阶段:模型训练
解决的问题:1750 亿参数的模型在单卡上连权重都放不下,传统数据并行需要每卡保存完整副本,显存直接爆掉。用 Megatron 张量并行将权重矩阵切分到多张卡,让模型「住」进多卡组成的超算集群。
具体案例:某大模型团队在 256 张 A100 集群上训练 130B 参数模型。采用 T=8(单节点内 8 卡张量并行)+ P=4(网络按层切 4 段流水线)+ D=8(8 组并行副本),训练稳定运行 3 个月,最终收敛效果达到预期。
多卡推理加速部署
阶段:模型推理
解决的问题:175B 模型部署到线上服务时,单卡推理延迟高达数秒,无法支撑真实业务。利用张量并行把权重分布到多张 GPU,让一次推理的前向传播由多卡协同完成,显著降低单卡负载和延迟。
具体案例:某企业用 FasterTransformer 搭配 Megatron 张量并行权重切分,将 175B 模型部署在 8×A100 上。单次推理延迟从 3.2 秒降到 0.8 秒,QPS 提升近 4 倍,成功支撑起线上的智能客服场景。
3D 并行组合调优
阶段:性能调优
解决的问题:训练任务 MFU 长期徘徊在 30%,GPU 算力大量浪费在通信等待上。需要分析 D、P、T 三种并行的配比,找到通信与计算的最佳平衡点。
具体案例:工程师诊断一个 32 卡集群任务,发现 T=8、P=2、D=2 的配置下,All-Reduce 频繁跨节点通信。调整为 T=8、P=4、D=1 后,通信只发生在节点内的 NVLink 上,MFU 从 32% 提升到 44%,训练时间缩短近三分之一。
Python 演示
import numpy as np def column_parallel(x, w): # 列并行: 把权重矩阵按列切成两块, 分别计算后拼接 half = w.shape[1] // 2 w0, w1 = w[:, :half], w[:, half:] y0 = x @ w0 y1 = x @ w1 return np.concatenate([y0, y1], axis=1) def row_parallel(h, w): # 行并行: 权重按行切分, 将两部分结果相加(模拟 All-Reduce) half = w.shape[0] // 2 w0, w1 = w[:half, :], w[half:, :] h0, h1 = h[:, :half], h[:, half:] out = h0 @ w0 out += h1 @ w1 return out def tensor_parallel_mlp(x, w1, w2): # 两层 MLP 的张量并行版: 第一层列并行, 第二层行并行 hidden = np.tanh(column_parallel(x, w1)) return row_parallel(hidden, w2) if __name__ == "__main__": np.random.seed(123) x = np.random.randn(8, 16) w1 = np.random.randn(16, 32) w2 = np.random.randn(32, 8) y_ref = np.tanh(x @ w1) @ w2 y_par = tensor_parallel_mlp(x, w1, w2) assert np.allclose(y_ref, y_par, atol=1e-8) print("验证通过: 张量并行 MLP 与串行 MLP 输出完全一致")
w[:, :half], w[:, half:]把权重矩阵按列切成左右两块,这正是列并行np.concatenate([y0, y1], axis=1)把两块 GPU 的输出横向拼接,得到完整结果w[:half, :], w[half:, :]第二层把权重按行切成上下两块,对应行并行out += h1 @ w1模拟 All-Reduce:把两部分乘积相加,恢复完整输出hidden = np.tanh(column_parallel(x, w1))第一层激活后的结果保持切碎状态,直接喂给第二层
常见误区
误区很多人初次接触分布式训练时,把张量并行和数据并行混为一谈,认为都是「把数据分给多个 GPU 同时算」。
正解数据并行是「同一个模型复制多份,每张卡吃不同数据,最后同步梯度」;张量并行是把一个巨大的权重矩阵拆开,多张卡共同完成同一次矩阵乘法。用厨房比喻:数据并行是多个厨师各做一整桌菜;张量并行是多个厨师合作做同一道菜。两者是正交关系,不是一回事。
为何常见:分布式训练里多个 GPU 同时工作,外观看都像「并行」,但切分对象完全不同——一个切数据,一个切模型。
误区有些人以为 T=64 一定比 T=8 快,于是把能用上的 GPU 全部分给张量并行。
正解张量并行每次 All-Reduce 都要跨卡通信,T 越大,通信量呈线性增长。超过单节点的 NVLink 范围后,跨机通信延迟会吞噬所有收益。实践中 T 通常取 4 或 8,再多应改用数据并行或流水线并行扩展。
为何常见:「并行」两个字天然让人觉得越多越好,忽略了通信成本这一隐形杀手。
误区认为两层 MLP 都做列并行也行,反正最后拼起来就行。
正解第一层列切分后,输出 Z 被切成 Z₁、Z₂ 两段;第二层必须用行切分,让 Z 的各段与 W₂ 的行块对应相乘再 All-Reduce 求和。如果第二层也用列切分,输入形状根本不匹配,计算直接崩溃。这是矩阵维度的数学约束,不是风格选择。
为何常见:只看到了「切分→拼接」的表面模式,忽略了中间维度匹配与通信点位的深层逻辑。
误区以为把模型代码丢给 Megatron,它会自动做张量并行,不需要改任何模型代码。
正解Megatron 要求你把模型里的线性层替换成它提供的并行层(如 ColumnParallelLinear、RowParallelLinear),Transformer 结构也要按它的规范重写。这本质上是「模型改动 + 框架配合」,并不是开箱即用的黑魔法。
为何常见:框架宣传中「一行代码并行」的口号容易让人误以为所有模型都能自动无缝迁移。
误区模型放不下时的第一反应永远是调大张量并行度,觉得这是唯一出路。
正解张量并行确实能降单卡显存,但它也会放大通信开销。更优的路径是多种手段组合:混合精度、序列并行、激活重计算、ZeRO 优化器都能显著减压。只有这些手段还不够时,才考虑扩大张量并行,并配合流水线并行一起使用。
为何常见:张量并行能立竿见影地降低显存占用,让人误以为它是终极解药,忽略了通信代价和其他更轻量的替代方案。
面试题
Q1. 张量并行的核心思想是什么?
- A.把输入数据切成多份分给不同 GPU
- B.把权重矩阵切分给多卡协同计算← 正确答案
- C.把网络层切成多段接力计算
- D.把训练过程按时间分段执行
答案:B。张量并行是把权重矩阵按行或列切分,多卡合作完成同一次矩阵乘法,对应选项 B。A 是数据并行,C 是流水线并行,D 是时间切片,都不符合张量并行的定义。
Q2. 「列并行」时权重矩阵 W 如何切分?
- A.按行切成上下两部分
- B.按列切成左右两部分← 正确答案
- C.按对角线切成两部分
- D.随机位置切成两部分
答案:B。列并行沿 W 的列方向切分,得到左右两块 W₁、W₂,每块形状为(H, H_out/2)。按行切分是行并行的做法,对角线和随机切分都没有数学等价性。
Q3. 张量并行合并各卡结果时常用的通信算子?
- A.Broadcast 算子
- B.All-Gather 算子
- C.All-Reduce 算子← 正确答案
- D.Scatter 算子
答案:C。行并行最后需要把各 GPU 的部分和加起来,这个「多卡求和并广播给所有人」的操作就是 All-Reduce。Broadcast 是单发多收,Scatter 是切分发数据,All-Gather 是收集但不求和,都不符合。
Q4. 一个标准 Transformer 层的参数量约为多少?
- A.4 × H × H 个参数
- B.8 × H × H 个参数
- C.12 × H × H 个参数← 正确答案
- D.16 × H × H 个参数
答案:C。标准 Transformer 层包含 QKV 三个投影(3H²)、输出投影(H²)、MLP 两层(4H²+4H²),合计 12H²。4H² 只覆盖 Attention 部分,8H² 只覆盖 MLP 部分,16H² 是多余的估算。
Q5. Megatron 在 MLP 块中如何安排行列并行?
- A.第一层列切分、第二层行切分← 正确答案
- B.第一层行切分、第二层列切分
- C.两层都采用列切分方式
- D.两层都采用行切分方式
答案:A。第一层列切分使中间激活保持切碎状态,第二层行切分配合 All-Reduce 恢复完整输出。如果两层都列切分,第二层输入维度不匹配;反过来的顺序会让第一层输出无法被第二层消费。只有 A 符合矩阵维度约束。
Q6. 张量并行相比数据并行的正确描述有哪些?
- A.能训练单卡放不下的超大模型← 正确答案
- B.权重矩阵被切分到多张卡管理← 正确答案
- C.完全不需要 GPU 间通信
- D.对节点内高带宽互联依赖强← 正确答案
答案:ABD。张量并行把超大权重切分到多卡,因此可以训练单卡装不下的模型,A、B 正确;它的 All-Reduce 通信对 NVLink 等高速互联高度依赖,D 正确;C 错误,行并行阶段必须通信。数据并行才不需要切分权重。
Q7. 3D 并行包含哪些并行策略?
- A.数据并行← 正确答案
- B.张量并行← 正确答案
- C.流水线并行← 正确答案
- D.模型量化并行
答案:ABC。3D 并行 = 数据并行(D)× 流水线并行(P)× 张量并行(T),三者正交组合。模型量化是一种压缩技术,不属于并行策略,D 是混淆项。
Q8. 下列哪些属于张量并行通信优化手段?
- A.f-b 融合减少通信次数← 正确答案
- B.计算与通信重叠进行← 正确答案
- C.将小消息打包成大批次传输← 正确答案
- D.加大 All-Reduce 的参与 GPU 数量
答案:ABC。f-b 融合减少 All-Reduce 调用次数,计算通信重叠让通信「隐身」,消息打包提升带宽利用率——三者都是经典优化。D 反而增加通信成本,属于错误方向。
Q9. f-b 融合的核心收益是什么?
- A.减少 All-Reduce 通信次数← 正确答案
- B.提升单卡浮点运算能力
- C.削减模型的参数量
- D.完全消除显存占用
答案:A。f-b 融合的核心是把相邻模块的 All-Reduce 合并或与下一层计算重叠,从而减少通信等待次数、隐藏通信延迟。它不改变单卡算力,也不改变模型参数量和显存占用。
Q10. 跨节点训练时张量并行度 T 通常取多少?
- A.与单节点 GPU 数量一致← 正确答案
- B.等于总 GPU 数量
- C.固定为 1 不参与并行
- D.随机选取任意整数
答案:A。张量并行的 All-Reduce 通信量巨大,跨节点互联(如 InfiniBand)带宽远低于节点内 NVLink,因此 T 通常取单节点 GPU 数(如 8),让通信尽量留在节点内部。取总 GPU 数会导致大量跨节点通信,训练效率急剧下降。