Repository navigation
roadmap: restore Motrix as a tensor-only Manager HOST_BRIDGE backend for canonical G1 training #2054
Description
Activity
Phase 0 integration branch created:
dev/issue-2054-motrix-tensor-runtimefromdevelop/tensor-runtime@90068b82.- added a commit that references this issue
on Oct 4, 2026 Phase 0 complete; Phase 1 public-width contract merged.
Integration branch:
dev/issue-2054-motrix-tensor-runtime.Phase 0 audit conclusions
- Motrix is blocked at UniLab registry/CLI/owner layer.
- unisim already has a usable packed HOST_BRIDGE lifecycle:
- one packed control D2H;
- one packed selected-reset D2H;
- one packed full state/sensor H2D;
- one packed post-reset selected-row H2D.
- Existing unisim tests cover transfer counts, row preservation, bounded validation, and no hidden CUDA→CPU detours.
- Historical Motrix owners are not restorable:
- SAC owner predates the fused tensor reward/reset owners and retunes rewards;
- FlashSAC owner was a sim2sim eval owner, not canonical training;
- the old task-owned host-bridge runtime violates current governance.
- Main performance gaps are backend-internal, not task-layer:
- selected reset is a multi-call host transaction, not a compiled selected-row write;
- selected read computes full state/body/sensor sources before selecting rows;
- reset/read plans may duplicate ownership and buffers.
- MotrixLab is useful as an implementation reference for compiled selected-row write/query programs, but its direct/NumPy manager architecture must not enter UniLab.
Phase 1 merged
unisim PR #339 →
roadmap/issue-1811-tensor-manager, mergecbcb3c6.Adds:
MotrixBackend.get_public_state_widths() -> PublicStateWidths(nq, nv)
and proves public widths match public state layout and packed reset validation.
All remote CI passed:
- Python 3.10 Linux/macOS/Windows
- mypy + pyright
- source distribution
The selected-reset publication boundary remains explicitly paired commit + selected H2D read; Motrix does not falsely declare
AUTHORITATIVE_VIEWS.Current heads
Repo Branch Commit UniLab dev/issue-2054-motrix-tensor-runtime90068b82unisim roadmap/issue-1811-tensor-managercbcb3c6Next: Phase 2 boundary baseline and A/B attribution on the canonical G1 scenes.
- added a commit that references this issue
on Oct 4, 2026 Phase 2 Path C merged: selected packed publication no longer computes unselected rows.
unisim PR #340 →
roadmap/issue-1811-tensor-manager, mergebc61643.Before:
- selected publication assembled full public qpos/qvel;
- then full tracked-body state;
- then full native sensor batches;
- only afterwards selected reset rows.
After:
- selected qpos/qvel assembled for reset rows only;
- selected tracked-body state uses a new fused selected-row/selected-link read;
- native sensors use the existing row-local API;
- the same stable selected host/device packet and one H2D scatter remain.
Transfer counts and stable views are unchanged. This is a host-boundary compute reduction, not an additional or hidden transfer.
New contract tests:
- full-batch
get_state/get_body_state_ware rejected during selected publication; - selected world-frame body aliases match authoritative full world reads after reset.
Remote CI: Linux/macOS/Windows Python 3.10, type checks, and source distribution all passed.
Current unisim head:
bc61643.Phase 2 boundary attribution on canonical G1 flat scene (2048 envs).
Local diagnostic measurements after unisim #339/#340. Values are mean over 30 iterations after 5 warmups, unless noted.
Selected packed reset + selected publication
Rows MuJoCo/mjbatch Motrix Motrix / MuJoCo 1 0.495 ms 0.668 ms 74% 128 (1/16 batch) 1.028 ms 1.017 ms 101% 2048 9.360 ms 3.530 ms 265% At the canonical 1/16 reset cadence, Motrix selected reset/publication is already at parity with mjbatch. Full-batch reset is faster on Motrix, while sparse resets are comparable.
Control + 3 physics substeps + one packed full read
Backend Mean Median MuJoCo/mjbatch 13.979 ms 13.885 ms Motrix 26.177 ms 25.876 ms Ratio: 53.4% of MuJoCo/mjbatch.
This cycle dominates every control step, while selected reset/publication is a small phase at the 1/16 cadence. Therefore the remaining Motrix gap is primarily in MotrixSim CPU physics/native full-read work, not D2H/H2D or selected reset orchestration.
Host reset sub-attribution (Motrix, 2048 envs, 128 reset rows)
Mean selected
set_statewall time: 0.346 ms.Largest sub-phases:
Sub-phase Mean native data slice 0.129 ms native selected data reset 0.064 ms forward kinematics 0.050 ms link pose cache refresh 0.036 ms actuator control hold 0.021 ms dof position write 0.016 ms dof velocity write 0.015 ms qpos conversion 0.007 ms mask 0.002 ms Interpretation
- Selected read optimization (docs: add FlashSAC to support matrix and algorithms doc #340) removed full-batch host computation from selected publication.
- Reset orchestration is not the dominant cost at canonical cadence.
- The 46.6% cycle gap is concentrated in the control-step/full-read path:
- MotrixSim native 3-substep CPU physics;
- full state/sensor assembly and the packed H2D boundary.
- A compiled reset transaction would target a phase already around 1 ms per canonical reset cycle and is therefore lower priority than control-step/full-read work.
Next
- Instrument the Motrix control/full-read cycle into
write_control, nativestep_n, state/sensor pack, and H2D. - Determine whether full read duplicates native state/sensor reads already performed by MotrixSim and eliminate only proven duplication.
- If the remaining cost is native MotrixSim physics, record that boundary and proceed to UniLab owner enablement; do not trade contract strength for speculative host optimization.
Phase 2 control-cycle attribution refinement.
The same canonical G1 flat scene, 2048 envs, three physics substeps, and one packed full read were decomposed after the aggregate measurement.
Motrix
Phase Mean Median packed control D2H 0.046 ms 0.044 ms control submission to native data 0.068 ms 0.063 ms MotrixSim step_n(..., 3)24.787 ms 24.335 ms link pose refresh + velocity invalidation 0.111 ms 0.112 ms state/sensor host pack 0.742 ms 0.657 ms packed H2D 0.060 ms 0.052 ms MuJoCo/mjbatch comparable boundary
Phase Mean Median packed control D2H 0.044 ms 0.041 ms backend step + native bridge 13.799 ms 13.726 ms packed full read 0.129 ms 0.110 ms Conclusion
Transfer boundaries are already negligible:
- Motrix control D2H: ~0.046 ms
- Motrix packed full H2D: ~0.060 ms
The aggregate Motrix/MuJoCo ratio of ~53.4% is overwhelmingly explained by native MotrixSim CPU physics: ~24.8 ms vs the complete MuJoCo backend step boundary of ~13.8 ms. Python orchestration and explicit D2H/H2D account for under 1 ms.
The remaining host-pack cost is ~0.74 ms. It is the only non-native optimization candidate, and even eliminating it entirely would change the ratio by roughly 2%, below the measured native physics gap.
Boundary decision: continue contract-first UniLab owner enablement rather than speculative host rewrite. Further Motrix throughput work belongs primarily in MotrixSim native physics, not the packed HOST_BRIDGE contract.
- added a commit that references this issue
on Oct 4, 2026 Phase 3 complete: canonical Motrix owners merged.
PR #2056 →
dev/issue-2054-motrix-tensor-runtime, merge60ab8473.Enabled surface
Exactly two canonical workloads:
uv run --extra motrix train --algo sac --task g1_walk_flat --sim motrix uv run --extra motrix train --algo flashsac --task g1_motion_tracking --sim motrix
Other Motrix owners remain out of scope and stay
Registered, not production claims.Owner decisions
- Active tensor Manager scope now includes Motrix alongside MuJoCo/MJWarp/Genesis/Newton.
- CLI fails closed when
motrixsimis absent. - Both factories use the current generic Manager-Based runtime.
- SAC walk owner:
- tensor reset events;
G1WalkResetOwner;- fused walk reward pack;
- fused termination pack;
events.pd_gains: null.
- FlashSAC motion owner:
TensorMotionCommandCfg;MotionResetOwnerowning command/action/observation/metric reset;- no unsupported reset randomization.
- Neither owner uses fixed variants.
- Packed HOST_BRIDGE reset selection now recognizes event-manager tensor terms, enabling
scoped_device_event_tensor_with_host_commitfor tensor reset events.
Validation
make check: pass.- Focused registry/CLI/config/support/benchmark tests: pass.
- Real CUDA Manager rollouts:
- SAC walk: finite 5-step rollout; obs/critic 98/101.
- FlashSAC motion: finite 3-step rollout; obs/critic 160/289.
- End-to-end 256-env × 3-iteration smokes:
- SAC walk: completed, normal shutdown, collector exit 0, finite rewards.
- FlashSAC motion: completed, normal shutdown, collector exit 0, finite rewards.
- No residual training/Motrix process.
- No direct mode, generic NumPy Manager, NumPy RNG owner, tensor-runtime switch, hidden reset composer, or backend-private task probing.
Current heads
Repo Branch Commit UniLab dev/issue-2054-motrix-tensor-runtime60ab8473unisim roadmap/issue-1811-tensor-managerbc61643Next: Phase 4 local 160×2048 ×3 interleaved throughput gate against MuJoCo/mjbatch.
Phase 4 first measured baseline.
Both Motrix runs completed 160/160 at 2048 envs on the local workstation, with no play/ONNX. MuJoCo/mjbatch reference runs used the same shape and measurement contract.
Workload Backend Status Iter Tail steps/s Tail window Shutdown Collector Ratio SAC / g1_walk_flatMotrix completed 160/160 61,117.173 20 normal_completion exit 0 64.76% SAC / g1_walk_flatMuJoCo/mjbatch completed 160/160 94,377.964 20 normal_completion exit 0 — FlashSAC / g1_motion_trackingMotrix completed 160/160 56,626.750 20 normal_completion exit 0 64.63% FlashSAC / g1_motion_trackingMuJoCo/mjbatch completed 160/160 87,622.321 20 normal_completion exit 0 — No residual training/Motrix process remained after the runs.
Both Motrix workloads exceed the initial 35% floor and the 50% optimization target, and nearly reach the 60% stretch gate. This is consistent with the Phase 2 attribution: explicit D2H/H2D is ~0.1 ms/control step, while the remaining gap is dominated by MotrixSim native
step_nCPU physics.Final acceptance still requires three interleaved Motrix runs per workload, reporting every run. The MuJoCo references will also be interleaved with those acceptance runs.
Phase 4 interleaved acceptance evidence (3 Motrix runs per workload, MuJoCo/mjbatch references interleaved).
Interleaved order for each of rounds 1–3: SAC Motrix → SAC MuJoCo → FlashSAC Motrix → FlashSAC MuJoCo.
Every run: 160×2048, no play/ONNX,tail_iteration_count=20, normal shutdown, collector exit 0.SAC /
g1_walk_flatBackend Run Tail steps/s Motrix 2026-10-04_14-21-50_motrix61,117.173 Motrix 2026-10-04_14-25-15_motrix63,204.377 Motrix 2026-10-04_14-26-33_motrix63,328.873 MuJoCo 2026-10-04_14-23-25_mujoco94,377.964 MuJoCo 2026-10-04_14-25-34_mujoco94,445.013 MuJoCo 2026-10-04_14-26-53_mujoco90,992.450 Motrix min/median/max: 61,117.173 / 63,204.377 / 63,328.873
MuJoCo min/median/max: 90,992.450 / 94,377.964 / 94,445.013
Worst-run ratio: 67.17%FlashSAC /
g1_motion_trackingBackend Run Tail steps/s Motrix 2026-10-04_14-22-36_motrix56,626.750 Motrix 2026-10-04_14-25-50_motrix55,490.442 Motrix 2026-10-04_14-27-09_motrix56,342.518 MuJoCo 2026-10-04_14-23-54_mujoco87,622.321 MuJoCo 2026-10-04_14-26-14_mujoco87,084.407 MuJoCo 2026-10-04_14-27-32_mujoco90,448.674 Motrix min/median/max: 55,490.442 / 56,342.518 / 56,626.750
MuJoCo min/median/max: 87,084.407 / 87,622.321 / 90,448.674
Worst-run ratio: 63.72%Gate result
Gate SAC walk FlashSAC motion ≥35% MuJoCo initial gate pass pass ≥50% optimization target pass pass ≥60% stretch pass pass All runs completed 160/160 with finite training state and no residual collector/Motrix process after the sequence.
Phase 2 attribution remains controlling: explicit D2H/H2D is approximately 0.1 ms/control step, selected reset is at parity at the canonical 1/16 cadence, and the remaining gap is dominated by MotrixSim native
step_nCPU physics. No contract weakening or speculative host rewrite is warranted.Phase 5 closeout validation and integration state.
Final integration head:
dev/issue-2054-motrix-tensor-runtime@44207bfd.Commands and outcomes:
make check— pass.make test— 1,863 passed / 20 skipped / 0 failed.make test-all— pass, including benchmark import smoke (35/35 module mode, 36/36 script mode).- Focused slow canonical contract gate — 129 passed / 8 skipped.
- The initial slow run exposed three stale test expectations from before Motrix enablement:
- Motrix must be present in the FlashSAC Manager registry;
- the tensor reset-event assertion applies to the Motrix owner, not MuJoCo owners;
- non-canonical Motrix support cells are
MISSINGrather than absent from the generated matrix.
- Those corrections were merged in test(motrix): align flashsac owner scope with canonical runtime #2057, test(motrix): scope tensor event assertion to Motrix owner #2058, and test(support): allow absent Motrix support cells #2059, then the final validation above was rerun with MuJoCo/MJWarp/Motrix/Newton extras installed.
Merged UniLab PRs on the integration branch:
- feat(motrix): restore canonical packed host-bridge owners #2056
feat(motrix): restore canonical packed host-bridge owners→60ab8473 - test(motrix): align flashsac owner scope with canonical runtime #2057
test(motrix): align flashsac owner scope with canonical runtime→1a468e0d - test(motrix): scope tensor event assertion to Motrix owner #2058
test(motrix): scope tensor event assertion to Motrix owner→84cb0bcb - test(support): allow absent Motrix support cells #2059
test(support): allow absent Motrix support cells→44207bfd
No
mainmutation and no PyPI release.- added a commit that references this issue
on Oct 4, 2026 - added a commit that references this issue
on Oct 8, 2026
Roadmap: restore Motrix as a tensor-only Manager HOST_BRIDGE backend for canonical G1 training
Follow-up to #2045 and #2048 with the same governance and acceptance discipline. The enabled physics backend is Motrix; the reference runtime boundary is MuJoCo/mjbatch. Other shelved adapters remain out of scope.
Goal
Restore Motrix as an active tensor-only Manager-Based HOST_BRIDGE backend for exactly two canonical training workloads:
g1_walk_flat/ Motrixg1_motion_tracking/ MotrixMotrixSim remains CPU-authoritative. This roadmap does not attempt to make it DEVICE_RESIDENT. The D2H/H2D host bridge is a legitimate public boundary, but every semantic crossing must be explicit, packed, countable, and bounded.
Development and validation occur on the local workstation. Server deployment is out of scope.
Development governance (non-negotiable)
env.tensor_runtime/env.tensor_runtime_device.unisim.backend.base.SimBackendAPIs/capabilities.main; do not publish PyPI artifacts.run_summary.json:tail_env_steps_per_secremains decisive.Current audit
Runtime scope
Current active tensor Manager scope:
Motrix remains shelved:
Evidence:
src/unilab/base/registry.pykeepsmotrixin_SHELVED_SIM_BACKENDS.src/unilab/cli.pykeeps Motrix out ofSUPPORTED_SIMS.register_env(..., sim_backend="motrix")currently fails closed.--sim motrixis rejected before dependency detection.Task registration and owners
No canonical Motrix factory is registered:
G1WalkFlat:mujoco,mjwarp,genesis,newtonG1MotionTrackingSAC:mujoco,mjwarp,genesis,newtonNo Motrix owner YAML exists under
src/unilab/conf.The historical owners removed in
402aed69are not directly restorable:Local runtime
After
uv sync --extra motrix:Focused existing Motrix backend smokes pass, including construction, stepping, state reads, body state, and quaternion convention. Existing unisim packed host-bridge adapter tests pass.
Existing public tensor lifecycle
The unisim Motrix backend already declares:
Public APIs already present:
compile_host_bridge_iostep_tensorset_state_tensorget_state_viewsget_sensor_viewget_tensor_capabilitiesThe packed plan already owns stable host/device buffers and semantic transfer counters:
Existing adapter coverage proves selected-row preservation, bounded validation, no hidden CUDA-to-CPU detours, portable parity, and fail-closed fixed variants/randomization.
Gap 1 — Public state-width contract
Motrix does not implement
get_public_state_widths():PublicStateWidths(nq, nv).This must be repaired in unisim before owner enablement.
Gap 2 — Selected-reset publication semantics
MuJoCo/mjbatch declares:
Motrix cannot truthfully declare that today because:
set_state_tensorcommits selected rows through the CPU bridge;Do not add a false capability declaration. The initial owner must preserve the paired reset/read boundary. A stronger public reset transaction/readiness declaration is optional follow-up work and requires its own contract tests.
Gap 3 — Selected reset host commit is not a compiled transaction
The non-portable Motrix
set_statepath currently:The portable path uses disjoint indices but still makes multiple native calls rather than one compiled selected-row reset program.
MotrixLab provides a public reference pattern:
The equivalent semantics must live inside the unisim Motrix host boundary; UniLab must not call MotrixLab APIs directly.
Gap 4 — Selected read computes full-batch sources
Current selected packed reads:
This preserves semantics but can dominate motion tracking with many tracked bodies. MotrixLab's compiled query program supports selected-row execution and stable views:
The backend should adopt the same public-shaped pattern internally without leaking MotrixLab manager architecture into UniLab.
Gap 5 — Reset randomization and fixed variants
Motrix tensor reset rejects randomization. The canonical SAC base still declares
pd_gains; the owner must explicitly set it tonull. Fixed variants must remain absent. Any future packed randomization payload is a separate unisim public contract, not a host fallback.Gap 6 — Canonical owner tests and support evidence
Existing tests cover the adapter boundary, not canonical Manager training. Needed:
Gap 7 — Diagnostic benchmark scope
The G1 FlashSAC backend benchmark currently rejects Motrix as shelved. It should accept Motrix as diagnostic-only and report boundary timing/counters. End-to-end training remains decisive.
Reference implementation boundary
/home/user/ws/simulator/MotrixLabis useful evidence for:It must not be imported by UniLab task/runtime code. Its direct/NumPy manager architecture is not a governance model for this roadmap.
Proposed phases
Phase 0 — Contract and boundary baseline
develop/tensor-runtime.Exit: every canonical requirement maps to an existing public API or a concrete unisim gap.
Phase 1 — Public unisim contract parity
Minimum changes:
get_public_state_widths().AUTHORITATIVE_VIEWS.Exit: canonical reset composition no longer depends on backend-private state-shape inference.
Phase 2 — HOST_BRIDGE optimization
Maintain the existing path as the A/B baseline.
Then optimize only where evidence attributes cost:
Acceptance for every optimization:
Phase 3 — UniLab canonical owner enablement
Only after Phase 1:
motrixsimdependency diagnostics.g1_walk_flat/motrix.yamlg1_motion_tracking/motrix.yamlpd_gains.Exit: both canonical train commands construct, reset, train, and shut down normally through Manager-Based API only.
Phase 4 — Local performance convergence
Commands:
Reference:
Measure:
At least three interleaved runs per workload; report every run.
Initial gates, subject to the first honest Phase 4 baseline:
g1_walk_flatg1_motion_trackingOptimization target: ≥50%. Stretch: ≥60%.
Motrix is not required to match mjbatch exactly, but acceptance requires attribution showing that the remaining gap is dominated by MotrixSim native CPU physics rather than avoidable Python, reset, selected-read, or transfer-boundary work. If the first baseline materially exceeds the initial gate, raise the floor before optimization.
Every run must:
tail_iteration_count=20;Phase 5 — Closeout
make checkmake testmake test-alldevelop/tensor-runtime;Explicit non-goals
tensor_runtimeswitches.