B300集群实战:NVFP4量化与P-D分离部署大模型吞吐调优
2026/9/8 7:29:51 网站建设 项目流程

1. 为什么用 B300 跑这两个模型

B300 出来之后,我们内部就在盘算手上的模型服务要不要迁过去。手里正好有 GLM-5.2-NVFP4 和 Kimi-K3 两组测试权重:前者是官方直接发布的 NVFP4 量化版本,后者我们先用 BF16 跑基线、再切 FP8 对比。在 16 卡 B300 集群上测出来的吞吐、缓存命中和部署手感,基本代表了当前 4-bit 推理的主流水平。这篇文章不写云里雾里的理论,就把我们拿到机器后从零搭环境、测压、调参、踩坑的全过程摊开聊。

先说结论,方便没时间看完全文的同学:

  • 16 卡 B300 拆成 2 组 TP=8 副本,跑 GLM-5.2-NVFP4,256 并发、共享系统提示词占比约 70% 的混合负载,综合吞吐大约比同模型 FP8 版本高 1.6~1.9 倍;
  • P-D 分离加 prefix cache 配置到位后,输入侧有效吞吐能翻 2 倍以上,TTFT(首 token 延迟)从 1.2s 压到 400ms 以内;
  • NVFP4 在 B300 上不是单纯省显存,它把权重搬移量砍半,decode 阶段直接吃满内存带宽的增益;
  • 网络层有一个坑:CX8 网卡的归属和固件版本必须提前确认,我们为这个排查了整整一个下午。

这篇内容适合谁看:正在做 B300/GB300 集群评估的 SRE、推理框架开发、运维,或者想在 vLLM/SGLang 上部署 4-bit 量化大模型的同学。新手也能看,原理部分我会尽量讲人话,参数部分可以直接抄。

1.1 模型版本的差异不是名字后缀那么简单

GLM-5.2-NVFP4 不是“GLM-5.2 顺手压到 4bit”这么简单。官方这次是把权重直接按 NVFP4 格式重新规整过,包括通道粒度(per-channel/per-group)的缩放因子都预计算好,推理时不需要在 GPU 上临时做量化,省掉了批处理场景下重复的 quantization kernel 开销。Kimi-K3 目前没有官方 NVFP4 版本,所以我们测的是 BF16 基线和 FP8 在线量化两类配置,作为对照组。

为什么在意这一点?因为“预量化”和“运行时量化”在高吞吐场景下差距巨大。运行时把 BF16/FP16 转成 FP8 或 FP4 需要额外的计算 kernel,虽然 B300 的 tensor core 处理这些很快,但在 memory-bound 的 decode 阶段,任何多余 kernel 都会挤占内存带宽配额。GLM-5.2-NVFP4 这种权重直接以 NVFP4 格式存放的方式,加载时就能直接被 tensor core 读取,完全省掉这部分开销。

1.2 测试指标的选定

我们这次重点看三个指标:

  • 吞吐(tokens/s):分 decode 吞吐和 prefill 吞吐统计,取稳定压测 10 分钟以上的平均值;
  • 缓存命中率(%):输入 tokens 中直接复用 KV cache 的比例,反映 prefix cache 和 P-D 分离的整体配置效果;
  • TTFT / TPOT:首 token 延迟和每 token 延迟,高吞吐场景不能只盯着吞吐,端到端体验要能压住 P99 延迟。

说实话,跑完一轮完整压测之后我的体感是:单卡性能是底座,但真正拉开差距的地方在“缓存命中率”和“调度策略”。同样一批请求,把 prefix cache 配好之后的综合吞吐和没配相比,差距大到离谱。所以后面我用一大节专门讲缓存命中,这部分是最值得抄作业的。

2. 16 卡集群的硬件拓扑与网络细节

这次测试用的集群是 2 台 B300 整机(每台 8 卡),组成 16 卡环境。每张 B300 是 288GB HBM3e,内存带宽标称约 8TB/s,单卡 FP4 稀疏算力比 B200 又涨了一截。8 卡之间通过 NVLink-C2C 加 NVSwitch 全互联,跨节点走 InfiniBand NDR 400Gbps RDMA。整体拓扑不复杂,但有几个点不确认清楚,后面调试会非常折磨人。

2.1 B300 和上一代的差距在哪

