☰
Megatron分布式训练十年:从张量并行到4D并行的核心策略与实践
2026/10/19 8:44:03 网站建设 项目流程

1. 为什么会有Megatron:一张显卡装不下模型的年代

1.1 显存账本:参数、梯度、优化器和激活值

先帮大家把显存这笔账算清楚,因为整个Megatron十年演进,本质就是围绕这本账展开的。假设我们要训练一个100亿参数的模型,用最常规的FP16混合精度:权重按2字节/参数算,10B参数就是20GB;梯度再来一份,又是20GB;Adam优化器更夸张,它要维护FP32主权重(4字节)、一阶矩(4字节)、二阶矩(4字节),加起来12字节/参数,光优化器状态就120GB;这还没算前向传播过程中每一层都要保留的激活值,长序列大batch下轻松几十GB。合计一下就知道了,百亿模型想要放进一张卡,在2019年是做梦——当时的顶级训练卡普遍只有16GB到32GB显存,连千亿模型的思想实验都跑不起来。

所以Megatron出现之前,大家不是不想做大模型,是物理上做不到。这个背景特别重要,因为后面所有的并行策略演进,都像在围着这本显存账做减法:把权重分摊、把梯度分摊、把优化器分摊、把激活值分摊。今天很多人直接用着现成的训练框架,很难体会到当年每一步分摊方案背后那种"卡着显存上限抠空间"的紧张感。

这篇东西不是论文翻译,也不是官方手册的复述。我想以一个在一线训练团队折腾了多年的使用者的身份,把这十年Megatron到底演进了什么、每一步改动解决的是哪个具体疼点、以及我在实操里踩过的坑,一次说清楚。适合两类人看:一类是刚接触大模型分布式训练、想搞懂"为什么训练框架要设计得这么复杂"的工程师;另一类是已经在用类似方案、想回头理解底层权衡的老手。

1.2 数据并行为什么失灵

如果只是觉得"模型太大算得慢",那大家早就用数据并行搞定了——每张卡复制一份完整模型,各自喂不同的batch,梯度算完再互相拉齐。数据并行对训练吞吐的贡献是真真切切的,今天依然是大规模训练里最基础的加速手段。但它有一个死穴:显存占用是按卡数"复制"的,不是"分摊"的。模型参数一旦超过单卡显存,数据并行直接失效,因为每个副本都放不下。

"算不过来"和"放不下"是两个完全不同的病。算不过来,加大数据并行度就行;放不下,就得把模型本身拆开。Megatron针对的是后者。它最大的历史贡献,不是发明了某种花哨的优化算法,而是把"拆模型"这件事从学术讨论变成了工程上可落地、可扩展、可组合的整套方案。

1.3 拆模型的几把刀

Megatron给出的方案,可以理解成拆模型的三把刀:第一把按层切,把Transformer第1到第8层放0号卡,第9到第16层放1号卡,数据像接力棒一样在卡间传递,这叫流水并行;第二把在层内切,把某一层的权重矩阵从中间劈开,几张卡合起来算同一层,这叫张量并行;第三把把序列维度切掉,一段token分布到不同卡上各自处理,这叫序列并行。后来混合专家模型成了主流,又补了第四把刀——专家并行,把专家层分散到多张卡上,token按路由动态去找对应的专家。

这几个方向不是一天想出来的,而是随着模型一年年变大,被显存和通信的物理现实一脚一脚逼出来的。接下来的主线,就是看这些刀怎么被一把一把磨出来、磨锋利。

2. 十年演进的核心技术解构

2.1 张量并行:第一个真正的大模型突破口

2019年前后Megatron公开的最核心创新是张量并行。这里用一个全连接层把原理讲透:假设一层要计算Y = XW,W的形状是[k, n]。把W按列切成n份,每张卡只存自己那份W_i,那么每张卡拿着完整的X和自己那份W_i,算出部分结果Y_i,最后把各卡的Y_i在输出维度上拼接起来,就得到了完整的Y。整个过程只需要一次跨卡通信来做输出聚合,非线性激活之前不需要同步。

