vLLM-Omni TTS 推論エンジニアリング

vLLM-Omni TTS 推論エンジニアリング

TL;DR

vLLM-Omni は、Talker と Code2Wav のステージ固有のボトルネックに対処することで複数のモデルの TTS 推論を最適化し、最大で 172% 高いオーディオスループットを達成し、Qwen3-TTS の高い並行性においてエンドツーエンドのレイテンシーをほぼ半分に削減しました。

TTS 推論が従来の LLM 推論と異なる点

TTS 推論は自己回帰モデルを使用しますが、マルチステージパイプライン(Talker と Code2Wav)およびストリーミング音声出力の厳しいレイテンシー予算により、テキスト専用の LLM とは異なるサービスボトルネックに直面します。ここで、チャンクサイズは最初のパケットレイテンシーとクロスチャンク音声品質の両方に影響します。

最適化の概要

vLLM-Omni は、固定されたレシピを適用するのではなく、各 TTS モデルのパイプライン構造、デコード状態、バッチシェイプ、数値制約に基づいて最適化を選択します。ステージ分離、バッチプリプロセッシング、torch.compile、GPU 常駐状態などの技術は特定のアーキテクチャにのみ有益です。

Qwen3-TTS: フル最適化パス

Qwen3-TTS に対して、コネクタチャンクを Code2Wav デコードウィンドウからデカップリングし、ステージ 0 のプリプロセッシングをバッチ処理し、ホットパスのオーバーヘッドをクリーンアップし、数値精度を fp32 に合わせることで、H20 × 2 で c=64 のときにオーディオスループットを 61.5% 向上させ、P99 エンドツーエンドレイテンシーをほぼ半分に削減しました。

1. ストリーミング: コネクタチャンクを Code2Wav デコードウィンドウからデカップリング

コネクタストリーミングチャンクサイズ (codec_chunk_frames) を Code2Wav の内部デコードウィンドウ (decode_chunk_framesdecode_left_context_frames) からデカップリングすることで、独立したチューニングが可能になります:小さなコネクタチャンクは最初のパケットレイテンシーを削減し、Code2Wav はクロスチャンク音声の連続性のために 300 フレームのデコードウィンドウと 25 フレームの左コンテキストを維持します。

2. スループット: ステージ 0 デコードプリプロセッシング

Talker デコードプリプロセッシング(スピーカー埋め込みの準備、trailing_text のメンテナンス、入力埋め込みの構築)をバッチ処理することで、デコードホットパスでの per-request Python オーバーヘッドを排除し、高い並行性における小さなテンソル割り当てとカーネル起動による GPU アイドル時間を削減しました。

3. ホットパスのクリーンアップ

O(N²) の req_id_to_index ルックアップを辞書に置き換え、非ストリーミングパスを早期にスキップし、コーデック禁止マスクを事前に計算し、Code2Wav の CUDA Graph キャプチャをチューニングすることで、頻繁な c=64 デコードループでの Python オーバーヘッドをモデル計算を変更せずに削減しました。

4. 数値精度: コード予測子の fp32 アラインメント

Talker のコード予測子を分割し、PyTorch ネイティブな実装で RMSNorm 分散、RoPE cos/sin、注意、QKV 投影を fp32 に保つことで、短シーケンス・高頻度の自己回帰ステップにおける bfloat16 フューズドカーネルからの精度ドリフトを防ぎました。

5. 検証

最適化を積み重ねた後、H20 × 2 での Qwen3-TTS のオーディオスループットは 26.55 から 42.88 audio-s/s (+61.5%) に増加し、c=64 でのボイスクローンにおける P99 エンドツーエンドレイテンシーは 17.7s から 9.0s に低下しました。ウォームな並行性スイープでは、固定コストの償却により E2E が非線形に増加することが示されました。

VoxCPM2: シングルステージ ハイブリッド TTS

VoxCPM2 に対して、whole-forward torch.compile は MiniCPM4 Talker の Python-to-compiled バウンダリを削減し、CFM/LocDiT デコードテイルをリクエスト間でバッチ処理することで、H20 × 1 で c=64 のときにオーディオスループットを 172.0% 向上させました。

torch.compile の探索

fullgraph=FalseModel.forward 全体を torch.compile でラップすることで、PagedAttention のブレイクにもかかわらず Dynamo が 28 層の MiniCPM4 ループを最適化し、cudaLaunchKernel の数を約 71% 削減し、カーネル時間を約 27% 削減しました。一方、レイヤーごとのコンパイルだけでは未解決のバウンダリのため起動数を削減できませんでした。

CFM/LocDiT デコードテイルのバッチ処理

CFM/LocDiT、feat_encoder、および stop_headlm_h、残差出力、およびプレフィックスフィーチャ条件をリクエスト間でバッチ処理し、結果を散らばして戻すことに加えて、スライドウィンドウ VAE デコードとフューズド演算を組み合わせることで、tiny な per-request ディフュージョンワークロードを効率的な GPU バッチに変換し、H20 × 1 のスループットを 4.19 から 10.83 req/s (+158.8%)、オーディオスループットを 12.16 から 33.07 audio-s/s (+172.0%) に向上させました。c=64 のとき。

