首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >30-671B-MoE级别 训练暴露了哪些infra问题

30-671B-MoE级别 训练暴露了哪些infra问题

作者头像
anzhsoft
发布2026-07-27 19:28:51
发布2026-07-27 19:28:51
1390
举报

到 671B/MoE 级别,问题不再是“哪个阶段慢一点”,而是并行坐标、CPU 内存、checkpoint、reshard 和权重同步能不能共同维持训推闭环。

第 29 篇讲 Fully Async Policy:当 rollout 和 trainer 分开跑,吞吐、新鲜度和 off-policy correction 会形成三角关系。第 30 篇把规模继续推大:如果模型是数百 B 参数的 MoE,trainer 不是一个普通 update worker,rollout 也不是一个简单推理进程,整个系统会同时被并行维度、内存层级和权重形态约束。

本文的核心判断是:671B/MoE 级别暴露的 infra 问题,不是单个 GPU kernel 或单个配置开关能解释的。它要求训练侧用 Megatron/MCore 组合 TP、PP、EP、ETP、CP 和动态 batch,要求显存不够时把参数、梯度、optimizer state 挪到 CPU,要求 checkpoint 能在不同并行布局之间 reshard,还要求训练权重能被重新导出成 rollout backend 可加载的 named tensor stream。规模越大,越不能把这些边界当成实现细节。

先看总图。读图时注意:DeepSeek-V3 671B scale demo 只是入口,真正的系统压力分布在四条链路上:并行坐标、长上下文与 batch、offload/CPU 内存、checkpoint/weight sync。

671B/MoE 训练暴露的 infra 压力地图

这张图也解释了第 30 篇和前面几篇的关系。第 25-29 篇把 step timing、data movement、队列和异步讲清以后,671B/MoE 会把这些问题全部放大:gen受 rollout TP、KV cache 和长尾影响;update_actor受 Megatron 并行和 offload 影响;save_checkpointupdate_weights受 sharded checkpoint、bucket 和推理侧加载影响。

1. scale demo 先把系统假设摊开

verl 的 examples/grpo_trainer/README.mddeepseek_v3_671b列为 scale demo,并在矩阵里标出 DeepSeek-V3 671B 使用 vLLM rollout、Megatron 训练、NVIDIA 平台(examples/grpo_trainer/README.md:48-5668-90)。对应脚本 run_deepseek_v3_671b_megatron.sh开头写明这是 DeepSeek-V3 671B 的 GRPO scale demo,并建议至少 12 节点、每节点 8 张 80GB+ GPU(examples/grpo_trainer/run_deepseek_v3_671b_megatron.sh:1-12)。

下面这张图把脚本里的关键默认值放在一起。读图时注意,训练侧和 rollout 侧的并行形态不同:actor 用 Megatron 的多维并行,rollout 用 vLLM TP;这意味着权重更新时必须跨形态转换。

DeepSeek-V3 671B scale demo 的关键配置

脚本里,训练 batch 是 96,mini-batch 是 32,最大 prompt/response 分别是 2048/8192,actor 默认 TP=8、PP=12、EP=8、ETP=1、CP=1;rollout TP 默认 32,rollout.n=8,actor 开启 dynamic batch,并启用 param、grad、optimizer offload(examples/grpo_trainer/run_deepseek_v3_671b_megatron.sh:20-4883-125127-145)。这不是一组随意参数,而是把问题拆成三类资源:模型计算如何切、序列和 batch 如何进 worker、显存不够时状态放在哪里。

所以第 30 篇不把“671B”当成一个夸张标签,而把它当成源代码里的系统压力样本:一旦模型大到需要 TP/PP/EP/CP 同时存在,训练/推理之间就没有简单的一份权重,也没有简单的一批样本。

2. MoE 让并行维度变成坐标系统

第 20 篇讲过 Megatron/MCore 是 worker 内部的并行坐标。到 671B/MoE,这个坐标不再是可选优化。McoreEngineConfig显式暴露 param/grad/optimizer offload、TP、EP、ETP、PP、VPP、CP、sequence parallel、distributed optimizer 和 distributed checkpoint 相关开关(verl/workers/config/engine.py:149-218verl/trainer/config/engine/megatron.yaml:1-57)。

下面这张图要看的重点是“坐标不是一维的”。TP、PP、EP、ETP、CP 切的是不同压力;rollout TP 又是另一套推理布局。越大的 MoE 模型,越需要同时管理这些坐标之间的转换。

MoE 训练里的多维并行坐标

