Skip to content

roadmap: 彻底移除 Numba 残留并将训练 runtime 收口为 Torch-only / 显式 NumPy leaf 边界 #2124

Closed

Description

@TATP-233

Scope level

roadmap

Work type

feature

Area

other

Problem

UniLab 已经完成 NpEnv/tensor_runtime 开关移除,但当前审计确认 tensor-only 迁移仍有两类残留:

  1. Numba 是 NpEnv 时代残留,且 Tensor path 也会被污染

    • unisim-core 1.7.15 已无 Numba 实现或依赖;unisim.backend.body_state 是纯 NumPy helper。
    • UniLab 仍直接依赖 numba>=0.67(默认与 ROCm profile)。
    • Production Numba 只剩:
      • src/unilab/tasks/motion_tracking/common/kernels.py 的 CPU motion kernels;
      • src/unilab/base/cpu_runtime.py 的 numba.set_num_threads 线程池 cap。
    • manager_terms.py 顶层无条件 import kernels,且 _NumbaBodyTerm、bad_anchor_pos_z_only 构造时即使 command 已是 tensor carrier 也会 configure Numba。
    • uv tree --invert --package numba 显示除 UniLab direct dependency 外,只剩 genesis-world extra 传递引入 Numba。Genesis 传递依赖不构成 UniLab/unisim 保留 Numba 实现或线程池管理的理由。
  2. NumPy 仍大量存在于 Manager/task 热路径,远超出 CPU backend 接口边界

    • src/unilab 中 62 个 Python 文件直接 import NumPy,约 2,182 行含 np.,约 1,010 行含 np.ndarray 类型标注,46 行 .numpy() 转换。
    • 残留分布在 Manager core、generic MDP terms、reset/event composer、entity facade、motion tracking CPU command、locomotion task terms、generic NumPy utilities。
    • 这与 ADR-0012 的目标不一致:Manager 训练 runtime 的 authoritative carrier 应只有 torch.Tensor;NumPy 只允许存在于 concrete CPU backend adapter 的 packed HOST_BRIDGE staging,以及明确 cold asset/materialization/serialization/rendering leaf 内部。

当前特别不一致的运行时事实:

  • PPO/APPO MuJoCo、SAC base/inherit owner 仍使用 CPU/NumPy MotionCommandCfg。
  • FlashSAC 所有 backend owner 与 SAC MJWarp 已使用 TensorMotionCommandCfg,证明 Tensor command 也适用于 HOST_BRIDGE CPU-authoritative backend。
  • SAC Genesis 当前继承 NumPy command;但 Genesis scope 已在 roadmap: tensor-only Manager-Based runtime and three-backend scope reduction #1811 后暂缓,需在本 roadmap 中明确不作为验收阻塞。
  • TensorMotionCommand(MotionCommand) 仍继承 CPU/NumPy base 初始化路径,再分配 Torch carrier,是中间态结构。
  • Manager 仍同时持有 env.rng: np.random.Generator 和 TorchManagerRng,导致 command/event/noise/motion sampling 双 RNG 语义并存。

本 roadmap 的目的不是简单把 NumPy 从依赖列表删除。NumPy 仍会被 unisim-core public legacy API、ONNX Runtime、NPZ asset、MuJoCo/Viser rendering 等外部边界使用。目标是先消灭训练 runtime 的 NumPy authoritative carrier,再把剩余 NumPy 固定为显式 leaf/adapter 边界,并用架构 gate 防回归。

Deliverable

交付一个完成边界收口的 tensor-only UniLab runtime:

  • Manager 热路径没有 NumPy authoritative carrier、NumPy RNG stream、NumPy/ Torch dual term branches 或隐藏 host fallback。
  • 所有 G1 motion tracking production owner 使用 TensorMotionCommand。
  • Production source 不 import/configure/tune Numba;UniLab 默认与 ROCm dependency profile 不再 direct require Numba。
  • EnvCfg.cpu_ids 保留 Linux process/existing-thread affinity,不再拥有 Numba 线程池策略。
  • UniLab runtime/task 代码只消费 UniSim public tensor lifecycle / packed host bridge API,不直接调用 legacy NumPy backend getter/step/reset 作为训练热路径。
  • NumPy 仅保留在:
    1. UniSim concrete CPU backend adapter 内部;
    2. cold asset/materialization;
    3. serialization/ONNX/NPZ;
    4. playback/rendering/visualization。
  • 这些例外由 architecture gate allowlist 固化。
  • ADR-0012 得到补充或由新 ADR 明确 NumPy/Numba leaf 边界、上游 SimBackend legacy NumPy API 的处置,以及 Genesis extra 传递 Numba 的依赖策略。
  • 文档、测试、lock/profile 同步更新,最终 make test-all 通过。

Scope and delivery boundaries

In this work item

  • G1 motion tracking owner/runtime 全部切到 Tensor command,删除 CPU MotionCommand 热路径与 Numba kernels。
  • cpu_runtime 收缩为 OS affinity owner,删除 Numba cap。
  • Manager core、generic MDP terms、noise/buffers/RNG 的 tensor-only 收口。
  • reset/event/DR 与 entity facade 的 host staging 下沉或改为 public packed tensor API。
  • locomotion task terms 的 tensor 化。
  • cold loader / terrain / diagnostics / visualization / ONNX 的 NumPy leaf 化与 allowlist。
  • dependency、lock、tests、docs 和 architecture gate。