很多人问 B300 的“上一代”是啥。按 NVIDIA 这代的命名逻辑,B300 的上一代核心是 B200(Blackwell 架构),再往前是 H200/H100(Hopper 架构)。B300 和 B200 的关系有点像当年 A100 到 H100 的演进:同一个架构代系,但把 HBM 容量、带宽和算力做了整体提升。B300 最大变化是显存从 192GB 提到 288GB,HBM3e 的堆叠容量变大,带宽维持在高位的基础上继续往上顶。

单纯从部署模型的角度说,B300 最大的价值是把“400B 级模型单卡装下”变成了现实。约 400B 规模的参数如果按 NVFP4 算,权重约 200GB,加上 KV cache 和激活,288GB 单卡能装得很轻松;换成 FP8 的话,权重约 400GB,单卡装不下,只能拆双卡,吞吐直接打折。这也是为什么我们这次特别看重 NVFP4 的实测效果——它直接决定了能不能用最小的硬件拓扑跑最大的模型。

2.2 CX8 网卡到底是不是模组自带的

这个热搜问题我们自己也纠结过。简单结论:在 GB300 NVL72 这种机架级整机方案里,CX8(ConnectX-8)网卡是集成在计算模组(compute tray)上的,出厂即带,不需要单独插 PCIe 卡;但在自主组装的 8 卡 HGX B300 基板上,网络接口还是走标准 PCIe 插槽,需要自己配网卡。

我们这套 2 台 8 卡机器属于后者,所以组网时额外配了 CX8 网卡。这里有个非常容易踩的坑:CX8 的 firmware 版本和 mlx5 驱动不匹配时,RDMA 建链会间歇性失败,表现为主机之间 ping 正常、nccl 测试时好时坏,非常难定位。后面排查章节我会详细说。还没下单的朋友建议提前问清楚供应商:机器带的是什么网卡、什么固件版本、驱动是否配套。这三个问题每个都能省你半天时间。

2.3 NVLink/NVSwitch 和 RDMA 的分工

16 卡集群组网时很容易把两个网络混在一起。简单区分:NVLink/NVSwitch 是卡与卡之间的高速互联,带宽极高,但只在单机内有效(同一 NVSwitch 域);跨机器通信必须走 RDMA 网络。

对我们这次部署的影响是:tensor parallel 的通信必须放在 NVLink 域内,pipeline parallel 或 DP 的梯度同步可以放 RDMA。所以 16 卡最自然的切法是两组 TP=8,每组内部 8 卡 NVLink 全互联,两组之间用 RDMA 同步或处理不同的请求。这样每个 GPU 的权重分片只有原模型的 1/8,通信压力小,吞吐最高。我们也试过 TP=16 跨机方案,但因为跨机通信走 400G RDMA,相对 NVLink 还是慢一个数量级,实际吞吐反而掉 15%~20%。

3. NVFP4 量化:显存减半背后的硬件逻辑

如果只看营销材料,你可能觉得 NVFP4 就是“把 FP8 再砍一半变成 4 bit”,听起来很简单。但真正决定它能不能落地的,是硬件在计算时怎么处理这些 4 bit 数据。这一节把原理讲清楚,后面遇到精度或者性能问题就好排查了。

3.1 FP4 不是简单的“多砍一位”

NVFP4 是 NVIDIA Blackwell 架构引入的 4-bit 浮点格式,和传统的 INT4 定点格式有本质区别。FP4 保留了指数位,动态范围比 INT4 大很多,对权重分布不均匀的大模型更友好。具体来说,NVFP4 有两种子格式:E1M2(1 位指数、2 位尾数)和 E2M1(2 位指数、1 位尾数),分别应对权重和激活的不同数值分布特性。

在 B300 的 tensor core 里,FP4 不是靠“把数据转回 FP16 再算”来运行的,而是硬件直接支持 FP4 输入的矩阵乘法。这意味着权重以 FP4 存储在显存里,计算时不需要做解压缩到高精度的步骤,直接进 tensor core。这一步很关键:它同时省了显存带宽和计算时间。打个比方,如果上一代是“货车拉货到仓库再拆箱”,那 B300 跑 NVFP4 就是“集装箱直接放上托盘进仓库”,中间省掉了一次拆箱动作。

3.2 权重预量化 vs 运行时量化

GLM-5.2-NVFP4 是预量化权重,文件在磁盘上就是 NVFP4 格式。加载时 vLLM 直接加载进显存就行,不需要在启动时跑一遍量化 kernel。Kimi-K3 我们测的是 BF16 到 FP8 的运行时量化,每次加载部署时要额外花几分钟做权重转换,而且转换 kernel 还得吃一小部分显存作为临时 buffer。