源码上,MegatronEngine._init_device_mesh()调用 mpu.initialize_model_parallel(),一次性传入 TP、PP、VPP、CP、EP 和 ETP(verl/workers/engine/megatron/transformer_impl.py:131-158)。MBridge provider 构造时也会写入同样的并行字段,并设置 variable_seq_lengths=True、MoE dispatcher、router load balancing 等字段,再应用用户覆盖项(verl/workers/engine/megatron/transformer_impl.py:190-238)。DeepSeek-V3 的 MCore config converter 还会写入 MoE expert 数、top-k、shared expert、router score、router dtype、grouped GEMM 等字段(verl/models/mcore/config_converter.py:349-374)。

这带来一个工程解释:MoE 不是把 dense 模型“多加几个专家”这么简单。EP/ETP 决定专家权重和 token 分发在哪些 rank 上,PP 决定层在哪些 pipeline stage 上,CP/SP 决定长序列的 token 维度怎样分担。任何一个维度错配,后续的 batch、checkpoint 和 weight sync 都会被牵连。

3. 长上下文和 dynamic batch 让 step 变成 token 账

671B scale demo 的最大 prompt+response 默认是 10240 tokens,并且 ppo_max_token_len_per_gpu直接取这个长度。actor 侧 use_dynamic_bsz=True,trainer 还启用 balance_batch=Trueexamples/grpo_trainer/run_deepseek_v3_671b_megatron.sh:24-2992-95167-180)。这说明大模型 RL step 的执行单位不只是样本数,而是每个 rank 实际承担多少 token。

下面这张图把 long context 和 dynamic batch 放在同一条线上。读图时注意:rollout.n扩大样本数,长 response 拉长 token 数,dynamic batch 再把它们切进 Megatron micro-batch。

长上下文把 batch size 问题变成 token 预算问题

Megatron 训练执行时,forward_backward_batch()先把 sp_size设成 context_parallel_size,统计全局 loss mask token 数,再调用 prepare_micro_batches();如果启用 dynamic batch,prepare_micro_batches()要求设置 max_token_len_per_gpu,并用 max_token_len_per_gpu * sp_size作为切分预算(verl/workers/engine/megatron/transformer_impl.py:599-674verl/workers/engine/utils.py:58-96)。VPP 存在时,micro-batch 数还必须满足 microbatch_group_size_per_vp_stage的整除约束。

这解释了为什么“batch size”在这里不能只按样本数理解。GRPO 的 rollout.n、response length、dynamic batch、CP/SP、PP/VPP schedule 会共同决定一次 update 的实际工作量。第 25 篇的 timing 到这里要升级成 token 账:同样的 train_batch_size=96,不同 response 长度和 MoE routing 会让每个 rank 的真实负载完全不同。

4. offload 把瓶颈从 GPU 显存推到 CPU 内存

DeepSeek-V3 671B demo 默认 offload=Trueoptim_offload=True,并把 optimizer offload fraction、CPU offload、D2H/H2D overlap、precision-aware optimizer 写成可配置项(examples/grpo_trainer/run_deepseek_v3_671b_megatron.sh:42-4483-91108-110)。这不是单纯“节省显存”,而是把训练状态放进更复杂的内存层级。

下面这张图要看的重点是 offload 的方向和代价:参数、梯度、optimizer state 可以从 GPU 挪到 CPU,但会引入 pinned buffer、D2H/H2D copy 和 host memory 峰值问题。

offload 把显存问题转成 CPU 内存和拷贝问题

MegatronEngine初始化时读取 param_offloadgrad_offloadoptimizer_offload,构建 optimizer 和 checkpoint manager 后调用 self.to(device="cpu", model=..., optimizer=..., grad=...)verl/workers/engine/megatron/transformer_impl.py:88-96385-441)。to("cpu")会把 model 和 optimizer 分别交给 offload_megatron_model_to_cpu()offload_megatron_optimizer();反向 to(device)再调用 load 函数恢复到 GPU(verl/workers/engine/megatron/transformer_impl.py:502-528)。

最有代表性的源码证据在 offload_megatron_model_to_cpu()。注释写明 Megatron 里 bf16 参数、fp32 grad、fp32 main parameter 和 optimizer state 分别按 model parallel 和 DP group 切分;函数会为 DDP buffer 复用 pinned cpu_data,并解释如果每次 offload 都重新 .cpu().pin_memory(),会造成 2x host memory 瞬时峰值,在大 Megatron 模型上可能超过 cgroup limit 导致 OOM(verl/utils/megatron_utils.py:493-567)。optimizer offload 还会移动 fp32 copy params、exp_avgexp_avg_sq,并清理全局 memory buffer(verl/utils/megatron_utils.py:618-768)。

这说明 CPU 内存不是“备用仓库”,而是训练系统的第一等资源。到了 671B/MoE,offload 是否稳定、CPU pinned buffer 是否复用、optimizer state 是否分批回搬,都会影响 step 能否持续运行。

