☰
Megatron-LM `distributed` 包深度解析:DDP 梯度同步与 `finalize_model_grads` 全流程
2026/10/12 1:57:08 网站建设 项目流程
  • 人工智能
  • 大模型
  • 强化学习
  • AI Agent
  • 微调

【免费下载链接】OpenClaw-RL

OpenClaw-RL: Train any agent simply by talking

项目地址:https://gitcode.com/gh_mirrors/op/OpenClaw-RL
点击查看免费下载

导读

megatron.core.distributed是 Megatron-LM 中负责"优化器更新前跨所有 rank 完成模型梯度同步"的分布式基础组件:它既提供了将模型包装起来、以连续内存 buffer 存储梯度并支持通信与反向传播重叠的DistributedDataParallel,也提供了跨数据并行、张量并行(序列并行)、流水线并行与专家并行等全部并行模式统一收口梯度的finalize_model_grads。读完本文,你将理解 Megatron-LM 梯度同步的分桶机制、all-reduce/reduce-scatter 两种路径的选择逻辑、各类配置参数的作用,以及训练循环中梯度从 backward 到 optimizer step 之间的完整调用链。

一、distributed包的整体定位

根据官方 API 文档 Megatron-LM/docs/source/api-guide/distributed.rst,该包的目标非常聚焦:在 optimizer step 之前,在每个 rank 上完成模型权重梯度的收口(finalize)。它由两部分核心能力构成:

  1. 分布式数据并行包装器(DistributedDataParallel):在数据并行副本之间对梯度执行 all-reduce 或 reduce-scatter;
  2. finalize_model_grads方法:跨不同并行模式同步梯度,例如流水线不同 stage 上共享(tied)层的梯度、因专家并行(expert parallelism)而分散在不同 rank 上的 MoE 专家梯度等。

包的对外导出定义在 megatron/core/distributed/init.py:DistributedDataParallel、DistributedDataParallelConfig、finalize_model_grads,以及FullyShardedDataParallel、TorchFullyShardedDataParallel等 FSDP 相关实现。可见该包不仅覆盖传统 DDP,也延伸到了 FSDP 路径。

二、DistributedDataParallel:梯度连续缓冲与通信重叠

2.1 设计目标

DistributedDataParallel(源码见 megatron/core/distributed/distributed_data_parallel.py)是一个模型包装器,其类注释明确了两个设计要点:

  • 梯度存储在连续的 buffer 中(contiguous buffers),避免大量小张量的分散通信;
  • 支持通信与反向传播重叠:把完整模型的梯度拆分为更小的 bucket,对每个 bucket 异步发起 all-reduce / reduce-scatter,从而让通信与后续 backward 计算并行进行。

它继承自 megatron/core/distributed/data_parallel_base.py 中的_BaseDataParallel模板类。模板类定义了forward、no_sync、start_grad_sync、finish_grad_sync、zero_grad_buffer、scale_gradients、broadcast_params等"协议方法",DistributedDataParallel在这些接口上给出真正的分布式实现,而 Megatron FSDP 路径同样遵循这套接口约定。

2.2 构造流程与核心机制

构造函数签名(distributed_data_parallel.py):

DistributedDataParallel( config: TransformerConfig, ddp_config: DistributedDataParallelConfig, module: torch.nn.Module, disable_bucketing: bool = False, pg_collection: Optional[ProcessGroupCollection] = None, )

初始化时按如下顺序组织内部结构:

(1)进程组分配。通过ProcessGroupCollection.setup_process_groups_for_ddp解析出dp_group、dp_cp_group(含上下文并行的数据并行组)、intra_dp_cp_group、expt_dp_group、intra_expt_dp_group(专家数据并行相关)、tp_group、pp_group、ep_group等一系列进程组,供后续不同类参数的梯度使用不同组做通信。

(2)bucket 尺寸决策。若用户未显式指定bucket_size,默认取max(40000000, 1000000 * dp_group.size())——DP 规模越大,bucket 越大,以保证 NCCL ring-reduce 每次通信的 chunk 足够大,处于带宽受限(bandwidth-bound)而非延迟受限(latency-bound)状态;若关闭overlap_grad_reduce,则bucket_size置为None(即不切分,整段梯度一次通信)。此外,流水线 stage 非首段(pp_rank > 0)或传入disable_bucketing=True时也会关闭分桶,因为此时数据并行通信不在关键路径上(distributed_data_parallel.py)。

