NVIDIA details how MJWarp scales MuJoCo robot sims to 2,048 GPU worlds

NVIDIA has published the second entry in its 'State of Simulation for Physical AI' blog series, a technical walkthrough of moving a MuJoCo robotics simulation onto MJWarp (MuJoCo Warp), a GPU implementation of MuJoCo's physics pipeline built on NVIDIA's Warp framework. The worked example is an SO-101 follower robot arm on a table with two 44 mm cubes: the task is to grasp the red cube and stack it on the blue one. The article scales this single scene up to as many as 2,048 parallel MJWarp environments running on an NVIDIA GPU, while explicitly stopping short of training a reinforcement-learning policy on the result; that is left to later installments covering Newton and Isaac Lab.
The piece frames MJWarp's benefit precisely: it does not necessarily make one simulated world step faster, but it lets hundreds or thousands of worlds advance together in a single mjw.step call, raising aggregate throughput (total world-steps per second) rather than cutting the latency of any one world. That trade-off favors reinforcement learning and large-scale sampling, where collecting experience volume matters more than single-environment speed.
The workflow first validates the scene as an ordinary MuJoCo CPU simulation: a control loop runs at 50 fps with 10 physics substeps per control frame, giving a physics timestep of 0.002 seconds, over 600 control frames. Success is not judged by the process simply exiting cleanly; the article insists on checking two measured conditions after the cubes settle, a horizontal center error (xy_err) no greater than 0.015 m and a vertical separation (dz) between 0.035 m and 0.055 m, matching the geometry of the 44 mm cubes. Only after this CPU baseline is validated does the guide move the same model to MJWarp and batch it, with tuning advice such as capturing the repeated mjw.step kernel launches into a CUDA graph and sizing contact/constraint buffers (nconmax, naconmax, njmax) tightly rather than generously. An optional variant of the task uses a different robot profile ('reBot') with its own buffer limits of nconmax=256 and njmax=500.
The article also introduces two general Warp capabilities not used in this particular SO-101 example: differentiability, where a wp.Tape records forward kernel launches and replays their adjoints in reverse for gradient computation, and opt-in deterministic execution, added in Warp version 1.15, which trades some performance for reproducible kernel ordering since GPU atomics are scheduler-dependent by default and can otherwise make repeated runs of the same kernel differ slightly. It notes that MJWarp's compact solver relies on MuJoCo's own Newton constraint solver and its sleeping mechanism, distinct from the separate Newton physics-engine framework covered elsewhere in the series. Readers are pointed to pip-installable packages (warp-lang, mujoco-warp), a viewer tool (mjwarp-viewer) and a companion GitHub repository with the runnable code, though the article itself flags that the repository placeholder given is not yet a confirmed, executable URL and that dependency and asset versions still need to be pinned before publication.
Key facts
- The tutorial scales an SO-101 robot arm's cube pick-and-place MuJoCo scene up to 2,048 parallel MJWarp environments on GPU, without training a policy.
- Success on the stacking task is checked via two thresholds after the cubes settle: horizontal center error xy_err ≤ 0.015 m and vertical separation 0.035 m ≤ dz ≤ 0.055 m, for 44 mm cubes.
- The CPU baseline rollout runs at 50 fps with 10 physics substeps per frame (0.002 s timestep) over 600 control frames before migration to MJWarp.
- Warp supports differentiable kernels via wp.Tape and, since version 1.15, opt-in deterministic execution to counter scheduler-dependent GPU atomics.
- MJWarp's compact solver uses MuJoCo's own Newton constraint solver and sleeping mechanism, distinct from the separate Newton physics-engine framework.
Why it matters
As robotics and physical-AI teams lean on reinforcement learning and large-scale sampling to train policies, running one simulated world at a time on CPU becomes a bottleneck. MJWarp's pitch, laid out in this article, is that GPU-scale batching of thousands of near-identical worlds raises the total experience collected per second, even though any single world does not step faster in isolation. That reframes the goal of a simulation pipeline from per-step latency to aggregate throughput.
Who it affects
The guide targets robotics and machine-learning engineers building sim-to-real pipelines on MuJoCo who want to move existing CPU scenes to GPU-scale batched simulation, using NVIDIA's Warp and MJWarp stack as the bridge, ahead of policy training in tools like Isaac Lab, mjlab or MuJoCo Playground.
How to use it
Warp itself installs via pip install warp-lang (version 1.15 or later needed for GPU determinism), with examples browsable through python -m warp.examples.browse or tutorial notebooks. MJWarp installs via pip install mujoco-warp, with mjwarp-viewer for inspecting scenes and a Colab tutorial available. The full worked example, including the SO-101 pick-and-place scene and its CPU-to-MJWarp migration code, lives in a companion GitHub repository intended to be cloned and run with a Python 3.12 virtual environment and pinned requirements.
How solid is it
This is a first-party NVIDIA engineering blog, the second in a stated series, and it is detailed and methodical about setup, timestep matching and success validation. The retrieved text does not include the article's later sections, so no measured throughput or speedup numbers achieved with MJWarp are available here, only the target scale of up to 2,048 parallel environments and the methodology for getting there. The article itself also flags, before the code walkthrough, that the given repository placeholder is not yet a confirmed executable URL and that dependency and asset versions still needed pinning at the point captured.
Risks and caveats
The piece is explicit that a successful process exit alone does not prove the pick-and-place task succeeded; developers following the workflow need to check the position-based xy_err and dz thresholds themselves. It also warns that GPU atomics are scheduler-dependent by default, so repeated runs of the same kernel can produce slightly different results unless Warp's opt-in deterministic mode is used, at some cost to performance. No policy training or reinforcement-learning results are covered in this article; it is limited to preparing, validating and scaling the simulation environment.
“MJWarp's value is not necessarily a faster step for one world.”
— the article