Compatibility and known limitations#
Platforms and toolchain#
There is one artifact per GPU architecture. A robot
.sois compiled for thesm_XXof the GPU that registers it (orcuda_arch=); loading it on a different architecture is refused at context creation with a clear error. The model, the API and the generated code carry over between machines; the binary does not.The GPU test receipt and the release timing ran on Linux x86-64 with CUDA toolkit 13.2 and one RTX 5090 (sm_120); the table below lists that environment. CUDA 12 toolkits and other GPUs are untested. Jetson-class devices are within the design (single-block kernels, resource tiers, runtime memory fitting); the Orin ran the smoke set listed below and the Xavier the header-only example, but no receipt covers them yet.
The host compiler standard is C++17 for the code generator, benchmarks and a numpy-only build. With the
[torch]extra the wrapper reads the standard that torch’s ATen header guard demands and compiles with it. The torch we run (2.12.0, cu128) compiles with C++17. A torch that demands C++20 needs an nvcc and host compiler accepting C++20, and that path is untested here.GRID_RBD_CXX_STDforces the standard.The
[jax]/[torch]extras pin the CPU packages; install the CUDA wheel yourself. We runjax[cuda12](jax-cuda12-plugin0.10.0) and a cu128 torch wheel;jax[cuda13]and other torch wheels are untested. A CPU-only jax is refused at handle construction with that hint. See Installation for the PyPI install and its extras.
What we ran#
One machine produced every piece of GPU evidence in this release: the full
test receipt (gpu-proof.json, verified by CI), the release timing on the
release measurements page, and the
installed-wheel check of the release playbook. Everything validated ran in
fp32, the default compute precision; the fp64 tier (dtype="float64") is
an alpha feature outside the receipt.
GPU architecture |
GPU |
CUDA toolkit (nvcc) |
Driver |
Python |
torch wheel |
jax plugin |
OS |
What ran |
Date |
|---|---|---|---|---|---|---|---|---|---|
sm_120 (compute capability 12.0) |
NVIDIA GeForce RTX 5090, 32 GB |
13.2 (V13.2.86) |
615.71.09 |
CPython 3.12.3 |
2.12.0.dev20260408+cu128 (CUDA 12.8 runtime) |
jax 0.10.0 with jax-cuda12-plugin 0.10.0 |
Ubuntu 24.04.5, Linux 7.0.0-38, x86-64 |
full receipt; release timing; install check (a fresh venv with torch 2.11.0+cu128 and jax 0.11.2 from PyPI) |
receipt 2026-10-15; timing 2026-09-27 to 2026-10-07; install check 2026-10-15 |
sm_87 (compute capability 8.7) |
NVIDIA Jetson AGX Orin, 64 GB |
13.2 (V13.2.78) |
L4T R39.2 (JetPack; driver API 13.2) |
CPython 3.12.3 |
2.14.0+cu130 (NVIDIA Jetson build) |
jax 0.11.1 (NVIDIA Jetson build) |
Ubuntu 24.04.4, Linux 6.8.12-tegra, aarch64 |
smoke runs on the 0.5.1 main checkout, no receipt: the iiwa14 numpy, torch and jax wrappers (30, 25 and 60 tests), the CUDA equivalence harness on iiwa14 fixed and go2 floating (72 tests), the g1 plant Hessian; pinocchio 3.9.0 and mujoco 3.9.0 from PyPI aarch64 wheels |
2026-10-16 |
sm_72 (compute capability 7.2) |
NVIDIA Jetson AGX Xavier, 32 GB |
11.4 (V11.4.315) |
L4T R35.3.1 (JetPack 5) |
CPython 3.8.10 and 3.9 only; grid-rbd needs 3.10 |
not applicable |
not applicable |
Ubuntu 20.04, Linux 5.10.104-tegra, aarch64 |
header-only CUDA: the fused control step example, built against an iiwa14 header generated on the x86-64 machine, compiled with nvcc 11.4 for sm_72 and validated fused against layered; the generator, the bindings and the test suite do not install on this Python |
2026-10-16 |
The toolkit and the framework wheels are separate things. nvcc 13.2
compiles the generated kernels and the per-robot .so. The torch wheel
carries its own CUDA 12.8 runtime libraries for torch’s kernels, and the
jax-cuda12-plugin carries CUDA 12 runtime libraries for XLA; neither uses
nvcc. The driver has to satisfy every runtime in the process, and
615.71.09 does. A jax[cuda13] plugin, a torch wheel other than cu128, a
CUDA 12 toolkit and CPython 3.10, 3.11 or 3.13 on a GPU are untested; the CI
wheel builds for CPython 3.10, 3.11 and 3.13 and the CPU test lane on 3.10 and
3.13 run on CPU only. The Jetson rows record smoke runs, not receipts. The
Orin receipt is recorded under receipts/ once the per-architecture receipt
table is on main; the Xavier stays header-only because JetPack 5 ships CUDA
11.4 and Python 3.8, below the floors of the generator and the bindings.
Runtime contexts#
Every native call resolves a runtime context by id; handle.context()
opens an isolated one (own arena, tables, streams, launch overrides) and a
handle is the one owner of its context. Runtime-parameter mutations give the
context a new model_version, and torch/JAX backwards refuse a forward that
ran under a different version. Concurrent asynchronous calls on one context
share its scratch buffers, so each context carries one ordered pipeline; use a
context per pipeline, as execution is not fully asynchronous. Ownership,
workspace_slots, versioning and the synchronisation points are specified in
Runtime contexts.
Captured CUDA graphs (torch)#
handle.capture(...)replays only on its context at the captured model epoch: a replay after a mutation is refused (recapture) and a replay after the context was closed is refused (never a launch into freed memory). Replays of one graph are serialized;static_outis overwritten by the next replay.Capturing a backward is unsupported. Do not mix graph replay and concurrent eager calls on the same context.
Operands#
One rule set per operand class is enforced natively on all three surfaces
(1 <= B <= max_batch, exact last dim, every operand carrying the leading
batch). Configuration inputs have width nq; velocities, accelerations and
generalized forces have width nv, and floating and spherical quaternions
make these widths different. What each surface coerces, refuses or elides is
specified in Operand validation; layouts are in
Input / Output ABI (h_q_qd_u).
Native interface stability#
The generated
grid.cuhkeeps its inline entry points (init_gridData_checkedgained an optional trailing allocator-pool argument; the pool-less allocator spellings remain).The per-robot wrapper
.so’sextern "C" grid_rbd_*symbols are private to the package: they are consumed only by the pybind core of the same content-keyed build and gained a leadingctx_idin 0.5.0, the first packaged release. Do not link against them directly.
Differentiation#
First-order autograd (torch
backward,jax.grad/vjp) runs the analytic gradient kernels; higher-order differentiation through those kernels is not provided.*_wrt_paramsis the local sensitivity of the compiled model to its inertial parameters (a parameters argument does not install a new runtime model).Second-order tensors are values (
idsva_so/fdsva_so), not autograd-composable operators. Per-method and per-joint-type restrictions are collected on Python backend interfaces.
Build cost#
A full-feature humanoid build is expensive (see the cold/warm table on the fast-robot-setup page); subset builds (
algorithm_list=,enable_mujoco_kernels=False) are the practical path when compile time or memory matters. Generated-source portability is not binary portability.
Sanitizer diagnostics with JAX#
Running a process that initializes the JAX CUDA backend under NVIDIA Compute Sanitizer reports one CUDA API warning during JAX’s device-allocator query (
cuDeviceGetAttribute: fabric handle support requires IMEX channels) and, for a standalone JAX reduction, a selective device-code recompilation notice. Both come from JAX 0.11 and the CUDA 13 toolchain and reproduce in a process that imports no GRiD; the numerical results are correct and the NumPy and PyTorch surfaces pass the same sanitizer with zero errors. We record this as an accepted limitation of the combined sanitizer invocation rather than a defect of the wrapper: the sanitizer exit code of a JAX-initialized process is nonzero, and the release checks state it so instead of suppressing the warning.