Repository navigation
roadmap: macOS tensor runtime for MuJoCo/mjbatch off-policy training #2055
Description
Activity
Progress update (macOS bring-up complete, acceptance run in flight)
Root cause of the first macOS failure
flashsac + g1_motion_tracking --sim mujocofailed at the first autoreset with
RuntimeError: ManagerBased tensor reset-state mutation requires an active reset
(TensorMotionCommand._resample_command→write_motion_state_tensor_to_sim).Diagnosis: the env-side reset dispatch in
ManagerBasedRlEnv.resetonly opens a
tensor transaction through the packed host bridge when
ResetStateTransaction.can_commit_packed()is true. That probe duck-types
SimBackend.get_public_state_widths(), which did not exist at the sibling
commits pinned bytensor_runtime_workspace.json(unisim09d5caed). The
contract exists at thedevelop/tensor-runtimebranch tips (unisim
5e835923,PublicStateWidths+ mujoco/genesis/mjwarp implementations; the
mujoco host plan'sapply_resetalready validates(rows, nq=36)/(rows, nv=35)
parity with the Manager layout). The stale pins also predated unilab-rl
single-device/inference-transport fixes (1d83704,e5b3488).Base realignment (recorded decision)
Sibling integration branches are based on the
develop/tensor-runtimebranch
tips, not the stale manifest pins; the manifest was updated on the UniLab
integration branch (commitd2950202). This matches UniLab HEAD's own test
expectations (tests/envs/test_env_configs.pycalls
backend.get_public_state_widths()), so the pins were stale relative to the
declared base branch. Bases now:- unisim
5e835923(= tip), unilab-rl036fcba6(= tip), mjbatch-unib3a3b480(= tip == main, unchanged) - UniLab
dev/issue-2055-macos-tensor-runtimefromdevelop/tensor-runtime(90068b82)
With this,
can_commit_packed() == Truefor the mujoco G1 owners and the reset
dispatch takesscoped_device_event_tensor_with_host_commit— no UniLab
runtime code change was needed for the training path itself.Training evidence (macOS arm64, torch 2.14.0, MPS learner, CPU physics)
Run Result uv run train --algo sac --task g1_walk_flat --sim mujoco algo.max_iterations=100completed 100/100, 225,280 steps, ~18.2k steps/s, normal_completion, collector exit 0, cleanup errors[]uv run train --algo flashsac --task g1_motion_tracking --sim mujoco algo.max_iterations=100completed 100/100, 405,504 steps, normal_completion, collector exit 0run_summary.jsonconfirmsenv_public_device=cpu,learner_device=mps,
cuda_context_initialized=false,tensor_native_env=true,
cuda_graph.backend=eager(correctly inert off CUDA),metric_schema_version=1.
No residual collector processes after either run. SAC re-run after the base
change: same green result.Gates on the integration head
make check: pass (ruff, mypy 144 files, pyright 0 errors).make test(non-slow): 1801 passed, 59 skipped — was 1724 passed /
62 failed / 18 errors before the test-layer fixes (commitf2fb4519):- the fake-runtime/mock-worker CUDA-only backend suites
(genesis/isaacgym/isaacsim/fixed-variants) now bypass the factory
platform gate (which has dedicated coverage in
test_cuda_backend_platform_preflight.py), restoring 58 failed + 18
errored tests on all CUDA-less hosts; - targeted skips: CUDA observation naming test, mjwarp-extra soak command
test, Linux-/procsoak resource test; dropped the never-committed
outputs/velb_compare/micro_velb.pybenchmark-scope entry.
- the fake-runtime/mock-worker CUDA-only backend suites
- Focused slow lane:
test_env_configs.py -k mujoco5 passed (now includes a
new selected-row reset regression case through the packed host-bridge tensor
command commit, commitb6c293fe), G1 owner contract 17 passed / 4 skipped
(newton cases now skip off-CUDA), flashsac owner contract 10 passed.
Acceptance
Full-budget
sac + g1_walk_flat --sim mujoco(owner default
algo.max_iterations=5000) is running unattended with
training.play_render_mode=record(avoids the interactive mjpython viewer;
playback + ONNX export still exercised). Result follows.- unisim
Acceptance complete — roadmap delivered on the integration head
Full-budget acceptance run on macOS arm64 (torch 2.14.0, CPU physics + MPS learner):
uv run train --algo sac --task g1_walk_flat --sim mujoco training.play_render_mode=record- 5000/5000 iterations, 10,260,480 env steps in 11.8 min (~14,305 steps/s,
457,760 replay rows/s) —normal_completion, collectorexitcode 0,
cleanup errors[], no residual processes. - Learned gait: final mean reward 278.98, best 303.60, mean
episode length 946.85 (from ~49 at init). - Post-train play on the final checkpoint: ONNX export verified
(max_diff 7.84e-07), 800-frame playback video rendered
(play_render_mode=recordto avoid the interactive mjpython viewer in an
unattended run; playback + export paths fully exercised). run_summary.json:env_public_device=cpu,learner_device=mps,
cuda_context_initialized=false,cuda_graph.backend=eager,
metric_schema_version=1.
Pre-PR gate on the integration head:
make test-allpass (check + coverage
lane + benchmark smoke 35/35, 36/36).PR: #2061 (
dev/issue-2055-macos-tensor-runtime→develop/tensor-runtime).
Sibling repos (unisim, unilab_rl, mjbatch_uni) required zero code changes —
their integration branches track thedevelop/tensor-runtimetips recorded in
the updatedtensor_runtime_workspace.json. All acceptance criteria checked.
Remote CI will run when the PR tomainis opened later (per workflow, local
results + review are the gate for a non-mainbase).- 5000/5000 iterations, 10,260,480 env steps in 11.8 min (~14,305 steps/s,
Summary
g1_walk_flatand FlashSAC +g1_motion_tracking. Final acceptance is one full SACg1_walk_flattraining run on macOS.dev/issue-<N>-macos-tensor-runtime) based ondevelop/tensor-runtime(siblings based on thetensor_runtime_workspace.jsonpins); materialize the workspace; fix macOS breakages in the owner layers behind device/platform gates; iterate withalgo.max_iterations=100smoke trainings; finish with the repo gate and the full acceptance run.mainordevelop/tensor-runtimemutation in any repo, no PyPI publication, no CUDA performance/runnability regression, no training-semantics change. Multi-GPU DP stays CUDA-only. No macOS CI job is added (follow-up candidate).uni_rlowns learners/collectors/replay/IPC; unisim owns the SimBackend tensor contract and the mujoco adapter; mjbatch_uni owns the CPU batch executor.require_offpolicy_replay_deviceacceptscuda|mpsonly); a pure-CPU off-policy learner is out of scope; (2) sibling bases are the workspace manifest pins, not branch tips; (3) macOS CI coverage deferred.Repository evidence
develop/tensor-runtime(90068b8) completed the npenv→torchenv switch; the old NpEnv runtime and the tensor-runtime switch are removed (ae851eb4,759153cd).HOST_BRIDGEbackend: the Manager env is CPU-tensor authoritative by design on every platform (src/unilab/envs/manager_based_rl_env.py:372-377); unisim declaresmacos_tensor_profile = "CPU-authoritative host bridge only"for mujoco (unisim/support.py, tensor-runtime branch).get_default_device()resolves cuda → xpu → mps → cpu (src/unilab/utils/device.py:17-25); uni_rl implements an MPS replay pipeline and MPS fused optimizers, tested on CPU-only torch builds..so, live 4-sim CPUBatch.step());cpu_idsaffinity is Linux-only there.mainlack the tensor-runtime API (HostBridgeTransferPlanet al.), sounilab.base.torch_envfails to import; the workspace manifest pinsdevelop/tensor-runtimecommits (unisim09d5caed, unilab-rl75680c23, mjbatch-unib3a3b480).slowlane.Scope
Included:
uv sync, import gates green.algo.max_iterations=100):uv run train --algo sac --task g1_walk_flat --sim mujocouv run train --algo flashsac --task g1_motion_tracking --sim mujocomake check,make test, focused slow contract tests for the two tasks;make test-allbefore the final PR.g1_walk_flat--sim mujoco training run on macOS (owner YAML defaultalgo.max_iterations), normal shutdown, metrics/logs inspected.Explicitly excluded: pure-CPU off-policy learner device, multi-GPU on macOS, new public contracts, new ADRs unless a structural decision emerges, macOS CI jobs, PyPI publication,
main/develop/tensor-runtimemutation.Acceptance criteria
import unilab.base.torch_envand backend construction succeed on macOS with the workspace materialized.g1_walk_flat--sim mujoco trains on macOS (CPU physics, MPS learner) foralgo.max_iterations=100with normal shutdown and expected metric schema.g1_motion_tracking--sim mujoco trains on macOS foralgo.max_iterations=100with normal shutdown.make check,make test, and focused slow tests for the two tasks pass on the integration head.g1_walk_flat--sim mujoco training completes on macOS (default iteration budget, normal shutdown, collector exit 0, no residual processes).main, ordevelop/tensor-runtime.Governance
Declared base:
develop/tensor-runtime(UniLab) and thetensor_runtime_workspace.jsonsibling pins. Integration branch per repo:dev/issue-<N>-macos-tensor-runtime. No PyPI release. Related: #1706 (NpEnv removal), #2052 (Newton canonical tensor runtime), tensor-runtime sibling dependency transition policy in5-contributing_workflow.md.