[RFC] Offload blocking TTS/speech ops to thread pool to unblock event loop#2511
Merged
linyueqian merged 3 commits intovllm-project:mainfrom Apr 7, 2026
Merged
Conversation
44ed9ac to
d31d27d
Compare
…ent loop Offload synchronous CPU-bound TTS preprocessing operations to a shared ThreadPoolExecutor(max_workers=1) to prevent blocking the asyncio event loop under concurrent TTS requests. This is the same class of fix as vllm-project/vllm#34789 applied to the renderer pipeline. Affected methods in _prepare_speech_generation(): - _build_voxtral_prompt: sync tokenizer.encode_speech_request() - _build_fish_speech_prompt: lazy AutoTokenizer.from_pretrained() + tokenization + np.save() - _estimate_prompt_len: lazy AutoTokenizer.from_pretrained() + model computation _build_tts_params is intentionally kept synchronous: offloading it would break atomicity with validation for uploaded-voice requests, since delete_voice() can mutate self.uploaded_speakers between the await point and the dict access. max_workers=1 serializes tokenizer access to avoid Rust RefCell "Already borrowed" errors from concurrent use. Closes: vllm-project#2476 Signed-off-by: Bvicii <yizhanhuang2002@gmail.com>
d31d27d to
a1dbcd6
Compare
Contributor
Author
|
@linyueqian PTAL |
Contributor
Author
|
@hsliuustc0106 Hi, I think this PR is ready for review now, PTAL, thank you. |
vraiti
pushed a commit
to vraiti/vllm-omni
that referenced
this pull request
Apr 9, 2026
… loop (vllm-project#2511) Signed-off-by: Bvicii <yizhanhuang2002@gmail.com>
bob-021206
pushed a commit
to jasonlee-1024/vllm-omni
that referenced
this pull request
Apr 21, 2026
… loop (vllm-project#2511) Signed-off-by: Bvicii <yizhanhuang2002@gmail.com> Signed-off-by: bob-021206 <binyan_github@163.com>
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.
Purpose
Offload synchronous CPU-bound TTS preprocessing operations to a shared
ThreadPoolExecutor(max_workers=1)to prevent blocking the asyncio event loop under concurrent TTS requests. This is the same class of fix as vllm-project/vllm#34789 applied to vllm-omni's TTS/speech serving layer.Offloaded methods (called from
async def _prepare_speech_generation()):_build_voxtral_prompt: synctokenizer.encode_speech_request()_build_fish_speech_prompt: lazyAutoTokenizer.from_pretrained()+ tokenization +np.save()_estimate_prompt_len: lazyAutoTokenizer.from_pretrained()+ model computationIntentionally kept synchronous:
_build_tts_params: offloading would break atomicity with validation for uploaded-voice requests, sincedelete_voice()can mutateself.uploaded_speakersbetween the await point and the dict access.max_workers=1serializes tokenizer access to avoid RustRefCell"Already borrowed" errors from concurrent use.Closes #2476
Test Plan
Unit tests:
Event loop responsiveness benchmark (Qwen3-TTS, 500 reqs @ concurrency 50):
Test Result
Environment: A100-SXM4-80GB, Python 3.11.5, vllm 0.19.0, Qwen3-TTS-12Hz-0.6B-CustomVoice
Unit Tests
Event Loop Responsiveness —
/healthlatency during 500 reqs @ concurrency 50Throughput — 500 reqs @ concurrency 50
No regression. Fix branch is slightly faster (~3-4% throughput, ~10% better P99 RTF).
Shutdown
SIGTERM under load: server exited within <1s, no hung workers.
shutdown(wait=False, cancel_futures=True)cancels queued work cleanly.Essential Elements of an Effective PR Description Checklist
supported_models.mdandexamplesfor a new model. Please runmkdocs serveto sync the documentation editions to./docs.