vLLM-Omni TTS 推理工程
vLLM-Omni TTS 推理工程
TL;DR
vLLM-Omni 通过解决 Talker 和 Code2Wav 阶段的特定瓶颈,优化了多模型的 TTS 推理,实现了音频吞吐量最高提升 172%,并在高并发下使 Qwen3-TTS 的端到端延迟几乎减半。
How TTS Inference Differs from Traditional LLM Inference
TTS 推理使用自回归模型,但由于其多阶段流水线(Talker 和 Code2Wav)以及流式音频输出的严格延迟预算,面临的服务瓶颈与纯文本 LLMs 不同,其中块大小既影响首包延迟也影响跨块音频质量。
Optimization Overview
vLLM-Omni 根据每个 TTS 模型的流水线结构、解码状态、批次形状和数值约束选择优化措施,而不是应用固定的配方,因为诸如阶段分离、批量预处理、torch.compile 和 GPU 常驻状态等技术仅对特定架构有益。
Qwen3-TTS: A Full Optimization Path
对于 Qwen3-TTS,将连接器块与 Code2Wav 解码窗口解耦、批量处理 Stage 0 预处理、清理热路径开销以及将数值精度对齐到 fp32,在 H20 × 2 上并发度 c=64 时使音频吞吐量提升 61.5%,P99 端到端延迟降低近一半。
1. Streaming: Decoupling Connector Chunks from the Code2Wav Decode Window
将连接器流式块大小(codec_chunk_frames)与 Code2Wav 的内部解码窗口(decode_chunk_frames 和 decode_left_context_frames)解耦,允许独立调节:小连接器块降低首包延迟,而 Code2Wav 保持 300 帧的解码窗口以及 25 帧的左上下文,以实现跨块音频连续性。
2. Throughput: Stage 0 Decode Preprocessing
批量处理 Talker 解码预处理(说话人嵌入准备、trailing_text 维护、输入嵌入构建)消除了解码热路径中的每请求 Python 开销,减少了因小张量分配和内核启动而在高并发下导致的 GPU 空闲时间。
3. Hot-Path Cleanup
将 O(N²) 的 req_id_to_index 查找替换为字典、提前跳过非流式路径、预计算 codec 不允许的掩码以及调整 Code2Wav 的 CUDA Graph 捕获,在频繁的 c=64 解码循环中减少了 Python 开销,而不改变模型计算。
4. Numerical Precision: fp32 Alignment for the Code Predictor
将 Talker 代码预测器拆分,通过 PyTorch 原生实现将 RMSNorm 方差、RoPE cos/sin、注意力和 QKV 投影保持在 fp32,防止在短序列、高频自回归步骤中由于 bfloat16 融合内核导致的精度漂移。
5. Validation
在叠加优化后,Qwen3-TTS 在 H20 × 2 上的音频吞吐量从 26.55 提升至 42.88 audio-s/s(+61.5%),在 c=64 时语音克隆的 P99 端到端延迟从 17.7s 降至 9.0s,温度并发 sweep 显示由于固定成本摊销导致端到端增长非线性。
VoxCPM2: Single-Stage Hybrid TTS
对于 VoxCPM2,对 MiniCPM4 Talker 使用整体前向 torch.compile 减少了 Python 到编译边界,并在请求之间批量处理 CFM/LocDiT 解码尾部,在 H20 × 1 上并发度 c=64 时音频吞吐量提升 172.0%。
Exploring torch.compile
将整个 Model.forward 用 torch.compile 包裹并设置 fullgraph=False,使 Dynamo 能够在 PagedAttention 中断的情况下优化 28 层 MiniCPM4 循环,cudaLaunchKernel 次数减少约 71%,内核时间减少约 27%,而仅逐层编译则由于未解决的边界未能降低启动次数。
CFM/LocDiT Decode-Tail Batching
在请求之间批量处理 lm_h、残差输出和前缀特征条件,用于 CFM/LocDiT、feat_encoder 和 stop_head,随后将结果散射回去,结合滑动窗口 VAE 解码和融合操作,将微小的每请求扩散工作负载转换为高效的 GPU 批处理,在 H20 × 1 上并发度 c=64 时请求吞吐量从 4.19 提升至 10.83 req/s(+158.8%),音频吞吐量从 12.16 提升至 33.07 audio-s/s(+172.0%)。
Higgs Audio V3: Dynamic Batches and Multi-Codebook State
对于 Higgs Audio V3,将多码本解码状态移至 GPU 常驻批量张量并使用局部 MLP CUDA Graph(而非 PIECEWISE),避免了 Python 开销和同步,在单个 H20 上并发度 c=16 时实现了 35.26 audio-s/s 的吞吐量。
Moving Decode State to the GPU
将每请求的 Python 字典状态(_decode_last_codes、_decode_has_codes、延迟计数、EOC 倒计时等)转换为 GPU 常驻批量张量,消了解码热路径中的 Python 循环和 D2H 同步,状态更新现在发生在批量 GPU 轨迹上。
Adapting CUDA Graph to Dynamic Batch Shapes
使用均匀的单令牌解码批次进行 CUDA Graph 捕获(其中 decode_mask 全为 True),避免了音频反馈机制的布尔掩码导致的形状不匹配,确保尽管调度器中存在动态批次,图形形状仍然稳定。
Local MLP CUDA Graph vs. PIECEWISE
局部 MLP CUDA Graph(覆盖 post_attention_layernorm + mlp)在 Higgs v3 上优于 PIECEWISE 图,因为该模型的多码本延迟模式导致数据依赖的嵌入查找和注意力前索引操作,这些操作会破坏更大的图或需要昂贵的同步。
A Rejected Staging-Overlap Design
一种一步音频暂存重叠设计以隐藏 D2H 复制被拒绝,因为在动态批次下结构不安全;调度器引起的请求重新排序或完成可能破坏光标到请求的映射,使得该方法在没有请求 ID 键控和排空钩子的情况下不可靠。
Fish Speech S2 Pro: When Generic Attention Becomes the Bottleneck
对于 Fish Speech S2 Pro,模型特定的 q_len=1 注意力内核和快速 AR 缓冲区重用解决了由通用注意力开销和重复分配导致的 GPU 端瓶颈,在 H20 上并发度 c=64 时实现了 23.72 audio-s/s 的吞吐量。
Model-Specific Attention Kernel
一个针对 Fish 的 Triton 内核用于 SlowAR 解码注意力(处理 q_len=1、fp16/bf16、head_dim=128、块大小 16、GQA 布局),替换了纯解码步骤中的通用分页/可变长度注意力,对于长序列使用分部-部分-组合,并在 CPU 侧设置上限以避免在路径选择期间同步。
Fast AR Buffer Reuse and Compile
预分配并重用 _embed_buf、_k_cache 和 _v_cache 张量以实现快速 AR,消除了短序列解码步骤中的重复分配;同时使用 torch.compile 并设置 fullgraph=False 和 dynamic=True 对四层 transformer 的子图进行备忘,尽管 SDPA 内部存在中断。
DAC and Runtime-Side Optimizations
将编解码器有效载荷传输从 Python list[int] 切换到张量序列化,启用 fp16 DAC 支持,实现帧数批处理的 DAC 批处理,并通过异步块处理将连接器传输与 DAC 计算重叠,以减少在高并发下的分配、GC 压力和阻塞。
Performance Data
这些优化在 vLLM-Omni cookbook 基准测试中带来了可衡量的收益,跨多个模型得到验证。
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× |