执行摘要
- 一句话:修复启动脚本路径与续行符错误并补 AMD 硬件配置
- 推荐动作:该 PR 属于小范围修复,可直接阅读;重点关注 command_utils.py 中 rsync_simple 的参数转发模式,以及后续 #1898-#1911 系列 PR 对启动脚本的测试保护,理解本 PR 如何为快照测试铺路。
功能与动机
PR body 仅标注 Part of #1837(重构与增强跟踪 issue)。实际动因是部分启动脚本因路径硬编码和缺失续行符无法运行,例如 examples/infra_features/low_precision 下多个脚本 source 相对路径错误,scripts/run-kimi-k2-*.sh 缺少续行符导致后续参数被吞,另外 NUM_GPUS_OF_HARDWARE 缺少 AMD 硬件声明会导致使用新硬件的启动脚本抛 KeyError。
实现拆解
- 修正示例脚本中的模型配置路径:对 examples/infra_features/low_precision 下的 4 个 int4 示例,将未生效的
source "${SCRIPT_DIR}/../../models/xxx.sh" 改为 "${SCRIPT_DIR}/../../../scripts/models/xxx.sh",使模型脚本能被正确加载;对 examples/lora/run-qwen3-4B-megatron-lora.sh,修正 REPO_ROOT 向上级目录的层数(由 ../../.. 改为 ../..),并去掉 source 路径中的多余 miles/ 前缀,同时将 eval 配置路径中的 miles/ 前缀移除。
- 修复续行符缺失:在 scripts/run-kimi-k2-Instruct.sh 与 scripts/run-kimi-k2-Thinking.sh 中,为
--update-weight-buffer-size $(( 4 * 512 * 1024 * 1024)) 这一行补上末尾的 \,否则 shell 会把下一行的 ${MODEL_ARGS[@]} 当作普通参数,导致模型参数被静默吞掉。
- 扩展命令工具能力:在 miles/utils/external_utils/command_utils.py 中,
rsync_simple 新增 num_nodes 可选参数并转发给 exec_command_all_ray_node,使调用方可限制 rsync 只在指定节点上执行;同时为 NUM_GPUS_OF_HARDWARE 增加 MI350X 与 MI355X(各 8 GPU),避免新硬件启动脚本因 KeyError 失败。
- 补充单元测试:在 tests/fast/utils/test_command_utils.py 中新增两个测试:
test_every_supported_hardware_declares_its_gpus_per_node 参数化覆盖所有已声明硬件并断言 GPU 数量大于 0;test_rsync_simple_limits_itself_to_the_requested_node_count 验证 num_nodes 参数确实被传递给 exec_command_all_ray_node。
关键文件:
miles/utils/external_utils/command_utils.py(模块 命令工具;类别 source;类型 core-logic;符号 rsync_simple): 核心命令工具修改:rsync_simple 增加 num_nodes 转发,NUM_GPUS_OF_HARDWARE 新增 AMD 硬件声明,影响多个启动脚本。
tests/fast/utils/test_command_utils.py(模块 单元测试;类别 test;类型 test-coverage;符号 test_every_supported_hardware_declares_its_gpus_per_node, test_rsync_simple_limits_itself_to_the_requested_node_count): 新增两个单元测试,分别覆盖硬件声明完整性和 rsync_simple 的 num_nodes 转发,确保回归不复发。
examples/lora/run-qwen3-4B-megatron-lora.sh(模块 示例脚本;类别 other;类型 core-logic): 修复 REPO_ROOT 层级计算和 source 路径,是路径类修复的典型代表,关系 LoRA 示例能否运行。
scripts/run-kimi-k2-Instruct.sh(模块 启动脚本;类别 other;类型 core-logic): 修复缺失续行符导致后续参数被吞的问题,直接影响 Kimi-K2 训练任务的启动。
关键符号:rsync_simple, test_every_supported_hardware_declares_its_gpus_per_node, test_rsync_simple_limits_itself_to_the_requested_node_count
关键源码片段
miles/utils/external_utils/command_utils.py
核心命令工具修改:rsync_simple 增加 num_nodes 转发,NUM_GPUS_OF_HARDWARE 新增 AMD 硬件声明,影响多个启动脚本。
# miles/utils/external_utils/command_utils.py
def rsync_simple(path_src: str, path_dst: str, num_nodes: int | None = None):
# 新增 num_nodes 参数,转发给 exec_command_all_ray_node,
# 使调用方可以把 rsync 限制在指定数量的节点上,避免全集群广播
exec_command_all_ray_node(
f"mkdir -p {path_dst} && rsync -a --info=progress2 {path_src}/ {path_dst}",
num_nodes=num_nodes,
)
NUM_GPUS_OF_HARDWARE = {
"H100": 8,
"GB200": 4,
"GB300": 4,
# 新增 AMD 硬件声明,避免使用这些硬件的启动脚本因 KeyError 失败
"MI350X": 8,
"MI355X": 8,
}
tests/fast/utils/test_command_utils.py
新增两个单元测试,分别覆盖硬件声明完整性和 rsync_simple 的 num_nodes 转发,确保回归不复发。
# tests/fast/utils/test_command_utils.py
import pytest
from miles.utils.external_utils import command_utils
@pytest.mark.parametrize("hardware", ["H100", "GB200", "GB300", "MI350X", "MI355X"])
def test_every_supported_hardware_declares_its_gpus_per_node(hardware):
"""缺少声明的硬件会在启动脚本运行时抛 KeyError,因此这里必须覆盖所有已支持硬件。"""
assert command_utils.NUM_GPUS_OF_HARDWARE[hardware] > 0
def test_rsync_simple_limits_itself_to_the_requested_node_count(monkeypatch):
"""prepare_cp 依赖节点数限制,确认转发逻辑没有被破坏。"""
calls = []
monkeypatch.setattr(command_utils, "exec_command_all_ray_node", lambda cmd, **kwargs: calls.append(kwargs))
command_utils.rsync_simple("/src", "/dst", num_nodes=4)
# 必须原样把 num_nodes 传给底层执行器
assert calls == [{"num_nodes": 4}]
评论区精华
本 PR 无 review 评论,仅有一条 issue 评论为 Gemini Code Assist 停用通知;唯一审核 yueming-yuan 的 APPROVED 也未附文字,因而没有实质交锋。
- 无实质 review 讨论 (other): 无争议,直接合并。
风险与影响
- 风险:
- rsync_simple 签名变更:新增可选参数 num_nodes,默认 None,已保持向后兼容,但若其他调用方未适配或 exec_command_all_ray_node 对 None 处理不当,可能影响 rsync 行为,需要调用方同步确认。
- 脚本路径修复依赖相对位置:示例脚本的 source 路径修正依赖仓库目录结构保持稳定,若未来重新组织 scripts/models 目录,这些硬编码相对路径可能再次失效。
- 硬件字典新增条目:NUM_GPUS_OF_HARDWARE 仅新增 MI350X / MI355X,若其他 AMD 硬件(如 MI300)被使用,仍会触发 KeyError,需持续补充声明。
- 影响:直接影响是让多个 low_precision 示例和 Kimi-K2 启动脚本可以正确执行,避免无提示的失败;间接影响是为后续 #1898-#1911 系列启动脚本测试保护提供了前置修复,保证快照测试能稳定运行。对用户而言,使用这些脚本进行模型训练的工程师不再遇到路径或续行符错误;对团队而言,该 PR 清除了重构链条上的一些阻塞问题。
- 风险标记:rsync_simple 签名扩展需调用方确认, 示例脚本依赖相对路径稳定性, 硬件字典仅补充两种 AMD 型号
关联脉络
- PR #1898 Derive the miles checkout location instead of hardcoding it in launch scripts: 同为 #1837 系列,解决启动脚本硬编码路径问题的不同方面,本 PR 修复路径错误,该 PR 改为推导路径。
- PR #1899 Snapshot the external commands of every shell launch script: 系列中为 shell 启动脚本建立快照测试,本 PR 修复的脚本是快照测试的对象。
- PR #1901 Snapshot the commands and generated configs of every python launch script: 系列中通过快照测试保护启动脚本命令,与本 PR 的修复形成前后配合。
- PR #1902 Cover the public surface of command_utils with unit tests: 为 command_utils 补齐测试,与本 PR 新增的 rsync_simple 测试同属对命令工具的测试加固。
参与讨论