(3)参数分类与缓冲分配。按参数的allreduce属性把参数分为两类:需要跨 DP 组 all-reduce 的稠密参数(dense params)与不参与常规 all-reduce 的专家并行参数(expert parallel params),分别为它们分配独立的_ParamAndGradBuffer(见 megatron/core/distributed/param_and_grad_buffer.py)。缓冲分配还会按(param_dtype, grad_dtype)分组:若开启grad_reduce_in_fp32,梯度以 fp32 累加(对 bf16 模型尤其重要);对 fp8 参数则使用torch.uint8作为实际存储 dtype。

(4)梯度缩放因子的计算。为了最终得到"除以 DP 规模"的效果,代码提供两种等价路径(distributed_data_parallel.py):

  • average_in_collective=True:非专家参数预缩放因子为1.0,在 DP 组内做平均归约;专家参数预缩放edp_size/dp_size,再在专家 DP 组内做平均归约,最终缩放仍为1/dp_size;
  • average_in_collective=False:所有参数先预缩放1/dp_size,再在集体通信中做求和归约。

(5)注册 backward hook。为每个requires_grad的参数注册反向 post-hook(_make_backward_post_hook):在反向传播中把param.grad累加到param.main_grad并置空param.grad;若开启overlap_grad_reduce,则通知所属 bucket group 登记"该参数梯度已就绪"(distributed_data_parallel.py)。当 bucket group 内所有参数的梯度都就绪时,异步通信(all-reduce 或 reduce-scatter)会自动发起,实现通信与反向传播的重叠。

2.3 对外核心方法

DistributedDataParallel暴露的方法与_BaseDataParallel模板一一对应,是训练循环直接调用的入口:

方法作用
zero_grad_buffer()每个训练迭代开始时清零所有梯度缓冲,并重置grad_added_to_main_grad标记与 bucket group 元数据(distributed_data_parallel.py)
start_grad_sync()对全部 bucket group 发起梯度同步(all-reduce 或 reduce-scatter);overlap_grad_reduce=True时为异步派发,否则为同步调用(L510-L520)
finish_grad_sync()等待/执行梯度同步完成(L522-L532)
scale_gradients(factor)按因子缩放缓冲内全部梯度,供 per-token loss 归一化使用
start_param_sync()发起模型参数的 all-gather 同步(分布式优化器路径下,overlap_param_gather=True时异步派发)(L460-L472)
broadcast_params()从 DP 源 rank 向其他 DP rank 广播参数(用于随机初始化的数据并行对齐)
no_sync()上下文管理器,临时关闭梯度同步(梯度累积场景,见 L447-L458)

值得注意的是start_param_sync与overlap_param_gather的配合:当启用分布式优化器且overlap_param_gather=True时,参数 all-gather 通过 forward pre-hook 与 forward 计算重叠(enable_forward_pre_hook,L354-L364),并在finish_param_sync中等待对应 bucket 的 all-gather 句柄;align_param_gather=True时所有流水线 stage 同时发起 all-gather,避免各自按需发起造成的错峰。

2.4 分桶与通信聚合的底层实现

bucket 与 bucket group 的具体实现位于 megatron/core/distributed/param_and_grad_buffer.py:

  • _ParamAndGradBucket负责一个参数子集的 param/grad 视图(param_data、grad_data),记录param_to_index映射与未填充元素数numel_unpadded;
  • _ParamAndGradBucketGroup将多个 bucket 编组,使它们的通信可以聚合(coalesce)为少数几个内核调用。当组内全部参数梯度就绪时自动发起异步通信;在use_distributed_optimizer下,通信组为"分布式优化器实例内部组",否则为数据并行组。

通信内核的合并利用了 PyTorch 的 coalescing manager:文件开头会探测 NCCL 后端是否支持reduce_scatter_tensor_coalesced(PyTorch 2.2+ 才具备),支持时用_coalescing_manager把同一 bucket group 内多个 bucket 的 all-gather/reduce-scatter 合并派发,否则回退到顺序执行(param_and_grad_buffer.py)。此外,_ParamAndGradBucketGroup还提供check_grads方法,在通信前检查各 bucket 梯度的 NaN、Inf 与异常大梯度(对应check_for_nan_in_grad/check_for_large_grads配置),配合重跑状态机(rerun_state_machine)实现故障定位。

