先看证据

Ling-3.0-flash-fp4(124B 参数,5.1B 激活)测试模型
NVIDIA DGX Spark(GB10,128 GB 统一内存,273 GB/s)运行硬件
GSM8K 准确率从 96.89% 微降至 96.82%(无统计学显著差异)关键事实
GSM8K 任务解码吞吐从 37.81 升至 53.89 tok/s(+42.5%)关键事实
平均端到端延迟从 15.21 秒降至 11.49 秒(-24.5%)关键事实
TPOT 从 26.45 ms 降至 18.56 ms(-29.8%)关键事实

第一把杠杆:为真实形状编译内核

NVIDIA 在开发者博客上发布了一组针对 MoE 推理的调优结果。测试对象是蚂蚁集团 inclusionAI 的 Ling-3.0-flash,一个总参数 124B、每个 token 只激活 5.1B 参数的 MoE 模型,原生支持 256K 上下文。运行环境不是数据中心机架,而是一台 DGX Spark:基于 GB10 Grace Blackwell 超级芯片,128 GB 统一内存,内存带宽 273 GB/s,稀疏 FP4 峰值算力约 1 petaFLOP,官方标称可推理最高 200B 参数的模型。整个测试的 batch size 固定为 1。

这个配置值得单独说清楚,因为它决定了后面所有数字的含义。DGX Spark 是一台桌面系统,它服务的场景是单人、单请求、本地推理,而不是多租户吞吐。128 GB 统一内存让 124B 的 FP4 权重能塞进来,但 273 GB/s 的带宽与数据中心 GPU 动辄数 TB/s 的 HBM 不在一个量级。于是问题从“算得快不快”变成了“每生成一个 token 要读多少字节”。NVIDIA 的性能分析给出的答案很直接:解码阶段受内存带宽限制,读取模型权重主导了执行时间。

突出出来的两个耗时点是 MoE 专家计算和 LM head 的词表投影。前者因为路由机制每次只激活部分专家,后者因为每次生成 token 都要把整个词表矩阵读一遍。这两个观察直接对应两把杠杆:让每个解码步少搬字节,让每次验证多产 token。三项优化就是围绕这两把杠杆展开的。

第三把杠杆:让一次验证换回更多 token

LM head 是一个 157,184 × 2,560 的矩阵,以 BF16 存储。每生成一个 token,整个矩阵都要被读取一遍。在 batch size 为 1、带宽受限的场景里,这不是一个可以忽略的常数项,而是一笔稳定的每步税。

NVIDIA 的做法很克制:只对这一层在加载时做在线 FP8 量化,其他权重不动。读取量直接减半。启用方式是设置环境变量 SGLANG_ENABLE_FP8_LM_HEAD=1,注意它与基线的 --enable-fp32-lm-head 互斥,两者不能同时开。这个细节值得留意,因为它暗示了这条路径在框架里是分支实现,而非正交开关。

与 Humming 组合后,合成负载吞吐达到 43.94 tokens/s,相比基线提升 21.7%,相比只用 Humming 再提升 11.4%。把两项放在一起看,可以清楚看到它们的收益是加性的:一个减少每步的内核开销,一个减少每步的权重读取,两者的成本模型不重叠。

真实负载上的结果:42.5% 从哪里来

前两项优化的方向是“每步更便宜”,第三项改的是“总共多少步”。Ling-3.0-flash 内置了 NEXTN 预测层,因此不需要额外挂一个草稿模型:草稿一次提出 3 个 token,目标模型在一个 4 位置的验证窗口里一次核对它们。

代价结构必须算清楚。一次验证的花费约为普通解码步的 2.26 倍,而且主要成本仍在 MoE 而非注意力:验证四个 token 时,最多可能激活 32 个专家而不是 8 个。所以 MTP 是否划算,几乎完全取决于每轮能接受几个 token。在合成负载上,平均每轮接受 3.90 个 token,吞吐跳到 102.88 tokens/s,相对基线提升 185.1%。这个数字看起来惊人,但它是最有利于推测解码的那类负载。

NVIDIA 自己在材料里明确提醒,不能拿合成负载的增益外推到其他场景。原因也写得很直白:合成输出更重复、采样方式不同、输出长度分布也不同。接受长度是这三项优化里唯一高度依赖输入分布的量,也是整篇文章最容易被误读的那个数。

