Skip to content

Fix MuJoCo collector tensor device placement #2100

Description

@TATP-233

Summary

Split the MuJoCo-side implementation target out of #2096. MJWarp is explicitly out of scope.

Add an explicit training-level option:

training.collector_tensor_device = cpu | cuda

The default is cpu. For a MuJoCo HOST_BRIDGE runtime, automatic learner CUDA selection must not implicitly move the collector/Manager tensor carrier to CUDA. Only an explicit training.collector_tensor_device=cuda request may select accelerator carriers. A public cuda request resolves to the collector process's current/rank-local Torch CUDA ordinal; do not expose ambiguous global CUDA indices.

Problem And Evidence

#2096 identifies ae7396b3ccddb14737691929b34336f65af10e93 as the MuJoCo regression: backend capability acceptance (torch_devices=("cpu", "cuda")) was treated as a Manager placement preference. This moved the CPU-authoritative HOST_BRIDGE Manager plane to CUDA and introduced avoidable H2D/D2H transfers, GPU finite reductions, and learner/collector CUDA competition.

The direct environment path now defaults unset HOST_BRIDGE carriers to CPU, but the off-policy assembly path can still derive a CUDA carrier from automatically detected learner device selection. Therefore a field default alone is insufficient: the effective default SAC path must remain CPU even when the learner uses CUDA.

Delivered Behavior

  • Add training.collector_tensor_device with values cpu and cuda; default cpu.
  • Keep backend TensorLifecycleCapabilities.torch_devices as an acceptance inventory. Do not rename or redefine that capability as placement preference.
  • Route the explicit training selection into the existing Manager carrier placement owner field without overloading torch_devices.
  • For MuJoCo HOST_BRIDGE only:
    • default run uses CPU Manager/collector carriers and may still use a CUDA learner;
    • explicit cuda uses the current/rank-local CUDA carrier and remains fail-closed against backend capabilities and runtime availability.
  • Preserve MJWarp DEVICE_RESIDENT behavior unchanged; no MJWarp owner/config/tests are changed by this issue.
  • Avoid applying this fix broadly to Motrix, Drake, Superdex, or other backends unless independently scoped.

Acceptance Criteria

  • Default SAC MuJoCo training with an available CUDA learner records an effective CPU collector/Manager carrier, including:
    • collector_tensor_native=false
    • env_public_device=cpu
    • CPU inference transport
    • CUDA learner device where applicable
  • Explicit training.collector_tensor_device=cuda records the CUDA carrier and remains subject to backend capability validation.
  • Invalid values and unavailable CUDA requests fail closed with actionable errors.
  • Multi-process/multi-GPU routing resolves cuda after CUDA_VISIBLE_DEVICES/rank-local remapping; no global-index ambiguity is introduced.
  • The option is preserved through the pickleable EnvFactory/spawn collector path.
  • Existing MJWarp placement and tests remain unchanged.

Validation

Focused:

uv run pytest tests/envs/test_manager_based_rl_env.py -k "host_bridge or manager_tensor"
uv run pytest tests/base/backend/test_process_device.py
uv run pytest tests/scripts/test_train_scripts.py -k "collector_tensor_device or host_bridge"

Performance evidence must use the complete default SAC run from #2096, not collector-only benchmarking, and confirm tail throughput plus apply_action recover to the issue's target profile. Explicit-CUDA behavior should be smoke-checked without making it the performance default.

Final PR gate:

make check
make test
make test-all

Scope And Contracts

  • Owner layers: training config/routing, Manager env carrier placement, process-device routing, tests, and relevant docs/config schema.
  • Governing architecture decision: ADR-0012 (docs/sphinx/source/adr/ADR-0012-sole-tensor-manager-and-scoped-backends.md). Clarify the explicit request source there or in its maintained docs if needed.
  • Driving investigation: Bug: SAC G1 MuJoCo throughput regressed after automatic HOST_BRIDGE Manager CUDA placement #2096.
  • Intended PR base: main.
  • Material impact: MuJoCo training behavior, Linux/CUDA collector placement, and public training configuration.

Activity

  1. TATP-233 commented on Oct 9, 2026

    @TATP-233
    CollaboratorAuthor

    Completed by #2101 (merge cbafb507, implementation 5290ed82). Current main pins the validated behavior and records the focused/full checks plus default and explicit-CUDA SAC runs in the PR. Audit reference: collector default is CPU in src/unilab/conf/sac/config.yaml and related routing tests are present.

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

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions