Skip to content

kokoro: make the GPU path actually fast (+ streaming) - #189

Merged
SearchSavior merged 4 commits into
SearchSavior:mainfrom
meatposes:kokoro-gpu
Oct 6, 2026
Merged

SearchSavior merged 4 commits into
SearchSavior:mainfrom
meatposes:kokoro-gpu

Conversation

@meatposes

Copy link
Copy Markdown
Contributor

follow up to #186. builds on #186 and #188, so those commits show up here until they merge.

#186 gets kokoro onto the GPU, but on its own it's slow: openvino recompiles kernels for every new output length, so every new sentence costs 11-13s. this fixes that:

  • text front end (bert, durations, f0) runs as an openvino CPU graph. token count changes every request so it can't sit on the GPU without recompiling
  • vocoder compiled at fixed frame buckets (64-512) with static shapes, all warmed at load. input padded with reflect (zero padding throws off adain) and trimmed back
  • longer inputs get cut in a pause and decoded in pieces
  • ConvTranspose1d rewritten polyphase and snake alpha folded into the neighbouring layers, both exact. static reshape doesn't work without the first one, and together they get the vocoder off the slow reference kernels
  • SineGen uses exact sizes, the float scale factor broke past ~1536 frames
  • converted IRs cached in cache_dir so reloads skip conversion

also adds streaming: openarc_tts.kokoro.stream=true returns audio/L16 (24kHz mono) chunk by chunk instead of the whole file.

B50, sentences it hadn't seen:

per sentence GPU actually used
main (device: GPU) ~2s no, it's pytorch on CPU
#186 alone 11-13s yes
this PR 0.18-0.37s yes

30s of audio renders in 0.77s, streaming starts playing at 0.18s. sounds the same as CPU to me.

costs ~2.5GB VRAM and ~80s for the first load. set cache_dir and NEO_CACHE_PERSISTENT=1 + NEO_CACHE_DIR so restarts don't recompile, and OMP_NUM_THREADS=4 or torch spins ~13 cores per request. only tested on a B50.

meatposes and others added 4 commits October 3, 2026 20:55
chunk_forward_pass built a new KPipeline every request, which reloads the g2p
and spacy models, ~0.9s each time. cache them per lang_code, clear on unload.
on GPU the whole kokoro IR recompiles kernels for every new output length,
7-11s per request. fix:

- text front end (bert, durations, f0/n) runs as an openvino CPU graph, token
  count changes every request so it can't live on the GPU
- vocoder compiled at fixed frame buckets (64..512), static shapes, warmed at
  load. inputs padded with reflect (zeros skew adain's time stats) and trimmed
- longer inputs are cut in pauses and decoded in pieces
- ConvTranspose1d rewritten polyphase and snake alpha folded into the
  neighbouring layers, both exact. static reshape fails without the first,
  and they move the vocoder off the slow reference kernels
- SineGen uses exact sizes, the float scale factor broke above ~1536 frames
- converted IRs cached in cache_dir so reloads skip conversion

B50: median 0.17s per sentence vs 10.6s before, ~2.5GB VRAM.
openarc_tts.kokoro.stream=true returns audio/L16 (24kHz mono) chunk by chunk
as each text chunk finishes instead of waiting for the whole file. first
chunk is kept short so audio starts in ~0.1-0.25s.
@SearchSavior
SearchSavior merged commit 9300e68 into SearchSavior:main Oct 6, 2026
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.

2 participants