vLLM-Omni TTS 推理工程
vLLM-Omni TTS 推理工程
TL;DR
vLLM-Omni 透過解決 Talker 和 Code2Wav 階段中的特定瓶頸,為多個模型優化了 TTS 推理,在高併發情況下為 Qwen3-TTS 實現了高達 172% 的音訊吞吐量提升,並將端到端延遲降低了近一半。
TTS 推理與傳統 LLM 推理有何不同
TTS 推理使用自回歸模型,但由於其多階段流水線(Talker 和 Code2Wav)以及對串流音訊輸出嚴格的延遲預算,面臨著與純文本 LLM 不同的服務瓶頸;其中,分塊大小(chunk size)會同時影響首包延遲(first-packet latency)和跨分塊的音訊品質。
優化概述
vLLM-Omni 根據每個 TTS 模型的流水線結構、解碼狀態、批次形狀(batch shapes)和數值約束來選擇優化方案,而非採用固定配方,因為像階段分離、批次預處理、torch.compile 和 GPU 駐留狀態(GPU-resident state)等技術僅對特定架構有效。
Qwen3-TTS:完整的優化路徑
對於 Qwen3-TTS,將連接器分塊(connector chunks)與 Code2Wav 解碼窗口解耦、對 Stage 0 預處理進行批次處理、清理熱路徑(hot-path)開銷,並將數值精度對齊至 fp32,這在 H20 × 2 且 c=64 的情況下,將音訊吞吐量提升了 61.5%,並將 P99 端到端延遲降低了近一半。
1. 串流:將連接器分塊與 Code2Wav 解碼窗口解耦
將連接器串流分塊大小 (codec_chunk_frames) 與 Code2Wav 的內部解碼窗口 (decode_chunk_frames 和 decode_left_context_frames) 解耦,可以實現獨立調優:較小的連接器分塊可降低首包延遲,而 Code2Wav 則維持 300 幀的解碼窗口加上 25 幀的左上下文,以確保跨分塊的音訊連續性。
2. 吞吐量:Stage 0 解碼預處理
對 Talker 解碼預處理(說話者嵌入準備、trailing_text 維護、輸入嵌入構建)進行批次處理,消除了解碼熱路徑中的每個請求的 Python 開銷,減少了高併發下由小張量分配和內核啟動(kernel launches)引起的 GPU 空閒時間。
3. 熱路徑清理
將 O(N²) 的 req_id_to_index 查詢替換為字典、提前跳過非串流路徑、預計算 codec 不允許的遮罩(masks),並針對 Code2Wav 調優 CUDA Graph 捕獲,在不改變模型計算的情況下,減少了頻繁的 c=64 解碼循環中的 Python 開銷。
4. 數值精度:Code Predictor 的 fp32 對齊
透過 PyTorch 原生實現將 Talker code predictor 拆分,使 RMSNorm 方差、RoPE cos/sin、attention 和 QKV 投影保持在 fp32,防止了在短序列、高頻自回歸步驟中因 bfloat16 融合內核(fused kernels)導致的精度漂移。
5. 驗證
堆疊優化後,Qwen3-TTS 在 H20 × 2 上的音訊吞吐量從 26.55 增加到 42.88 audio-s/s (+61.5%),在 c=64 進行語音克隆時,P99 端到端延遲從 17.7s 降至 9.0s;隨著併發增加,由於固定成本的攤銷,端到端延遲呈現非線性增長。
VoxCPM2:單階段混合 TTS
對於 VoxCPM2,全前向 torch.compile 減少了 MiniCPM4 Talker 中的 Python-to-compiled 邊界,而在 c=64 情況下,跨請求對 CFM/LocDiT 解碼尾部進行批次處理,使 H20 × 1 上的音訊吞吐量提升了 172.0%。
探索 torch.compile
在 fullgraph=False 的情況下將整個 Model.forward 包裝在 torch.compile 中,讓 Dynamo 能夠優化 28 層的 MiniCPM4 循環(儘管存在 PagedAttention 中斷),將 cudaLaunchKernel 數量減少了約 71%,內核時間減少了約 27%;而僅對單層進行編譯則因無法解決邊界問題而未能降低啟動次數。
CFM/LocDiT 解碼尾部批次處理
在將結果散射回之前,對 CFM/LocDiT、feat_encoder 和 stop_head 的 lm_h、殘差輸出和前綴特徵條件進行跨請求批次處理,結合滑動窗口 VAE 解碼和融合操作,將微小的單請求擴散工作量轉化為高效的 GPU 批次,在 c=64 時將 H20 × 1 的吞吐量從 4.19 req/s 提升至 10.83 req/s (+158.8%),音訊吞吐量從 12.16 提升至 33.07 audio-s/s (+172.0%)。
Higgs Audio V3:動態批次與多 Codebook 狀態
對於 Higgs Audio V3,將多 codebook 解碼狀態移至 GPU 駐留的批次張量,並使用本地 MLP CUDA Graph(而非 PIECEWISE),避免了 Python 開銷和同步,在 c=16 時於單個 H20 上實現了 35.26 audio-s/s 的吞吐量。
將解碼狀態移至 GPU
將每個請求的 Python 字典狀態(_decode_last_codes、_decode_has_codes、延遲計數、EOC 計數等)轉換為 GPU 駐留的批次張量,消除了解碼熱路徑中的 Python 循環和 D2H 同步,狀態更新現在發生在批次 GPU 軌跡上。
使 CUDA Graph 適應動態批次形狀
使用統一的單 token 解碼批次進行 CUDA Graph 捕獲(其中 decode_mask 全為 True),避免了音訊回饋機制布林遮罩導致的形狀不匹配,確保了在調度器進行動態批次處理時具有穩定的圖形形狀。
本地 MLP CUDA Graph vs. PIECEWISE
涵蓋 post_attention_layernorm + mlp 的本地 MLP CUDA Graph 在 Higgs v3 上的表現優於 PIECEWISE 圖,因為該模型的多 codebook 延遲模式會導致數據依賴的嵌入查找和 pre-attention 索引操作,這會破壞較大的圖或需要昂貴的同步。
一個被拒絕的階段重疊設計
為了隱藏 D2H 複製而設計的單步音訊階段重疊設計被拒絕了,因為在動態批次下結構上不安全,因為調度器引起的請求重排序或完成可能會破壞游標與請求的映射,若沒有請求 ID 鍵值和 drain hooks,該方法是不可靠的。
Fish Speech S2 Pro:當通用 Attention 成為瓶頸
對於 Fish Speech S2 Pro,針對特定模型的 q_len=1 attention kernel 和 Fast AR 緩衝區重用解決了來自通用 Attention 開銷和重複分配的 GPU 端瓶頸,在 H20 上於 c=64 時實現了 23.72 audio-s/s 的吞吐量。
特定模型 Attention Kernel
一個針對 SlowAR 解碼 Attention 的 Fish 特定 Triton kernel(處理 q_len=1, fp16/bf16, head_dim=128, block size 16, GQA layout)取代了純解碼步驟中的通用 paged/varlen attention,並針對長序列採用 split-partial-combine 策略,並在 CPU 端設置上限以避免路徑選擇期間的同步。
Fast AR 緩衝區重用與編譯
為 Fast AR 預分配並重用 _embed_buf、_k_cache 和 _v_cache 張量,消除了短序列解碼步驟中的重複分配,而 torch.compile(使用 fullgraph=False 和 dynamic=True)則為四層 Transformer 緩存了子圖,儘管存在 SDPA 內部中斷。
DAC 與運行時優化
將 codec 負載傳輸從 Python list[int] 切換到張量序列化,啟用 fp16 DAC 支援,實現了幀數批次 DAC 批次處理,並透過非同步分塊處理將連接器傳輸與 DAC 計算重疊,在高併發下減少了分配、GC 壓力和阻塞。
性能數據
優化在各個模型中都帶來了可衡量的增益,這已在 vLLM-Omni cookbook 基準測試中得到驗證。
Qwen3-TTS (c=64, p=512, H20 × 2, 語音克隆)
| 指標 | 優化前 | 優化後 | 變化 |
|---|---|---|---|
| 音訊吞吐量 | 26.55 audio-s/s | 42.88 audio-s/s | +61.5% |
| 中位數 E2EL | 9654ms | 5699ms | −41.0% |
| P99 E2EL | 17686ms | 8956ms | −49.4% |
| P99 TTFP | 7558ms | 5563ms | −26.4% |
VoxCPM2 (c=64, H20 × 1, CFM 批次處理前後)
| 指標 | 優化前 | 優化後 | 變化 |
|---|---|---|---|
| 請求吞吐量 | 4.19 req/s | 10.83 req/s | +158.8% |
| 音訊吞吐量 | 12.16 audio-s/s | 33.07 audio-s/s | +172.0% |
Fish Speech S2 Pro (H20, 單 GPU, c=64, Triton KV cache + 張量負載)
| 指標 | 數值 |
|---|---|
| 音訊吞吐量 | 23.72 audio-s/s |
| 請求吞吐量 | 5.95 req/s |
| 平均 TTFP | 899.67 ms |
| 平均 E2EL | 10.47 s |
Higgs Audio V3 (H20, 單 GPU, c=16, eager + 本地 MLP 圖)
| 指標 | 數值 |
|---|---|
| 請求吞吐量 | 5.18 req/s |
| 音訊吞吐量 | 35.26 audio-s/s |
| Wall time | 96.5s |
| 相對於基準的加速比 | 2.70× |