Transformer的MLP通常有两层线性变换,这两层在Megatron里是刻意配对设计的:第一层按列切分,第二层按行切分,这样两次AllReduce通信可以被非线性激活函数"夹"在中间合并处理。整个Transformer每一层实际只需要两次全量AllReduce通信。这个设计的重要性怎么强调都不过分——通信次数直接决定训练速度,少一次AllReduce,瓶颈就松一分。

为什么要费这个劲拆层内矩阵?道理跟一根太粗的木头一口灶烧不动、要劈成几片分灶烧一样。张量并行把每一层的计算量和显存都按TP大小均分,卡越多,单卡负担越小。但代价也极其明显:每层都要做AllReduce,通信量随模型宽度线性增长。所以TP规模受卡间带宽硬约束,业内典型值是4或8。之前有个朋友非要用TP=16,机架间通信直接把他训练速度打掉了四成,后面再不敢挑战这个经验值。

2.2 流水并行:把接力跑的空闲时间压到极致

张量并行解决的是单层太大,但模型层数很多时,光靠TP把全部层拆完也不现实,于是有了流水并行:把模型切成若干段,每段放一张卡上,数据从前往后依次流过各段。朴素流水有个著名问题叫气泡:因为同一时刻只有一段在算,其他段在空等,整个流水线的GPU利用率上不去,白瞎了好硬件。

Megatron的优化思路是"微批次"。把一个batch拆成很多个micro-batch,让它们一个接一个打进流水线,同时让前向和反向在时间上交错执行,这就是经典的1F1B调度。它的效果是,把空闲气泡压缩到流水线的启动和排空阶段,稳定运行阶段几乎每个GPU都有活干。气泡比例大约等于(p-1)/(m+p-1),p是流水级数,m是微批次个数。从这个公式就能看出来,m要尽量大、p不能太大。后来出现的VPP虚拟流水并行,把每个物理级再切成多个虚拟子级,用更细粒度交错去填气泡,本质也是顺着这条路继续压榨。

流水并行还有个隐形成本:段与段之间要传完整的激活和梯度张量,每次都是一次跨节点通信。所以PP同样不宜开太大,常用范围是4到8级。我见过有人把160层的模型开成PP=20,结果光等通信就等到崩溃。层数再深,也要在气泡和通信之间找一个自己的平衡点。

2.3 序列并行与激活重计算:跟激活值较劲

时间推到2021年前后,百亿级模型越来越常见,显存压力从权重和优化器转移到了激活值上。激活值这东西很讨厌:它每层都产生,大小跟序列长度、batch size、hidden size三者相乘成正比,长序列训练时能把显存吃掉一大半。Megatron后续的两个改动,都朴实但极其实用。

第一个是序列并行。Transformer里除了Attention和MLP,还有LayerNorm、Dropout这类计算量不大但需要完整hidden state的操作。序列并行的思路是:这些算子不再由每张TP卡重复计算整段序列,而是按序列维度切开,一段序列轮流在不同卡上处理。这样连LayerNorm这部分的激活存储也被平分掉了,通信模式也从每层两次AllReduce优化成了更省的模式。对超长序列,这招收益非常明显,我自己的长文本训练基本离不开它。

第二个是激活重计算,也叫梯度检查点。前向传播时把大部分中间激活丢掉,反向传播要用的时候再临时算回来。这是典型的用算力换显存:重算一个Transformer层的FLOPs大约是前向一次的成本,但可以把激活显存从"每层全保存"降到"只保存每个Transformer层的输入"。Megatron还支持选择性重计算,只对Attention或MLP里开销最大的部分重算,不是无脑全量。我在实操中只要序列长度超过2048,必然开重计算,不然80GB卡就像漏水的桶,装一会儿就满。

2.4 分布式优化器、专家并行与模块化重构

到了几千亿参数阶段,权重和梯度分摊完了,最夸张的反而是优化器状态。一个千亿模型,Adam三件套的FP32状态就要1.2TB以上,单卡根本不可能装下。Megatron随后引入分布式优化器,把优化器状态按数据并行维度切分到不同卡上,类似把一个人的记账本拆成多人各自记账:前向时把权重收集回来,反向阶段用reduce-scatter把梯度分片归并到对应卡上,各卡只更新自己保存的那份状态。这样一来,数据并行越大越省显存,模型规模上限一下子被推高了一大截。

混合专家模型成为趋势后,专家并行也被纳入体系:专家层分散到多张卡,token动态路由过去,通信走all-to-all。Megatron把专家并行和数据并行、张量并行、流水并行统一抽象成描述并行度的几个轴,这就是后来圈内常说的"4D并行"。近几年项目又做了一次大的模块化重构,把张量并行、流水并行、序列并行、分布式优化器、重计算、检查点等能力沉淀成可组合的核心组件库,下游框架可以像搭积木一样组合这些基础件。这个重构的分量,在工程上比又提出一个新并行策略还重要——它决定了这套体系能不能活到下一个十年。

3. 并行方案怎么落地:从理论到真实集群

3.1 4D并行怎么组合:先TP、再PP、最后DP

很多新手把几种并行混在一起就懵了,其实组合顺序有讲究。我给出一个多年实践验证过的正确顺序:先确定张量并行,让它跑在单个节点内的NVLink高速互连上;再确定流水并行,让它跑在节点之间;最后确定数据并行,拿最宽的维度把整个训练规模撑满。

举个例子:假设有16台机器,每台8张卡,共128张卡,要训练一个70B参数模型。可以先开TP=8,每张卡负责模型宽度的1/8;再开PP=2,把层切成两段,一个流水线组占2台机器;这样总共形成8个流水线组,数据并行就是8。整体是TP8 × PP2 × DP8。这样安排的好处是,通信最频繁的张量并行永远在NVLink内部完成,通信最稀疏的数据并行横跨所有机器,各种通信压力在时间上错开,不至于互相挤占带宽。

这里有一条我自己试错试出来的铁律:TP不要超过节点内GPU数,PP不要开太大,DP越大越好。这三个顺序是从无数次训练趟出来的经验,除非你的集群拓扑特殊,否则别去挑战。调并行参数的时候,把TP、PP、DP看成一把三脚凳——三条腿任意一条拼命加高,都会让另外两条承担额外压力。

3.2 显存估算:动手之前先算账

我强烈建议在配置任何训练任务之前,用公式粗算单卡显存:单卡显存约等于模型权重和优化器总字节数除以DP大小,再加上激活值除以TP和EP相关切分,最后留出通信缓冲区余量。权重、梯度、优化器状态这三项按16字节/参数记大概:7B模型约112GB,70B模型约1.12TB,175B模型约2.8TB,这还没算激活值。拿着这个数你立刻会理解为什么不同规模要用不同并行方案:

模型规模三件套总量典型可行并行是否必须分布式优化器
7B约112GBDP8 + TP2 + 序列并行建议开
70B约1.12TBTP8 × PP2 × DP8必须开
175B以上2.8TB以上TP8 × PP4 × DP16+强制开

7B模型看起来单卡80GB能装下权重,但三件套加上激活值就够呛,需要DP分摊优化器。70B模型则必须TP、PP、DP一起上,且重计算基本是标配。千亿以上,分布式优化器就是生存条件而不是性能选项了。

3.3 超大规模训练的真实代价

到了五千亿参数那个量级,业内曾在一组跨多个集群、数千张卡的环境里把训练跑完。做法说起来并不神秘:把模型按流水和张量的精细组合切到每一张卡,每个GPU实际只保存几十GB的权重、梯度和优化器状态,辅以大规模激活重计算。但做起来极其折磨人——每个并行轴的通信拓扑、每段流水的负载均衡、每层重计算的显存收益,都要在训练前反复推演。

