Qwen3-235B vLLM Bench Serve 压测与性能分析
这篇文章整理的是 Qwen3-235B-A22B-FP4 在 vLLM OpenAI API 上的压测方法与结果解读。项目资料里使用 vllm bench serve 做统一 workload 压测,并对 CX8 与 89144 两套平台做了同口径对比。为了公开发布,文中隐藏真实 endpoint、路径、端口和内部脚本目录,只保留测试方法、参数口径和聚合指标。
一、推理压测不能只看 tok/s
很多大模型推理压测只展示 tokens/s,这很容易误导。推理服务的用户体验至少由四类指标共同决定:
| 指标 | 含义 | 关注点 |
|---|---|---|
| TTFT | Time To First Token,首 token 延迟 | 用户是否等得住 |
| TPOT | Time Per Output Token,输出阶段每 token 延迟 | decode 是否顺滑 |
| E2E latency | 端到端请求延迟 | 请求整体完成时间 |
| tok/s / QPM / TPM | 吞吐指标 | 系统容量和成本效率 |
对于长输入场景,TTFT 受 prefill 影响很大;对于长输出场景,TPOT 更能反映 decode 性能;对于高并发,排队和调度会显著影响 P95/P99。只看平均值或峰值都不够。
二、测试对象和服务参数
| 项目 | 说明 |
|---|---|
| 模型 | Qwen3-235B-A22B-FP4 |
| Serving | vLLM OpenAI-compatible API |
| 并行 | 单机 TP8 / PP1 |
| 数据集 | random synthetic dataset |
| 接口 | /v1/completions |
| 工具 | vllm bench serve |
服务启动参数核心如下:
vllm serve <model-path> \
--served-model-name Qwen3-235B \
--host 0.0.0.0 \
--port <api-port> \
--tensor-parallel-size 8 \
--enable-expert-parallel \
--max-num-seqs 32 \
--max-model-len 8192 \
--max-num-batched-tokens 8192 \
--gpu-memory-utilization 0.9 \
--enable-chunked-prefill \
--no-enable-prefix-caching \
--kv-cache-dtype fp8 \
--trust-remote-code
项目里还记录了一组 forced-RoCE/Spectrum-X 通信参数,其中比较关键的是:
NCCL_P2P_DISABLE=1
NCCL_SHM_DISABLE=1
NCCL_IB_GID_INDEX=3
NCCL_CROSS_NIC=1
NCCL_IB_ADAPTIVE_ROUTING=1
NCCL_NET_PLUGIN=<spectrum-x-plugin>
这里要特别注意:NCCL_P2P_DISABLE=1 会禁用本机 GPU P2P,使 TP8 decode 中频繁的 GPU 间通信更可能走 NET/IB 路径。它是解释性能差异的重要假设,但最终必须通过单变量 A/B 验证,不能只凭参数推断下结论。
三、vLLM Bench Serve 命令模板
vllm bench serve 的价值是把请求形态、并发、结果保存和百分位指标固定下来:
vllm bench serve \
--backend openai \
--model Qwen3-235B \
--tokenizer <model-path> \
--endpoint /v1/completions \
--host <api-host> \
--port <api-port> \
--dataset-name random \
--random-input-len 4000 \
--random-output-len 1000 \
--ignore-eos \
--max-concurrency 16 \
--num-prompts 64 \
--request-rate 10000 \
--percentile-metrics ttft,tpot,itl,e2el \
--metric-percentiles 50,90,95,99 \
--save-result \
--save-detailed \
--plot-timeline \
--plot-dataset-stats \
--result-dir ./results/public \
--result-filename qwen3_4000_1000_c16.json
几个参数需要解释:
| 参数 | 作用 |
|---|---|
--dataset-name random |
用固定 token 长度生成合成请求,便于复现 |
--ignore-eos |
尽量让请求生成到指定输出长度 |
--max-concurrency |
控制最大并发,而不是无限冲击服务 |
--num-prompts |
请求总数,过少容易被偶发抖动影响 |
--request-rate 10000 |
近似 burst 压测,观察系统可承载能力 |
--save-detailed |
保存单请求明细,便于分析长尾 |
--percentile-metrics |
输出 TTFT、TPOT、ITL、E2E 的分位数 |
四、当前两组结果
CX8 架构当前完成了两组同口径测试,每组 64 请求,全部成功:
| case | completed | failed | avg latency ms | p95 latency ms | avg TTFT ms | p95 TTFT ms | avg TPOT ms | p95 TPOT ms | QPM | TPM | completion tok/s | total tok/s |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
1000/300/c6 |
64 | 0 | 10,148.55 | 10,425.89 | 517.11 | 717.29 | 32.21 | 34.02 | 34.62 | 45,007.20 | 173.10 | 750.12 |
4000/1000/c16 |
64 | 0 | 43,333.27 | 45,863.40 | 2,436.43 | 5,451.42 | 40.94 | 42.35 | 22.14 | 110,679.00 | 368.93 | 1,844.65 |
这两组 workload 的含义不同:
1000/300/c6 更接近短输入、短输出、中等并发,用来看 TTFT、排队和 decode 轻负载表现。
4000/1000/c16 更重,输出更长,并发更高,更能放大 decode 阶段每 token 延迟和通信路径差异。
五、CX8 与 89144 对比(这里是服务器机型对比)
89144 的同口径手工重跑结果。两组对比都显示 89144 在吞吐和 TPOT 上明显优于 CX8。
89144是可以混跑IB网络与P2P,CX8是GPU之间通信统一走IB网卡
1000/300/c6
| metric | CX8 | 89144 | 结论 |
|---|---|---|---|
| QPM | 34.62 | 51.12 | 89144 高约 47.67% |
| TPM | 45,007.20 | 66,465.00 | 89144 高约 47.68% |
| completion tok/s | 173.10 | 255.64 | 89144 高约 47.68% |
| avg latency ms | 10,148.55 | 6,874.84 | 89144 低约 32.26% |
| avg TTFT ms | 517.11 | 464.14 | 89144 低约 10.24% |
| avg TPOT ms | 32.21 | 21.44 | 89144 低约 33.44% |
4000/1000/c16
| metric | CX8 | 89144 | 结论 |
|---|---|---|---|
| QPM | 22.14 | 27.81 | 89144 高约 25.65% |
| TPM | 110,679.00 | 139,068.60 | 89144 高约 25.65% |
| completion tok/s | 368.93 | 463.56 | 89144 高约 25.65% |
| avg latency ms | 43,333.27 | 34,494.69 | 89144 低约 20.40% |
| avg TTFT ms | 2,436.43 | 2,466.93 | 两者接近,CX8 略低 |
| avg TPOT ms | 40.94 | 32.06 | 89144 低约 21.69% |
从这两张表可以看出,差距主要不在 TTFT,而在 TPOT/ITL,也就是 decode 阶段。
六、为什么怀疑通信路径
当前 CX8 服务使用 forced-RoCE 参数,其中 NCCL_P2P_DISABLE=1 和 NCCL_SHM_DISABLE=1 会让本机 TP8 中的 GPU 间通信更多走 NET/IB/GDRDMA。项目资料里也记录了一个现象:89144 一旦禁用 P2P,吞吐会接近 CX8;而保留 P2P 时,TPOT 和 completion tok/s 更好。
因此当前最值得优先验证的假设,不是模型、压测工具或 tokenizer,而是通信路径:
P2P/CUMEM 可用路径
-> 本机 GPU 间 decode 通信更短
-> TPOT 下降
-> completion tok/s 上升
forced-RoCE/NET 路径
-> decode 阶段频繁通信经过 NET/IB
-> 每 token 延迟升高
-> E2E latency 被拉长
当然,最终结论必须通过单变量 A/B 验证,不能只凭经验判断。
七、推荐 A/B 实验
下一步建议只改一个变量:打开本机 P2P。
NCCL_P2P_DISABLE=0
NCCL_DEBUG=INFO
NCCL_DEBUG_SUBSYS=INIT,NET,GRAPH,ENV
然后重跑:
1000/300/c6
4000/1000/c16
观察四类证据:
| 证据 | 判断 |
|---|---|
| NCCL 日志 | 是否从 NET/IB/GDRDMA 转向更多 P2P/CUMEM |
| TPOT / ITL | 是否显著下降 |
| completion tok/s | 是否显著上升 |
| E2E latency | 是否随 TPOT 改善而下降 |
如果打开 P2P 后 CX8 的 TPOT 明显下降,就可以把通信路径作为主要归因,并继续用相同 workload 复测 batch token、并发和插件版本等变量。
八、压测报告应该怎么写
一份可复盘的 vLLM 压测报告建议至少包含:
- 模型、量化格式、served name。
- 服务参数:TP、PP、max model len、max num seqs、batch tokens、KV cache dtype。
- NCCL/RDMA 参数,尤其是 P2P、SHM、IB、GID、插件。
- workload:input/output/concurrency/requests/request rate。
- 成功数、失败数、错误类型。
- TTFT、TPOT、ITL、E2E 的 P50/P90/P95/P99。
- QPM、TPM、completion tok/s、total tok/s。
- 是否预热,是否冷启动,是否存在 lazy compile。
- 原始 JSON 和图表路径。
九、参考资料
- vLLM Bench Serve:https://docs.vllm.ai/en/latest/cli/bench/serve/
- vLLM Benchmark CLI:https://docs.vllm.ai/en/latest/benchmarking/cli/
- vLLM Metrics:https://docs.vllm.ai/en/stable/design/metrics/
十、总结
Qwen3-235B 这组压测最有价值的地方,不是某个 tok/s 数字,而是展示了如何用 vLLM bench serve 固定 workload,用 TTFT/TPOT/E2E/吞吐矩阵拆解瓶颈,并进一步通过 NCCL 单变量 A/B 定位通信路径。
对于 TP8 这类强通信场景,decode 阶段的 TPOT 往往比平均延迟更能说明问题。只要把 workload、服务参数、NCCL 参数和结果指标记录完整,后续换平台、换驱动、换 NCCL 插件或调整 P2P/RoCE 策略,都可以用同一套方法复测。