Skip to content

Fix GPU memory waste in demo.py and a viewer scene-corruption bug - #104

Open
Zawaer wants to merge 3 commits into
Robbyant:mainfrom
Zawaer:fix/memory-and-viewer-bugs
Open

Fix GPU memory waste in demo.py and a viewer scene-corruption bug#104
Zawaer wants to merge 3 commits into
Robbyant:mainfrom
Zawaer:fix/memory-and-viewer-bugs

Conversation

@Zawaer

@Zawaer Zawaer commented Aug 22, 2026

Copy link
Copy Markdown

Summary

Three independent fixes found while running demo.py end-to-end on a real capture (native Windows + WSL2):

  • demo.py: the full image sequence was eagerly copied to GPU before inference even though inference_streaming/inference_windowed already slice off and transfer one frame at a time internally. On longer sequences this wastes several GB of VRAM holding pixels for frames that aren't being processed yet, and was directly responsible for OOMs on an 8GB GPU. Also switched the checkpoint load to map_location="cpu" to avoid a transient double-memory-copy at load time.
  • lingbot_map/vis/point_cloud_viewer.py: _regenerate_cameras() (triggered by the camera downsample slider, and hit repeatedly during save_video()) removed and recreated frustum handles but never cleaned up the paired camera_frame axes FrameHandle it also creates. Re-adding a node at an already-live path eventually raises Cannot assign to 'position'/'visible' on a removed FrameHandle. Since viser replays its full scene-edit history to every newly-connecting client, this error gets baked permanently into that history — once triggered, the viewer is broken for all future connections until the server process is restarted, with no way to recover the in-memory reconstruction short of a full rerun. Also fixed a matplotlib.cm.get_cmap deprecation warning (removed in newer matplotlib).
  • demo_render/render_cuda_ext/setup.py: the CUDA extensions failed to build at all on native Windows (MSVC) — added the required /std:c++20 / /Zc:preprocessor flags, gated to sys.platform == 'win32' so Linux/macOS builds are unaffected.

Test plan

  • Ran demo.py in both --mode streaming and --mode windowed on native Windows through a full room-scan clip; confirmed GPU memory no longer includes the full image sequence and the run completes without the memory-growth OOM seen before.
  • Reproduced the viewer corruption (drag camera downsample slider a few times, or click Save Video) before the fix, confirmed it no longer occurs after tracking/removing camera_frame handles.
  • Built the CUDA extensions on native Windows with MSVC after the setup.py change; confirmed the win32-gated flags don't touch the Linux/macOS compile args path.

Zawaer added 3 commits August 22, 2026 23:54
- Keep the full image sequence on CPU (pinned) instead of eagerly
  copying it to GPU before inference. inference_streaming/
  inference_windowed already slice off and transfer one frame at a
  time internally, so the eager copy just held thousands of frames'
  pixels on GPU for the ~1 frame ever in flight, wasting several GB
  of VRAM on long sequences for no benefit.
- Load the checkpoint with map_location="cpu" instead of the target
  device, avoiding a transient double-memory-copy (checkpoint tensors
  on GPU + model params on CPU) during the state_dict load before the
  model is moved to device.
_regenerate_cameras() removed and recreated camera frustum handles when
the camera downsample slider changed, but never removed the paired
"camera_frame" axes FrameHandle that add_camera() also creates at
/frames/{step}/camera_frame. Re-adding a node at an already-live path
on repeated slider changes (or during save_video()'s per-frame replay)
eventually raises "Cannot assign to 'position'/'visible' on a removed
FrameHandle". Because viser replays its full history of scene edits to
every newly-connecting client, this error gets baked permanently into
that history -- once triggered, the viewer stays broken for all future
connections until the server process is restarted.

Track camera_frame handles the same way frustum handles already are,
and remove both before regenerating.

Also replaces the deprecated matplotlib.cm.get_cmap with
matplotlib.colormaps[...] (removed in newer matplotlib releases).
MSVC's default preprocessor and C++ standard aren't enough to compile
these pybind11/torch extension bindings, failing the build outright on
native Windows. Add the required MSVC flags (/std:c++20,
/Zc:preprocessor), gated to sys.platform == 'win32' so gcc/clang builds
on Linux/macOS are unaffected.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant