AREXOpen in interactive Feed

AREX Feed Article

vLLM 希望 Fractalyze 将 Qwen3-Omni 优化贡献到上游:帖文称单张 RTX 5090 上首音频延迟从 213 ms 降至 23 ms

October 6, 2026

10 月 5 日,vLLM 官方 X 账号 公开称赞 Fractalyze 对 vLLM-Omni 上 Qwen3-Omni 的推理优化,并表示希望这些优化被贡献到上游。帖文转述的测试结果是:单张 RTX 5090、AWQ-4bit 权重、batch 1(批大小为 1)的文本提示测试,把首音频延迟从原版 vLLM-Omni 的 213 ms 降到 23 ms。帖文写道:「我们希望看到这些优化被贡献到上游的 vLLM-Omni,让更多用户受益!」

这组数字来自 Fractalyze 前一天的公布:10 月 4 日,其账号 给出首音频 213 ms → 23 ms、文本生成速度 64.1 → 238.1 tok/s 的对比,注明条件是「同一份 AWQ-4bit 权重、batch 1」。随后的给出了完整测量、配置、限制与复现步骤的链接;这些材料与代码都能在其 vllm-omni fork 的 上找到。据 Fractalyze 的 ,他们用编译器加速 AI 与密码学计算。

另一组容易混淆的数据来自 vLLM-Omni :下图记录的是在 A100 上逐层叠加优化后,Qwen3-Omni 首音频时间的下降曲线。它与 Fractalyze 在 RTX 5090、batch 1 下的单组测试环境不同,不能直接比较。

图:Qwen3-Omni 在 A100 上逐层叠加优化后的首音频时间(Time to First Audio),三条线对应并发 1、4、10。

三组对照,一张 RTX 5090,同一份权重

Fractalyze 的写明了实验设置:10 月 2 日,三组配置在同一张 RTX 5090 上先后各跑一轮,使用同一份 AWQ-4bit 权重(cyankiwi 发布的 Qwen3-Omni-30B-A3B-Instruct 量化版)。每轮是 3 个文本提示各重复 5 次,先跑一个预热请求,之后再发 15 次探测请求。首音频(time to first audio,TTFA)指流式返回里第一个音频 chunk 到达的时间,TTFT 指第一个文本 token 到达的时间;RTF 是生成耗时与音频时长的比值,越低越省时间。

配置首 token(TTFT)首音频(TTFA)文本速度RTF
原版 vLLM-Omni57 ms(49~60)213 ms(206~220)64.1 tok/s0.112
确定性 Marlin18 ms(17~19)42 ms(39~43)185.2 tok/s0.058
kernels(全部开启)16 ms(15~17)23 ms(21~24)238.1 tok/s0.052

表内数字是首轮 15 条回复的中位数,TTFT 与 TTFA 括号内为最小~最大;之后追加的 15 次探测请求给出同一量级的 TTFA:214、41、23 ms。Fractalyze 的把这组结果概括为:首音频时间约为原来的九分之一,文本速度接近 4 倍。

对照组跑在 vLLM-Omni 的 69de153f 提交上,部署配置由上游的双 H100 配置改写成单卡版本,显存、长度与批大小等限制按 32 GB 收紧。两个优化组跑在同一展示分支的 379804a6 提交上,第二行启用了确定性 Marlin 和少量开关,第三行开启全部内核与开关。质量检查用 Qwen3-ASR-1.7B 把每条回复的音频转写回文本、再与该回复自身的文本比对,15 条回复上三组分别为 1.59%、2.64% 和 1.01%。这组数字由 Fractalyze 自行测量并公开,测量文档给出了每组的提交、配置与运行环境,可供他人复现。

megakernel 与「把第一帧提前」

Qwen3-Omni 的语音输出是一条三阶段流水线:Thinker 负责多模态理解与文本生成,Talker 把隐状态转成 codec token,Code2Wav 再把 codec token 解码成波形。用户听到的第一个声音,取决于这三段何时把第一块数据交给下一段。vLLM 博客今年 7 月的一篇逐层拆解过这条链路:批处理、CUDA Graph、async chunk(阶段间的异步分块交接)、异步输出、阶段副本、热路径清理,每一项针对不同环节;其中 async chunk 处理的,是下游阶段等齐整段上游数据带来的延迟。