三、DistributedDataParallelConfig:全部配置项详解

配置类定义在 megatron/core/distributed/distributed_data_parallel_config.py,以下按功能分组梳理(默认值均以当前仓库为准):

3.1 通信重叠与数据并行策略

参数默认值说明
overlap_grad_reduceFalse是否让梯度 all-reduce / reduce-scatter 与反向计算重叠(按 bucket 异步派发)
overlap_param_gatherFalse是否让参数 all-gather 与 forward 计算重叠(分布式优化器路径)
align_param_gatherFalse为 True 时所有 PP stage 同时发起参数 all-gather,否则各 stage 独立按需发起
use_distributed_optimizerFalse为 True 时用 reduce-scatter 聚合梯度并清理原始模型参数(DistOpt 路径);为 False 时用 all-reduce
num_distributed_optimizer_instances1将 DP 域分片为多个分布式优化器实例(partial DistOpt),默认 1 即 DistOpt 覆盖整个 DP 域
average_in_collectiveFalse在集体通信内直接做平均,而非先除以 dp_size 再做求和

3.2 数值精度与安全校验

参数默认值说明
grad_reduce_in_fp32False梯度通信/累加以 fp32 进行(bf16 模型常用)
reduce_scatter_with_fp32_accumulationFalse用"线上低精度、本地 fp32 累加"的 reduce-scatter 实现(通过 all-to-all 保持与 ring 实现相当的通信量),且不支持num_distributed_optimizer_instances > 1
check_for_nan_in_gradFalse通信前检查梯度中的 NaN 与 Inf
check_for_large_gradsFalse通信前检查异常大的梯度
gradient_reduce_div_fusionTrue梯度归约与除法融合执行

3.3 分桶调优

参数默认值说明
bucket_sizeNone每个 bucket 最大参数数。未指定时用默认max(40000000, 1000000 * dp_size);overlap_grad_reduce=False时强制为None(不分桶)
pad_buckets_for_high_nccl_busbwFalse将 bucket 大小对齐到 2^16 的大次幂,保证大 DP 规模下 NCCL 消息长度(ring 算法下为bucket_size / dp_size)可被 2 的幂整除,以获得高总线带宽

3.4 FP8 / MXFP8 支持

参数默认值说明
fp8_param_gatherFalse计算参数保持 fp8,参数 all-gather 也以 fp8 进行
reuse_grad_buf_for_mxfp8_param_agFalse复用梯度缓冲做 MXFP8 参数 all-gather,仅在fp8_recipe=mxfp8且fp8_param_gather=True时可用;校验逻辑要求同时开启overlap_param_gather与overlap_grad_reduce
keep_fp8_transpose_cacheFalseMegatron FSDP 路径下是否保留 fp8 transpose 缓存

3.5 FSDP 相关

参数默认值说明
use_megatron_fsdpFalse使用 Megatron FSDP 代码路径做 DDP(取代已废弃的use_custom_fsdp)
data_parallel_sharding_strategy'no_shard'FSDP 分片策略,合法值为'no_shard'、'optim'、'optim_grads'、'optim_grads_params'
outer_dp_sharding_strategy'no_shard'混合分片数据并行(HSDP)下外层 DP 组的分片策略
suggested_communication_unit_sizeNoneFSDP 单次通信的元素数,影响 all-gather 预取行为
preserve_fp32_weightsTrueMegatron FSDP 的 ParamAndGradBuffer 中保留 fp32 权重
nccl_ubFalse为 param/grad buffer 分配并注册 NCCL userbuffer,启用 SM 高效的 NCCL 算法(配合 SHARP 效果更佳);__post_init__会拒绝与PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True同时使用
fsdp_double_bufferFalse为 Megatron FSDP 通信分配持久双缓冲,nccl_ub=True时会自动开启
disable_symmetric_registrationFalse禁用对称(窗口)userbuffer 注册,回退到常规本地注册

3.6 其他

参数默认值说明
delay_wgrad_computeFalse延迟权重梯度计算以提升批级通信重叠

3.7 从命令行参数到配置对象的组装

