ADR-0019 CUDA Learner Forbids CPU Carrier¶
语言: 简体中文
Status: Proposed
Date: 2026-10-21
Owners: Training / RL runtime maintainers
Supersedes: None
Superseded by: None
Roadmap: Issue #2483
Context¶
#2479 的归因重测确认:CUDA learner 下 CPU 载体与 CUDA 载体 + CUDA MPS 吞吐持平 (87.4k vs 88.4k steps/s,噪声内)。CPU 载体的存在价值已从”性能路径”退化为”平台 兜底”,但它仍作为合法配置出现在 CUDA learner 路径上,使新跑法可以静默选入一个 无性能收益、徒增 host 边界拷贝的拓扑。
ADR-0018 把 collector tensor 驻留收口为单一旋钮
training.collector_tensor_device;本 ADR 在该一维旋钮上收紧值域的合法组合:
cpu × CUDA learner 不再是默认合法组合。
Decision¶
CUDA learner 禁止显式 CPU 载体,fail closed。两个执行面同步收紧:
off-policy placement:
src/unilab/rl/runtime/placement.py的resolve_inference_placement在解析出cpu请求且 learner 为 CUDA 设备族时 抛出带迁移提示的ValueError;env 载体路由:
src/unilab/base/process_device.py的apply_collector_tensor_device_override在显式cpu、已知 CUDA learner、 HOST_BRIDGE 后端时同样 fail closed(on-policy 与 play 路径经此覆盖)。auto不受影响:CUDA learner 的auto本来就解析为cuda。
显式逃生门是环境变量,不是配置键。归因基线/调试 run 设置
UNILAB_ALLOW_CUDA_LEARNER_CPU_CARRIER=1(真值集1/true/yes/on)显式 opt-in; 读取点收口在src/unilab/process_context.py的cuda_learner_cpu_carrier_opted_in,训练配置层把它绑定到 placement 的allow_cpu_carrier_with_cuda_learner参数。不新增 Hydra 键,保持 ADR-0018 的 单一旋钮配置面;逃生门是纯部署层设施,不进 owner YAML。逐条豁免依据:
CPU learner:learner 设备族为
cpu,host ring 是唯一拓扑,无设备边界 可跨越;规则以 CUDA 设备族为触发条件,天然不命中。macOS torch.mps learner:learner 设备族为
mps,同样不命中设备族检查。 Apple Silicon 上没有 CUDA IPC/MPS 等价物,CPU 载体是 mps learner 唯一可用的 host bridge 拓扑(staging policycpu_ring_explicit_learner_device_copy)。ROCm/HIP:ROCm PyTorch 使用
cuda设备命名空间,单看设备族会误伤;以torch.version.hip判定 HIP 构建后豁免。ROCm 没有 CUDA MPS 等价物 (training.cuda_process_sharing仅限 NVIDIA),CPU 载体是其唯一的进程共享 缓解路径。
Stable Contracts¶
Contract |
Owner / planned evidence |
|---|---|
CUDA learner + 显式 |
|
配置层绑定逃生门 |
|
env 载体路由同步收紧 |
|
逃生门环境变量读取 |
|
入口端到端行为 |
|
支持矩阵配对契约文字 |
|
Alternatives Considered¶
直接删除 CPU 载体(无逃生门)。Rejected:#2479 的归因基线需要可重复地跑出 CPU 载体 + CUDA learner 拓扑作为对照臂;ROCm/macOS/CPU learner 也仍依赖该路径。
逃生门做成 Hydra 配置键(如
training.allow_cuda_learner_cpu_carrier)。 Rejected:会在 ADR-0018 刚收口的单一旋钮旁重新长出一个永久性配置面;环境变量 把逃生门限定在部署/调试层,且不会让 owner YAML 表达出一个被禁止的拓扑。只在 off-policy placement 一层收紧。Rejected:on-policy(PPO/APPO)与 play 路径 经
apply_collector_tensor_device_override同样可以选出 CPU 载体 + CUDA learner;单层收紧会让契约依入口而不一致。
Consequences¶
training.collector_tensor_device=cpu与非 ROCm CUDA learner 的组合在配置读取/ 路由时即报错,报错文本给出auto/cuda迁移路径与逃生门变量名。归因基线 run 通过
UNILAB_ALLOW_CUDA_LEARNER_CPU_CARRIER=1复现旧拓扑;其 run_config.json 中的device_resolution.collector_tensor=cpu与staging_policy=cpu_ring_explicit_learner_actor_h2d_action_d2h仍是识别该拓扑的 审计证据。支持矩阵的 HOST_BRIDGE
cpu/cudaTorch devices 列描述的是后端能力清单,不因 本契约改变;矩阵正文新增 pairing contract 说明,把”能力存在”与”CUDA learner 下默认禁用”区分开。之后不得引入绕过该禁令的第二逃生通道;新的豁免平台必须扩展本 ADR 的豁免清单 并给出逐条依据。
Evidence In Repo¶
禁令与逃生门参数:
src/unilab/rl/runtime/placement.py::resolve_inference_placement配置层绑定:
src/unilab/training/tensor_runtime.py::resolve_collector_tensor_placementenv 载体路由:
src/unilab/base/process_device.py::apply_collector_tensor_device_override逃生门读取:
src/unilab/process_context.py::cuda_learner_cpu_carrier_opted_in吞吐持平的测量来源:#2479 归因收口与三臂基线;契约决策记录:#2483