5. checkpoint 和 reshard 是跨并行布局的合同

规模变大以后,checkpoint 不只是容灾。它还要表达“当前权重和 optimizer state 是怎样被 TP/PP/EP/DP 切开的”,并允许后续在不同并行布局下恢复或同步。McoreEngineConfig因此有 use_dist_checkpointingdist_checkpointing_pathdist_ckpt_optim_fully_reshardable和 memory-efficient fully reshardable 格式等字段(verl/workers/config/engine.py:194-199verl/trainer/config/engine/megatron.yaml:37-57)。

下面这张图展示 checkpoint 的角色变化。读图时注意:checkpoint metadata 不是附属信息,它决定 optimizer state 是按 DP 可重分片,还是按 TP/PP/EP/DP 更完整地重分片。

distributed checkpoint 把权重形态写进 metadata

MegatronCheckpointManager.get_checkpoint_name()会把 TP rank、PP rank 和 EP rank 写进路径;generate_state_dict()则从每个 VPP/model chunk 生成 sharded_state_dict,optimizer 也通过 optimizer.sharded_state_dict()进入同一份 state dict(verl/utils/checkpoint/megatron_checkpoint_manager.py:212-256258-320)。_build_sharded_state_dict_metadata()会根据配置把 distrib_optim_sharding_type写成 dp_reshardablefully_reshardable,并记录 memory-efficient 选项(verl/utils/checkpoint/megatron_checkpoint_manager.py:322-360)。

保存和加载时,verl 走 Megatron dist checkpointing,并用 FullyParallelSaveStrategyWrapper/ FullyParallelLoadStrategyWrapper包住 DP+CP group(verl/utils/checkpoint/megatron_checkpoint_manager.py:629-672verl/utils/megatron/dist_checkpointing.py:29-75)。这和 FSDP/Automodel 路径里的 reshard()呼应:FSDP2 构建时有 reshard_after_forward,eval/offload 边界会显式调用 module.reshard();Automodel offload 前也会先 model.reshard()再搬到 CPU(verl/workers/engine/fsdp/transformer_impl.py:400-419879-886verl/workers/engine/automodel/utils.py:197-218)。

所以 weight resharding 不是一个保存格式细节,而是大模型系统的恢复和迁移能力。训练时的 shard、checkpoint 里的 shard、rollout 侧需要的完整或重新切分权重,三者不一定一样。

6. 权重同步把训练并行形态重新导出给 rollout

一轮 RL step 最后仍然要回到 train/serve 闭环:actor 更新完成后,rollout 必须拿到新权重。RayPPOTrainerupdate_actor后把 checkpoint_manager.update_weights()放进 timing_raw["update_weights"]verl/trainer/ppo/ray_trainer.py:1548-1585)。到 671B/MoE,这一步会暴露前面所有边界:训练侧权重按 Megatron 并行切,rollout 侧按 vLLM TP 加载,中间还要考虑 bucket、KV cache 和未完成请求。

下面这张图画的是权重同步数据面。读图时注意:get_per_tensor_param()不是“拿一个 state dict”,而是把 Megatron 内部的 PP/EP/ETP 切分重新组织成 rollout 能消费的 named tensor stream。

权重同步把 Megatron 权重重新导出给 rollout

非 naive 路径里,ActorRolloutRefWorker.update_weights()会调用 actor engine 的 get_per_tensor_param(),再交给 checkpoint engine send_weights();naive 路径则要先恢复 rollout weights、更新权重、必要时把 actor 参数 offload 回 CPU,再恢复 KV cache(verl/workers/engine_workers.py:663-743)。MegatronEngine.get_per_tensor_param()会把 Megatron module 加载回 GPU,并通过 bridge 导出 HF 权重或 adapter 权重(verl/workers/engine/megatron/transformer_impl.py:715-744)。

更底层的 per_tensor_generator()会先在 PP group 上收集所有层的元信息并 broadcast tensor;遇到 MoE expert 权重时,如果 EP size 大于 1,会在 EP group 上 all-gather 专家参数;如果 ETP size 大于 1,还要继续在 ETP group 上 gather,最后再交给权重转换逻辑(verl/utils/megatron_utils.py:1072-1178)。Checkpoint Engine 再把 named tensor stream 切成 bucket chunk,NCCL 后端还注明 send/recv 双 buffer 会带来 2 * bucket_size的 device memory overhead(verl/checkpoint_engine/base.py:96-189495-563verl/checkpoint_engine/nccl_checkpoint_engine.py:102-143230-305)。

