Skip to content

LesionSegmenter: GPU-resident export (no CPU round trip) - #121

Merged
aperson30 merged 1 commit into
BodyMaps:mainfrom
aperson30:speed/gpu-resident-export
Aug 3, 2026
Merged

LesionSegmenter: GPU-resident export (no CPU round trip)#121
aperson30 merged 1 commit into
BodyMaps:mainfrom
aperson30:speed/gpu-resident-export

Conversation

@aperson30

@aperson30 aperson30 commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

The LesionSegmenter export stage moves the ~1.5 GB, 43-channel logit volume off and back onto the GPU on every request, because predict_logits_from_preprocessed_data returns logits on the CPU while the export resample (already GPU-patched, PR #108) runs on the GPU. This keeps the whole export GPU-resident.

What changes

The cold path now does the export in place on the GPU — same resample function, same spacings, same argmax — and returns only the small uint8 label map. No 1.5 GB round trip.

Measured (size-stratified sample vs current convert_logits output)

case export before after speedup differing voxels
945 (anisotropic) 25.4× 0
1787 11.0× 0
3398 3.6× 0
2388 55.2× 0
6816 2.5× 0
3276 2.5× 0

Bit-identical to the current output on every case (0 differing voxels), including anisotropic cases where a naive trilinear shortcut diverges. Median export ~5s → ~1s.

Safety

  • Guarded to plain softmax-argmax label spaces (argmax(logits) == argmax(softmax(logits))); region-based models fall back to convert_logits, unchanged.
  • This is a pure speed change to how the same segmentation is computed — it is not an approximation.
  • Verified end-to-end: ran the cold path on a real case (valid output, no errors) on top of the per-stage bit-exactness check.

predict_logits_from_preprocessed_data returns logits on the CPU, so the export
step moves the ~1.5 GB, 43-channel logit volume CPU->GPU to run the (already
GPU-patched) resample, then argmaxes and comes back. The transfer and CPU-side
handling dominate the stage.

Keeping the export resident on the GPU -- same resample function, same spacings,
same argmax, only the small uint8 label map returned -- removes that round trip.

Measured on a size-stratified sample against the current convert_logits output:
bit-identical (0 differing voxels across every case, including anisotropic ones
where a naive trilinear shortcut would differ), and 3.6-25x faster on the export
stage (median export ~5s -> ~1s). Guarded to plain softmax-argmax label spaces;
region-based models fall back to convert_logits.

Verified end to end by running the cold path on a real case (valid output, no
errors) in addition to the per-stage bit-exactness check.
@aperson30
aperson30 merged commit f36f015 into BodyMaps:main Aug 3, 2026
8 checks passed
aperson30 added a commit that referenced this pull request Aug 4, 2026
Two speed additions to the persistent LesionSegmenter service, both of which only
make sense for a warm/persistent process:

torch.compile (gated by LESIONSEG_COMPILE, default off): compiles the patch-level
network once at startup with max-autotune-no-cudagraphs. The sliding-window patch is
a constant [128,224,224], so one compile serves every patch of every case. Measured
1.18x on inference, accuracy-safe (voxel agreement 0.99996, lesion Dice 0.999 vs
eager). The ~20s-3min compile is paid once at startup, behind the health gate -- while
it runs, lesionseg_predict.py falls back to the cold path so the site keeps working.
Env-gated so it can be dropped without a redeploy if a node shows the compile-latency
variance seen on some shared GB10 nodes; the warm predictor's main win (cold-start
elimination) is independent of it.

GPU-resident export (default for softmax-argmax models): predict_logits returns logits
on the CPU, so convert_logits moves the ~1.5 GB, 43-channel volume CPU->GPU for the
(GPU-patched) resample and back. This runs the same resample, spacings and argmax
GPU-resident and returns only the uint8 label map. Verified 0 differing voxels vs
convert_logits across a size-stratified sample incl. anisotropic cases; 3.6-25x on the
export stage. Region-based models fall back to convert_logits.

Verified the service starts, compiles, and listens; export logic matches PR #121
(shipped) which was validated bit-exact.
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