Related follow-up or separate outcomes

  • 不在本 roadmap 内做 PyPI release 或 published dependency transition;发布仍遵循 workflow 的单独 release gate。
  • 不恢复 Genesis production support;Genesis 仅作为 optional extra 的传递依赖问题处理。
  • 不永久删除 unisim-core 中暂缓 backend adapters;永久删除是独立维护者决策。
  • 不把 benchmark 设施升级、多步执行/graph lifecycle 或 inference overlap 方案纳入本 roadmap;perf: public multi-step MJWarp lifecycle execution for slow-host servers #2043 保持独立。
  • NumPy 从 pyproject.toml direct dependency 移除与否是本 roadmap 后期的独立决策,不是前期目标。只要 runtime 边界收口,metadata 保留与否可依据当时外部 leaf 需要 re-evaluate。

Roadmap relationship and target branch

Definition of done

Phase 0 — 决策与基线

  • Maintainer 确认 roadmap declared base 与 integration branch。
  • 确认 NumPy allowlist 边界:
    • UniSim concrete CPU adapter;
    • cold asset/materialization;
    • serialization/ONNX/NPZ;
    • playback/rendering/visualization。
  • 确认 UniSim legacy NumPy SimBackend API 的处置:deprecated、internal-only,或由完整 public tensor/packed API 替代后删除。
  • 确认 Genesis extra 传递 Numba 的策略:允许安装但禁止 UniLab runtime import/tune;不因 Genesis 恢复 UniLab Numba API。
  • 确认 RNG 终态:单一 TorchManagerRng,删除 env.rng NumPy stream,不做 NumPy bitstream parity。
  • 补充 ADR-0012 或新增 ADR,记录 NumPy leaf 边界、Numba 移除和上游 contract 决策。
  • 建立当前 G1 motion / walk representative workload 的 focused benchmark 基线,至少覆盖 MuJoCo HOST_BRIDGE 与 MJWarp;记录 manager step/reset/reward/update timing 和 transfer counters。