我个人的体会是:真正限制大模型规模的不是单卡显存,而是你能否把并行轴安排得足够细、通信调度足够高效。Megatron这十年的价值,恰恰是把这套"把不可能拆成可能"的工程方法固化成了可复用的基础设施。

4. 实操过程与核心环节实现:一套可复现的训练配置

4.1 从零跑通一个中规模GPT模型的启动脚本

以Megatron风格的训练入口为例,一套中等规模GPT类模型的启动脚本长这样:

python -m torch.distributed.launch \ --nproc_per_node=8 pretrain_gpt.py \ --num-layers 40 \ --hidden-size 5120 \ --num-attention-heads 40 \ --seq-length 2048 \ --micro-batch-size 1 \ --global-batch-size 256 \ --tensor-parallel-size 8 \ --pipeline-parallel-size 4 \ --sequence-parallel \ --recompute-activations \ --use-distributed-optimizer \ --lr 1e-4 \ --min-lr 1e-5 \ --weight-decay 0.1 \ --adam-beta1 0.9 \ --adam-beta2 0.95 \ --lr-decay-style cosine \ --clip-grad 1.0 \ --save /data/checkpoints \ --save-interval 1000 \ --load /data/checkpoints \ --log-interval 10

这套配置假设你有8台8卡机器共64张卡。TP8表示每台机器内8张卡共同算一层;PP4表示4台机器接力算不同层的段;这样剩下两个流水线副本,DP就是2。全局batch 256等于micro-batch 1乘以梯度累积次数再乘以DP,这个对应关系很多人第一次都会搞反。

几个参数我当时都踩过坑,逐个说:micro-batch-size在流水并行下用1最稳,显存不够先减它,不要急着砍模型层数;tensor-parallel-size设成8能充分利用NVLink,但前提是每台机器正好8张卡,跨节点凑TP要谨慎;sequence-parallel和recompute-activations是长序列训练的黄金搭档,双双降显存;use-distributed-optimizer只要模型超过单卡可容纳范围就应该开,但要注意它改了检查点格式。

4.2 三个结构性参数怎么选:TP、PP、micro-batch数量

除了命令行参数,更值得花心思的是三个结构性选择。

TP的口诀是"先满足显存,再满足带宽"。算得出来每卡需要多少显存,如果TP8还放不下,先想办法压激活或开分布式优化器;把这些都压到底还差,才考虑换更大TP。但TP一旦超过节点内的GPU数,跨节点通信就会把训练打成低速,这时候宁可加深PP也不要无脑加TP。

PP的口诀是"气泡和通信延迟要平衡"。流水级数越大,每级分到的层越少,单卡负担越小,但气泡越大。实战中4到8是甜点区。40层模型开PP8,每级处理5层,合理;同样40层开PP16,每级只剩2.5层,气泡高到让你怀疑人生。

micro-batch数量的口诀是"越多越好,但别撑爆显存"。因为气泡比例里m是分母的一部分,m大则气泡小。通常做法是先设成1确认能跑通,再把显存余量都用来堆micro-batch数量,直到接近OOM边缘。这个"压着极限跑"的习惯,能帮你把训练吞吐榨出15%到20%的余量。

4.3 训练中的监控曲线与稳定性

跑训练时我一般盯三个东西:loss曲线、单次迭代耗时、梯度平均范数。loss曲线长时间不走,去看学习率和global batch是否匹配——batch变大后学习率也要相应调,不是只看loss数值;迭代耗时突然翻倍,多半是通信或显存交换导致,优先怀疑TP/PP配置和网络拓扑;梯度范数反复爆掉,那就是clip-grad没生效或loss scale出了问题。

检查点这块特别提醒:分布式优化器开启后,检查点保存的是分片的优化器状态,加载时必须保证TP、PP、DP配置完全一致,否则状态对不上。我的多年习惯是:每次改并行配置或者升级版本之前,先用最小模型跑一步save和load验证。这个动作只要两分钟,能帮你省掉后面的几小时排错。

