# PR #2360 完整报告

- 仓库：`radixark/miles`
- 标题：examples: select fully-async with --fully-async in the GLM-5.2 Daytona recipe
- 合并时间：2026-08-12 07:15
- 原文链接：http://prhub.com.cn/radixark/miles/pull/2360

---

# 执行摘要

- 一句话：Daytona 配方改用 --fully-async 以启用参数互斥校验
- 推荐动作：值得快速浏览，特别是对全异步 rollout 参数互斥设计感兴趣的读者，可对照 miles/utils/arguments.py 中 _resolve_rollout_functions 理解校验意图。长期建议为该配方补充一条启动脚本快照测试或文档说明，避免再次出现绕过校验的写法。

# 功能与动机

PR body 指出：run_glm5_2_744b_a40b_daytona.py 原本通过 --rollout-function-path 指向 FullyAsyncRolloutFn 来选中全异步 rollout，而该参数与 --fully-async 互斥（_resolve_rollout_functions 断言 rollout_function_path is None），导致配方走在跳过校验的路径上。换用 --fully-async 后，colocate、partial-rollout、pause-generation-mode abort、recompute-logprobs-via-prefill、rollout-all-samples-process-path 及 multi-LoRA 等不兼容检查开始对配方生效，配方当前配置均能通过这些检查。

# 实现拆解

1. 变更入口：examples/experimental/openenv/glm52_tbench2/run_glm5_2_744b_a40b_daytona.py 的 _execute_train 函数。
2. 具体改动：在 rollout_args 字符串拼接中，将 --rollout-function-path miles.rollout.fully_async_rollout.FullyAsyncRolloutFn 替换为 --fully-async，其余参数（如 --pause-generation-mode in_place、--rollout-submission-granularity sample）保持不变。
3. 行为等价性论证：resolve_rollout_function_paths 在两种情况下都解析到 FullyAsyncRolloutFn；--fully-async 只被 _resolve_rollout_functions 和 train.py 驱动守卫两处读取，因此运行时无其他变化。配方已显式设置 --rollout-submission-granularity sample，不依赖 fully-async 默认值。
4. 配套改动：无。PR 明确说明没有快照测试覆盖该配方（tests/snapshots/launch_scripts/ 中没有对应 fixture），pre-commit run --all-files 通过，未在硬件上执行验证。

关键文件：
- `examples/experimental/openenv/glm52_tbench2/run_glm5_2_744b_a40b_daytona.py`（模块 示例脚本；类别 source；类型 core-logic；符号 _execute_train）: 唯一变更文件，也是本 PR 的核心：rollout_args 的选择方式从 --rollout-function-path 切换为 --fully-async，使配方重新接入参数互斥校验，是整个变更的入口和全部内容。

关键符号：_execute_train

## 关键源码片段

### `examples/experimental/openenv/glm52_tbench2/run_glm5_2_744b_a40b_daytona.py`

唯一变更文件，也是本 PR 的核心：rollout_args 的选择方式从 --rollout-function-path 切换为 --fully-async，使配方重新接入参数互斥校验，是整个变更的入口和全部内容。

```python
def _execute_train(args: ScriptArgs):
    _assert_openenv_deps()

    load_save_path = f"{args.output_dir}/{args.run_id}/checkpoints"
    hf_name = f"{args.model_name}_fp8" if args.fp8_rollout else args.model_name
    ckpt_args = (
        f"--hf-checkpoint {args.model_local_dir}/{hf_name} "
        f"--ref-load {args.model_local_dir}/{args.model_name}_torch_dist "
        f"--load {args.load_from or load_save_path} "
        f"--save {load_save_path} "
        f"--save-interval {args.save_interval} "
    )

    rollout_args = (
        # 用 --fully-async 代替 --rollout-function-path 选中全异步 rollout：
        # 前者会触发 _resolve_rollout_functions 中的互斥校验（覆盖 colocate /
        # partial-rollout / pause-generation-mode abort / multi-LoRA 等不兼容项），
        # 而直接传函数类路径会绕过这些检查。
        "--fully-async "
        "--pause-generation-mode in_place "
        f"--async-max-concurrent-samples {args.async_max_concurrent_samples} "
        # 每个完成的样本释放一个提交槽，而不是等整组完成：
        # 长时程 agentic 任务里，等组内最慢的兄弟样本是 rollout 吞吐的主要瓶颈。
        "--rollout-submission-granularity sample "
        f"--prompt-data {args.prompt_data} "
        "--input-key prompt "
        "--apply-chat-template "
        "--rollout-shuffle "
        f"--num-rollout {args.num_rollout} "
        f"--rollout-batch-size {args.rollout_batch_size} "
        f"--n-samples-per-prompt {args.n_samples_per_prompt} "
        f"--rollout-max-response-len {args.rollout_max_response_len} "
        "--max-seq-len 131072 "
        "--rollout-temperature 0.8 "
        f"--global-batch-size {args.global_batch_size} "
        "--balance-data "
    )

```

# 评论区精华

本 PR 没有任何 review 评论，评审人 Zhichenzzz 直接给予 APPROVED。唯一的技术论证来自 PR body：作者逐条说明 resolve_rollout_function_paths 在切换前后解析到同一对 rollout/eval 函数，args.fully_async 只被 _resolve_rollout_functions 和 train.py 驱动守卫两处读取，因此行为等价，且新写法能补上互斥校验。

- 暂无高价值评论线程

# 风险与影响

- 风险：
 1. 静态验证未覆盖运行时行为：作者声明未在硬件上执行验证；train_async.py 对 --fully-async 的守卫分支与显式 rollout_function_path 路径若有隐藏差异，可能改变运行行为（可能性较低，因为解析逻辑已确认等价）。
 2. 无测试快照：tests/snapshots/launch_scripts/ 无此 recipe 的 fixture，后续若修改 _resolve_rollout_functions 或 fully-async 语义，该配方的回归不易被 CI 捕获。
 3. 对未来校验的依赖：现在配方依赖 _resolve_rollout_functions 的互斥断言；若未来 fully-async 分支改变默认行为（如默认提交粒度），该配方可能受影响，但当前已显式设置 --rollout-submission-granularity sample，风险低。
 - 影响：影响面极窄：仅修改 1 个示例脚本，库代码零改动。对运行 GLM-5.2 × TB2 Daytona 配方的用户，运行行为不变，但启动时会更早暴露参数不兼容错误，而非静默绕过校验。对团队和系统无迁移成本。总体影响程度低。
 - 风险标记：缺少测试覆盖 , 未在硬件验证 , 参数语义耦合

# 关联脉络

- PR #2220 Add the GLM-5.2 744B x terminal-bench-2 Daytona example: 本 PR 正是对该新增配方脚本的修正，2220 是 run_glm5_2_744b_a40b_daytona.py 的原始来源。
- PR #2366 docs: rewrite the fully async page around schedule, data path, eval, and metrics: 同属 fully-async 功能线，2366 系统梳理了全异步模式的 schedule、数据路径等语义，可与本 PR 对照理解 --fully-async 的完整参数行为。