Backends and devices
Radar runs propagation and synthesis in one native CUDA library and processing in PyTorch. What runs where, the device rules, and memory use.
Radar has one compute backend for simulation: a native CUDA library, _radar_native, that ships inside the wheel. PyTorch does the rest. This page explains what runs where, how the device is chosen, and what costs memory.
What runs where#
| Work | Runs in |
|---|---|
| One-way propagation (line of sight, reflections) | Channel's native CUDA kernels |
| Round-trip composition, scattering, antenna pattern weights | Radar, on the GPU |
| FMCW, OFDM and pulsed synthesis, and their VJP and JVP | Radar's native CUDA library |
| Receiver chain (noise, LNA, AGC, ADC) | Native CUDA for noise and LNA, PyTorch for the other stages |
Signal processing (witwin.radar.processing) | PyTorch, including torch.fft |
| Session orchestration, validation, scene authoring | Python and PyTorch |
The installed package never compiles CUDA code at run time, and there is no pure-PyTorch fallback for synthesis. If the native library cannot load, or was built for a different PyTorch version, CUDA version or platform, Radar raises an error instead of running a slower path.
The device#
Radar(device="cuda") is the default. The radar's device is where its antenna positions live and where target tensors and cubes are created.
- If you ask for CUDA and
torch.cuda.is_available()is false, construction raisesRuntimeError. Passdevice="cpu"explicitly to build a radar on a machine without a GPU. - A CPU radar can be constructed, configured and inspected, and the processing functions run on CPU tensors.
trace,simulateandstreamneed CUDA. radar.to(device)returns a copy on another device.
Targets do not carry a device: the radar supplies its own when the session starts. A position tensor you pass in PointTargets keeps its own device, so create it on radar.device.
Exact runtime identity#
The native library is compiled against one PyTorch and CUDA version. Release 0.4.1 needs PyTorch 2.10.0 with CUDA 12.8 exactly. A library whose recorded PyTorch version, CUDA version, C++ ABI or platform differs from the running one is refused at load time instead of risking a silent ABI mismatch. witwin.radar.deployment.require_supported_runtime() checks all of this; see Installation.
The library is compiled for compute capability 7.0 to 12.0 (see the list on the installation page), with PTX for 12.0 for forward compatibility. Release testing ran on compute capability 12.0 (RTX 50 series).
Memory#
GPU memory depends mostly on how many times the world is evaluated per frame and how many paths each evaluation has.
simulatekeeps every frame's cube and stacks them at the end, so peak memory grows with the number of frames. On one 3-TX, 4-RX, 128-chirp, 256-sample walking-person scene, 128 stacked frames peaked at 1233 MiB against 73 MiB when streamed.streamyields one frame at a time, so its peak stays flat. Use it for long sequences.tracekeeps every evaluated observation's rows in the returnedPaths, about 20 bytes per live row per observation. WithMotion.adc()a frame haschirps · num_tx · samplesobservations, so a rich scene can cost gigabytes per frame. Trace one frame at a time if the sequence is long.
Performance#
Speed depends on the scene, the motion sampling and the number of paths, so measure your own workload. Two reference points from the repository's PERFORMANCE.md, measured on an RTX 5080:
- A full SMPL walking person (128 scatter sites, 3 TX by 4 RX, 128 chirps by 256 samples, adaptive motion, beat output) ran 300 frames in 14.3 s, a median of 45 ms per frame, with processing excluded.
- On a 13-interval MIMO frame, raising adaptive
nodesfrom 2 to 5 raised the probe count from 27 to 105 and the frame time from 95.5 ms to 173.5 ms. Keep the defaultnodes=2unless the phase tolerance, notmax_interval, is what shortens the intervals.
The main levers, from largest to smallest:
motion:staticis one evaluation per frame;adcis one per ADC sample;adaptiveis usually in between.reflections: each extra bounce multiplies the path count.- The number of targets, transmitters and receivers.
rediscover_every_frames, which skips topology discovery between frames at the cost of completeness.