在我们 16 卡集群上实测:同一模型权重,FP8 在线量化比 NVFP4 预量化每次冷启动多花 4~6 分钟。别小看这几分钟,日常发版、扩副本、故障重启都会遇到,一天发三次版本就多了二十分钟的无效等待。更重要的还是 decode 性能差异,预量化的权重加载路径更短,token 生成阶段的吞吐优势大约在 8%~12%。如果你的模型支持预量化格式,优先选预量化版本。

3.3 精度损失怎么验证

4-bit 量化最让人担心的是精度。我们的验证办法很简单:拿 1000 条业务问句,分别用 FP16 基线、FP8、NVFP4 跑一遍,对比输出文本的 ROUGE-L 相似度和下游任务的准确率。GLM-5.2-NVFP4 官方预量化版本在 ROUGE-L 上和 FP16 差不到 1 个点,在数学和代码任务上差距更小,基本可以接受;Kimi-K3 的 FP8 在线量化在长上下文抽取任务上偶尔会漏细节,需要结合业务容错度决定是否启用。

有一点提醒:不要只看平均指标,要按任务类型拆开看。我们遇到过某类表格理解任务在 NVFP4 下降幅超过 5%,但平均指标只有 1% 的情况。如果你有分类、抽取这类对数值敏感的业务,建议单独跑一遍回归测试再定方案。

4. 部署配置与吞吐调优实战

这一节是最实操的部分。我们会从并行策略选型一直讲到 vLLM 最终配置,再贴一组实测吞吐数据。所有参数都是我们在 16 卡 B300 上实际跑过、稳定复现过的,你可以直接拿去做 baseline。

4.1 并行策略怎么选

16 卡集群部署两个模型,每个模型各占 8 卡(TP=8),这是最标准的做法。GLM-5.2-NVFP4 权重约 200GB(约 400B 规模参数按 NVFP4 折算),TP=8 时每卡权重 25GB,加上每卡预留的 150GB 以上 KV cache 空间,能支持非常大的并发 batch。Kimi-K3 因为用的是 FP8,权重约 400GB,TP=8 时每卡权重 50GB,KV cache 空间被压缩,但依然够用。

为了对比,我们也试过 TP=16(跨机)。结论前面说了:跨机通信带宽成为瓶颈,高并发下吞吐反而下降。所以如果模型能塞进单机 8 卡,尽量别跨机做 TP。另外,如果模型实在太大需要跨机,建议用 pipeline parallel 而不是把 TP 拉满跨机,通信量完全不是一个量级。

4.2 vLLM 配置明细

直接贴我们最终用的 vLLM 启动参数,以 GLM-5.2-NVFP4 为例:

python -m vllm.entrypoints.openai.api_server \ --model /data/models/glm-5.2-nvfp4 \ --tensor-parallel-size 8 \ --gpu-memory-utilization 0.92 \ --max-num-seqs 256 \ --max-model-len 131072 \ --enable-prefix-caching \ --kv-cache-dtype fp8 \ --enforce-eager \ --disable-log-requests

参数含义拆开讲一下:

  • --tensor-parallel-size 8:TP 并行度,8,对应单机 8 卡;
  • --gpu-memory-utilization 0.92:显存利用率 92%,剩下的留给 CUDA context 和碎片;
  • --max-num-seqs 256:单个 GPU 允许同时调度的序列数上限,这个值是吞吐和延迟平衡的关键;
  • --max-model-len 131072:最大上下文长度 128K;
  • --enable-prefix-caching:打开自动前缀缓存;
  • --kv-cache-dtype fp8:KV cache 用 FP8 存储,比 FP16 省一半显存;
  • --enforce-eager:关闭 CUDA graph,FP4 模型在部分 CUDA graph 捕获环境下会和量化 kernel 冲突,这个坑后面细说。

4.3 实测吞吐数据

压测用的是自研的负载工具,混合场景模拟线上真实请求:45% 多轮对话、30% 单轮问答、25% 长文档处理,并发从 32 逐步加到 512,每档跑 10 分钟。下面这组成绩是稳定复现过的(数据已做脱敏处理):

配置模型并发decode 吞吐(tokens/s)TTFT P99(ms)TPOT P99(ms)
TP=8GLM-5.2-NVFP412818,50062028
TP=8GLM-5.2-NVFP425632,00098045
TP=8GLM-5.2-NVFP451235,2003200110
TP=8Kimi-K3 FP812813,20078038
TP=8Kimi-K3 FP825622,400150068
TP=8Kimi-K3 FP851224,1004800180