这就是第 30 篇最重要的系统结论:671B/MoE 训练不是“训练端成功 update 就结束”。只有当权重能从 Megatron 的训练并行形态,经过导出、bucket、通信、rollout adapter,重新进入推理服务,RL 训练才真正闭环。

小结:规模把局部优化变成系统合同

放回第五组,前五篇分别拆了 profiling、吞吐、data movement、队列化和 fully async。第 30 篇把它们收束到生产级 scale-out:671B/MoE 级别的问题不是某个阶段独立慢,而是多个系统合同同时变硬。

代码语言:javascript
复制
Megatron TP/PP/EP/ETP/CP
-> dynamic token budget and micro-batch schedule
-> param/grad/optimizer offload and CPU memory
-> distributed checkpoint and reshard metadata
-> named tensor stream and rollout weight update
-> production train/serve loop

读完这一篇,应该能看懂为什么大模型 RLHF 的 infra 讨论不能只停留在 GPU 数量。GPU 只是其中一层资源;同样关键的还有 CPU 内存峰值、参数同步带宽、checkpoint metadata、expert weight gather、rollout TP 布局和异步系统里的权重新鲜度。下一组会把这些工程事实翻译给 PM 和行业分析师:一次 RL 后训练的成本账,应该怎样从 GPU 时长、rollout 数、response length、验证频率和权重同步一起算。

本文源码索引

  • examples/grpo_trainer/README.md:48-90:GRPO 示例矩阵中 DeepSeek-V3 671B scale demo 的定位、backend 和平台。
  • examples/grpo_trainer/run_deepseek_v3_671b_megatron.sh:1-1220-4883-125127-145167-186:671B scale demo 的节点建议、长上下文、TP/PP/EP/CP、offload、rollout TP 和 trainer 配置。
  • verl/workers/config/engine.py:77-218verl/trainer/config/engine/megatron.yaml:1-57:EngineConfig/McoreEngineConfig 的 offload、并行维度、distributed optimizer/checkpoint 和 fully reshardable optimizer checkpoint 配置。
  • verl/workers/engine/megatron/transformer_impl.py:88-160190-238:MegatronEngine 如何读取 offload/router replay,并把 TP/PP/EP/ETP/CP 注入 model parallel 和 provider。
  • verl/models/mcore/config_converter.py:349-374:DeepSeek-V3 MCore config 中的 MoE expert、router、shared expert、grouped GEMM 等字段。
  • verl/workers/engine/megatron/transformer_impl.py:599-674verl/workers/engine/utils.py:58-96:Megatron dynamic micro-batch、CP/SP token budget 和 VPP micro-batch 整除约束。
  • verl/workers/engine/megatron/transformer_impl.py:385-441502-528589-597:Megatron engine 初始化、to(cpu/device) 和 checkpoint load/save 时的 offload/load 行为。
  • verl/utils/megatron_utils.py:493-567618-768:Megatron model/optimizer offload、pinned CPU buffer 复用、CPU/GPU 回搬和 optimizer state 迁移。
  • verl/utils/checkpoint/megatron_checkpoint_manager.py:212-360629-672verl/utils/megatron/dist_checkpointing.py:29-75:Megatron distributed checkpoint 路径、state dict、reshard metadata 和 fully parallel save/load。
  • verl/workers/engine/fsdp/transformer_impl.py:400-419879-886verl/workers/engine/automodel/utils.py:197-218:FSDP/Automodel 路径中的 reshard_after_forward、eval/offload 边界和 reshard()调用。
  • verl/trainer/ppo/ray_trainer.py:1548-1585verl/workers/engine_workers.py:663-743:actor update 后如何进入 update_weights,以及 naive/non-naive 权重同步分支。
  • verl/workers/engine/megatron/transformer_impl.py:715-744verl/utils/megatron_utils.py:1072-1178:Megatron 权重如何导出,并在 PP/EP/ETP group 上 gather 成 rollout 可消费的 named tensor stream。
  • verl/checkpoint_engine/base.py:96-189448-492495-563verl/checkpoint_engine/nccl_checkpoint_engine.py:102-143230-305:CheckpointEngine 合同、非 naive 更新生命周期、bucket split/merge 和 NCCL bucket 传输。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-07-24,如有侵权请联系 cloudcommunity@tencent.com 删除
目录
  • 1. scale demo 先把系统假设摊开
  • 2. MoE 让并行维度变成坐标系统
  • 3. 长上下文和 dynamic batch 让 step 变成 token 账
  • 4. offload 把瓶颈从 GPU 显存推到 CPU 内存
  • 5. checkpoint 和 reshard 是跨并行布局的合同
  • 6. 权重同步把训练并行形态重新导出给 rollout
  • 小结:规模把局部优化变成系统合同
  • 本文源码索引
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档