feat: warn before an unbatched MultiStartProdigy jvp exhausts memory - #1453
Merged
Conversation
With batch_size=None the search vmaps every start into one value_and_grad, and the only signal that this will not fit is XLA's RESOURCE_EXHAUSTED raised from inside the compiled program, naming a byte count and nothing else. Nothing points at batch_size, the one knob that fixes it. That cost two nightly release runs in 2026-07, after which two workspace scripts were hand-patched with magic numbers. Adds, before the full vmap is compiled: probe the batched jvp at widths 1 and 2 via XLA's own memory analysis, split the result into fixed and per-start components, and if the projected n_starts footprint exceeds available memory, warn naming a batch_size that would fit. Two probe points rather than one on purpose. Workspace guidance has claimed VRAM 'does not scale with batch size for the persistent buffers, so if it fits at batch_size=1 you can push it up' — true only when the per-start slope is small next to the fixed cost, and for an interferometer jvp it is not: the incident measured ~1.79 GB per start, so the single-start probe that 'fit' predicted nothing. Analysis.print_vram_use gains a flag and now names what it measured. It profiled fitness.call — the likelihood, not the jvp — so its number could not bound a gradient search's footprint, which is how a fit that looked modest reached ~86 GB. Warn only, never auto-apply: batch_size is numerically inert so auto-batching would be safe in principle, but silently changing the execution shape of every existing run on the strength of a projection is not a trade to make unattended. Known limitation, documented at the call site: memory_analysis reports 0 on a CPU-only JAX build, which is where the release harness runs, so the projection is skipped there rather than guessing. The CPU path relies on the now-unfiltered traceback instead. Making it measurable is follow-up work that needs a real run to validate. The projection arithmetic is pure Python and unit-tested here; the JAX measurement it consumes belongs to autofit_workspace_test, per this suite's existing JAX boundary. Refs #1452 (phase 3 of 3). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0171voyyTrr91hJ3vU5AjeVz
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 3 of 3 for #1452.
What and why
With
batch_size=None,MultiStartProdigyvmaps every start into onevalue_and_grad. The only signal that this will not fit is XLA'sRESOURCE_EXHAUSTED: Out of memory allocating N bytes, raised from inside the compiled program with nothing pointing atbatch_size— the one knob that fixes it. That cost two nightly release runs in 2026-07, after which two workspace scripts were hand-patched with magic numbers.Before the full vmap is compiled, this now probes the batched jvp at widths 1 and 2 via XLA's own memory analysis, splits the result into fixed and per-start components, and warns naming a
batch_sizethat would fit.Two probe points, not one, on purpose. Workspace guidance claimed VRAM "does not scale with batch size for the persistent buffers, so if it fits at
batch_size=1you can push it up (e.g. to 50)" — true only when the per-start slope is small next to the fixed cost. For an interferometer jvp it is not: the incident measured ~1.79 GB per start, so 48 starts wanted ~86 GB while the single-start probe fitted comfortably. A one-probe model reproduces the bad advice. (That prose is corrected in PyAutoLabs/autolens_workspace#… on the matching branch.)Analysis.print_vram_usegains agradientflag and now names what it measured. It profiledfitness.call— the likelihood, not the jvp — so its number could never bound a gradient search's footprint.Design choices worth reviewing
batch_sizeis documented numerically inert, so auto-batching would be safe in principle — but silently changing the execution shape of every existing run on the strength of a projection isn't a trade to make unattended. Escalating to auto-batch is a reasonable follow-up once the probe has run on real hardware.Analysis.batched_memory_bytesis new;print_vram_usegains an optionalgradient=False(existing calls unchanged, though their output string now names the mode).Known limitation — please read
memory_analysisreports 0 bytes on a CPU-only JAX build, which is where the release harness runs. The projection is skipped there rather than guessing, so this does not fix the CI OOM — it helps GPU users, and the CPU path relies on the now-unfiltered traceback from PyAutoLabs/PyAutoHands (phase 2). Documented at the call site. Making the CPU path measurable needs a live run to validate and is deliberately not attempted here.Testing
The projection arithmetic is pure Python and unit-tested in
test_multi_start_gradient.py, matching that suite's existing boundary ("plumbing is pure NumPy and tested here… keeping JAX out of the library unit suite"). Cases cover recovery of the incident's exact per-start cost, non-monotonic/identical probes (no negative slope), and six degenerate budget combinations.The JAX probe itself has not been executed. It was authored in an environment with no
jax,autofitorpytestinstalled, sopytest test_autofit/has not been run andbatched_memory_byteshas never called into XLA. Please run the suite and one realMultiStartProdigyfit before merging.Generated by Claude Code