Skip to content

Harden PocketTTS FlowLM step allocation against OOM (follow-up to #55 decoder fix)#59

Draft
5uck1ess wants to merge 1 commit into
0xShug0:mainfrom
5uck1ess:fix/pocket-tts-flowlm-oom
Draft

Harden PocketTTS FlowLM step allocation against OOM (follow-up to #55 decoder fix)#59
5uck1ess wants to merge 1 commit into
0xShug0:mainfrom
5uck1ess:fix/pocket-tts-flowlm-oom

Conversation

@5uck1ess

Copy link
Copy Markdown
Contributor

Draft — follow-up to the Mimi decoder OOM hardening on fix/pocket-tts-mimi-decoder-oom (this PR is based on that branch; retarget to main once it merges).

While verifying that branch on a 3090 under real VRAM pressure (#55), I found the SIGABRT still reproduces at tighter memory — just in a sibling pocket_tts runtime the branch doesn't touch: FlowLMStepRuntime, reached via PocketTTSSession::prepare. Its ggml_backend_alloc_ctx_tensors (and two ggml_gallocr_alloc_graph calls) are unguarded, so a failed CUDA buffer alloc returns null and the following write_tensor/graph use trips GGML_ASSERT(buf != NULL) at ggml-backend.cpp:327.

This applies the same treatment you used in the decoder to all three FlowLM allocation sites:

  • params buffer (alloc_ctx_tensors) — null-check → runtime_error
  • prompt graphggml_gallocr_reserve + alloc_graph-or-throw
  • lazy step graph (ensure_step_graph_allocated) — same, freeing the partial gallocr so a retry doesn't leak

Because a throw from the constructor skips the destructor, the destructor cleanup is factored into an idempotent release_runtime() that the failure paths call, so the ggml context and any partial buffers are freed rather than leaked.

Verified on an RTX 3090 (A/B, squeezing free VRAM with a filler then synthesizing a cloned voice):

  • Original bug: main SIGABRTs on the ~3 GB Mimi reserve at ~1.1 GB free.
  • Your branch: fixes that, and lowers peak VRAM (same synth that aborted main at 1143 MiB free succeeds at 997 MiB free) — but still SIGABRTs in FlowLM at ~250 MiB free.
  • With this change: at 227 MiB free the same synthesis returns a clean 500 (FlowLM step parameter buffer allocation failed (out of memory)) and the server stays responsive — no abort.

Draft because you may prefer to fold it into the decoder branch or adjust the messages/idiom. Happy to adapt.

Extends the 0xShug0#55 hardening from the Mimi decoder to FlowLMStepRuntime, the
sibling pocket_tts runtime reached via PocketTTSSession::prepare. Under VRAM
pressure its unguarded ggml_backend_alloc_ctx_tensors returns null and the
following write_tensor calls trip GGML_ASSERT (ggml-backend.cpp:327),
SIGABRT-ing the whole server instead of failing the one request.

Guards all three allocation sites (params buffer, prompt graph, lazy step
graph) with the same reserve/alloc-or-throw idiom as the Mimi decoder fix,
and factors the destructor cleanup into an idempotent release_runtime() so a
constructor throw does not leak the ggml context or partial buffers.

Verified on an RTX 3090: at ~227 MiB free a synthesis that previously
SIGABRT'd now returns a clean 500 and the server stays responsive.
@0xShug0
0xShug0 changed the base branch from fix/pocket-tts-mimi-decoder-oom to main July 15, 2026 14:09
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