5. 常见问题与排查技巧实录

5.1 训练速度上不去,GPU利用率很低

这个现象几乎每个大规模训练项目都会遇到。第一反应查通信:用带宽测试工具分别测节点内和节点间的实际带宽;如果TP组里混了跨节点卡,性能断崖式下跌。第二查流水线调度:确保micro-batch数量不是1,因为m=1时流水线全程都在气泡里,利用率惨不忍睹。第三查数据加载:数据读取来不及会把卡饿死,把预取和并行worker数量调上去,或者把样本换成带索引缓存的高效格式。

5.2 恰好OOM:压显存的四个标准动作

显存溢出是出现频率最高、也最容易刷经验的问题。按优先级试这几个动作:先开激活重计算,这是收益最大的单一开关;再开序列并行,把激活沿序列维度摊薄;然后把micro-batch从2改1,直接减少单卡前向规模;最后开分布式优化器,把优化器状态分摊到DP组。四个动作都做完了还OOM,才去动模型结构或batch。不要一上来就改TP和PP,那会牵一发动全身。

还有一个容易被忽略的显存大头:通信缓冲区。NCCL在启动时会预分配一大块显存,训练启动即占掉不少。某些版本可以通过环境变量调小缓冲区,但调太小又会让通信变慢。这个参数要靠实测找到平衡,不要凭感觉乱设。

5.3 检查点加载不上或loss跳变

我至少碰到过三次:训练中断后加载检查点,loss突然飙升。罪魁祸首基本都是并行配置和保存时不一致,或者分布式优化器状态没有正确切分和聚合。先核对启动参数是否和保存时一模一样,再核对版本升级后检查点格式是否兼容,最后查数据shuffle的seed——如果每个rank用了不同seed,加载后数据顺序就乱了,loss自然跳。

5.4 常见问题速查表

现象直接原因处理顺序
GPU利用率低TP跨节点、流水气泡大先查拓扑,再增大micro-batch数
OOM激活太大、优化器未分摊重计算→序列并行→减micro-batch→分布式优化器
通信超时NCCL版本、网卡拓扑换NCCL版本、检查拓扑、调缓冲区
loss不收敛学习率、global batch、seed错核对学习率、检查batch大小、统一seed
检查点加载错并行配置不一致保存前记录完整启动参数备用

5.5 一个容易被忽略的坑:改变并行度不等于能直接续训

很多人在训练中途想调TP或者PP大小,觉得"反正模型就放在那,我改个参数重新加载不就行了"。实际不是这样——Megatron的检查点是和并行配置强绑定的,TP从8改成4,张量切分方式全变了;PP从4改成8,流水段边界全变了;分布式优化器的分片位置也全变了。除非框架本身支持检查点重分片转换,否则你面对的就不是续训,而是从零开始。

我前年就吃过一次大亏:一个70B模型训到一半,为了腾机器把TP从8改成4,结果发现检查点加载进去后loss直接乱掉,最后只能回滚到旧配置重新排队。从那以后,我定了一条规矩:训练启动前就把最终规模想清楚,中途只调不影响并行拓扑的参数。

我个人这十年做分布式训练最大的感悟是:Megatron的每一个演进节点,几乎都是被显存和通信的物理现实逼出来的。张量并行为了解决单层放不下,流水并行为了解决层数放不下,序列并行和激活重计算为了把激活值从显存里挤出去,分布式优化器为了把优化器状态摊到更多卡上。这些技术单看都不复杂,难的是组合在一起后那种牵一发动全身的调试痛苦。

最后再分享一个实用小技巧:在跑正式训练之前,先用一个只有2层的小模型把整条pipeline跑通一遍,包括save和load、异常中断恢复、以及改变micro-batch后的行为验证。这半小时的提前演练,往往能帮你省下后来的好几天排错时间。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询