Phase 1 — 移除 Numba 与 G1 motion CPU command

  • 所有 G1 motion production owner 选择 TensorMotionCommand:
    • PPO MuJoCo;
    • APPO MuJoCo;
    • SAC canonical base;
    • FlashSAC canonical base,并移除各 backend overlay 的重复 override。
  • manager_terms.py 不再 import kernels.py,tensor terms 构造路径不再 configure Numba。
  • 拆开 TensorMotionCommand 对 CPU MotionCommand NumPy base 初始化的继承污染。
  • 删除 src/unilab/tasks/motion_tracking/common/kernels.py。
  • motion reward/termination terms 全部 Torch-only;NumPy reference 只保留为 tests-only 或删除。
  • cpu_runtime.py 保留 process/existing-thread affinity,删除 NUMBA_NUM_THREADS special case 与 numba.set_num_threads。
  • 更新 EnvCfg.cpu_ids 注释与中文 SAC 文档。
  • 从 pyproject.toml、pyproject.rocm.toml 删除 direct Numba dependency,并更新 uv.lock / uv.rocm.lock。
  • tests/scripts/test_rocm_dependency_profile.py 不再断言 root direct Numba;断言不能改成“lock 完全无 Numba”,因为 Genesis extra 仍可传递包含 Numba。
  • architecture gate 禁止 src/unilab/** import Numba。
  • focused gates 覆盖 G1 owner config、motion parity、selected reset、CPU affinity、ROCm profile。
  • 与 Phase 0 基线比较 MuJoCo/MJWarp G1 motion performance;记录 transient regression 与原因,不允许无 attribution 的性能下降进入 integration head。

Phase 2 — Manager core 与 generic MDP tensor-only

  • 删除 Manager public/internal execution 的 NumPy carrier、NumPy row selector、NumPy command/reward/termination/obs branches。
  • managers/_types.py、manager base docs、manager protocols 改为 Torch-only contract。
  • 删除 ManagerBasedRlEnv.rng: np.random.Generator;TorchManagerRng 为唯一 RNG。
  • _manager_tensor 不接受/转换 NumPy result。
  • Observation/reward/termination/action/command term contracts 全部要求 Torch tensor。
  • noise model/cfg、circular/delay buffers、recorder carriers Torch-only。
  • Observation partial reset、finite checks、invalid-row diagnostics 不通过 .cpu().numpy() 实现常规热路径。
  • seed/reset/selected-row reproducibility contract tests 更新。
  • 增加 architecture gate:src/unilab/managers/**、src/unilab/envs/** 禁止 NumPy import 与 .numpy(),除非进入 Phase 0 allowlist。

Phase 3 — reset/event/DR 与 entity host boundary 下沉

  • reset_state.py 不再拥有 CPU authoritative NumPy staging;UniLab 构造 Torch rows/payload。
  • Event/DR reset payload 全部 tensor carrier;device reset randomization 走 public capability,不支持则 fail closed。
  • entity.py public Manager-facing view 不暴露可变 NumPy authoritative carrier。
  • UniLab 停止在训练热路径直接调用 legacy NumPy backend API:
    • get_base_pos
    • get_body_*
    • get_sensor_data
    • legacy step
    • legacy set_state
  • HOST_BRIDGE selected/full read 统一通过 HostBridgeTransferPlan 或新的 public packed tensor contract;删除 task-local get_*_rows + torch.as_tensor(np...) fallback。
  • 如需要,先扩展/发布 unisim-core public tensor contract,再消费;不得调用 backend-private方法或按 backend name 分支。

Phase 4 — locomotion task terms tensor 化

  • locomotion command/reward/contact/gait/air-time/swing/sensor terms 改为 Torch carrier。
  • height scan 消费 public tensor state/tracked body view,不调用 get_base_pos()。
  • terrain spawn/reset path 不持有 NumPy authoritative state。
  • G1/Go2 production owner config/tests 更新。
  • 既有 task parity tests 保持语义验收,不要求 NumPy bitstream parity。

Phase 5 — cold path 与 external leaf 收口

  • MotionLoader 作为 cold NPZ leaf:内部 parse,输出 immutable Torch table/metadata,不向 runtime 返回可变 NumPy carrier。
  • TensorMotionSampler 输入不再要求 NumPy arrays。
  • terrain generation/materialization 保留 cold-path NumPy,但输出 backend-owned materialization 或 Torch/plain immutable data;step/reset 不生成 terrain。
  • dtype_config.py 改为 Torch dtype owner,或由 backend tensor spec 声明 dtype。
  • 删除或迁移 src/unilab/utils/rotation.py、geometry.py、tensor.py、seed.py 中 runtime NumPy utility;CPU reference 移 tests-only 或由 owner module 替代。
  • ONNX、NPZ diagnostics、playback、MuJoCo/Viser rendering 改为 lazy-import explicit leaf,模块内部消化 host format,不进入 env/Manager public contract。
  • 最终 architecture gate allowlist 列出所有剩余 NumPy leaf,并禁止新 runtime import。

Phase 6 — 收口与最终 gate

  • make check 通过。
  • make test 通过。
  • make test-all 通过。
  • focused MuJoCo HOST_BRIDGE 与 MJWarp G1 motion/walk end-to-end training runs 通过,并使用 tail_env_steps_per_sec 记录结果。
  • 与 Phase 0 baseline 比较,解释所有非噪声 regression;性能不达标时不得关闭 roadmap,需拆出带 owner 的 optimization issue。
  • support matrix、架构文档、中文/英文用户指南同步。
  • changelog 记录 breaking boundary:
    • CPU MotionCommand 移除;
    • NumPy Manager carrier/RNG 移除;
    • Numba direct dependency 移除;
    • legacy NumPy backend API 在 UniLab runtime 禁用。
  • strict search 验证:
    • production source 无 Numba import;
    • pyproject.toml / pyproject.rocm.toml root 无 Numba;
    • src/unilab/managers、src/unilab/envs、task runtime 无未 allowlist NumPy;
    • active task runtime 无 hidden .numpy() fallback。

Dependencies and blockers

Proposed owner

Env / Manager / Backend / Training maintainers

Validation plan

每个阶段

  • Focused tests:
    • G1 motion owner config;
    • motion parity;
    • selected reset/readiness;
    • Manager RNG reproducibility;
    • observation/reward/termination contracts;
    • event/DR capability fail-closed;
    • CPU runtime affinity;
    • dependency/ROCm profile;
    • architecture boundary。
  • 对 MuJoCo HOST_BRIDGE 与 MJWarp 各保留 representative training/smoke gate。

最终 integration head

make check
make test
make test-all

性能验收

  • 使用 perf: end-to-end MJWarp training throughput gate and tensor-native closeout #2023 建立的 tail_env_steps_per_sec 合同,而非 collector active-window 单点或 benchmark-only 结果。
  • 至少覆盖:
    • FlashSAC / g1_motion_tracking;
    • SAC 或 canonical walk owner;
    • MuJoCo HOST_BRIDGE;
    • MJWarp。
  • 与 Phase 0 baseline 做成对比较;非噪声 regression 必须有 attribution 和后续优化计划。
  • Genesis 不进入 final performance gate;当前处于暂缓 runtime scope。

架构验收

  • src/unilab/** 无 Numba import。
  • Manager/env/task training runtime 无未 allowlist NumPy import。
  • 常规训练热路径无 hidden .cpu().numpy() / torch.from_numpy fallback。
  • 剩余 NumPy 只出现在显式 allowlist leaf。
  • UniLab runtime 不调用 backend-private API 或 backend-name capability branch。

兼容性说明

  • 不保留 CPU MotionCommand compatibility alias。
  • 不保留 Manager NumPy carrier compatibility branch。
  • 不保证 NumPy RNG bitstream parity;只验证 owner seed 下的 Torch RNG reproducibility。
  • Genesis optional extra 可能因上游继续安装 Numba,但 UniLab 不 import、不调优、不声明兼容责任。

Activity

  1. TATP-233 commented on Oct 10, 2026

    @TATP-233
    CollaboratorAuthor

    Phase 0 决策确认与落地

    Maintainer 判断题结论

    决策 结论
    Roadmap integration base 不复用历史 develop/tensor-runtime。新建集成分支 dev/issue-2124-tensor-runtime-closeout,基于当前 main@f76b6d0f;main 本身不被修改。
    NumPy 边界 只允许:CPU backend adapter 内部、cold asset/materialization、serialization/ONNX/NPZ、playback/rendering/visualization。
    Legacy NumPy backend API 彻底移除 legacy API 与旧代码,不保留兼容层。
    Genesis / Numba Genesis extra 可传递安装 Numba;UniLab/unisim 不 import、不调优、不声明兼容责任。
    RNG 彻底替换为 TorchManagerRng;删除 env.rng NumPy stream;不保证旧 NumPy bitstream。
    ADR 新增 ADR,而不是只修改 ADR-0012。
    Phase 0 benchmark G1 motion + G1 walk,MuJoCo HOST_BRIDGE + MJWarp;指标用最后 completed iterations 的 aggregate,不用 final 单次。
    性能规则 非噪声 regression 必须归因;无归因性能下降不得进入 integration head。

    已落地

    • 新增 ADR:docs/sphinx/source/adr/ADR-0015-no-numba-and-explicit-numpy-leaf-boundaries.md
    • 更新 ADR index:ADR-0000-index.md、README.md
    • 新 integration branch:dev/issue-2124-tensor-runtime-closeout
    • branch head:98fb3771(base:main@f76b6d0f)
    • 上游指标 issue:perf: use a 100-iteration tail throughput window for run summaries unilabsim/unilab_rl#103
      • 当前 unilab-rl==1.4.11 tail window 是 20;
      • roadmap 要求 last 100 completed iterations aggregate;
      • 该 issue 跟踪将默认 window 改为 100,并输出 configured/actual count。

    Phase 0 benchmark 证据

    主机:AMD Ryzen 9 9950X3D,RTX 4090,driver 580.178.04。
    日期:2026-10-10。
    head:f76b6d0f(baseline 在 ADR commit 前执行)。

    End-to-end

    当前 logger tail 是 20 iterations,因此以下只是 Phase 0 feasibility/profiling,不是最终 gate;最终 gate 等待 unilab_rl#103 的 100-iteration 指标。

    Owner / task Backend iterations tail steps/s final steps/s
    FlashSAC / G1 motion MuJoCo 120 52,269.04 48,810.11
    FlashSAC / G1 motion MJWarp 120 25,517.01 25,040.25
    SAC / G1 walk MuJoCo 120 35,512.11 35,572.27
    SAC / G1 walk MJWarp 120 21,273.87 27,561.38

    Manager/reset timing

    benchmark_env_step.py,512 envs,50 warmup,300 measured steps:

    Task / backend median total ms update state ms reset done ms throughput
    G1 walk / MuJoCo 10.892 1.775 3.179 46,987/s
    G1 walk / MJWarp 8.942 2.432 2.449 52,847/s
    G1 motion / MuJoCo 13.898 4.695 3.373 36,395/s

    g1_flashsac_backend.py,512 envs,50 warmup,300 iterations:

    Backend iteration mean ms update state mean ms reset done mean ms backend reset mean ms throughput
    MuJoCo 8.081 1.906 1.601 0.966 63,362/s
    MJWarp 8.223 1.734 1.537 0.271 62,261/s

    说明:benchmark_env_step.py 的 G1 motion inventory 目前只声明 MuJoCo;MJWarp motion timing 使用 g1_flashsac_backend.py 的 real public backend tensor lifecycle probe。更新 benchmark inventory 属于后续迁移工作,不阻塞 Phase 0。

    Phase 0 状态

    • Maintainer 确认 declared base 与 integration branch。
    • 确认 NumPy allowlist 边界。
    • 确认 legacy NumPy SimBackend API 处置:彻底移除,无兼容层。
    • 确认 Genesis extra 传递 Numba 策略。
    • 确认 RNG 终态。
    • 新增 ADR-0015 并更新 ADR index。
    • 建立本地 RTX 4090 Phase 0 feasibility/timing baseline。
    • unilab_rl#103 发布 100-iteration tail 指标并用它重跑 authoritative baseline。
  2. TATP-233 commented on Oct 10, 2026

    @TATP-233
    CollaboratorAuthor

    Phase 1 本地实现与验证(待 child PR)\n\nBranch: feat/issue-2124-remove-numba-motion-cpu-command(基于 integration branch dev/issue-2124-tensor-runtime-closeout)\nCommit: be3f9df5\n\n### 已完成\n- 删除 motion_tracking/common/kernels.py 及全部 Numba import/configure/warmup。\n- MotionCommand 本体重构为 device-resident Torch command,直接持有 TensorMotionSampler/Torch metrics/public tensor views;删除 CPU NumPy MotionSampler 热路径和 TensorMotionCommand compatibility alias。\n- motion reward/termination/joint limit terms 收口为 Torch-only carrier,不再保留 NumPy/Torch branch。\n- G1 motion production owner 统一 MotionCommandCfg:PPO/APPO/SAC base/FlashSAC base;删除各 backend overlay 的重复 command override。\n- TensorMotionSampler 构造输入从 NumPy 改为 Torch tensor,clip/frame table 构造不再经过 NumPy。\n- EnvCfg.cpu_ids 只保留 Linux process/existing-thread affinity;删除 NUMBA_NUM_THREADS special case 与 numba.set_num_threads。\n- 默认/ROCm dependency profile 删除 direct numba,并更新 uv.lock/uv.rocm.lock。default lock 仍因 Genesis extra 传递包含 numba;ROCm lock 当前无 Genesis extra,因此 lock 内也没有 numba,但测试只断言 root 无 direct numba,不把“lock 完全无 Numba”作为验收。\n- architecture gate:src/unilab/** 禁止 Numba import 和 NUMBA_/set_num_threads 配置。\n- 修正 slow Newton runtime 缺依赖时从 error 变为 skip。\n\n### 本地验证\n- make check ✅\n- make test ✅(1884 passed, 42 skipped, 497 deselected)\n- make test-all ✅(check + coverage tests + benchmark smoke;1884 passed, 42 skipped)\n- 额外 slow motion/env focused matrix:uv run pytest tests/envs tests/tasks tests/base/test_cpu_runtime.py tests/scripts/test_rocm_dependency_profile.py -q -m '' ✅(499 passed, 16 skipped)\n\n### 尚未完成 / 下一步\n- [ ] 发布 child PR 指向 integration branch,等待 review/merge。\n- [ ] 用最终 Phase 1 head 跑 MuJoCo/MJWarp G1 motion 性能对比,并与 Phase 0 baseline 归因比较(最终 gate 仍等待 unilab_rl#103 的 100-iteration tail)。\n- [ ] Phase 2+ 继续收口 Manager core/generic MDP/NumPy allowlist。\n

  3. TATP-233 commented on Oct 10, 2026

    @TATP-233
    CollaboratorAuthor

    Child PR: #2125(base 为 integration branch dev/issue-2124-tensor-runtime-closeout)。PR body 已记录 final head be3f9df5 的 make check / make test / make test-all 结果。性能对比仍未声明完成,等待 merge 后的 integration head 与 100-iteration tail 合同。

  4. TATP-233 commented on Oct 10, 2026

    @TATP-233
    CollaboratorAuthor

    Phase 1 child-head performance feasibility check\n\nPR #2125 head: be3f9df5(child branch,尚未 merge 到 integration head)。仍为 profiling 证据,不替代最终 last-100-iteration gate。\n\n### Phase-local public backend probe\ng1_flashsac_backend.py, 512 envs, 50 warmup, 300 measured iterations:\n\n| Backend | Phase 0 throughput | Phase 1 throughput | Delta | Phase 0 iteration mean | Phase 1 iteration mean |\n|---|---:|---:|---:|---:|---:|\n| MuJoCo | 63,362.22 | 63,682.36 | +0.51% | 8.0805 ms | 8.0399 ms |\n| MJWarp | 62,261.24 | 62,558.70 | +0.48% | 8.2234 ms | 8.1843 ms |\n\n### Production Manager/reset probe\n\nbenchmark_env_step.py, G1 motion / MuJoCo, 512 envs, 50 warmup, 300 measured steps:\n\n| Metric | Phase 0 | Phase 1 |\n|---|---:|---:|\n| throughput | 36,394.93/s | 36,472.32/s |\n| median step | 13.898 ms | 14.064 ms |\n| median update state | 4.6948 ms | 4.7544 ms |\n| median reset done | 3.3733 ms | 3.4538 ms |\n\nMedian step/reset 变化约 0.17–0.24 ms,在该 probe 的 run-to-run band 内;backend/update phase means 与 phase-local probe 均无 regression。未发现需要 attribution 的非噪声 regression。\n\nArtifacts: /tmp/issue2124-phase1-motion-{mujoco,mjwarp}-probe.json, /tmp/issue2124-phase1-motion-mujoco-envstep.json.

  5. TATP-233 commented on Oct 10, 2026

    @TATP-233
    CollaboratorAuthor

    Phase 1 review blocker 修复(PR #2125 head 39aa30cd)

    自查发现的三个问题已在当前 PR head 修复并通过完整本地 gate:

    1. task-layer NumPy fallback 已删除:MotionCommand reset/write 只走 write_motion_state_tensor_to_sim;不存在 .cpu().numpy() + legacy root/joint write 分支。
    2. 新增 owner-subset tensor transaction:
      • DEVICE_RESIDENT: command step 打开 full-domain owner tensor transaction,实际发生 state write 的动态 subset 通过 SimBackend.set_state_tensor 一次提交;
      • HOST_BRIDGE: 同一 owner subset 通过公开 HostBridgeTransferPlan.apply_reset 以 Torch rows/qpos/qvel 一次提交;
      • subset 必须在 active domain 内且唯一,同一事务禁止改变 write-row-set;reset DR 混入 step-owner transaction fail closed。
    3. wrap 生命周期 fail closed:truncate_on_clip_end=false 且无 active tensor transaction 时,在 sampler advance / reset RNG consumption 之前报错,并验证 frame carrier 未推进、没有 resample 被发布。不再存在 inactive compute 时静默跳过 wrap 的路径。
    4. 诊断去 masking:reset_done_sampler_host_transfer_count 不再单独作为空洞断言;新增真实递增的 reset_done_sampler_dispatch_count(按 reset 事件差分),测试同时断言 dispatch 发生与 host transfer 为 0。

    同时修复一个测试污染 bug:test_motion_feature_layout_is_cached... 之前把 bound method 恢复到 MotionCommand 类上,污染后续 __new__ fixture 的 motion layout(joint width 29 被污染为 3),导致看起来像 Dynamo shape guard 故障。现在正确恢复原 class function。

    本地验证(39aa30cd):

    make check                 # passed
    make test                  # 1891 passed, 42 skipped
    make test-all              # passed; coverage 1891 passed, 42 skipped;
                               # benchmark imports module 34/34, script 35/35
    uv run pytest tests/tasks/test_motion_term_parity.py tests/base/test_reset_state.py \
      tests/envs/test_env_configs.py -q -m ''
                               # 106 passed, 5 skipped
    

    Phase 1 最终 100-iteration tail 性能 gate 仍按计划等待 integration head + unilabsim/unilab_rl#103,不在该 blocker 修复中伪造结论。

  6. TATP-233 commented on Oct 10, 2026

    @TATP-233
    CollaboratorAuthor

    Phase 2 child PR #2126:Manager noise/temporal buffers Torch-only

    从当前 integration branch 新开 feat/issue-2124-manager-noise-buffers-tensor-only,base 仍为 dev/issue-2124-tensor-runtime-closeout(不影响 main)。

    当前 head:bf9bcdc6

    完成内容:

    • NoiseCfg.apply / NoiseModel 契约改为 Torch-only:
      • 删除 NumPy data 分支、NumPy RNG 参数、Torch->NumPy->Torch host detour;
      • UniformNoiseCfg / GaussianNoiseCfg / SegmentwiseUniformNoiseCfg / ConstantNoiseCfg 全部在 observation tensor 的 dtype/device 上执行;
      • generator 缺失或 device 不匹配 fail closed。
    • DelayBuffer lag/phase/hold sampling 只消费 torch.Generator,删除 NumPy generator fallback。
    • CircularBuffer / DelayBuffer:
      • append/backfill/lag selector 全部要求 Torch tensor;
      • 删除 torch.from_numpy(np.ascontiguousarray(...)) 隐式转换;
      • NumPy 输入显式 TypeError。
    • ObservationManager 不再把 env.rng 传给 noise model / noise cfg / delay buffer;这些 owner 统一消费 Manager Torch generator。
    • Architecture gate 新增:src/unilab/managers/_buffers/** 与 _noise/** 禁止 NumPy import。
    • 相关测试改为 Torch stream reproducibility,并新增 NumPy carrier rejection;不保留 NumPy noise RNG bitstream parity(符合已确认决策)。

    本地验证(bf9bcdc6):

    uv run pytest tests/managers tests/envs -q --maxfail=8
                               # 479 passed, 6 skipped
    make check                 # passed
    make test                  # 1903 passed, 42 skipped
    make test-all              # passed; coverage 1903 passed, 42 skipped;
                               # benchmark imports module 34/34, script 35/35
    

    尚未完成(Phase 2 后续):

    • Manager public term contracts / _types.py 全部 Torch-only;
    • 删除 ManagerBasedRlEnv.rng,TorchManagerRng 成为唯一 RNG;
    • _manager_tensor 拒绝 NumPy;
    • observation/reward/termination/action/command manager 的 row selector 与 diagnostics host conversion 收口;
    • 最终 Manager/env NumPy allowlist gate。
  7. TATP-233 commented on Oct 10, 2026

    @TATP-233
    CollaboratorAuthor

    Phase 2 child PR #2127:Manager core seams 去 NumPy

    分支 feat/issue-2124-manager-env-types-tensor-only,base dev/issue-2124-tensor-runtime-closeout,当前 head d1d01a81。

    完成内容:

    • manager_base.py:
      • 删除 NumPy import;
      • class term 示例契约改为 torch.Tensor。
    • curriculum_manager.py:
      • 删除 NumPy import;
      • scalar finite validation 改用 math.isfinite,语义不变。
    • event_manager.py:
      • 删除 NumPy import;
      • interval range finite validation 改用 math.isfinite,语义不变。
    • Architecture gate:上述三个 Manager core 模块禁止 NumPy import。

    范围说明:reward/termination/action 与 entity-facing term contract 未在本 PR 声称完成,因为生产 term 仍消费 NumPy-backed entity data;本 PR 不通过隐藏 Torch conversion 制造看似更大的边界。它们按 #2124 Phase 2/3 继续拆分迁移。

    本地验证(d1d01a81):

    uv run pytest tests/managers tests/envs tests/tasks/test_package_boundary.py -q --maxfail=8
                               # 482 passed, 6 skipped
    make check                 # passed
    make test                  # 1899 passed, 42 skipped
    make test-all              # passed; coverage 1899 passed, 42 skipped;
                               # benchmark imports module 34/34, script 35/35
    
  8. TATP-233 commented on Oct 10, 2026

    @TATP-233
    CollaboratorAuthor

    Phase 2 child PR #2128:Manager scheduling RNG 收口

    分支 feat/issue-2124-manager-core-rng,base dev/issue-2124-tensor-runtime-closeout,当前 head 063d394c。

    完成内容:

    • CommandTerm resampling time draw:
      • 删除 env.rng.uniform(...) + torch.as_tensor(...) fallback;
      • 缺少 TorchManagerRng 时 fail closed。
    • EventManager interval time sampling:
      • 删除 NumPy RNG fallback;
      • 缺少 TorchManagerRng 时 fail closed。
    • Focused fixtures 显式持有 TorchManagerRng;partial-reset noise reproducibility 改为检查 Torch generator state。
    • 新增缺 Torch RNG 的 fail-closed 测试。
    • Architecture gate 禁止 command_manager.py / event_manager.py 重新出现 .rng.uniform scheduling fallback。

    范围说明:本 PR 尚未删除 ManagerBasedRlEnv.rng,因为 task/event sampling consumers 仍存在。后续 child 先迁移这些 consumers,再移除 environment-owned NumPy stream;不提供 NumPy RNG bitstream parity。

    本地验证(063d394c):

    uv run pytest tests/tasks/test_package_boundary.py tests/managers tests/envs -q --maxfail=8
                               # 483 passed, 6 skipped
    make check                 # passed
    make test                  # 1900 passed, 42 skipped
    make test-all              # passed; coverage 1900 passed, 42 skipped;
                               # benchmark imports module 34/34, script 35/35
    
  9. TATP-233 commented on Oct 10, 2026

    @TATP-233
    CollaboratorAuthor

    Phase 2 child PR #2129:generic MDP event sampling 切换 Torch RNG

    分支 feat/issue-2124-generic-mdp-torch-rng,base dev/issue-2124-tensor-runtime-closeout,当前 head a48d2e97。

    完成内容:

    • generic event sampling 全部改为 TorchManagerRng:
      • PD gain reset sampling;
      • generic model-field reset randomization axes,包括 shared-random / log-uniform;
      • rigid-body mass、mass/inertia scale、COM startup/reset sampling;
      • gravity reset sampling;
      • velocity push linear/angular delta;
      • body impulse duration/cooldown/force/torque;
      • encoder bias reset sampling;
      • legacy uniform root-state reset 的 SE(3) pose/velocity sampling。
    • src/unilab/envs/mdp/events.py 中删除全部 env.rng / self._env.rng 引用。
    • 缺少 Manager Torch RNG 时 _require_torch_rng fail closed。
    • Architecture gate 禁止 generic event terms 重新引用 environment NumPy RNG。
    • focused fixtures 持有 TorchManagerRng,startup sampling count 改为观察 Torch RNG。

    范围说明:legacy NumPy writer APIs 仍保留给这些 event,这是 #2124 Phase 3 reset/entity composer 的迁移对象。本 PR 不再保留任何 NumPy compatibility RNG path。

    本地验证(a48d2e97):

    uv run pytest tests/envs/mdp/test_events.py tests/tasks/test_package_boundary.py -q
                               # 61 passed
    uv run pytest tests/envs tests/tasks/test_package_boundary.py tests/managers -q --maxfail=8
                               # 483 passed, 6 skipped
    make check                 # passed
    make test                  # 1900 passed, 42 skipped
    make test-all              # passed; coverage 1900 passed, 42 skipped;
                               # benchmark imports module 34/34, script 35/35
    
  10. TATP-233 commented on Oct 10, 2026

    @TATP-233
    CollaboratorAuthor

    Phase 2 child PR #2130:generic commands / IMU bias 切换 Torch RNG

    分支 feat/issue-2124-generic-command-obs-torch-rng,base dev/issue-2124-tensor-runtime-closeout,当前 head 450d8984。

    完成内容:

    • UniformPoseCommand:
      • per-axis sampling;
      • zero-command bucket sampling;
      • 全部使用 TorchManagerRng;
      • 缺 Torch RNG fail closed。
    • UniformVelocityCommand:
      • command axes;
      • heading selection;
      • standing/world/forward masks;
      • 全部使用 TorchManagerRng;
      • 缺 Torch RNG fail closed。
    • cached IMU mounting-misalignment quaternion:
      • 使用 TorchManagerRng.standard_normal/uniform;
      • 缺 Torch RNG fail closed;
      • 保留“同一 env 内 gyro/gravity 共享同一安装误差”的语义。
    • 删除以下文件的 env.rng / self._env.rng 引用:
      • src/unilab/envs/mdp/observations.py
      • src/unilab/envs/mdp/commands/pose_command.py
      • src/unilab/envs/mdp/commands/velocity_command.py
    • Architecture gate:generic command/observation term files 禁止 environment NumPy RNG 引用。

    范围说明:仍存在的 legacy host carrier(如 pose command 的 NumPy storage)属于 Phase 3 entity/composer 迁移;本 PR 不保留任何 NumPy RNG fallback。

    本地验证(450d8984):

    uv run pytest tests/envs/mdp/test_observations.py tests/envs/mdp/test_command_terms.py \
      tests/envs/mdp/test_uniform_velocity_command.py tests/tasks/test_package_boundary.py -q --maxfail=8
                               # 48 passed
    uv run pytest tests/envs tests/tasks/test_package_boundary.py tests/managers -q --maxfail=8
                               # 485 passed, 6 skipped
    make check                 # passed
    make test                  # 1902 passed, 42 skipped
    make test-all              # passed; coverage 1902 passed, 42 skipped;
                               # benchmark imports module 34/34, script 35/35
    
  11. TATP-233 commented on Oct 10, 2026

    @TATP-233
    CollaboratorAuthor

    Phase 2 child PR #2131:locomotion task RNG 切换 Torch

    分支 feat/issue-2124-locomotion-torch-rng,base dev/issue-2124-tensor-runtime-closeout,当前 head 9a079d3c。

    完成内容:

    • G1 gait phase reset:

      • independent / offset_phase 两种模式均使用 TorchManagerRng;
      • 删除 environment NumPy RNG fallback;
      • 缺 Torch RNG fail closed;
      • 新增 fail-closed 测试。
    • RoughTerrainReset:

      • pose / orientation / velocity sampling 全部使用 TorchManagerRng;
      • 删除 env.rng;
      • 缺 Torch RNG fail closed。
    • Architecture gate:

      • tasks/locomotion/g1/manager_terms.py
      • tasks/locomotion/common/rough_manager_terms.py

      禁止 environment NumPy RNG 引用。

    范围说明:RoughTerrainReset 仍显式使用 legacy NumPy root-state writer,这是 Phase 3 composer/entity 迁移对象;本 PR 不保留 environment NumPy RNG path。

    本地验证(9a079d3c):

    uv run pytest tests/envs/locomotion/g1/test_manager_terms.py -q -m '' --maxfail=5
                               # 13 passed
    uv run pytest tests/envs tests/tasks/test_package_boundary.py tests/managers -q --maxfail=8
                               # 482 passed, 6 skipped
    make check                 # passed
    make test                  # 1899 passed, 42 skipped
    make test-all              # passed; coverage 1899 passed, 42 skipped;
                               # benchmark imports module 34/34, script 35/35
    

    至此,除 #2125 将删除的 legacy motion CPU command 之外,生产 task / generic Manager / env MDP 层已无 env.rng consumers。#2125 合入后即可删除 ManagerBasedRlEnv.rng。

  12. TATP-233 commented on Oct 10, 2026

    @TATP-233
    CollaboratorAuthor

    Phase 2 integration rehearsal(七个 child 合并预演,未改动远端集成分支)

    由于当前 7 个 child PR 均 OPEN / MERGEABLE / CLEAN,我在本地从 origin/dev/issue-2124-tensor-runtime-closeout 建立临时 rehearsal 分支,按以下顺序合并:

    1. 39aa30cd  #2125 Phase 1 remove Numba / G1 CPU motion command
    2. d1d01a81  #2127 Manager core seams 去 NumPy
    3. 063d394c  #2128 Manager scheduling Torch RNG
    4. a48d2e97  #2129 generic events Torch RNG
    5. 450d8984  #2130 generic commands / IMU bias Torch RNG
    6. 9a079d3c  #2131 locomotion Torch RNG
       #2126 bf9bcdc6 的 owner 文件在 #2131 merge 过程中以该 PR 内容恢复并合并
    7. RNG 终态收口(rehearsal-only commit 689a2b8c)
    

    合并冲突与已验证解法

    所有冲突都只在 tests/tasks/test_package_boundary.py 的 architecture-gate 追加区,不存在生产代码语义冲突。解法是保留双方 gate:

    • Numba production gate
    • Manager core NumPy import gate
    • Manager scheduling NumPy RNG fallback gate
    • generic event RNG gate
    • generic command/observation RNG gate
    • locomotion RNG gate
    • environment-owned NumPy RNG construction gate

    另发现并修正一个机械合并问题:tests/envs/mdp/test_events.py 中 _transaction_env 的 device / torch_rng 参数因 #2129 与 #2126 变更重复,删除重复项。

    RNG 终态 rehearsal commit 689a2b8c

    在七个 child 合并后的 head 上完成:

    • 删除 ManagerBasedRlEnv.rng 与其 NumPy construction;
    • seed() 只更新共享 TorchManagerRng,保持 generator identity;
    • _initial_episode_steps() 使用 TorchManagerRng.integers;
    • _types.py 删除 rng structural property;
    • TorchManagerRng 文档更新为唯一 Manager RNG;
    • test fixture Cartpole reset adapter改用 Torch RNG;
    • Isaac Cartpole reward test 显式避开 staggered timeout,避免 autoreset 后用 reset 状态重建 reward 的测试假设错误;
    • architecture gate 禁止 manager_based_rl_env.py 重新构造 environment NumPy RNG。

    当前 rehearsal head 的 strict search:

    production env.rng / _env.rng / ManagerBasedRlEnv self.rng: 0
    

    剩余 self.rng / np.random.default_rng 只在:

    • motion_loader.py cold/sampler legacy class(Phase 5 cold leaf / legacy CPU sampler边界);
    • terrain_spawn.py cold terrain curriculum owner(Phase 5 cold-path leaf)。

    它们不是 environment-owned Manager RNG。

    Rehearsal 验证

    在包含全部七个 child + RNG 终态收口的 head:

    make check                 # passed
    make test                  # 1906 passed, 42 skipped
    make test-all              # passed; coverage 1906 passed, 42 skipped;
                               # benchmark imports module 34/34, script 35/35
    uv run pytest tests/managers tests/envs tests/tasks -q --maxfail=8
                               # 580 passed, 6 skipped
    

    Review / merge 建议

  13. TATP-233 commented on Oct 10, 2026

    @TATP-233
    CollaboratorAuthor

    Rehearsal 更新:RNG 终态收口 commit 已从 689a2b8c 强化到 0e4f9e63,并重新跑完整 gate。

    新增强化:

    • _types.py 中 torch_rng 类型从 TorchManagerRng | None 收紧为 TorchManagerRng。
    • ManagerBasedRlEnv._torch_generator 不再保留可选分支。
    • CommandManager 构造时直接要求 TorchManagerRng,缺少即 fail closed;resampling 无 optional branch。
    • EventManager 构造时直接要求 TorchManagerRng;interval sampling 无 optional branch。
    • ObservationManager 构造时直接要求 TorchManagerRng,同时保留 device mismatch fail-closed。
    • test_torch_rng.py 删除 “NumPy Manager stream independent” 旧语义测试,改为确认 Torch adapter 是唯一 Manager stream;NumPy import 一并删除。
    • 相关 focused fixtures 补充 TorchManagerRng,fail-closed 测试现在断言 construction 即失败,而不是允许构造后 reset 再失败。

    0e4f9e63 strict search 仍为:

    production env.rng / _env.rng / ManagerBasedRlEnv self.rng: 0
    

    重新验证:

    make check                 # passed
    make test                  # 1906 passed, 42 skipped
    make test-all              # passed; coverage 1906 passed, 42 skipped;
                               # benchmark imports module 34/34, script 35/35
    uv run pytest tests/managers tests/envs tests/tasks -q --maxfail=8
                               # 580 passed, 6 skipped
    
  14. 152 remaining items

  15. TATP-233 commented on Oct 11, 2026

    @TATP-233
    CollaboratorAuthor

    最终集成 PR

    按 workflow 的 roadmap 规则,集成分支已完成验证并开启回到 declared base main 的最终 PR:

    • merge: Numba closeout and Torch-only tensor runtime #2273:dev/issue-2124-tensor-runtime-closeout → main
    • PR head:df91a9e8
    • 远端 main-base CI 全绿:ruff lint/format、mypy、pyright、coverage test、benchmark smoke、Sphinx docs。
    • PR 记录了 last-100 E2E 性能证据、架构 strict audit、本地 make check/test/test-all 结果,以及 PyPI 发布依赖过渡的明确边界。

    当前 #2273 只剩仓库 review policy 的 maintainer review;auto-merge 未启用,等待维护者 review 后合入。main 本身至此仍未被修改。

  16. TATP-233 commented on Oct 11, 2026

    @TATP-233
    CollaboratorAuthor

    补充:#2273 的默认 reviewer 指向了 PR 作者,GitHub 拒绝该请求;已改为请求 motion owner @caozx1110 review。CI 已全绿,main branch policy 只差 1 个 approving review。

  17. added 12 commits that reference this issue on Oct 19, 2026
    be3f9df
    bf9bcdc
    d1d01a8
    a48d2e9
    450d898
    9a079d3
    694985f
    4f8e818
    55e4519
    b1c7e58
    2428c66
    912a740
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions