五种并行策略全解析:大模型分布式训练核心指南 如果你跟我一样是做算法出身第一次面对分布式训练脚本时大概率会有这种体验模型结构门清loss曲线看得津津有味但看到训练框架里--tensor-parallel-size 8、--pipeline-parallel-size 4、--data-parallel-size 8这种参数时就只剩一个念头——这些到底在切什么为什么非得这么切。我之前也以为“分布式”就是把卡凑多、把模型塞进去。直到真正动手把一个LLM从单卡搬到多卡把TP、DP、PP、CP、EP这五个概念逐一对着显存、带宽、训练时间去理解才意识到并行策略本质上是一套“怎么切模型、怎么切数据、怎么同步结果”的取舍。这篇是“算法同学学Infra”系列的第二篇我用尽量靠近算法的语言把这五种并行策略一口气讲清楚。看完你至少能回答三个问题每种并行切的是什么维度通信代价有多大实际训练或推理时怎么组合。1. 先想清楚一件事并行策略到底在解决什么在讨论具体技术之前得先对齐一个共识在单卡上跑大模型究竟卡在哪答案是两个地方一是显存墙二是算力墙。显存墙最容易理解。一个7B参数的模型BF16精度下权重就要占14GB看起来单张A100 80GB似乎能装下但训练不是只有权重。每个参数还要占用梯度空间Adam优化器还要额外保存一阶矩和二阶矩这两项状态通常以FP32保存。粗略一算权重加梯度加优化器状态就超过100GB还没算前向传播过程中必须保留的激活值。激活值的大小取决于batch和序列长度一放大又是几十GB开销。单卡放不下这是分布式计算最原始的动机。算力墙更加隐蔽。即便模型塞进单卡单卡算力也远远不够。训练一个像样的LLM要几千亿token过一遍单卡几个月都跑不完所以得用大量GPU并行计算。但算力叠加不等于效率叠加因为多卡协同需要交换数据。GPU算力动辄几百TFLOPS而主流网络带宽只有每秒几十到几百GB量级上差了一大截。一旦通信比例过高加的卡越多浪费越严重。这时“并行策略”的定义就清晰了把一个大模型的存储和计算拆到多张卡上同时尽量压低卡与卡之间的通信代价。拆的对象不同就有了五种并行。后面我会反复强调一条主线每个并行策略“切的是什么维度、同步的数据量有多大、对网络带宽有多敏感”。把这三件事想清楚基本就掌握了LLM分布式计算的全部骨架。2. DP数据并行最贴近算法直觉但梯度同步不是免费的2.1 原理每个卡各算各的batch数据并行Data ParallelismDP之所以适合作为入门第一讲是因为它和算法同学熟悉的“小批量随机梯度下降”几乎是一一对应的。做法很简单每张卡各自保存一份完整的模型副本训练时把一个大的全局batch平均切成N份分给N张卡。每张卡独立做前向传播、反向传播算出自己那份数据对应的梯度接着所有卡把梯度做一次全局同步all-reduce得到平均梯度再用它更新各自手中的模型副本。一轮结束后所有卡上的模型参数完全一致再进入下一轮。这个思路对算法同学来说格外自然——batch维度本来就是样本独立假设把不同样本分到不同卡上互不影响。模型结构不需要任何改动训练框架早就把DP封装好了所以它也是最早被大规模使用的并行策略。2.2 梯度同步的通信账但“每步同步一次梯度”这件事不是免费的。模型有多大梯度同步的通信量就有多大。以7B参数模型为例每个梯度如果用FP32保存就是4字节那么一次迭代每张卡要同步28GB的梯度裸数据。实际工程里all-reduce的通信量还要再乘一个系数因为环状实现里每个节点既要发出去也要收回来整体大约相当于把这份数据在网络里流转两遍。也就是说每训练一步光是梯度同步就要在网络里搬运五六十GB的数据。这个数字落到硬件上是什么概念现代数据中心常见的800Gbps高速网络理论带宽大概100GB/s左右搬完这些数据至少半秒钟。如果你的机间网络还停留在200Gbps那就要好几秒。假设模型单步纯计算只要0.3秒通信却占了0.5秒系统效率就崩了。更麻烦的是模型越大这个梯度同步的通信量越线性上涨。所以“模型太大了就靠堆DP卡来提速”在工程上根本走不通——最终会被梯度通信锁死。2.3 ZeRO与FSDPDP的显存改良版既然传统DP每个卡都要保存完整模型副本显存浪费太严重工程上便出现了ZeRO和FSDP这套改良方案。它的核心思路是把模型参数、梯度、优化器状态这三种东西按DP维度切分到不同卡上也就是每卡只保存完整状态的N分之一而不是全部。计算时需要用哪一层参数就通过all-gather把那一层的权重从其他卡收集过来反向算完梯度后再用reduce-scatter把属于自己负责的那份梯度收回来其他梯度分发给对应设备。这样单卡显存从“必须装下完整模型”降为“装下N分之一”模型规模再大也就有了训练的可能。这里必须澄清一个很多文章会带偏的认知FSDP并没有让通信量变小它只是把显存压力分摊了。每次迭代参数要all-gather一遍梯度要reduce-scatter一遍算上回传网络里搬的数据量和传统DP是同一数量级的。FSDP解决的是“放得下”而不是“跑得快”。2.4 DP的真正适用范围所以DP不是大模型的最终解法它最舒服的使用场景始终是“模型本身能放进单卡”的时候。比如小模型全参微调单张A100就能装下权重、梯度和优化器状态那用DP就是最优解逻辑简单、框架成熟、通信不是瓶颈。再比如LoRA、QLoRA这类参数高效微调可训练参数只有几个百分点DP的梯度同步量被压得很低随便堆卡效果都不错。反过来如果是70B级别的全量训练单卡连权重都放不下DP就只能跟TP、PP组合使用或者靠FSDP的权重切分把模型塞进多卡。3. TP与PP拆算子与拆层是两种思路完全不同的模型切法DP解决的是数据维度的并行可当模型单卡装不下的时候必须动模型本身的结构。这就有两种截然不同的切法张量并行Tensor ParallelismTP和流水线并行Pipeline ParallelismPP。3.1 张量并行TP把矩阵乘法拆开做TP的切法算法同学其实很熟——它就是分块矩阵乘法。以一个线性层Y XW为例权重矩阵W可以按列切成W1和W2交给GPU0和GPU1分别计算XW1和XW2最后拼在一起得到完整输出。也可以按行切开每个设备负责一部分输入特征的计算最后做一次All-Reduce把分块结果累加。真实Transformer的TP实现通常是把hidden维切开。Self-Attention里的QKV投影按列切分输出投影按行切分MLP第一层按行切、第二层按列切。每引入一个切分点在层内就要多一次All-Reduce同步。一个标准Transformer层里attention和MLP两处各需要一次所以每层至少做两次跨卡同步。层数越多这个频率越高。TP的通信量其实不算大。按每批处理4096个token、hidden size为4096、BF16精度来算一次All-Reduce也就三十几MB。问题在于它是“高频小报文”模式每个Transformer层都要来两次同步一次前向加一次反向至少要翻倍。这种模式对单次延迟极其敏感所以TP对互连带宽要求最高。实践中TP几乎只能在一台机器内部做依靠NVLink的高带宽和低延迟跨节点做TP基本等于自废武功。TP带来的收益也很直接每个设备只保存N分之一的权重单卡显存压力大幅降低计算量也摊给了N张卡。这也是为什么大模型训练里只要机内带宽充足TP几乎是“单机内必选”。3.2 流水线并行PP按层切段像工厂流水线PP的思路跟TP完全不同。它不去动单个算子内部的计算而是把模型按层切成若干段每段交给一组设备。数据流像工厂流水线前向传播从第一段进入算完传给第二段再传给第三段直到输出反向传播再沿相反顺序传回梯度。最朴素的实现是“串行等待”一个时刻只有一段在计算其他段全部空闲总耗时和单卡跑完整模型差不多完全赚不到并行收益。为了让大家同时干活引入micro-batch机制把大batch再切成更小的微批第一段算完一个微批后立刻传给第二段自己接着算下一个微批让各段同时处理不同微批。工程上再配1F1B调度一个前向、一个后向交替执行设备利用率可以拉到比较高的水平。但PP再怎么优化也会留下一种叫“气泡时间”的浪费。流水线从启动到灌满、再从排空到收尾总有设备在等待。气泡占比粗略估算大约是 (PP-1) 除以 (PP-1 微批数量)。PP4时只切8个微批气泡可能接近30%把微批加到32个可以压到10%以下。不过微批越多激活值占用越高这又是和显存打架的取舍。跟TP比PP的通信量小得惊人只在相邻两段之间的边界传一次激活值大小是微批与序列长度和hidden size的乘积也就几十MB而且频率低。所以PP可以放心大胆地跨节点跑普通数据中心网络就够用。这也是TP和PP在工程上天然互补的原因。3.3 TP优先还是PP优先工程上的直觉是“TP优先于PP”。只要机内带宽足够、卡数够用先用TP把模型的张量维度切了因为TP通信频率太高必须用高速互联而高速互联资源通常只覆盖很小一块物理范围。等到TP切到头还是放不下再上PP做跨节点扩展。现实中很多70B级别模型的训练配置就是这种思路的典型代表一台8卡机器内部TP8把每层张量切成8份机器之间PP4把80层模型切成4段分别放在4台机器上。这样每个并行策略都贴合物理拓扑通信代价最小。4. CP上下文并行长序列场景下绕不开的第四维4.1 KV cache带来的显存压力再看一种单卡扛不住的情况。假设模型只有几B参数权重随便放但用户上下文窗口从8K一路涨到128K甚至1M。这时候的瓶颈不在权重而在KV cache和attention的中间激活。KV cache的大小等于每token固定字节数乘上下文长度。粗略算一个7B规模、32层、标准MHA结构的模型每个token、每层都要给K和V各存一份向量算下来每个token在整模型里要占几百KB上下文一到32K光KV cache就要吃掉十几甚至几十GB。模型再大一点、序列再长一点单卡就是铁定装不下。DP按batch切分但一个长句子只有一个样本batch没法切TP按hidden维切对KV cache的token维压力反而缓解有限PP按层切每一层该有的KV总量还是落在对应卡上。于是有了专门切序列维的并行上下文并行Context ParallelismCP。4.2 Ring Attention到底在做什么CP把一条长序列切成N块分给N张卡每张卡只负责算自己那块的Q、K、V。但标准attention里输出需要所有token的K和V如果只做全量KV的All-Gather虽然显存分摊了但通信量和完整KV一样大而且每张卡依然要把全量KV放到显存里才能算attention等于白切。工程上更常用的做法是Ring Attention。把参与CP的卡排成一个环每张卡先算好当前块的K、V然后按环传下去。每张卡在每个时刻只持有一个K/V块用它和自己手上的Q、局部K计算部分attention score再按“局部softmax”的方式逐步累加。一个环全部转完所有token的KV都被消费过一次输出也就齐了。这个方案的关键好处是每张卡峰值显存只跟block大小相关而不是整条序列的长度attention的平方级计算量也被分摊到多卡并行。CP的通信量跟序列长度成正比而且每个attention块都要传KV频率并不低所以它对带宽要求蛮高通常限定在高速互联范围内使用。训练时期Prefill阶段是CP收益最大的场景因为Prefill本来就在处理长序列attention计算密度高CP能直接把计算量和存储同时摊开。4.3 CP与TP、PP的区别和配合CP和TP都发生在Transformer层内部一个切序列维一个切hidden维它们可以叠加TP负责模型宽度CP负责上下文长度DP负责样本数量。长上下文场景里常见的组合就是“TP × CP × DP”。推理时CP有个容易被忽略的尴尬点。decode阶段是自回归逐步生成每步只新出一个token。序列维被切开后不同设备各自持有之前算好的KV块每生成一个新token都可能要跨设备交换中间结果同步开销不小。所以有些推理框架只在Prefill阶段启用CPdecode阶段要么把序列尽量放回单卡要么做专门的CP解码优化。这个细节属于看技术文档时很难意识到的坑。5. EP专家并行MoE模型的专属解法5.1 稀疏激活带来的“专家切分”需求有了CP这个“切新维度”的先例EP就更好理解了。专家并行Expert ParallelismEP服务于MoE混合专家模型。MoE层里有一组专家可能是8个、64个甚至更多每个token经router打分后只被派给其中top-2个专家计算。模型总参数量很大但单个token实际参与的权重只有一小部分这就是稀疏激活。如果按Dense模型的方式直接做TP或PP会非常浪费。要么每个专家权重在每张卡上都复制一份显存直接爆炸要么被TP切得七零八落但稀疏激活又让大多数设备在大多数时间闲着。EP的思路是把不同专家放到不同设备上每台设备只保存其中几个专家router决定某个token去哪个专家这个token的hidden state就先发到目标专家所在设备算完再传回来。5.2 All-to-All通信与负载均衡困境EP的核心通信模式是all-to-all。这和DP、TP的All-Reduce完全不一样源设备上的token根据路由结果分别发往很多目标设备同时每台设备也会收到来自很多源设备的token。它更像“按内容分拣包裹”小包多、路径动态对网络拓扑尤其敏感。另一个绕不开的坑是负载均衡。真实数据里router对专家的选择绝不会均匀很可能少数专家收到一半token其他专家闲着。设备负载不均并行效率直接崩。工程上的常规解法有三类一是加一个辅助的负载均衡loss让router学得尽量均匀二是给专家设置容量因子限制单个专家最多接收的token数超出部分做重算或丢弃三是在推理场景用在线路由调整根据实时请求分布动态改变token分配。这些方案各有取舍但核心目的都一样让所有专家设备尽量忙起来。5.3 EP与DP的取舍标准这里有个非常实际的判断标准什么时候用EP什么时候用DP如果模型总参数量不大所有专家复制到每张卡也放得下那DP的MoE往往更好。因为每个token不需要跨卡传递路由完全在卡内完成通信为零。只有当专家总参数量大到单卡放不下才被迫用EP。即便决定用EP也要权衡batch大小。EP的通信开销来自“把token发给远程专家”batch越大一次批量发越划算通信占比越低。如果batch很小比如在线推理时单请求只有几十个token把token发到远程专家的网络代价可能比计算本身还高EP并不会让系统更快。因此EP不是MoE的唯一选项而是“显存不够时为了跑起来并压缩通信”的选择。实际工程里EP通常还要跟DP叠加一组设备放一部分专家另一组设备放另一部分专家两组之间用DP做数据并行。6. 组合与选型从7B到70B再到超长上下文6.1 三种典型场景的并行配置理解了每种并行的原理后真正的问题来了一个模型到底该上哪些并行各配多大我拿三个场景举例。第一个7B Dense模型8张A100 80GB序列长度4K。BF16权重只有14GB但全参数训练还叠加梯度和优化器状态单卡其实很紧张。入门级配置可以是TP2加DP4TP把hidden维切成2份DP把数据切成4份。这个组合实现简单、通信压力不大是很多人第一次跑多卡训练的默认选项。第二个70B Dense模型32张A100 80GB。BF16权重约140GB训练压力更大。典型配置是TP8加PP4DP先设18卡一台机器内做TP80层模型切成4段放到4台机器上做PP。等跑通之后再加DP2甚至更高复制出多个完整流水线副本提升吞吐。这刚好对应物理拓扑——节点内NVLink跑TP节点间普通网络跑PP通信模式各得其所。第三个MoE模型外加长上下文。这时并行维度通常会同时用到TP、CP、EP和DP。TP切共享层CP切序列EP把专家分布到卡上DP负责复制整份计算。看着复杂其实就是把前面那些“切法”当成相互独立的自由度需要哪个维度就开哪个维度。6.2 五种并行的参数对比并行策略切分维度核心通信模式带宽敏感度典型使用位置DP数据并行batch维All-Reduce或All-GatherReduce-Scatter中到高随模型规模线性增长所有层之外TP张量并行hidden维/算子维每层多次All-Reduce极高必须NVLink单节点内部PP流水线并行层维相邻stage点对点传递低普通网络即可跨节点CP上下文并行序列维KV块环形传递高长序列节点内EP专家并行专家维All-to-All高受路由动态影响MoE专家设备组这张表建议直接收藏。判断一个新框架某个参数有没有配错对照这五行基本能定位。6.3 训练和推理的差异化处理还有一个容易忽略的地方同一套并行策略放在训练和推理两个阶段瓶颈完全不同。训练时显存主要被参数、梯度、优化器状态和激活值占据目标是把吞吐最大化。PP的气泡、DP的梯度同步都是为了整体吞吐量可以接受的代价只要整张卡能被喂饱计算慢一点没关系。推理时显存主要被权重和KV cache占据目标从“吞吐”转成“延迟”。Prefill阶段计算密度高TP、CP都能明显加快decode阶段几乎被内存访问和KV cache读取主导这时候要尽量减少单条序列跨太多设备的情况避免每一步都做昂贵的跨卡通信。对算法同学来说我最常给的提醒是别把训练时的并行配置直接照搬到推理服务尤其是CP和PP它们在推理侧的行为和训练差别非常大必须用真实请求压测后再调。7. 调试与踩坑先把通信占比看明白再谈调优7.1 拿到Profiler再判断我见过太多人对着并行参数瞎猜。对算法同学来说第一个建议是不要猜去测通信占比。训练框架日志未必直接给你通信数据但NVIDIA的Nsight Systems、PyTorch自带的Torch Profiler都能看到NCCL调用在时间线上的分布。打开一次step的timeline看通信占用整个step的比例。如果超过30%你的并行组合大概率配得不合理可能是TP切太碎导致同步频率过高可能是DP模型太大导致梯度同步太重也可能是PP微批太少导致气泡太大。有理有据地调比拍脑袋换参数快得多。7.2 我踩过的几个具体坑TP跨节点是第一个大坑。TP每层要同步好几次跨节点延迟比NVLink高出一个量级还多结果就是整个训练流程被通信拖到几乎不缩放。TP的粒度永远先卡在“一台机器内的卡数”。PP的微批数量和气泡之间是典型权衡。微批越多气泡越小但激活值占用越高非常容易OOM。常规做法是先设一个保守的微批数观察气泡占比再逐步往上加。很多框架默认值其实偏保守手动调一调往往有惊喜。EP的All-to-All会被小batch拖死。推理时如果一次请求只有几十个token发给远端专家的数据包太小网络时间全耗在包处理上。给EP做并发合并、把多条请求攒成一个大batch比调多复杂的负载均衡算法都有效。长上下文的KV cache也容易让人误判。总以为模型权重才是显存大头实际序列一长KV cache可以比权重还夸张。先用GQA/MQA减少KV head数量或者把KV cache量化打开往往比硬加CP更划算。CP是解决“确实放不下”的手段而不是为了炫技。7.3 给算法同学的“最小上手路线”真想彻底搞懂这些并行我的建议是不要一上来就啃超大规模集群。先在单机8卡上跑一个7B模型分别试TP8和TP2DP4用profiler看通信差异再开PP2观察气泡时间如何变化然后换一个长序列数据集加上CP看看Prefill吞吐最后把模型换成开源的MoE模型调EP去理解All-to-All的通信模式。整个过程不需要新集群一台8卡机器就能完成。等你把这五轮实验跑完对并行策略的直觉就建立起来了。以后再遇到某个新训练框架的新参数你基本能在半小时内反应出它切的是哪个维度、代价是什么、极限在哪里。这套思考方式比记住任何一份静态配置都有用。