Stream long sequences
Use Radar.stream to produce long frame sequences one frame at a time, with flat GPU memory, and write them to disk as you go.
Radar.simulate stacks every frame into one cube at the end, so its memory grows with the number of frames. Radar.stream runs the same session and yields one frame at a time. Use it to generate datasets or long recordings.
Stream frames#
import numpy as np
times = [k / 10.0 for k in range(600)] # 60 s at 10 frames per second
for k, result in enumerate(radar.stream(scene, targets, times=times, reflections=1)):
rd = result.frame(0).range_doppler()
np.save(f"out/rd_{k:04d}.npy", rd.data.abs().cpu().numpy())Each yielded value is a one-frame Result: result.frame_count == 1 and result.cube.shape[0] == 1. The physics, the session state (compiled Scene, discovered topology, noise stream) and the per-frame cubes are the same as simulate with the same arguments.
Memory#
On one 3-TX, 4-RX, 128-chirp, 256-sample walking-person scene measured on an RTX 5080:
| Frames | Streamed peak | Stacked peak |
|---|---|---|
| 8 | 73.2 MiB | 106.2 MiB |
| 32 | 73.2 MiB | 303.6 MiB |
| 128 | 73.2 MiB | 1233.4 MiB |
Per-frame time was the same for both. The stacked peak reaches about three times the cube size because the frame list and the stacked tensor are both alive at the end.
Warning
A yielded result holds that frame's device tensors through its last_* diagnostics. If you keep every yielded result in a list, you use more memory than simulate, not less. Process each frame, keep what you need on the CPU, and drop the result.
Validation happens on iteration#
stream is a generator. It checks its arguments when you start iterating, not when you call it, so an invalid times or motion raises on the first next().
Stream or trace#
- Use
streamwhen you run one receiver over a long sequence. - Use
traceandechowhen you run several receivers over the same short sequence.