叠加不是自动的:一次静默回退的陷阱

为了给出一组更贴近实际的结果,团队跑完了 GSM8K 全部 1,319 道题,采用 5-shot 提示与思维链,batch size 仍为 1。这里的关键变化是接受长度:从合成负载的 3.90 掉到 2.68。MTP 的收益被直接削掉一截,但仍然为正。

| 指标 | 基线 | 三项叠加优化 | | --- | --- | --- | | 解码吞吐 | 37.81 tok/s | 53.89 tok/s(+42.5%) | | 平均端到端延迟 | 15.21 秒 | 11.49 秒(−24.5%) | | TPOT | 26.45 ms | 18.56 ms(−29.8%) | | P50 / P95 延迟 | 8.36 / 50.20 秒 | 6.11 / 38.60 秒 | | GSM8K 准确率 | 96.89% | 96.82% |

这张表里最值得看的不是吞吐那一行,而是最后一行。准确率从 96.89% 变成 96.82%,NVIDIA 称差异没有统计学上的可检测性。这意味着 FP8 词表量化与推测解码叠加后,没有在这份评测上换来可测量的质量下降。P95 延迟从 50.20 秒降到 38.60 秒,说明优化不是只改善了平均值,长尾也被一起拉短了,这对交互式使用体验更为关键。

顺带说明一处需要核对的地方:中文页面把准确率差异写成 +0.08,但两组数字是 96.89% 和 96.82%,方向应当是下降,英文表格也把差值列为负。这是翻译或表格排版上的不一致,不影响结论,但引用时最好以英文表的符号为准。

该带走什么,该怀疑什么

三项优化在成本模型上不重叠,Humming 和 FP8 LM head 削减每步开销,MTP 削减步数,所以它们理论上可以叠加。但这不等于叠加是免费的。NVIDIA 指出一个具体条件:FP8 LM head 与 MTP 同时开启时,草稿必须共享完整的 LM-head 模块。如果没做到,框架会静默回退,草稿会把 FP8 权重当成 BF16 来解读。

静默回退的后果很严重:接受长度掉到 1.00,也就是每一轮草拟全部被拒,只能退化为一次一 token,而验证的额外成本照付。吞吐于是跌破未优化的基线。这不是性能打折扣,而是比什么都不做更慢。对一个刚照着清单打开三个环境变量的工程师来说,这是最难排查的一类问题,因为你看到了“优化已启用”的配置,却得到了负收益。

NVIDIA 的应对建议朴素但有效:在启动时逐项确认每个优化真的生效,并指向 Ling cookbook notebook 中同时开启两者的正确写法。这其实给所有做推理部署的团队提了一个通用要求:当优化项之间存在隐式的模块共享约定时,“配置项已开”不能作为“优化已生效”的证据,必须有运行时校验。

如果只记一个数字,42.5% 并不是最有信息量的那个。更有用的是这套方法的分工:先 profile 确认瓶颈在带宽,再分别针对内核开销、权重读取、解码步数出手,最后在真实负载上验证,并主动说明合成负载的增益不能外推。+185.1% 与 +42.5% 的落差不是失败,而是推测解码的正常代价:它的收益天然由输入分布决定,重复性高的内容接受率高,需要谨慎推理的思维链输出接受率低。

放到更大的背景里,这套技术并不新。MoE 已经是被反复验证的架构选择,推测解码也早已是主流推理栈的标配。真正有信息量的是它们在一台 273 GB/s 带宽的桌面系统上如何组合,以及组合后要付出什么调试成本。对打算在桌面工作站部署大模型的人来说,可执行的判断有三条:一是确认模型是否自带预测层,否则 MTP 需要额外草稿模型,成本结构会变;二是把 FP8 LM head 当作单层改动来评估,它影响的是每 token 固定读取开销,在小 batch 场景收益明显;三是在启动脚本里加断言,确保每个优化项真的生效。

最后要说清边界。所有数字都来自 batch size 为 1 的单用户场景,评测集只有 GSM8K 一个,准确率的“无显著差异”也只在这个范围内成立。当 batch size 扩大,瓶颈会从权重读取转向算力与调度,三项优化的相对收益会重新分配,NVIDIA 的材料没有覆盖这一点。在把那 42.5% 写进任何容量规划之前,先在自己的负载上跑一遍接受长度,这比相信任何一个整篇博客里的峰值都更可靠。