十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

LLM分布式计算五大并行策略:从数据并行到专家并行全解析

LLM分布式计算五大并行策略:从数据并行到专家并行全解析 如何从算法视角理解 LLM 分布式计算五大并行策略先聊个很实际的感受很多算法同学做模型训练和推理时说白了就是调用 DeepSpeed、Megatron-LM 或者 vLLM 这些框架GPU 一跑起来就完事了。一旦遇到显存不够、训练速度上不去、推理延迟下不来就开始对着报错日志发愁最后只能把模型尺寸调小或者把 batch size 降下来。问题根源很大程度在于——你对大模型分布式计算的底层并行策略没有建立全局认知。这篇系列第二篇就专门解决这个痛点。我会用算法同学熟悉的语言把 LLM 分布式计算中最重要的五类并行策略讲透数据并行、流水线并行、张量并行、上下文并行、专家并行。这篇文章能帮你搞清楚每种并行的切分维度、通信开销、适用场景、优缺点以及它们在实际的大模型训练和推理框架里是怎么组合使用的。不管你是正在做大模型训练调优的算法工程师还是准备转入 AI Infra 方向的同学这篇文章都可以帮你建立一套完整的分布式并行知识框架。看完之后你在面对模型规模上不去的瓶颈时至少能判断出问题出在哪种并行维度上这比盲目调参有意义得多。1. 背景与动机为什么算法同学必须补这一课1.1 模型规模与单卡显存的天然矛盾算法同学对显存的感知往往停留在加载模型权重这个层面。比如 7B 参数的模型用 FP16 存储权重大约是 14GB看起来一张 A100 80G 也能放得下。但真实训练场景远不止这点消耗优化器状态一般要用 FP32 保存Adam 优化器每个参数会对应两份动量张量这样光优化器状态就是权重的 8 到 12 倍开销梯度本身也要 FP32 存储再加上激活值、中间计算结果、通信缓冲区一个 7B 模型用单卡训练实际显存占用轻松超过 120GB。推理场景也好不到哪去。虽然不需要优化器状态但 KV Cache 在长上下文场景下会吃掉大量显存7B 模型配上 32K 上下文KV Cache 可能比权重本身还大。更不用说模型在解码阶段需要同时保留算子和中间张量。这就是为什么模型做到一定规模单卡必然是放不下的分布式并行计算从可选项变成了必选项。1.2 算法同学普遍面临的理解断点我接触过很多算法背景的同事他们的分布式知识大多停留在用 nn.DataParallel 或者 DeepSpeed stage 2 把模型放到多卡上这种程度。一旦要解释清楚这几个问题就卡住了Megatron 的张量并行为什么要切分 attention 的 QKV 权重矩阵数据并行和 ZeRO 优化的本质区别是什么为什么 3D 并行配置是 TP8, PP4, DP24 而不是其他组合长序列训练里面Flash Attention 和上下文并行怎么配合这些断点的核心原因在于算法同学熟悉的是 PyTorch 的 Module 抽象但分布式并行是系统层面的抽象。并行策略决定了张量如何在设备间切分、通信如何编排、计算如何重叠。不理解这一层就很难真正驾驭大模型训练框架。1.3 系列文章的定位与目标这一篇不会停留在概念罗列上。我会把五种并行策略的切分方式、通信模式、显存分布、扩展性上限都展开并结合实际框架配置说明它们是怎么落地的。你可能会看到一点数学表达但我会尽量用生活化的语言去解释每个抽象概念。读懂这篇文章之后你应该具备三种能力第一看到一个模型配置和集群拓扑能说出为什么这样设计并行方案第二训练或推理出现性能问题能初步定位是通信瓶颈还是负载不均第三面试 AI Infra 岗位时能把并行维度的推导逻辑讲清楚而不是只背名词。2. 五大并行策略核心原理全拆解2.1 数据并行最朴素但不简单的切分思路数据并行应该是大家最早接触的并行方式。它的核心思想很直观每个设备GPU都保存一份完整的模型副本然后把训练数据切成多份每个设备用自己的那份数据独立计算前向和反向。梯度计算完成后通过 AllReduce 通信把大家的梯度汇总平均再用平均后的梯度去更新所有设备上的模型参数。这里面有一个很关键的细节值得展开。数据并行的通信量是跟模型规模线性相关的因为每次迭代都要把完整模型大小的梯度做一次全局聚合。比如一个 7B 模型用 FP32 存梯度就有 28GB用 8 卡数据并行每轮通信量就是这个量级的两倍左右。所以模型越大数据并行的通信压力就越大这也是为什么分布式并行不能只有数据并行一个维度。ZeRO 是数据并行的进阶形态它的核心洞察是既然每张卡都保存了全量模型副本其实存在大量冗余权重、梯度、优化器状态在每张卡上都有一份。ZeRO 把这三块内容做了分区存储ZeRO-1 切分优化器状态ZeRO-2 继续切分梯度ZeRO-3 连参数也切分掉。通信方式也从 AllReduce 变成了 Reduce-Scatter 加 All-Gather 的组合这样通信总量不变但每张卡的平均通信量大幅下降。数据并行的一个直观类比是不同小组拿着完全相同的教材模型各自做不同的练习题不同batch的数据做完之后把各自的错题和答案汇总提炼出统一的改进方向下次所有小组按改进后的方法继续做题。2.2 张量并行把矩阵切开从计算图内部动手如果说数据并行是每个设备各自为政那张量并行就是一个算子的活多个设备合着干。以 Transformer 结构中最重要的线性层为例假设输入 x 的维度是 [batch, seq_len, hidden_size]权重 W 的维度是 [hidden_size, output_size]。张量并行可以在 output_size 这个维度上把 W 切成多块每个设备只计算自己那一块的输出最后拼起来。Megatron-LM 提出了一种非常经典的行并行列并行组合模式专门用于 Transformer 的 MLP 结构和 Attention 结构。以 MLP 为例第一个线性层 W1 按列切成多块每个设备独立计算中间结果第二个线性层 W2 则按行切分需要先做一次 AllReduce 把中间结果聚合完全再做矩阵乘法。这样设计的精妙之处在于整个 Transformer block 只需要两次 AllReduce 通信分别位于 attention 输出层和 MLP 输出层附近通信次数被压缩到理论最小值。张量并行的核心代价是通信非常密集。矩阵乘法的结果是相互依赖的切分维度是计算维必须反复聚合中间结果。因此张量并行要求设备间的通信带宽极高实践上通常只在单机内部使用 NVLink 连接的 GPU 之间做张量并行。跨节点做张量并行通信延迟会急剧上升性能会很难看。一个直观类比是把一道大型矩阵乘法想象成一场多人接力。张量并行不是让几个人分别算不同的题目而是让几个人合作算同一道大题目每算一步都要把彼此的中间结果汇总同步这显然要求大家站在同一块黑板前面工作。2.3 流水线并行按层切分让模型像工厂流水线一样跑起来流水线并行按照 Transformer 层的深度方向切分。假设一个 32 层的模型切成 4 份每份包含 8 层放在不同的 GPU 上。数据像流水线上的物料一样依次经过 GPU0 的前 8 层再到 GPU1 的 8 层以此类推。前向传播时从 GPU0 传到 GPU3反向传播时按相反方向回传梯度。流水线并行最大的问题是会产生流水线气泡。最朴素的实现方式是每个设备等前一个设备算完才开始这样同一时刻只有一个 GPU 在干活其他都在空转利用率极低。为了解决这个问题业界提出了微批次micro-batch的概念把一个大 batch 切成 m 个微批次每个微批次独立流经流水线。这样不同的 GPU 可以同时处理不同的微批次填满流水线。GPipe 是最早的一版实现它在每个微批次完成后做一次全局梯度同步简单可靠但气泡占比依然比较高。之后的 PipeDream 系列和 1F1B 策略解决了启动阶段和收尾阶段的气泡问题。1F1B 的关键是让一个微批次的反向计算尽可能早地开始而不是等所有微批次前向做完再统一反传这样显存占用降低不少效率也大幅提升。流水线并行的一个关键优势是通信量很小。每个 Transformer 层之间只需要传递 hidden_states 和梯度这些张量的大小远小于模型权重总量。而且流水线并行可以跨节点部署甚至不同层可以运行在不同型号的 GPU 上。很多公司用混合硬件构建异构集群流水线并行就是核心依赖的并行方式。流水线的类比很直观汽车工厂有冲压、焊装、涂装、总装四个车间一辆车依次经过每个车间完成生产。如果每个车间等前一个车间完全处理好一辆车再接手那么只有一辆车在工厂里流动效率极低。优化方案就是多辆车同时在不同车间流动每辆车就是一个小微批次。2.4 上下文并行长序列时代的专用解法上下文并行是最近随着长文本模型大火而进入大家视野的并行策略。它的核心思想是在序列长度这个维度上做切分而不是在数据、层数或参数上做切分。为什么需要这样因为 Transformer 的自注意力机制有一个关键的平方复杂度问题序列长度是 32K 时注意力矩阵就是 32K×32K单单这一个中间矩阵用 FP16 存储就有 2GB 以上。而序列长度到 128K这个矩阵直接膨胀到 32GB单卡基本扛不住。上下文并行的核心做法是把序列的一段分配给一个设备每个设备只处理自己这一段 token 的 QKV 投影计算。但是注意力计算是全局的每个 token 的 attention 都要关注序列所有位置。这就引出两个研究方向一是 Ring Attention让 KV 在每个设备之间循环轮转每个设备依次拿到其他设备的 K/V 分块做局部注意力计算最终得到完整的注意力输出二是 DeepSpeed Ulysses 方案在计算 attention 之前做一次 All-to-All 通信把序列切分的布局转化为头数维度的切分让每个设备拥有完整序列但只负责一部分 attention head。上下文并行和张量并行经常被一起比较使用。张量并行在处理超长序列时也会遇到问题——只有 QKV 投影矩阵和输出投影层可以被切分注意力计算的核心部分依然需要完整序列数据通信次数很多。上下文并行则直接针对注意力部分做了专门的切分策略所以长序列场景下往往比张量并行更高效。不过需要特别强调一点上下文并行的通信量跟序列长度相关而且通信频繁度很高实际应用时通常会把上下文并行控制在较小的规模内比如 2 到 8 个设备再配合其他并行策略去扩展整体规模。2.5 专家并行MoE 模型专属的分布方案Mixture-of-Experts 架构在最近两年非常火其核心结构是原本的 FFN 层不再是单一的全连接层而是被替换成多个专家网络和一个门控路由。每个 token 经过门控网络路由只会激活少数几个专家比如 top-2这样就实现了用更少的计算量拥有巨量参数的效果。专家并行的核心思想是把不同的专家网络放置在不同的 GPU 上token 通过路由机制被发送到对应的专家所在的设备上去计算。因为每个 token 只需要访问少数专家所以大部分计算是局部的。但这也带来一个很棘手的问题token 在设备之间通信的频率非常高每个 Transformer 层都要做一次 All-to-All 通信。一个 token 从 GPU0 出发它的专家可能分布在 GPU2 和 GPU5 上那么它就必须被发送到这两个设备去完成计算再送回来。专家并行和数据并行在实际中通常是结合使用的。对于 MoE 模型主流做法是采用 EP 加 DP 的组合注意力等密集计算部分走数据并行每个设备有完整副本MoE 的专家部分则做专家并行切分分布在多个设备上。这样既能利用数据并行的简单高效又能发挥专家并行的参数扩展能力。专家并行的核心难题是负载均衡。如果某些专家特别热门大量 token 都被路由到同一台设备上那这个设备就成了性能瓶颈其他设备却在空转。DeepSpeed 的做法是做动态负载均衡根据每个专家的实时流量来调整专家副本和放置位置Switch Transformer 则通过辅助负载均衡损失在训练阶段就引导门控网络尽量均匀分配 token。3. 并行策略的选型逻辑与组合方案3.1 每种并行策略的通信与扩展性对比不同的并行策略在通信开销、显存分布、扩展边界上差异很大。我整理一张表方便横向对比。并行维度切分对象主要通信模式通信量特征单卡显存节省效果主要应用场景数据并行训练数据AllReduce / Reduce-Scatter All-Gather与模型大小相关无每卡全量副本小模型训练、超大批量训练张量并行权重矩阵AllReduce与激活尺寸相关权重、激活按切分比例下降单机多卡训练与推理流水线并行Transformer 层Point-to-Point与单层激活大小相关激活、权重按层数切分跨节点训练、异构集群上下文并行序列长度Ring / All-to-All与序列长度相关注意力中间值大幅降低超长序列训练与推理专家并行专家网络All-to-All与 token 交换量相关专家参数按设备分布MoE 模型训练与推理数据并行和专家并行是无切分或少量切分的并行方式通信模式比较简单张量并行和上下文并行是切入到单个算子内部的细粒度并行通信非常频繁流水线并行则是粗粒度的设备间切分通信最少但气泡问题需要优化。3.2 实际框架中如何组合使用这些并行策略单独使用任何一种并行策略都很难支撑起千亿级模型的训练。业界已经形成了几个主流的组合模式CCR的术语叫3D 并行即数据并行、张量并行、流水线并行三者叠加。Megatron-LM 提出并验证的经典做法是DP 在最外层PP 在中层TP 在最内层。假设有 64 张 GPU可以配置为 TP44 卡做张量并行、PP44 组流水线、DP44 路数据并行那么总 GPU 数 TP×PP×DP 4×4×4 64 张每个参数都有 64 个维度的组合关系。实际选型时要遵循一个基本原则高通信需求的并行维度应该约束在高速通信域内低通信需求的并行维度可以尽量扩大。GPT-3 175B 训练时在单个 DGX-A100 节点8 卡 NVLink 互联内部做 TP8然后 8 个节点之间通过 IB 网络做 PP8最外层再用 DP 做多副本并行。这样保住了通信性能也实现了大集群规模扩展。DeepSpeed 在这个框架里继续叠加 ZeRO 优化。对于模型规模特别大的场景ZeRO-3 可以配合流水线并行和张量并行一起使用。这样同一个参数可能同时在三个维度上做切分——张量维度、层维度、以及参数区间的维度。理解起来确实有点绕但核心思路只有一个每一维度切分解决一个特定的显存瓶颈点。推理侧的并行策略选择跟训练侧差异很大。训练侧重吞吐量尽量全部设备同步执行前反向推理侧重延迟和并发。vLLM 中常用的配置是张量并行加数据并行张量并行做单请求的加速数据并行做多请求的并发承载。对于超长上下文的推理场景会再叠加上下文并行来降低单卡的 KV Cache 压力。3.3 确定并行配置的几个关键公式与计算方法在实际工作场景中我们经常需要根据模型大小和显存需求来确定并行配置。把关键的计算方法整理一下第一步是计算总参数显存。FP16 或 BF16 的权重每 10 亿参数约占 2GB。7B 模型就是大约 14GB175B 模型大约 350GB。如果训练还要加上梯度和优化器状态。用 Adam 优化器时权重、梯度和优化器状态三者的显存占比大约是参数 1 份优化器状态 2 份一二阶动量都用 FP32梯度 1 份。实际每 10 亿参数训练显存大约需要 16GB 左右。第二步是计算分到单卡后是否放得下。以 70B 模型 BF16 训练为例参数加梯度加优化器状态总计约 70×16 1120GB如果单卡是 80GB那么权重分片后必须保证每卡占比不超过 70%还要留激活值空间也就是大约 56GB这意味着总切分份数至少为 1120/56 20 份。结合上一节的通信约束可能选择 TP8、PP4那么权重和优化器状态的切分是 32 份已经超出了需求可以降低 ZeRO 的等级或者扩大 batch size 来提升效率。第三步是估算激活值显存。激活值的计算公式相对复杂一般粗略估算为每层每 token 大约是 hidden_size 的 10 到 20 倍。序列长度 4096、hidden_size 8192 的情况下单层激活大约几十 MB 到几百 MB。层数多了之后激活显存总量会很可观。这也是为什么激活重计算、上下文并行会成为长序列训练的必需方案。实际配置时大家也不用太纠结精确计算可以参考 Hugging Face 和 DeepSpeed 提供的显存估算工具先粗算再实测。4. 训练和推理场景中的实操落地与配置详解4.1 从零配置一个 70B 模型的分布式训练方案光讲概念不够我拿一个实际配置案例来推演整个过程。假设手里有 32 张 A100 80G GPU希望训练一个 70B 参数的模型上下文长度 4096。70B 模型训练显存需求大约 70×161120GB32 张卡总共显存 2560GB理论上够放。但我们要考虑的并不是总显存够不够而是单卡显存是否够用。梯度同步通常要求所有卡结构一致所以每张卡的参数切分需要均匀。如果选择 TP8、PP4、DP1 的组合那么张量并行 8 卡把权重切成 8 份流水线 4 层再把层数分成 4 份总共切分 32 份。每张卡承载的参数显存是 1120/32 35GB加上激活值和通信缓冲区单卡 80GB 完全够用。但因为 DP1梯度同步和参数更新只在一组 TPPP 内进行无法通过增加数据并行来提升吞吐。如果换成 TP8、PP2、DP2那么总切分 32 份不变但 DP2 意味着有两份模型副本可以同时处理两份不同的数据。缺点是因为 PP2每张卡的层数更多激活值占用更高一些。对于 70B 模型 4K 上下文TP8、PP2、DP2 通常在吞吐和稳定性上表现比 TP8、PP4、DP1 更好。用 Megatron-LM 启动时的核心配置参数如下python -m torch.distributed.launch --nproc_per_node8 pretrain_gpt.py \ --tensor-model-parallel-size 8 \ --pipeline-model-parallel-size 2 \ --num-layers 80 \ --hidden-size 8192 \ --num-attention-heads 64 \ --seq-length 4096 \ --micro-batch-size 1 \ --global-batch-size 32 \ --use-flash-attn \ --recompute-activations这里 recompute-activations 是激活重计算用少量额外计算换显存——每个 Transformer 层的前向激活不保留所有中间值反向时重新算一遍。micro-batch-size 1 配合 PP2 使用global-batch-size 32 表示数据并行维度上是 16 个微批次×2 个流水线内的微批次拆分。这个参数组合经过实测稳定性和精度都符合预期。4.2 长序列训练中如何配置上下文并行长序列训练比如 128K 上下文是目前大模型迭代的主战场之一。假设同样用 32 卡 A100目标序列长度是 128Khidden_size 8192。单纯靠 TP 和 PP 很难搞定因为注意力矩阵的显存是平方级别增长的哪怕单卡只放很少的 batchattention 矩阵本身也会爆显存。这时候就要上上下文并行。NCCL 的 All-to-All 通信在这种场景下发挥关键作用。DeepSpeed Ulysses 的实现流程大致是QKV 投影在张量并行维度上正常计算然后通过 All-to-All 把序列切分换成头数切分让每个设备拥有一段完整序列的若干 attention head做局部 attention 计算再通过一次 All-to-All 把计算结果还原成序列切分的布局。这样每个设备上的注意力矩阵长度从 128K 降到了 128K/CP显存压力大大降低。使用 DeepSpeed Ulysses 时注意 CP 的值一般不超过 attention head 的数量而且 CP×TP 要能整除 head 数。例如 head 数为 64如果 TP4那么 CP 可以选择 2 或 4但不能是 8 或 16。这是很多配置报错的隐含前提。上下文并行的通信开销不能完全忽略。虽然每个设备只做局部 attention但 All-to-All 通信需要把每个 token 的 K/V 广播到所有设备。实际测试中CP4 时通信开销占总时长的比例大约在 10% 到 20%与序列长度和数据规模相关。如果测试发现通信占比过高优先考虑增大 TP 而不是继续提升 CP。4.3 MoE 模型训练时专家并行的配置策略目前主流的 Mixtral、DeepSeek-MoE 这类模型专家并行的配置策略跟密集型模型有明显差异。以 Mixtral 8x7B 为例每层有 8 个专家每个 token 激活 2 个专家专家参数量大约占模型总参数的 80% 以上。没有使用专家并行时8 个专家的权重在每个数据并行副本中都要完整保存这会造成显存浪费。使用专家并行后可以把不同专家分配到不同的 GPU 上每个 GPU 只保存一部分专家参数。比如把 8 个专家分布在 4 张卡上每张卡只保存 2 个专家。配置时有个关键点专家并行的度一般要匹配总 GPU 数量。假设有 32 卡集群做 MoE 训练可以用 EP4、TP4、PP2 再加 DP1 的组合。TP4 处理注意力部分的张量切分EP4 切分专家PP2 按层切分。组合后的总 GPU 数 4×4×232。但 MoE 训练有一个隐藏的显存问题专家经过 EP 切分后每个设备只保留部分专家参数但路由机制需要把 token 从各个设备汇总到专家所在的设备。如果 token 分布极不均衡个别设备收到的 token 可能特别多显存和算力双高。实践中需配合 load balancing loss同时限制 batch size 不要过大避免单卡的 token 数量超过处理上限。4.4 推理部署时并行策略的选择差异推理场景和训练场景在并行选型上有一个核心差异推理的 batch size 往往很小显存压力主要来自权重和 KV Cache。这意味着梯度同步的通信需求不复存在了并行配置的目标从降低每卡显存、提升吞吐变成降低单请求延迟、提升并发能力。推理时张量并行依然是最常用的维度。一个 70B 模型在 BF16 下权重约 140GB单卡 A100 80G 根本无法加载TP2 之后每卡 70GBTP4 之后每卡 35GB这样可以完全放进显存。对于 7B 甚至 13B 模型通常不需要张量并行单卡直接加载即可因为多卡通信引入的延迟可能比计算延迟还高。长上下文推理场景下KV Cache 的管理成为并行选型的重点。用 vLLM 这类推理框架时KV Cache 是动态分配的PagedAttention 技术把 KV Cache 切分成物理块按需分配。上下文并行在推理中主要用来解决单卡放不下超长上下文的 KV Cache的问题切分序列维度后每卡的 KV Cache 压力线性下降。推理的另一个考量点是连续批处理与动态调度。这种调度方式下模型权重在每张卡上是完整加载的只需要用数据并行去承载多个并发请求。多个模型副本各自独立处理请求请求进来后由调度器分配到合适的 GPU 上执行。因此大多数在线推理服务的首选是单机 TP 多机 DP的组合单机内用张量并行降低单请求延迟多机间用数据并行提升吞吐。5. 常见问题与故障排查实战5.1 通信瓶颈GPU 利用率不高但吞吐上不去这是我在实际项目里遇到最多的情况。训练时 nvidia-smi 看 GPU 的算力利用率compute utilization在 40% 到 60% 之间徘徊但训练速度怎么也上不去。这类问题的根源往往是通信等待时间太长GPU 在跑一步、等一步。排查第一步是检查通信时间占比。打开 Megatron-LM 或者 DeepSpeed 的 profiler 日志或者直接用 NVIDIA Nsight Systems 抓一轮迭代的时间分布。如果 AllReduce 和 All-to-All 通信耗时占到迭代总时长的 30% 以上基本可以确定是通信瓶颈。排查第二步是检查并行配置是否合理。最常见的问题是张量并行的跨节点部署。比如用两台 8 卡机器做 TP16张量并行通信全走 IB 网络带宽远低于 NVLink通信延迟成倍增长。解决办法是把 TP 收敛到单机 8 卡以内再用 PP 或 DP 扩展集群规模。排查第三步是检查通信和计算是否做了重叠。PyTorch 自带的多流通信机制会自动把 AllReduce 和反向计算重叠但有时会因为模型结构和梯度累积方式导致重叠失效。调试时可以尝试调整 micro-batch size让流水线更饱和或者开启通信 overlap 的开关。5.2 显存不足OOM 并不总是切分不够导致的很多人见到显存不足Out of Memory的第一反应是把所有并行度都调大。但 OOM 有几种完全不同的成因处理方式也不一样。如果是权重和优化器状态导致的 OOM把 TP 或 ZeRO 等级调大确实有效。但如果是因为激活值累积导致的 OOM调大 TP 效果有限更好的方案是开启激活重计算、减少 micro-batch size、或者加大 PP。如果是因为 KV Cache 导致的 OOM那是推理场景专用的显存类型可以通过调整调度策略、限制最大序列长度、或启用上下文并行来解决。实际调试 OOM 时建议先看 PyTorch 的显存分配器统计torch.cuda.memory_summary() 会打印详细的分配明细。重点看Reserved memory和Allocated memory之间的差距如果差距很大说明显存碎片化严重可以尝试设置环境变量 PYTHONMALLOCmalloc 并启用 PyTorch 的 expandable_segments。5.3 流水线并行中的气泡与负载不均问题流水线并行的气泡问题最直接的表现是 GPU 利用率呈现锯齿状分布。用 nvidia-smi dmon 监控每个 GPU 的利用率会发现有的 GPU 忙到 95%有的 GPU 只有 30%。气泡率可以通过公式计算PP4 时理论气泡上界大约是 (PP-1)/(PP-1micro-batch数)。micro-batch 越大气泡占比越低但显存占用也会上升。负载不均的另一个来源是模型层大小不一致。比如 embedding 层和最后的输出层往往比其他任意一层都大如果它们单独占了一个流水线阶段那个阶段就更容易成为瓶颈。解决思路是使用不均匀的层分配第一阶段放 embedding 加一层 transformer后面几个阶段放更多的层保证每个阶段的参数量大致接近。MoE 模型的负载不均是另一类问题专家路由不平衡会导致某些设备过热。调试时通过日志查看每个专家的 token 数量分布如果波动超过 20%就要调整负载均衡损失的权重或者考虑增加专家副本同一个专家在多个设备上放置副本路由时可以选择最空闲的那个。5.4 精度问题混合精度并行下结果不稳定分布式并行的精度问题排查起来更隐蔽。并行策略本身不会引入数值错误但分布式的梯度聚合和混合精度计算组合在一起很容易出现精度损失。最常见的问题是大规模 AllReduce 时浮点溢出。FP16 的动态范围有限当梯度值很小或者很大时直接做 AllReduce 求和可能精度丢失。解决办法是使用 BF16 替代 FP16BF16 的指数位和 FP32 相同只是尾数位少几乎不会出现溢出问题。另一个常见问题是梯度累积与并行策略叠加时数值行为会改变。如果开了梯度累积又同时用数据并行做梯度同步要确保累积的是同一份梯度而不是不同步的乱序累加。实现上需要用no_sync上下文管理器抑制中间同步只在最后一次微批次完成时触发梯度同步。5.5 关键教训汇总与排查建议在实际接触大量训练集群和推理服务之后我总结出几条非常实用的排查经验分享给大家参考。第一出现问题时先看拓扑约束。高通信的并行维度优先绑定在同一台机器内低通信的并行维度再跨节点扩展。违反了这个原则即便代码和参数都对性能也不会好。第二不要盲目追求大并行度。并行度越高通信开销和调度复杂度就越大。能用单卡解决的事情用单卡能上数据并行解决的事情不要上张量并行这个原则几乎所有规模场景都适用。第三从日志和监控数据入手定位。不要凭感觉猜测是通信问题还是计算问题。NVIDIA Nsight Systems 和 PyTorch Profiler 是定位分布式瓶颈最有效的两个工具。第四配置文件一定要保留记录。每次修改并行配置都记录当时的吞吐、loss 曲线、显存占用和通信时间慢慢积累出适合自己的配置数据库这是团队最宝贵的资产。6. 从算法视角看并行计算的本质与未来作为算法工程师我们一开始很容易陷入把模型调好就行的思维觉得分布式是 Infra 团队的职责。但大模型时代这个界限已经模糊了。模型的设计和并行方案从一开始就要一起考虑。比如模型在哪个层级放 MoE 专家每个专家多大路由机制怎么设计这些决策同时影响算法效果和系统性能。如果算法同学不理解并行计算的基本原理就很容易设计出模型效果达标但根本跑不动的结构。并行计算本质上就是在回答两个问题数据怎么分配计算怎么协调。数据分配决定了每张卡存什么计算协调决定了每张卡什么时候跟谁通信。TP 是算同一个矩阵的不同部分PP 是算同一个模型的不同层DP 是算不同数据CP 是算序列的不同段EP 是算不同专家。理解了这个统一的框架所有并行策略都能在脑子里串起来。未来较长一段时间内分布式训练和推理的核心挑战都会集中在通信效率和显存效率上。算法侧的新进展比如稀疏注意力、MoE 路由优化、量化等最终都要落到并行计算框架里面才能兑现实际收益。这也是我写这个系列的初衷作为算法同学不需要成为最顶级的 Infra 专家但至少要有一张并行计算的地图知道问题出在哪个区域去找对应的工具和方案。我自己在复盘这些并行策略时最强烈的感受是并行计算并没有特别高深莫测它本质上就是把大问题拆成小问题再组合起来。每个策略都是在维度切分、通信开销、显存占用这三者之间做取舍。理解并接受没有最优的并行配置只有最适合当前场景的配置这个理念比记住任何具体的配置都更重要。我也强烈建议看完这篇内容的读者找一台 4 卡甚至 8 卡的机器搭一个小的 GPT 模型亲手把 TP1/2/4、PP1/2、DP1/2/4 的组合都跑一遍记录吞吐和显存。纸上得来终觉浅动手跑一圈你对并行计算的理解会扎实很多。希望这篇文章对你有用下一篇我计划接着写分布式训练框架的落地细节包括 Megatron、DeepSpeed 和 vLLM 的资源调度与性能调优的深入实践。
返回列表