vLLM 在 Vera Rubin NVL72 上跑 DeepSeek-V4.1-Flash:吞吐达 GB300 NVL72 的 58 倍,单用户 387 tokens/s
DeepSeek-V4.1-Flash on Vera Rubin NVL72: 58x Throughput vs. GB300 NVL72 at 387 tokens/s
vLLM 团队在单台 NVIDIA Vera Rubin NVL72 上服务 DeepSeek-V4.1-Flash,每 GPU 吞吐 1.7M tokens/s、单用户 387 tokens/s,为 GB300 NVL72 的 58 倍,峰值吞吐 2.52M tokens/s、单用户最高 1,810 tokens/s。
vLLM 团队公开了在 Vera Rubin NVL72 上把 DeepSeek-V4.1-Flash 推到 58 倍 GB300 吞吐的逐项内核与内存池优化细节。

TL;DR:在一台 NVIDIA Vera Rubin NVL72 机架上,vLLM 以每 GPU 1.7M tokens/s 的速度服务 DeepSeek-V4.1-Flash,同时每个用户获得 387 tokens/s,是 GB300 NVL72 的 58×,峰值吞吐达到 2.52M,单用户达到 1,810 tokens/s。这些提升源于在 Rubin 的新特性上构建:针对其分离式内存和 FP4 张量核心调优的内核、面向低延迟的专用 decode 内核,以及通过 NVLink 共享的机架级 KV cache 和 Engram 表。
这是 DeepSeek-V4.1-Flash 系列的第三篇文章。第一篇介绍了 day-0 启动和内核融合。第二篇通过 P/D 分离和 Wide-EP 将模型扩展到 GB300 NVL72 机架。本文把同一套栈迁移到我们上个月介绍过的 Vera Rubin NVL72。
Rubin 开辟了新的优化途径。我们先从塑造了我们工作的硬件事实出发,然后依次介绍四组优化:
- 面向 DEP prefill 和 decode 的 Rubin 优化内核。1 我们为 Rubin 重做了 MoE、attention、GEMM、mHC 和 indexer 内核:受带宽限制的数据留在每个 SM 自己的内存域中,SM107 更宽的 MMA 指令每次发射完成更多工作,内核在等待之前就开始加载及其依赖项。DEP2 prefill 步骤约快 28%,DEP decode 步骤约快 25%。
- 面向最低延迟的专用 TP decode 路径。我们执行跨算子融合、将计算与通信重叠并进行调优,然后用 TP8 将模型分布到两个托盘上,在 batch size 为 1 时达到 1,810 tokens/s(P90)。
- 基于机架级内存池的 Dynamo 工作负载感知路由。Rubin 的速度带来高得多的并发度,因此我们池化机架内存:Mooncake KV 池从 DRAM 扩展到空闲 HBM,Engram 表分片到各 GPU HBM 上。即使在极高并发下,前缀命中率仍保持在 96.5–97%,仅靠路由就能在各 rank 间实现均衡。
性能概览
图 1:SemiAnalysis AgentX 在 NVIDIA Vera Rubin NVL72(vLLM、P/D 分离、Wide-EP)与 GB300 NVL72 上的对比。吞吐量统计缓存输入、未缓存输入和输出 token(GB300 来源)。
我们使用 SemiAnalysis AgentX 基准测试来衡量性能,作为具有代表性的 agentic 服务负载,与之前的文章保持一致。图 1 分别在两个标签页中比较了两个机架的原始吞吐量(每 GPU 每秒总 token 数,包括输入、缓存和输出)和功率归一化吞吐量。
我们如何测量
我们采用与上一篇 GB300 文章相同的方法。对于内核和模型前向分析,vllm bench forward 通过真实的 execute_model 路径对精确的 prefill 和 decode 批次计时,使用真实权重和真实 AgentX token。我们在运行数秒的循环中对 prefill 内核进行 A/B 测试,并在数值有差异时报告持续数值。
从 DeepSeek-V4.1-Flash 的视角看 Rubin
Vera Rubin NVL72 的三个特性驱动了下面的大部分决策。当某项优化是 Rubin 特有的,我们会说明它依赖其中哪一个。
- 每块 GPU 有两个内存域。SM 读取自身域的速度远快于交错内存,从另一个域读取则更慢。正如 Rubin 预览 所示,这对带宽受限的数据很重要:MoE 权重、LM head、MegaMoE 的 combine 缓冲区以及 mHC 残差流。
- SM107 新增了更宽的块缩放 MMA 指令。我们在 MegaMoE 和低延迟路由 GEMM 中使用了新的 K64 混合精度(FP8×FP4)MMA,每条指令完成的工作量翻倍:MegaMoE 在每 rank 8K+ token 时吞吐量提升 8–11%,低 batch size 的路由 GEMM 运行速度提升 12%。在 indexer 中,新的 K128 FP4 MMA 配合六 token 查询 tile,使 decode MQA-logits kernel 提速 15–22%。
- 72 块 GPU 共享一个 NVLink 域。TP8 可以跨两个计算托盘,几乎不增加 all-reduce 开销。Prefill 实例可以高效读取彼此的 HBM,因此大表不再需要复制到每个实例。
图 2:路由专家 GEMM 在单个 SM 共享内存中的权重阶段,分别使用 SM100 MXFP8×MXFP4 MMA 和 SM107 的 K64 MXFP8×MXFP4 MMA(基于打包 FP4)。
深入优化
Kernel
我们保留了 GB300 的三种引擎形态:DEP2 prefill、Wide-EP decode(DEP16 或 DEP32),以及用于最低延迟的 TP decode 路径(见下一节)。我们还保留了 DeepSeek 的 kernel 集合(MegaMoE、MegaAttn、Mega-mHC、MegaGate、DeepSelect),并针对 SM107 重建了其中大部分。
DEP prefill:每步耗时减少约 28%
在每 rank 32K token 时,prefill 步骤主要由专家 GEMM 主导;其余大部分时间用于将残差和 attention 的工作集通过 HBM 流式传输。因此这一轮的工作集中在 GEMM 周边的 kernel 以及 Rubin 的两个内存域上:Mega-mHC 将残差保留在 die-local 内存,MegaAttn 让其 tensor core 持续发射而不是等待加载,MegaGate 只对仍有可能进入 top 6 的专家打分。这些改进合计将 32K token 的 DEP2 prefill 步骤缩短了 28%。
图 3:prefill kernel 的三项改动:Mega-mHC 的 die-local 残差、MegaAttn 的流水线和 MegaGate 的候选过滤,以及它们累计带来的步骤耗时变化。
Prefill 优化细节
- MegaMoE:按最繁忙的 rank 确定 tile 大小。vLLM 在 eager prefill 中不会对 DP batch 做填充,因此在 86% 的真实 DEP2 prefill 步骤中,空闲 rank 按自身极小的 token 数来确定 MegaMoE tile 大小,而其专家却在服务繁忙 rank 的 token。现在 tile 大小跟随本地与 DP 平均 token 数中的较大者。在 40 步回放中,MegaMoE 时间下降 55%;在空闲 rank 旁,单请求 TTFT 在 8K 到 32K token 范围内改善 13–39%。
- Mega-mHC:残差流放在 die-local 内存中。在 prefill 规模下,Mega-mHC 受 HBM 带宽限制,每 token 流式传输约 100 KB 的四路残差。现在残差存放在一个跨两个内存域条带化的池中,Mega-mHC 为每个域维护一个任务计数器,因此每个 SM 先排空自己的域,再去帮助另一个域。这导致大网格受指令缓存限制,因此它们现在循环执行一份 Post 主体,而不是四份。在 32K token 时,Mega-mHC 每次调用从 354 µs 降至 317 µs;5K+ token 的 DEP2 步骤提速 0.6–1.3%。
- 在 SM107 的 K64 块缩放 MMA 上做 query 上投影。MegaAttn 的 [tokens × 1,280] × [1,280 × 32,768] query GEMM 从 cuDNN 的 SM100 kernel 迁移到 FlashInfer 的 CuTe DSL GEMM,使用 SM107 的 K64 MMA:在 4K 到 32K 行范围内提速 13–18%,在 16K–32K 时 DEP2 步骤耗时减少 1.1–1.7%。
- MegaAttn:让张量核心持续运转。在每个 rank 16K–32K token 的场景下,稀疏注意力受限于发射和加载延迟。现在空闲的 warp 会发射 SV,因此 QK 不再排在它们后面等待;KV 生产者会在等待槽位之前加载下一个块的 top-k 索引;集群启动控制 warp 会将下一个作业的索引行预取到 L2;下一个作业的查询会在当前作业最后一个 QK 之前加载。每个 TMEM lane 组现在会完整地为自己的键打分,因此 softmax 不再通过共享内存交换部分和。该内核在 16K–32K token 时快 15%,在 4K 时快 23%,DEP2 步骤提升 0.9–2.1%。
- Mega-mHC:带票据的任务环。在长提示下,固定的任务步幅使 RMSNorm worker 远远落后于 Post,导致它们重读 Post 的输出时未命中 L2。大网格现在从原子票据计数器领取任务(32K 时 −18%)。Norm 任务还会预先发出所有加载,下一个任务的系数提前到达,并且两个 Post warpgroup 共享同一份代码副本以节省指令缓存:在 4K 到 32K token 范围内,每次调用又提升 13–22%。
- MegaGate:每个 token 只读一次,只给竞争者打分。对于长提示,一对 CTA 从同一个共享内存阶段(M=256 和 M=128 UMMA)计算一个 token 块的全部 384 个专家,而不是按每 128 个专家组重读 token。路由器只对仍有可能进入前 6 的专家计算精确的 sqrt-softplus:第六大分数的上界和该函数的斜率给出每个专家的阈值,384 个中约有 7 个通过。该内核从 4K token 起快 3–13%(32K 时 77 → 68 µs)。
DEP 解码:每步时间减少约 25%
解码受 MoE 限制,与 GB300 上相同。与我们首个 Rubin 构建(该构建已具备 die-local 权重)、Wide-EP 调度变更和 MQA logits 变更相比,这些优化将 DEP32 解码步骤的目标前向(每个 rank 20 个请求 × 6 个 token,DSpark k=5,在单个 4-GPU 节点上模拟)缩短了约 25%。
图 4:Wide-EP 解码变更中的四项:die-local 专家权重、每个调度 token 一次 NVLink 往返、等待数据的 combine,以及跨 SM107 集群的 split-K 投影。
解码优化细节
- Die-local MegaMoE 权重。解码 MoE 受权重读取限制,而 SM 流式读取自己的内存域比交错内存快得多。vLLM 按输出列将专家权重拆分到各域,MegaMoE 只给每个域的 SM 分配本地 tile。DEP2 解码前向在批大小 32 时快 10.1%,在 168 时快 5.5%。
- Wide-EP 调度:每个 token 一次 NVLink 往返。在 DEP8 解码时,NVLink 仅以峰值的 39% 运行。每个拉取的 token 现在会在任何本地存储之前发出所有远程加载,只支付一次往返而不是两到三次。Warp 通过一次 fence 和一次选出的 release 发布拉取,专家计数以不返回的
red原子操作发出,因此第一个 SM 的 392 次远程更新不再串行化。MegaMoE 在 DEP8 时快 17%(192 → 160 µs)。 - MegaMoE:一个等待数据而非屏障的 combine。 combine 缓冲区在每次启动时都填入一个任何输出都无法取用的哨兵值,因此 CTA 在自身的 GEMM 任务完成后即可立即进行 combine,只重新读取仍持有哨兵值的 16 字节组,然后将其恢复。跨 rank 的尾部屏障在本次启动结束时发出信号,并在下一次启动开始时等待。在本地专家较少时,所有第一次 GEMM 任务都会在任一第二次 GEMM 任务之前被认领,从而保持权重持续流式传输。MegaMoE 在 decode 规模下提速 3.5–10.8%。
- SM107 集群上的 Split-K GEMM。 每个 rank 只有几十行时,注意力输入和输出投影启动的 CTA 太少,无法以全带宽流式传输权重。Split-K GEMM 将 K 分散到 SM107 集群上,并通过分布式共享内存归约部分和;当 CTA 的对等切片超过 28 KB 时,则从寄存器经 L2 归约。这些 GEMM 提速 10–38%,decode 前向在每 rank ≤16 个请求时提速 3.1%,在 17–24 个请求时提速 1.9%。
- MQA logits:六 token 分块与 SM107 的 K=128 MMA。 DSpark 验证每个请求向 indexer 发送 5–6 个 query 行。该 kernel 现在将它们打包成一个 192 宽的 tile,运行在两个 warpgroup 上,而不是两个 4-token tile 运行在三个 warpgroup 上;每个 128 维 head 作为一次 SM107 K=128 MMA 发出,而不是两次 K=64 MMA;并以立即数偏移存储,无需按 split 进行 64 位地址运算:在每请求 5–6 个 token 时提速 15–22%。
- Split Mega-mHC:关键路径上只保留下一层所需的部分。 下一层需要 Mega-mHC 的 Post、route collapse 和 RMSNorm,但不需要其后续的 mixes。现在一个小 kernel 只执行这三项,而 mixes 在旁路流上运行,并在下一个边界处汇合。它以合并的 16 字节块移动每条 route,每个 CTA 最多处理三个 token,因此在 212 个 SM 上 636 个 token 可在一波内完成。decode 前向在每 rank 20–30 个请求时提速 2.0–4.8%;合并重写使该 kernel 在 18–192 个 token 时再提速 30–58%。
- MegaAttn decode:更深的流水线。 Decode 注意力每个 CTA 运行一到两个 token,形成一条由 index 加载、KV 收集与解包,再到逐块 QK、softmax 和 SV 组成的延迟链。现在有三块 index 加载和四批 gather 保持在进行中;当每个 SM 只有一个任务时,空闲的 query warpgroup 负责解包 KV;kernel 在自身依赖等待结束后立即触发依赖项,使输出投影的序言与注意力重叠。该 kernel 在 6–424 行时提速 7–10%。
低延迟:带 TP 的专用 decode 路径
为实现最低延迟,我们运行一条专用的 decode 路径。我们从 GB300 文章中移植了它,为 Rubin 做了大幅重建,并将其以 TP8 分布在两个计算托盘上。在并发为 1 的真实 AgentX 会话中,固定 DSpark 接受率为每步 3.51 个 token,P50 下每用户从 1,117 token/s 提升到 1,844 token/s。除第一个专家 GEMM 外,一步就是一条由接近其延迟下限的小 kernel 组成的链。
图 5:专用 TP8 decode 路径的一步:引擎分布在两个计算托盘上,以及逐层 kernel 链及其边界已融合。
低延迟优化细节
- 跨两个托盘、基于 NVL72 的 TP8。 每个 rank 持有每个专家的 288 列切片和 8 个注意力 head。跨托盘 all-reduce 仅比托盘内 all-reduce 多 0.3 µs,因此 TP8 几乎免费地将每 GPU 权重读取减半。借助路由 GEMM 和稀疏 MLA 的原生 TP8 形状,一步提速 35%。
- SM107 上的 Packed-FP4 权重分级。第一个专家 GEMM 受限于每个 SM 在飞行中保留的权重字节数。UMMA 描述符只能寻址 256 KB 的共享内存,在 SM100 的单字节 FP4 布局下可容纳 7 级。SM107 的 K64 MMA 读取 packed FP4,因此同样的空间可容纳 11 级(图 2),每步节省 57 µs。
- 裸片本地 LM head。LM head 读取其权重的副本,该副本拆分在两个内存域中。每个 SM 只流式读取自己那一半,接近域本地上限。
- 一次完成 all-reduce 和 mHC。两个 all-reduce 都从各自的 GEMM 尾声直接发布到 Lamport 邮箱,使用 NVLink 多播存储。接收内核对各 rank 求和,应用 mHC Post,折叠四条路由并计算 RMSNorm;在 MoE 边界处,它还在网格等待之前运行 router GEMM(每步约 −30 µs)。下一层的 mHC pre-norm 在侧流上运行,分成 64 路(5.8 → 3.7 µs),路由 GEMM 为它留出 Rubin 212 个 SM 中的 16 个(−4 至 −10 µs)。
- 稀疏 MLA。在 TP8 下,每个 rank 运行一个 8 头稀疏 MLA 内核。当前一个内核仍在运行时,它收集除本步新增行之外的所有 KV 行,每个 PV 块在其 MMA 完成后立即将部分结果发送给所有者(−16 至 −21 µs)。Query RoPE 和 KV-cache 插入被融合到注意力周围的内核中,注意力也提前启动其序言(再 −36 µs)。
- 共享专家嵌入路由 GEMM。共享专家在 80% 的层中是 MoE 子层的尾部。在少于 16 行时,它现在运行在路由 GEMM 内部,每步节省 220 µs。
- 提前启动下一个内核。all-reduce 终结器在其自身网格等待后立即启动其依赖项(−16 µs),索引器的 MQA logits 在网格同步之前加载 KV(−24 µs)。
- Engram all-gather 在该层的流上。在 TP8 下,NCCL all-gather 在 Engram 的关键路径上增加了 22 µs。融合入口内核和该层自身流上的 Lamport all-gather 每步节省约 40 µs。
Dynamo 工作负载感知路由 + 机架级共享内存池
Rubin 计算速度快,因此一个机架能维持比 GB300 高得多的并发度,而所有这些智能体会话的活跃前缀超出了任何单 rank 缓存。在 GB300 上,我们将前缀保存在单 rank CPU 层中,并将每个会话固定到一个 rank;在 Rubin 的并发度下,该层太小,而固定导致一些 rank 空闲而另一些排队。我们通过在整个机架上池化内存来将内存推到极限:KV 放在 DRAM 和备用 HBM 中,通过 RDMA 加载,Engram 表放在 HBM 中,通过 NVL72 的 NVLink 读取。即使在非常高的并发度下,前缀命中率仍保持在 96.5–97%,接近理论命中率。由于没有会话绑定到某个 rank,仅工作负载感知路由就能保持各 rank 均衡。
图 6:每个 prefill rank 通过机架的 DRAM 和备用 HBM(RDMA)从一个 Mooncake 池加载 KV,并从对等节点的 HBM(NVLink)读取 Engram 表,因此 Dynamo 路由器可以将每个请求发送到负载最低的 rank。
Mooncake 池。 一个 Mooncake 存储横跨每个 prefill 和 decode tray 的 DRAM,取代了每 rank 的 CPU 层级,因此任何 rank 都可以通过 RDMA 加载任何前缀,被迁移的请求只需一次 KV 加载,而非重新计算。我们优化了 prefill 调度器等待该池的方式:查找在进程外异步运行,已在本地 HBM 命中的请求跳过查找但仍刷新其租约,KV 加载在查找返回时立即开始,而不是等到下一步。因等待查找而导致 prefill 步骤填充不足的时间占比从步骤时间的 6–14% 降至 0.5% 以下,因等待 KV 加载而填充不足的时间占比从 13.5% 降至 1%。
HBM 池。 DeepSeek-V4.1-Flash 很小,其每 token 的 KV 缓存也很小,因此服务一个请求只用到 prefill 和 decode GPU 的 HBM 的一小部分。一旦 Mooncake 持有前缀,其余部分就会闲置。现在每个 prefill rank 只保留足够一个最大长度请求使用的 KV 缓存,并将其余 KV 预算作为 HBM 段交给 Mooncake,大小自动确定,从而将池从 DRAM 扩展到每个 prefill GPU 的空闲 HBM;这些段通过相同的 RDMA 路径读取。HBM 池仍处于实验阶段。
Engram 池。 两个角色现在都将 Engram 的两张 94.4 GiB 哈希 n-gram 表保存在 HBM 中。Decode 已将它们拆分到其 DP rank 上(vllm#54371),但每个 DEP2 prefill 实例都在主机内存中保留了自己的副本,每个 tray 约 378 GiB。在 NVL72 上,prefill 引擎现在组成一个对等组来拆分这些表,18 个 GPU 上各 10.5 GiB,其余部分通过 NVL72 的 NVLink(而非 RDMA)从对等节点的 HBM 读取(vllm#66552,图 7)。查找比从主机内存读取时更快,释放出的主机内存可容纳约 1,500 个更多会话的活跃前缀。
图 7:每个实例的 Engram 表在主机 DRAM 中(之前)与拆分到对等组 HBM 上(之后)的对比。
工作负载感知路由。 由于每个前缀都在共享池中,会话不再需要固定在一个 rank 上,这消除了会话亲和性导致的 DP 不均衡。Dynamo 将每个请求放置在未缓存工作量最少的(worker, DP rank)上,这仅是配置更改。在三个 DEP2 实例、并发 4,800 的情况下,池加上路由使服务的请求数增加 68%,TTFT P50 从 29.8 s 降至 4.2 s,命中率从 91.8% 提升至 96.1%(图 8)。在 12 × DEP2 模拟中,一个 rank 空闲而另一个 rank 排队的时间从 10.3% 降至 1.3%,TTFT P90 从 0.98 s 降至 0.38 s。
图 8:三个 DEP2 prefill 实例在并发 4,800 时的请求数/秒、TTFT P50 和命中率。
致谢
我们感谢 DeepSeek 开源 DeepSeek-V4.1-Flash 及其内核,感谢 NVIDIA 提供 Vera Rubin NVL72 的早期访问。我们特别感谢 NVIDIA 的 Hanjie Qiu、Lisa Wang、Jie Hao、Yaoyao Ding、Pei Li、Xin Li 和 Pen Chung Li 在性能优化方面的密切合作以及对 vLLM 和 Dynamo 的持续支持。我们也感谢 Mooncake 团队提供的 KV 缓存存储,以及 SemiAnalysis 开发的 AgentX 基准测试。
本工作由 Inferact 主导。
脚注
-
DEP2、DEP16 和 DEP32 指在 2、16 和 32 个 GPU 上的数据并行注意力加专家并行。 ↩
来源:vLLM Blog · vllm.ai