几个解读:

  1. 并发 128 到 256,吞吐提升明显,说明之前 batch 太小,显存带宽没吃满;
  2. 并发 256 到 512,吞吐只有小幅提升,但 TTFT 涨了 2 倍以上,说明开始进入排队区;
  3. Kimi-K3 FP8 全程比 GLM-5.2-NVFP4 低 30% 左右,权重更大、每步读显存带宽更多是主因。

需要强调:不同模型版本、不同量化方案、不同请求分布下数据会有差异,这里给的是我们这套环境的基线。如果你拿到的数据比我们低很多,优先检查是不是 KV cache 没配够或者并发没打上去。

4.4 batch、KV cache、延迟的平衡

--max-num-seqs不是越大越好。我们实测 256 是最佳点,512 时吞吐虽然还能涨一点,但 P99 TTFT 已经明显恶化,线上体验受损。核心原因:batch 太大时,prefill 和 decode 混跑,prefill 的长序列会占用大量 GPU 算力,导致 decode 步长得不到及时调度,每个请求的 TPOT 都变慢。

这个阶段我们的调优建议是:先把 batch 从 32 开始翻倍试,每档跑 10 分钟看 TTFT/TPOT 的 P99 曲线,找到吞吐不再线性增长的那个点,然后往回退一档。不要光看平均吞吐,要盯 P99,尤其是线上有交互场景时。

5. 缓存命中与 P-D 分离部署

前面说了,缓存命中是这次测试里最值得细讲的部分。如果说 NVFP4 是"省了一半显存带宽",那 prefix cache 加 P-D 分离就是"把 prefill 计算量砍掉一大半"。这两个收益方向不同,但叠加起来效果非常可观。

5.1 Prefix Cache 的工作原理

大模型推理时,KV cache 是逐 token 计算的。如果两个请求开头部分相同(比如相同的 system prompt、相同的 few-shot 示例),它们的 KV cache 是可以复用的。vLLM 的 automatic prefix caching 和 SGLang 的 RadixAttention 都是干这个的,差别在于缓存的组织方式和淘汰策略。

实际业务里,绝大多数对话请求都带着同一个系统提示词,这部分可能占输入 tokens 的 30%~60%。把这些重复计算省掉,prefill 压力能降一大截,TTFT 直接受益。我们在 GLM-5.2-NVFP4 上测过:纯单轮问答场景,如果系统提示词 2000 tokens、请求平均 3000 tokens,打开 prefix caching 后 prefill 计算量减少约 25%~30%,TTFT 平均降 35% 左右。如果业务里你们用的是固定超长 system prompt,收益会更夸张。

5.2 P-D 分离部署的配置要点

P-D separation(prefill-decode 分离)是更进一步的做法:把 prefill 和 decode 拆到不同的实例上,prefill 实例负责长输入计算和 KV cache 生成,decode 实例负责 token 生成,两者之间通过共享 KV cache 或调度器传递状态。

我们最终部署形态是:16 卡拆成 2 个 prefill 实例加 2 个 decode 实例,prefill 实例负责接收新请求、计算初始 KV cache、输出给 decode 实例。这样做的优势是 prefill 和 decode 互不抢资源,长上下文预填充不再拖慢在线 token 生成。代价是架构复杂度上来了,需要额外的调度组件。

配置上有几个关键参数:

  • 在 vLLM 中使用--served-model-name配合预填充池/解码池配置,或者用 SGLang 的 PD 分离参数;
  • prefill 和 decode 实例要共享前缀缓存存储,否则缓存命中率会直线下降;
  • scheduler 的队列权重要配好,prefill 队列和 decode 队列的比例按“输入 tokens 与输出 tokens 的 1:3~1:5”来估,如果输出偏长,decode 实例要多配。

5.3 命中率数据与优化技巧

部署 P-D 分离加 prefix caching 之后,我们跑了一组业务流量回放:

场景无缓存仅 prefix cacheP-D + prefix cache
多轮对话命中率0%68%68%
长文档问答命中率0%21%21%
综合 prefill 吞吐(tokens/s)8,40015,20019,800
TTFT P99(ms)1,200780390

多轮对话的命中率最高(68%),因为每轮都带着历史上下文和固定的 system prompt;长文档问答命中率低(21%),因为每个文档内容差异大。综合下来,P-D 分离让 prefill 有效吞吐从 8.4K 提到 19.8K,TTFT 从 1.2s 压到 390ms,这个提升非常可观。

