Prhub

#3141 Dump debug train data once per DP/CP shard instead of on every rank

原始 PR 作者 yueming-yuan 合并时间 2026-09-08 14:10 文件变更 5 提交数 2 评论 0 代码增减 +56 / -2

执行摘要

优化训练调试数据写入策略,仅每个 DP/CP 分片写一次,大幅减少磁盘占用。

在使用 --dump-details 参数进行长周期训练时,所有训练 rank 都会将各自的 rollout 分片写入磁盘。然而,由于 Tensor Parallelism (TP) 的对等 rank 持有相同数据,且 Pipeline Parallelism (PP) 中仅最后一个 stage 计算 Dashboard 需要的 per-token 字段(如 log_probs, entropy),导致磁盘上产生了 tp_size * pp_size 份冗余副本。Dashboard 读者在加载时需要先进行去重,这浪费了磁盘空间并可能导致磁盘写满。

这是一个高质量、目标明确的优化和修复 PR。它不仅解决了实际痛点(磁盘空间浪费),还确保了功能的向后兼容性和测试覆盖。对于处理分布式训练调试数据的工程师来说,其门控写入和可见性探测的修复逻辑非常有参考价值。建议精读 save_debug_train_data 和 DumpReader._visible 的变更,理解其并行状态判断的设计。

讨论亮点

该 PR 仅由 Claude Bot 进行了自动评论,并由 Zhichenzzz 批准,没有详细的技术讨论。变更逻辑清晰,主要集中在对并行状态判断的应用。

实现拆解

  1. 核心训练数据写入逻辑改造:在 miles/utils/train_dump_utils.py 的 save_debug_train_data 函数中,引入并行状态检查。仅在 TP rank 为 0 且处于最后一个 PP stage 时才执行写入。这样确保每个 DP/CP 分片只写入一次。
  2. 策略损失调试输出优化:在 miles/backends/training_utils/debug_dump.py 的 maybe_dump_policy_loss_debug 函数中,同样增加了对 tp.rank == 0 的检查,跳过 TP 对等 rank 的重复计算和文件写入。
  3. Dashboard 可见性探测修复:修改 miles/dashboard/dump_reader.py 的 DumpReader._visible 方法,将检查特定 rank 0 文件的逻辑改为 glob 搜索任意 rank 文件,以适应 PP > 1 时 global rank 0 不再是写入者的场景。
  4. 测试配套更新与新增:新增 tests/fast/utils/test_train_dump_utils.py 文件,参数化测试验证写入逻辑。更新 tests/fast/dashboard/test_dump_reader_join.py 中的测试,使用非 rank-0 文件来验证可见性逻辑的健壮性。
文件 模块 状态 重要度
miles/utils/train_dump_utils.py 训练数据转储 modified 5.96
miles/dashboard/dump_reader.py 数据读取 modified 5.51
tests/fast/utils/test_train_dump_utils.py 测试 added 6.43

关键符号

save_debug_train_data maybe_dump_policy_loss_debug DumpReader._visible

关键源码片段

miles/utils/train_dump_utils.py core-logic

核心训练调试数据写入逻辑的改造点,实现了减少冗余写入的核心功能。

def save_debug_train_data(args, *, rollout_id, rollout_data):
    if args.save_debug_train_data is not None:
        parallel_state = get_parallel_state()
        # 仅当 TP rank 为 0 且处于最后一个 PP 阶段时才写入,避免冗余文件。
        # TP 对等 rank 持有相同数据,且只有最后一个 PP 阶段计算 per-token 字段。
        if parallel_state.tp.rank != 0 or not parallel_state.is_pp_last_stage:
            return
        save_debug_train_data_for_rank(
            args,
            rollout_id=rollout_id,
            rollout_data=rollout_data,
            rank=torch.distributed.get_rank(),
            cp_rank=parallel_state.cp.rank,
            cp_size=parallel_state.cp.size,
        )

评论区精华

并行状态门控写入的实现 设计

PR 通过分析 TP/PP/CP 并行模式下的数据冗余,提出了在写入端进行门控的解决方案。

结论:在 `save_debug_train_data` 和 `maybe_dump_policy_loss_debug` 中增加 `tp.rank == 0` 检查,在 `save_debug_train_data` 中增加 `is_pp_last_stage` 检查。 · 已解决

Dashboard 可见性探测逻辑的修复 正确性

由于新策略下 global rank 0 不再写入文件,原有的检查 `{rollout_id}_0.pt` 的探测逻辑会失效,导致新步骤数据短暂不可见。

结论:将硬编码的文件检查改为使用 `glob` 搜索任意匹配文件,确保在 `pp > 1` 时也能正确探测到新数据。 · 已解决

风险与影响

  1. 兼容性风险:旧格式的全 rank dump 文件仍可被正确读取,但新格式的 dump 文件不再包含冗余副本。对于依赖旧 dump 文件特定文件名(如 rollout_id_0.pt)的外部工具,可能需要适配。
  2. 逻辑正确性风险:条件判断 tp.rank != 0 or not is_pp_last_stage 是实现的关键。需要确保 parallel_state 在所有训练场景下都已正确初始化。FSDP 场景(tp.size == 1)不受影响,逻辑与之前一致。
  3. Dashboard 行为变更:_visible 方法从检查固定文件变为 glob 搜索,这增加了 I/O 操作,但影响范围仅限于判断新步骤是否可见的短暂窗口,性能影响可忽略。

用户影响:显著减少了使用 --dump-details 时的磁盘空间占用,提升了长周期训练的稳定性。对于开发者,调试流程更加高效,不再需要处理大量冗余文件。
系统影响:改善了训练集群的磁盘利用率和 I/O 性能。对 Dashboard 的数据加载和展示逻辑无负面影响,且通过修复可见性探测提升了可靠性。
团队影响:为并行训练下的调试数据管理提供了更优的实践,相关模式(基于并行状态进行门控写入)可被后续功能参考。

核心路径变更 数据格式兼容性

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论