图:Qwen3-Omni 在 vLLM-Omni 中的三阶段流水线。文本由 Thinker 流出,音频要经过 Talker 与 Code2Wav 才会出现第一个 chunk。

Fractalyze 在里列出两类改动。一类把阶段内的计算收进更少的内核启动:Thinker 的每个 decode 步骤、2~64 个 token 的提示块各用一次内核启动,Talker 的 decode 步骤和 code predictor(每帧生成 15 个 code)也是每次启动一个内核;这些 megakernel 按 RTX 5090 的计算架构 sm_120a 编译。Code2Wav 只在流式尺寸下捕获 CUDA Graph。另一类改动让首音频更早出现:Talker 的第一个音频帧随自己的预填充(prefill)一起发出,并在 Thinker 吐出第一个 token 时拿到输入;启用 FRAME0 时,这一帧直接用 Code2Wav 的权重解出来,经 CUDA IPC 送到 API;阶段之间用事件唤醒替代 1 ms 轮询;Talker 生成第一个音频帧时,Thinker 的 decode 最多让出 12 ms。async chunk 的首块也从默认的 4 个 codec 帧改成 1 帧。

表里的「确定性 Marlin」解决的是另一个问题:原版 vLLM-Omni 在 Marlin MoE(混合专家)上,相同请求可能因 split-K 归约顺序(随原子操作的行序而定)得到不同文本;补丁在预填充的分组矩阵乘(GEMM)前把每个专家的行排序,让相同请求得到相同比特。该分支固定依赖上游 vllm==0.30.0,所以这个修复以补丁形式随分支携带。启用这些开关时,三个阶段靠 CUDA MPS 共享同一张 GPU,让各自的核并行执行而不是分时轮转;所有开关默认关闭,需要显式设置 VLLM_OMNI_* 环境变量。

边界:文本提示、batch 1、一张 RTX 5090

已公布的测量对应一组具体的测试条件:一张 RTX 5090、文本提示输入、批大小为 1,样本为 3 个提示、每组 15 条计时回复。展示文档还列出几条适用边界:带图像或视频输入的提示、超过 64 个 token 的块,以及一个批次里有两个请求时,Thinker 仍走原版前向;在部分开关下,带音频、图像或视频输入的提示也保持原版路径。文档也提醒,kernel 的 CTA(线程块)数会改变归约的拆分方式,同一提示的文本会随 CTA 设置变化,只有在固定设置下才能逐字复现。

代码在 fork 分支,vLLM 希望贡献到上游

这批代码目前公开在 Fractalyze 自己的 fork 分支上。10 月 6 日核对上游仓库 (vLLM 项目下做全模态模型推理的框架)时,主分支文件树里还没有出现 megakernel 相关路径。

上游本身也在为缩短首音频时间叠加优化。vLLM-Omni 官方文档把 Qwen3-Omni 与 Qwen3-TTS 的语音生成放在一起,记录了批处理、CUDA Graph、async chunk 与流式输出如何逐层压低首音频时间;前面那张 A100 曲线就出自这份文档。Fractalyze 的部署配置也启用了上游已有的 async chunk。

回复里的两个问题:音频输入和并发

vLLM 帖文下,X 用户 问:「batch 1 下 23 ms 的首音频令人印象深刻。换到音频输入、再开几个并发会话,它还成立吗?那才是我想要的语音服务器数字。」另一位用户 则指出,batch 1、独占一张 5090 是最好的情况,首音频延迟会随排队退化,「batch 1 的 9 倍,到 batch 8 可能小得多」;而到了 23 ms 这个量级,瓶颈可能已经转移,「低于约 100 ms 时,语音代理里被感知到的延迟主要来自端点检测和网络」。

两位回复者关注的音频输入与并发会话,不在这次测量覆盖的条件里。接下来可以核验的两件事,一是这两类场景下的首音频数字,二是这批优化能否从 fork 分支进入 vLLM-Omni 上游仓库。

参考链接

  • *