Higgs Audio V3: ダイナミックバッチとマルチコードブック状態

Higgs Audio V3 に対して、マルチコードブックデコード状態を GPU 常駐のバッチテンソルに移動し、PIECEWISE の代わりにローカル MLP CUDA Graph を使用することで、Python オーバーヘッドと同期を回避し、単一の H20 で c=16 のときに 35.26 audio-s/s のスループットを達成しました。

デコード状態を GPU に移動

_per-request Python ディクト状態(_decode_last_codes_decode_has_codes、遅延カウント、EOC カウントダウンなど)を GPU 常駐のバッチテンソルに変換することで、デコードホットパスでの Python ループと D2H 同期を排除し、状態の更新は now バッチ GPU 軌道で行われます。

動的バッチシェイプに CUDA Graph を適応

CUDA Graph キャプチャのために uniform single-token デコードバッチを使用すること(ここで decode_mask はすべて True)により、オーディオフィードバックメカニズムのブーリアンマスクからのシェイプミスマッチを回避し、スケジューラーでのダイナミックバッチングにもかかわらず安定したグラフシェイプを確保しました。

ローカル MLP CUDA Graph vs. PIECEWISE

Higgs v3 のモデルでは、マルチコードブック遅延パターンによりデータ依存の埋め込みルックアップとプリアテンションインデックス操作が発生し、これがより大きなグラフを壊すか、高コストな同期を必要とするため、ローカル MLP CUDA Graph(post_attention_layernorm + mlp をカバー)は PIECEWISE グラフを上回りました。

棄却されたステージングオーバーラップ設計

D2H コピーを隠すための 1 ステップのオーディオステージングオーバーラップ設計は、ダイナミックバッチングにおいて構造的に安全でないと判断されました。スケジューラーによるリクエストの再順序付けまたは完了がカーソル・トゥ・リクエストマッピングを壊す可能性があり、リクエスト ID キーイングとドレインフックがない限りこのアプローチは信頼できません。

Fish Speech S2 Pro: ジェネリックアテンションがボトルネックになるとき

Fish Speech S2 Pro に対して、モデル固有の q_len=1 アテンションカーネルと Fast AR バッファの再利用により、ジェネリックアテンションオーバーヘッドと繰り返しの割り当てによる GPU サイドのボトルネックに対処し、H20 で c=64 のときに 23.72 audio-s/s のスループットを達成しました。

モデル固有のアテンカーネル

Fish 特有の Triton カーネル(SlowAR デコードアテンション、q_len=1、fp16/bf16、head_dim=128、ブロックサイズ 16、GQA レイアウト)は、純粋なデコードステップにおけるジェネリックページド/可変長アテンションを置き換え、長いシーケンスに対しては split-partial-combine を使用し、パス選択中の同期を避けるために CPU サイドの上限を設けました。

Fast AR バッファの再利用とコンパイル

Fast AR 用に _embed_buf_k_cache、および _v_cache テンソルを事前に割り当てて再利用することで、短シーケンスデコードステップでの繰り返しの割り当てを排除し、torch.compilefullgraph=Falsedynamic=True で使用して、SDPA 内部のブレイクにもかかわらず 4 層のトランスフォーマーのサブグラフをメモ化しました。

DAC とランタイムサイドの最適化

コーデックペイロード転送を Python list[int] からテンソルシリアル化に切り替え、fp16 DAC サポートを有効にし、フレームカウントバッチド DAC バッチ処理を実装し、非同期チャンク処理によるコネクタ転送と DAC 計算のオーバーラップを行うことで、高い並行性における割り当て、GC プレッシャー、およびブロックを削減しました。

パフォーマンスデータ

最適化により、vLLM-Omni クックブックベンチマークで検証されたとおり、モデル間で測定可能な向上がもたらされました。

Qwen3-TTS (c=64, p=512, H20 × 2, voice clone)

Metric Before After Change
Audio throughput 26.55 audio-s/s 42.88 audio-s/s +61.5%
Median E2EL 9654ms 5699ms −41.0%
P99 E2EL 17686ms 8956ms −49.4%
P99 TTFP 7558ms 5563ms −26.4%

VoxCPM2 (c=64, H20 × 1, before/after CFM batching)

Metric Before After Change
Request throughput 4.19 req/s 10.83 req/s +158.8%
Audio throughput 12.16 audio-s/s 33.07 audio-s/s +172.0%

Fish Speech S2 Pro (H20, single GPU, c=64, Triton KV cache + tensor payload)

Metric Value
Audio throughput 23.72 audio-s/s
Request throughput 5.95 req/s
Mean TTFP 899.67 ms
Mean E2EL 10.47 s

Higgs Audio V3 (H20, single GPU, c=16, eager + local MLP graph)

Metric Value
Request throughput 5.18 req/s
Audio throughput 35.26 audio-s/s
Wall time 96.5s
Speedup vs. baseline 2.70×

Sources