在训练入口 megatron/training/training.py 中,DistributedDataParallelConfig由命令行参数构造而来:bucket_size可来自--ddp-bucket-size或由--ddp-num-buckets换算(num_parameters // args.ddp_num_buckets),另有--ddp-pad-buckets-for-high-nccl-busbw、--ddp-reduce-scatter-with-fp32-accumulation、--ddp-average-in-collective等开关。随后用DistributedDataParallel(config=..., ddp_config=..., module=model_chunk, disable_bucketing=...)包装每个模型 chunk,其中disable_bucketing对第 2 个及以后的 model chunk(interleaved pipeline 的多 chunk 场景)传True,因为它们的通信已与计算重叠,无需再分桶。

四、finalize_model_grads:跨并行模式统一收口梯度

finalize_model_grads定义于 megatron/core/distributed/finalize_model_grads.py,签名如下:

finalize_model_grads( model: List[torch.nn.Module], num_tokens: Optional[torch.Tensor] = None, pg_collection: Optional[ProcessGroupCollection] = None, )

它应在每个 optimizer step 之前、backward 之后被调用,依次完成以下同步(与文档描述一一对应):

4.1 第一步:DP 副本间的 all-reduce / reduce-scatter

对每个模型 chunk 调用model_chunk.finish_grad_sync(),收口DistributedDataParallel中按 bucket 异步发起的梯度通信,确保数据并行副本间梯度一致(finalize_model_grads.py)。该步骤用config.timers中的all-grads-sync计时。

4.2 第二步:条件嵌入器梯度(Diffusion 模型)

_allreduce_conditional_embedding_grads针对在各 PP/VPP rank 上复制、带pipeline_parallel标记的条件嵌入器(如 DiT 的时间步嵌入器、FPS 嵌入器、标签嵌入器)梯度,跨 PP 组做 all-reduce,并先累加虚拟 PP rank 的梯度再广播回各副本(finalize_model_grads.py)。

4.3 第三步:非张量并行梯度(序列并行等)

_allreduce_non_tensor_model_parallel_grads在 TP 组内按两种归约语义处理(finalize_model_grads.py):

  • 求和(SUM):序列并行(config.sequence_parallel且参数带sequence_parallel标记)下的 LayerNorm 梯度,以及qk_layernorm下q_layernorm/k_layernorm参数的梯度;
  • 平均(AVG):带average_gradients_across_tp_domain=True标记的模块梯度。

_allreduce_layernorm_grads是该函数的向后兼容别名(计划在 mcore 0.14 移除)。

4.4 第四步:Embedding 梯度跨流水线 stage

  • _allreduce_word_embedding_grads:当词嵌入权重在首尾 PP stage 间共享(share_embeddings_and_output_weights)或 MTP 场景下,通过 embedding 进程组 all-reduce 词嵌入梯度(finalize_model_grads.py);
  • _allreduce_position_embedding_grads:跨编码器/解码器 stage 同步位置嵌入梯度(L262-L275)。

两者共用_allreduce_embedding_grad辅助函数,并处理 Megatron FSDP 下_local_tensor与DTensor的 unshard/reshard 转换。

4.5 MoE 专家偏置更新与临时张量重置

当moe_router_enable_expert_bias开启时,_update_router_expert_bias会跨 TP×CP×DP rank all-reducelocal_tokens_per_expert,并按moe_router_bias_update_rate更新 router 的 expert bias(finalize_model_grads.py)。随后reset_model_temporary_tensors清零临时张量并重置全局 aux loss 追踪器(L278-L290)。这部分逻辑同样被 megatron/core/transformer/cuda_graphs.py 的 CUDA Graph 路径复用。

4.6 可选:per-token loss 归一化

若传入num_tokens(per-token loss 模式),该值只在流水线末段存在,因此先从末段 broadcast 到整个 PP 组,再跨dp_cp_groupall-reduce 得到全局非 padding token 总数,最后调用model_chunk.scale_gradients(1.0 / num_tokens)对全部梯度归一化(finalize_model_grads.py)。注意此模式下average_in_collective必须关闭(构造 DDP 时已有断言)。

4.7 进程组来源

finalize_model_grads支持两种进程组获取方式:默认从parallel_state取tp、pp、embd、pos_embd、dp_cp组;或通过pg_collection(megatron/core/process_groups_config.py 中的ProcessGroupCollection)显式传入统一组织好的进程组集合。文档中的示例用法为:

pgs = ProcessGroupCollection() pgs.tp = tp_group pgs.pp = pp_group pgs.dp = dp_group model = TransformerModel(..., pg_collection=pgs) ddp_model = DistributedDataParallel(..., pg_collection=pgs) finalize_model_grads(..., pg_collection=pgs)

使用pg_collection时,finalize_model_grads会强制校验其包含tp、pp、embd、pos_embd、dp_cp属性,避免静默回退到全局默认进程组。

五、从 backward 到 optimizer step 的完整调用链

综合源码可梳理出典型 Megatron-LM 训练迭代中的梯度流:

  1. 迭代开始:zero_grad_buffer()清零梯度缓冲与元数据;
  2. forward/backward:各 bucket 的梯度随反向传播逐步就绪,overlap_grad_reduce=True时异步发起 all-reduce(DDP 路径)或 reduce-scatter(DistOpt 路径);
  3. backward 结束后调用finalize_model_grads(model, num_tokens=...):依次收口 DP 梯度同步、同步条件嵌入器/序列并行 LayerNorm/embedding 梯度、更新 MoE expert bias、重置临时张量,并按需用num_tokens归一化梯度(详见 finalize_model_grads.py);
  4. 优化器 step:DistOpt 下优化器消费 reduce-scatter 产生的本地梯度分片;下一个迭代前再次zero_grad_buffer()。

六、FSDP 扩展:Megatron FSDP 与 Torch FSDP2

distributed包还包含两条 FSDP 路径:

  • Megatron FSDP(megatron/core/distributed/fsdp/):通过use_megatron_fsdp=True启用,复用_ParamAndGradBuffer、支持混合分片(HSDP)、NCCL userbuffer(nccl_ub)与 fp8 等能力;
  • Torch FSDP2(megatron/core/distributed/torch_fully_sharded_data_parallel.py):根据 megatron/core/distributed/README.md,启用方式为:
--use-torch-fsdp2 --no-gradient-accumulation-fusion --ckpt-format torch_dist

并特别注明此时不应设置CUDA_MAX_CONNECTIONS=1,以保证 FSDP 通信与主流的计算能充分并行。对应配置类为TorchFullyShardedDataParallelConfig。

七、源码导航与进一步阅读

  • 核心 DDP 实现:megatron/core/distributed/distributed_data_parallel.py(DistributedDataParallel类在 L22 起)
  • 配置类:megatron/core/distributed/distributed_data_parallel_config.py(DistributedDataParallelConfig在 L8 起)
  • 梯度收口:megatron/core/distributed/finalize_model_grads.py(finalize_model_grads在 L396 起)
  • 分桶与通信底层:megatron/core/distributed/param_and_grad_buffer.py
  • 模板基类:megatron/core/distributed/data_parallel_base.py
  • 统一进程组:megatron/core/process_groups_config.py
  • 训练入口组装:megatron/training/training.py(DDP 包装见 L1088-L1115)
  • FSDP 说明:megatron/core/distributed/README.md 与 megatron/core/distributed/fsdp/src/README.md
  • 单元测试:tests/unit_tests/distributed/ 目录集中覆盖了本包的进程组、分布式状态与梯度同步逻辑

结语

megatron.core.distributed是 Megatron-LM 多维度并行训练中承上启下的关键组件:DistributedDataParallel以连续梯度缓冲、动态分桶与通信/计算重叠为手段,把数据并行的梯度同步做得高效且可配置;finalize_model_grads则在 optimizer step 前把数据并行、序列并行、流水线并行与专家并行产生的各类梯度统一收口,并兼顾 FP8、DistOpt、FSDP 与 per-token loss 等现代训练需求。理解这两者的配置语义与调用顺序,是排查梯度同步问题、调优大集群训练通信性能的起点。

  • 人工智能
  • 大模型
  • 强化学习
  • AI Agent
  • 微调

【免费下载链接】OpenClaw-RL

OpenClaw-RL: Train any agent simply by talking

项目地址:https://gitcode.com/gh_mirrors/op/OpenClaw-RL
点击查看免费下载

相关推荐

上一篇:终极免费方案:3步解决Mac NTFS读写难题,告别Windows文件交换烦恼
下一篇:终极免费在线3D模型浏览器:从零开始构建你的专业可视化平台

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

立即咨询