命中率优化的几个技巧:

  1. system prompt 尽量放在请求最前面,有些框架的 prefix cache 是按前缀匹配的,放中间会打断缓存命中;
  2. 多轮对话要使用框架自带的聊天模板复用,不要每次重拼完整历史,那样等于把已经算过的 KV cash 全部作废;
  3. 缓存条目不要设得过小,太小会导致高频请求的缓存频繁被淘汰,命中率反而下降;
  4. 如果业务里存在几十个固定请求模板,可以考虑在入口层做模板归一化,把相同前缀的请求打到一个实例上。

6. 碰到的坑和排查实录

这部分是花钱买来的经验。硬件刚到手的时候,我们觉得 B300 这种新卡应该很稳定,结果测试期间遇到了好几个诡异问题,每个都能让人怀疑人生。整理出来,希望你们少走弯路。

6.1 B300 集群的散热与维护

B300 功耗比 B200 更高,8 卡整机的满载功率轻松超过 15kW,对机房的散热和供电要求非常高。我们测试期间遇到过一次“性能悬崖”:跑满 512 并发 15 分钟后,整体吞吐突然掉了 40%,检查发现 GPU 温度到了 96°C 触发降频。调整机房空调风道和机柜位置后,温度稳定在 82°C 左右,问题解决。

建议:B300 集群上线前做一次满载热循环测试,至少连续跑 1 小时以上,观察温度和时钟曲线;散热不足的机房不要贸然上高并发压测,容易把卡降频甚至触发保护性关机。另外日常维护要多看nvidia-smi dmon采集的温度历史,不要等出故障再排查。

6.2 CX8 网络固件导致的 RDMA 偶发断连

这个坑前面提过,这里展开讲。症状是:NCCL 全互联测试(all_reduce)有时能过、有时在某个节点上卡住,重试几次又恢复正常;GPU 直连通信偶尔报错mlx5_0: timeout。排查了两轮硬件都没问题,最后发现是 CX8 网卡固件版本比驱动的预期版本旧了一大截,升级固件后问题完全消失。

排查方法供参考:

# 查看网卡固件版本 mlxup --query # 检查驱动与固件匹配情况 modinfo mlx5_core | head # 跑 NCCL 全互联测试 nccl-tests/build/all_reduce_perf -b 1G -f 2 -g 8 -n 10

遇到过类似问题的话,别急着换硬件,先查固件和驱动的版本矩阵。RDMA 的偶发问题有相当大比例是固件/驱动不配套导致的。

6.3 FP4 模型和 CUDA graph 的冲突

我们第一版配置用了 vLLM 默认的 CUDA graph 加速,启动时报了类似Cannot capture graph with quantized ops的错误,或者能启动但跑几个 batch 后随机报CUDA error: illegal memory access。排查后确认是 CUDA graph 捕获和 FP4 量化 kernel 的某些组合路径有兼容性问题。

解法很直接:--enforce-eager关掉 CUDA graph。代价是每步调度开销大一点,实测吞吐影响在 5% 以内,但稳定性大幅提升。如果框架后续版本修了这个问题,可以再开回来,但建议先在压测环境验证 30 分钟以上再上生产。

6.4 常见问题速查

现象可能原因建议处理
吞吐跑一会骤降GPU 温度过高触发降频检查散热、调整负载
NCCL/远端通信时好时坏网卡固件/驱动不匹配升级固件、跑 nccl-tests 验证
启动报 CUDA graph 错误FP4 kernel 与 graph 捕获冲突--enforce-eager
KV cache 命中率一直很低请求结构不连续/缓存条目太小调整缓存淘汰策略、优化 system prompt 位置
FP4 精度不达标模型本身不适合 4-bit/缩放因子异常用 ROUGE 等指标逐任务验证,必要时退回 FP8
跨机 TP 吞吐低于预期跨节点走 RDMA 带宽不足切 TP=8 本地部署,跨机只做数据并行

最后说点个人体会。这次实测最大的感受是:B300 的硬件底子确实强,但真正拉开体验差距的是缓存的命中率和部署配置的细节。NVFP4 让 400B 级模型在单卡跑成为了现实,而 prefix cache 加 P-D 分离让同样的硬件跑出了接近翻倍的业务吞吐。如果你也在评估 B300 集群,我建议先把缓存命中率这件事想清楚,这比堆机器更划算。另外,跟 B300 一起到的 CX8 固件问题,我们前前后后折腾了大半天,建议你拿到机器第一件事就去查固件版本,别等上了生产才发现。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询