Skip to content

perf: machine-adaptive, OOM-safe processing - #16

Merged
lguerard merged 3 commits into
mainfrom
perf/staging-graph
Jun 23, 2026
Merged

perf: machine-adaptive, OOM-safe processing#16
lguerard merged 3 commits into
mainfrom
perf/staging-graph

Conversation

@lguerard

@lguerard lguerard commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Optimises the processing/staging step itself, regardless of the user function, and makes it adapt to the host without OOM or CPU freeze.

Lighter graph

  1. overlap() + map_blocks() + trim_overlap() → one fused da.map_overlap(..., boundary="none", trim=True): only needed halos materialised, smaller task graph.
  2. Removed a full extra disk read — after staging the code re-read the entire staged store just to log a skip count (~250 GB of reads on a 250 GB stage). Gone; estimate_empty_tiles() gives that up front.

Adapts to the machine, can't OOM or freeze

  1. New safe_worker_count() sizes staging threads and merge processes to the host:
    • GPU → 1 tile at a time (no VRAM contention)
    • CPU → as many tiles as fit available RAM (tile size × overhead), capped to leave one core free so the box never fully freezes
    • new max_workers= override; a distributed client keeps managing its own concurrency

Not added (on purpose)

numba/cupy/arrow/xarray bring ~nothing here: the merge/relabel hotspots are already vectorized numpy + scipy C with no per-voxel Python loop, and the run is I/O-bound. Adding them would be deps for no gain.

Tests green (16 passed incl. boundary/overlap + new worker-count/max_workers); ruff clean.

🤖 Generated with Claude Code

lguerard and others added 2 commits June 23, 2026 09:30
- replace overlap() + map_blocks() + trim_overlap() with a single fused
  da.map_overlap(..., trim=True): only the needed halos are materialised
  and the task graph is smaller (no separate overlapped array)
- remove the post-staging skip-count pass, which re-read the *entire*
  staged store off disk just to log how many tiles were skipped —
  doubling the run's read I/O for a log line. estimate_empty_tiles()
  already reports that up front.

Both are independent of the user fn, so every run gets cheaper.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add safe_worker_count() and use it to size both the staging threaded
scheduler and the merge worker pool to the host:

- GPU → 1 tile at a time (no VRAM contention)
- CPU → as many tiles as fit available RAM (tile size × overhead),
  capped to leave one core free so the box never fully freezes
- new max_workers= knob to override; a distributed client keeps
  managing its own concurrency

So a run adapts to whatever machine it lands on and can't blow up RAM,
VRAM, or peg every core.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@lguerard lguerard changed the title perf: slim staging graph, drop redundant disk re-read perf: machine-adaptive, OOM-safe processing Jun 23, 2026
- raise the staging RAM budget from 60% to 80% of available memory
- add a Performance & memory guide (auto worker sizing, max_workers,
  no-OOM/freeze guarantees, what doesn't help) + nav entry

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@lguerard
lguerard merged commit 8a1753f into main Jun 23, 2026
1 check passed
@lguerard
lguerard deleted the perf/staging-graph branch June 23, 2026 07:43
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