执行摘要
- 一句话:修复外部引擎 debug_rollout_only 下 placement group 崩溃
- 推荐动作:该 PR 属于针对特定调试模式的 bugfix,建议合入。虽然代码变更简单,但涉及 placement group 布局,可能影响训练资源分配,值得快速审查。可关注后续是否有类似组合的其他布局问题。
功能与动机
PR body 明确指出,当使用 --rollout-external-engine-addrs 和 --debug-rollout-only 时,rollout_num_gpus 会被远程引擎的 GPU 数量覆盖(覆盖了本地 actor 维度),但 _get_placement_group_layout 对此组合返回 (0, 0),导致空 placement group 与非零的 actor world_size 不匹配,并在此处崩溃:https://github.com/THUDM/slime/blob/23464705f48d0dcb8beb7e983b60859929dd856f/slime/ray/actor_group.py#L114。因此需要修复该组合下的 placement group 布局逻辑。
实现拆解
本 PR 的修复分为两个主要步骤:
- 参数校验逻辑调整(
slime/utils/arguments.py):在 slime_validate_args 函数的 debug_rollout_only 分支中,如果 args.rollout_external 为真,则跳过 actor 维度覆盖逻辑(pass),否则保留原有覆盖逻辑。这样避免了在外部引擎场景下错误地修改 actor_num_gpus_per_node 和 actor_num_nodes。
- placement group 布局修复(
slime/ray/placement_group.py):在 _get_placement_group_layout 函数中,将 rollout_external 且 debug_rollout_only 分支的返回值从 (0, 0) 改为 (actor_num_gpus, 0),确保 placement group 中包含占位训练 actor 所需的 GPU 数。
- 单元测试更新(
tests/test_placement_group.py):将 external_debug_rollout 用例的期望值从 (0, 0) 更新为 (16, 0),以反映新的布局行为。
测试变更与源码变更联动,确保新逻辑被验证。
关键文件:
slime/ray/placement_group.py(模块 调度器;类别 source;类型 core-logic;符号 _get_placement_group_layout): 核心修复:修改 _get_placement_group_layout 返回值,解决空 placement group 崩溃问题。
slime/utils/arguments.py(模块 参数校验;类别 source;类型 core-logic;符号 slime_validate_args): 参数校验逻辑调整,避免外部引擎场景下 actor 维度被覆盖。
tests/test_placement_group.py(模块 测试;类别 test;类型 test-coverage;符号 test_placement_group_layout): 更新单元测试期望值,与修复逻辑保持一致。
关键符号:_get_placement_group_layout, slime_validate_args
关键源码片段
slime/ray/placement_group.py
核心修复:修改 _get_placement_group_layout 返回值,解决空 placement group 崩溃问题。
# slime/ray/placement_group.py
# 计算并返回 placement group 的布局 ( 总 GPU 数 , rollout 偏移量 )
def _get_placement_group_layout(args) -> tuple[int, int]:
# 根据 actor 节点数与每节点 GPU 数计算 actor 所需 GPU 总数
actor_num_gpus = args.actor_num_nodes * args.actor_num_gpus_per_node
# 仅训练调试模式:不需要 rollout,只创建 actor 的 PG
if args.debug_train_only:
return actor_num_gpus, 0
# 使用外部引擎(无本地 rollout)
if args.rollout_external:
# 调试 rollout 模式:跳过 rollout 引擎,但仍需为占位训练 actor 分配 GPU
if args.debug_rollout_only:
return actor_num_gpus, 0
# 正常外部引擎模式:actor 与 rollout 共享同一 PG
return actor_num_gpus, actor_num_gpus
# 其他调试 / 常规分支逻辑不变
if args.debug_rollout_only:
return args.rollout_num_gpus, 0
if args.colocate:
return max(actor_num_gpus, args.rollout_num_gpus), 0
return actor_num_gpus + args.rollout_num_gpus, actor_num_gpus
slime/utils/arguments.py
参数校验逻辑调整,避免外部引擎场景下 actor 维度被覆盖。
# slime/utils/arguments.py - 位于 slime_validate_args 函数中
if args.debug_rollout_only:
# 若使用外部引擎,跳过本地 actor 维度覆盖,保留原始 actor 配置
if args.rollout_external:
pass
# 常规 colocate 场景:rollout_num_gpus 未显式设置时,沿用 actor 配置
elif args.colocate and args.rollout_num_gpus is None:
args.rollout_num_gpus = args.actor_num_gpus_per_node * args.actor_num_nodes
elif args.rollout_num_gpus == 0:
args.actor_num_gpus_per_node = 0
args.actor_num_nodes = 0
else:
args.actor_num_gpus_per_node = min(8, args.rollout_num_gpus)
args.actor_num_nodes = args.rollout_num_gpus // args.actor_num_gpus_per_node
args.colocate = False
args.offload_train = args.offload_rollout = False
tests/test_placement_group.py
更新单元测试期望值,与修复逻辑保持一致。
# tests/test_placement_group.py
@pytest.mark.parametrize(
("overrides", "expected"),
[
# 其他用例 ...
# 外部引擎 + 调试 rollout 模式:应返回 actor_num_gpus (16) 和 Offset 0
pytest.param({"rollout_external": True, "debug_rollout_only": True}, (16, 0), id="external_debug_rollout"),
],
)
def test_placement_group_layout(overrides, expected):
assert _get_placement_group_layout(_args(**overrides)) == expected
评论区精华
该 PR 没有 review 评论或讨论线程。
风险与影响
- 风险:本次变更属于小范围修复,风险较低。但需要注意,PR body 提到该修复假设节点上有可用的 GPU 来创建占位训练 actor。如果实际环境不满足该假设,仍可能遇到资源不足问题。另外,修改
_get_placement_group_layout 的返回值可能影响 create_placement_groups 中 rollout bundle 的切片逻辑(基于 rollout_offset),但此处偏移为 0,影响有限。建议确认 debug_rollout_only 场景下 actor 进程能正常使用 placement group 的 GPU。
- 影响:影响范围限定在使用
--debug-rollout-only 且配合外部引擎(--rollout-external-engine-addrs)的开发调试场景。修复后这些场景可以正常创建 placement group,避免崩溃。对正常训练流程无影响,因为该分支仅在 debug 模式激活。测试更新保持了与源码同步,团队可安全合并。
- 风险标记:假设节点有可用 GPU, 外部引擎调试场景
关联脉络
- PR #2208 Support reloading the default process group: 涉及 Ray 资源管理,与 placement group 相关联。
- PR #2181 [3/n] Disaggregated rollout: engine-side /pull_weights: 涉及外部引擎与 rollout 解耦,可能影响外部引擎参数处理。
参与讨论