双 NVIDIA L20 实测:Qwen3.8-27B 的 BF16、FP8、MTP、单卡表现,以及与 Qwen3.6 MoE 的差距

双 NVIDIA L20 实测:Qwen3.8-27B 的 BF16、FP8、MTP、单卡表现,以及与 Qwen3.6 MoE 的差距

本文记录一次真实服务器上的部署与性能测试。目标不是做理想化的显卡跑分,而是回答一个更实际的问题:在两张 NVIDIA L20 上,Qwen3.8-27B 应该使用 BF16 还是 FP8?开启 MTP 后单路速度能提升多少?单卡是否值得?它能否替代当前速度超过 100 token/s 的 Qwen MoE Agent 模型?

一、先说结论

五种部署方式使用同一套输入和输出长度测试后,结果如下:

部署方式 单流 decode 单流端到端 TTFT 4 路并发总吞吐
Qwen3.8-27B BF16,双卡 TP2 25.96 token/s 25.54 token/s 369 ms 91.72 token/s
Qwen3.8-27B FP8,双卡 TP2 29.46 token/s 29.02 token/s 303 ms 123.73 token/s
Qwen3.8-27B FP8,双卡 TP2 + MTP3 56.33 token/s 53.68 token/s 473 ms 180.25 token/s
Qwen3.8-27B FP8,单卡 17.41 token/s 17.21 token/s 409 ms 72.70 token/s
现有 Qwen3.6-35B-A3B MoE,BF16 双卡 151.98 token/s 144.60 token/s 183 ms 367.79 token/s

结论可以概括成四句话:

  1. Qwen3.8 的 FP8 比 BF16 更快、更省显存,基本没有继续用 BF16 做主服务的性能理由。
  2. FP8 开启 MTP 后,单流 decode 从 29.46 提升到 56.33 token/s,提升 91.19%,效果非常明显。
  3. FP8 单卡虽然能够运行,但单流只有 17.41 token/s,不适合低延迟 Agent。
  4. 即便开启 MTP,Qwen3.8 的单流速度也只有现有 Qwen3.6 MoE 的 37%左右。如果替代条件是“速度不能相差太多”,那么当前仍不满足。

需要特别说明:token/s 不是“中文字符/秒”或“单词/秒”。不同 tokenizer、语言和输出结构会影响用户看到的实际文字速度。


二、服务器配置

这不是一台完全空闲的跑分服务器。测试期间 GPU 0 上还运行着一个 OCR 服务,占用约 1.57 GiB 显存,因此结果更接近真实业务共存环境。

硬件

项目 配置
CPU 2 × Intel Xeon Gold 6530
物理核心/线程 64 核 / 128 线程
NUMA 2 nodes
内存 251 GiB,无 Swap
GPU 2 × NVIDIA L20
单卡可见显存 46068 MiB,约 45 GiB
NVIDIA Driver 580.173.02
磁盘 447 GB + 1.7 TB 逻辑盘
文件系统 ext4,合计约 2.1 TB
测试时可用磁盘 约 1.2 TB

软件

项目 版本
操作系统 Ubuntu 22.04.5 LTS
Kernel 5.15.0-186-generic
Docker 29.4.1
Docker Compose v5.1.3
Qwen3.8 镜像 vllm/vllm-openai:qwen38
Qwen3.8 镜像 Digest sha256:4a2f33a884222f7049b983263ad9976f89452bb81affecf5b67d89ad35c1bc31
Qwen3.8 vLLM 0.1.dev19754+g3a0914114
现有 MoE vLLM 0.19.1.dev6+g6d4a8e6d2

两类服务使用的 vLLM 构建不同,所以这不是“完全相同软件栈下的学术对比”,而是“服务器上两个实际可部署方案的生产视角对比”。


三、模型与磁盘占用

本次下载和测试的主要模型:

服务器原有的对照模型实际是:

  • Qwen3.6-35B-A3B

它之前被口头称为“Qwen3.5 MoE”,但容器挂载目录和 config 均表明实际模型是 Qwen3.6-35B-A3B。其 Transformers 架构类仍叫 Qwen3_5MoeForConditionalGeneration,这是代码架构名称,不能据此把模型版本判断成 Qwen3.5。

模型 权重/目录占用 权重分片
Qwen3.8-27B BF16 51.747 GiB,du 约 52 GB 18
Qwen3.8-27B FP8 28.747 GiB,du 约 29 GB 66
Qwen3.6-35B-A3B BF16 du 约 67 GB 26

FP8 相比 BF16 少 23 GiB,权重体积下降 44.45%。

下载完成后逐个解析了 safetensors 文件头,并按 index 检查所有分片:

  • BF16:18/18,缺失 0,非空 incomplete 文件 0;
  • FP8:66/66,缺失 0,非空 incomplete 文件 0。

下载方式

网络环境使用 Hugging Face 镜像:

1
2
3
4
5
6
7
8
export HF_ENDPOINT=https://hf-mirror.com
export HF_HUB_DISABLE_XET=1

hf download Qwen/Qwen3.8-27B \
--local-dir /data/ai/models/Qwen3.8-27B

hf download Qwen/Qwen3.8-27B-FP8 \
--local-dir /data/ai/models/Qwen3.8-27B-FP8

实际部署中,第一次下载遇到 Xet CAS 401。加入 HF_HUB_DISABLE_XET=1 后改走普通 HTTP,两个模型均成功完成下载。


四、部署方式

所有 Qwen3.8 服务都采用 OpenAI-compatible API,监听 8000 端口。同一时间只运行一个大模型,避免显存互相影响。

公共参数如下:

  • 最大上下文:32768;
  • gpu-memory-utilization=0.90
  • max-num-seqs=8
  • max-num-batched-tokens=8192
  • text-only;
  • prefix caching;
  • reasoning parser:qwen3;
  • tool parser:qwen3_coder;
  • Tensor Parallel 双卡部署使用 TP2。

1. FP8 双卡基线

核心 Compose 配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
services:
qwen38-fp8:
image: vllm/vllm-openai:qwen38
container_name: qwen38-fp8
runtime: nvidia
network_mode: host
ipc: host
restart: unless-stopped

environment:
HF_HUB_OFFLINE: "1"
TRANSFORMERS_OFFLINE: "1"
CUDA_DEVICE_ORDER: PCI_BUS_ID
VLLM_WORKER_MULTIPROC_METHOD: spawn
PYTORCH_CUDA_ALLOC_CONF: expandable_segments:True

volumes:
- /data/ai/models/Qwen3.8-27B-FP8:/model:ro
- /data/ai/models/.cache/huggingface:/root/.cache/huggingface
- /home/qwen/cache/vllm:/root/.cache/vllm
- /home/qwen/cache/triton:/root/.triton

command:
- /model
- --served-model-name
- qwen3.8-27b-fp8
- --host
- 0.0.0.0
- --port
- "8000"
- --tensor-parallel-size
- "2"
- --disable-custom-all-reduce
- --dtype
- auto
- --max-model-len
- "32768"
- --gpu-memory-utilization
- "0.90"
- --max-num-seqs
- "8"
- --max-num-batched-tokens
- "8192"
- --language-model-only
- --enable-prefix-caching
- --reasoning-parser
- qwen3
- --enable-auto-tool-choice
- --tool-call-parser
- qwen3_coder

2. BF16 双卡

BF16 与 FP8 使用相同参数,只修改模型目录、served model name 和 dtype:

1
2
3
4
5
6
7
8
9
10
11
volumes:
- /data/ai/models/Qwen3.8-27B:/model:ro

command:
- /model
- --served-model-name
- qwen3.8-27b-bf16
- --tensor-parallel-size
- "2"
- --dtype
- bfloat16

3. FP8 双卡 + MTP

Qwen3.8 的 config 中包含一个 MTP hidden layer。按照官方 vLLM Qwen3.8 配方,在 FP8 TP2 基础上增加:

1
2
3
4
command:
# 其他参数不变
- --speculative-config
- '{"method":"mtp","num_speculative_tokens":3}'

served model name 单独设置成 qwen3.8-27b-fp8-mtp,避免与普通 FP8 混淆。

4. FP8 单卡

单卡固定使用 GPU 1,避开 GPU 0 上的 OCR:

1
2
3
4
5
6
7
8
9
environment:
NVIDIA_VISIBLE_DEVICES: "1"

command:
- /model
- --served-model-name
- qwen3.8-27b-fp8-single
- --tensor-parallel-size
- "1"

其他上下文、批处理和采样相关参数保持不变。

5. 现有 Qwen3.6 MoE

服务器原有容器使用以下核心参数:

1
2
3
4
5
6
7
8
9
模型:/models/Qwen3.6-35B-A3B
served-model-name:qwen-moe
dtype:bfloat16
tensor-parallel-size:2
max-model-len:49152
max-num-seqs:4
gpu-memory-utilization:0.85
enable-prefix-caching
enable-chunked-prefill

这个部署没有启用 MTP,也没有启用 text-only,因此还会初始化视觉 encoder cache。它依然明显快于 Qwen3.8,说明主要优势来自 MoE 每 token 只激活约 3B 参数,而不是测试参数偏向它。


五、部署中遇到的实际问题

1. L20 上的 custom all-reduce 报错

Qwen3.8 BF16 首次启动时,在 CUDA Graph 阶段出现:

1
custom_all_reduce.cuh:164 'invalid argument'

加入以下参数后,两种精度均通过 PyNCCL 稳定启动:

1
--disable-custom-all-reduce

因此所有双卡 Qwen3.8 结果都采用相同的 PyNCCL 通信方式。

2. L20 缐少部分 FP8 专门调优配置

官方 qwen38 镜像提示,部分 W8A8 block shape 没有对应的 NVIDIA L20 调优文件,会回退到默认 Triton FP8 kernel:

1
2
Using default W8A8 Block FP8 kernel config.
Performance might be sub-optimal!

这意味着本文记录的是当前镜像的真实表现,但未来 vLLM 如果补充 L20 专用配置,FP8 仍可能继续提升。

3. MTP 增加冷启动和首 token 延迟

MTP 需要额外编译 draft/eagle head 和 speculative CUDA Graph:

  • MTP engine profile/compile:约 215.84 秒;
  • 普通 FP8 首次 engine 初始化:约 206.23 秒;
  • 单卡首次 engine 初始化:约 204.04 秒。

编译会进入缓存,后续重启可以明显缩短,但第一次部署需要预留几分钟。


六、测试方法

为了避免只比较“短提示、短输出”的理想数据,本次使用较长上下文和固定长输出:

项目 设置
Prompt tokens 3472
每次输出 固定 512 tokens
预热 64 output tokens
单流测试 5 次
并发测试 4 路 × 3 轮
temperature 0
seed 42
ignore_eos true
请求方式 Streaming
客户端位置 与推理服务同机

指标定义:

  • decode token/s:首 token 之后的稳定生成速度;
  • 端到端 token/s:从发起请求到输出结束,包含 TTFT;
  • TTFT:Time To First Token;
  • 4 路总吞吐:四个独立请求同时进行时的合计输出速度。

这里的 4 路吞吐不是“单个回答达到 180 或 367 token/s”。它表示四个请求共享 GPU,四份回答的 token/s 相加。


七、完整结果

单流与并发

部署方式 decode 均值 端到端均值 TTFT 均值 4 路总吞吐
Qwen3.8 BF16 TP2 25.9619 25.5445 369.24 ms 91.7179
Qwen3.8 FP8 TP2 29.4640 29.0237 303.20 ms 123.7267
Qwen3.8 FP8 TP2 + MTP3 56.3328 53.6802 472.84 ms 180.2471
Qwen3.8 FP8 单卡 17.4080 17.2057 408.63 ms 72.7024
Qwen3.6-35B-A3B MoE TP2 151.9773 144.6014 183.17 ms 367.7857

稳定性

部署方式 decode min / median / max 4 路 min / median / max
BF16 TP2 25.9589 / 25.9604 / 25.9668 91.6760 / 91.7237 / 91.7539
FP8 TP2 29.4579 / 29.4610 / 29.4713 123.7133 / 123.7301 / 123.7367
FP8 TP2 + MTP3 54.9691 / 56.2572 / 58.4411 151.3570 / 188.4414 / 200.9430
FP8 单卡 17.4069 / 17.4082 / 17.4089 72.6561 / 72.6747 / 72.7766
Qwen3.6 MoE 151.9462 / 151.9739 / 152.0212 352.5549 / 373.7171 / 377.0850

普通 BF16、FP8 和单卡结果非常稳定。MTP 四并发波动明显更大,与不同输出片段上的 speculative acceptance rate 有关。

显存与 KV cache

部署方式 模型加载显存/卡 可用 KV cache/卡 KV tokens
Qwen3.8 BF16 TP2 25.17 GiB 13.66 GiB 389,802
Qwen3.8 FP8 TP2 13.85 GiB 24.32 GiB 693,589
Qwen3.8 FP8 TP2 + MTP3 14.07 GiB 23.73 GiB 534,820
Qwen3.8 FP8 单卡 27.57 GiB 9.43 GiB 134,485
Qwen3.6 MoE TP2 32.86 GiB 3.30 GiB 86,592

MTP 的模型显存只比普通 FP8 略高,但 speculative scheduling 和 padding 让 KV tokens 从 693,589 降到 534,820,下降约 22.89%。


八、如何理解这些结果

FP8 是否值得?

值得。

相对 BF16:

  • 单流 decode 提升 13.49%;
  • 端到端提升 13.62%;
  • 四路吞吐提升 34.90%;
  • 权重体积下降 44.45%;
  • KV cache tokens 增加约 77.93%。

在这台双 L20 上,普通部署应优先选 FP8。

MTP 是否值得?

对于长输出 Agent,值得。

FP8+MTP 相对普通 FP8:

  • 单流 decode:+91.19%;
  • 端到端:+84.95%;
  • 四路总吞吐:+45.68%;
  • TTFT:增加 55.95%。

服务端观测到:

  • 平均接受长度:2.31~2.70 tokens;
  • draft 接受率:43.5%~56.6%;
  • 第一个预测位置接受率最高,越往后越低。

因此 MTP 很适合 512-token 这类较长输出;对于几十 token 的短回答,较高 TTFT 会吃掉一部分收益。

单卡是否值得?

取决于目标。

如果目标是释放一张 GPU,单卡可以正常服务,甚至能够跑满四并发;但单流速度比 FP8 TP2 低 40.92%,四路吞吐低 41.24%。

所以单卡是“资源节省方案”,不是“低延迟方案”。

Qwen3.8 能否替代当前 MoE Agent?

只看速度,目前不能。

Qwen3.8 FP8+MTP 与现有 MoE 相比:

  • 单流 decode 只有 37.07%;
  • 单流端到端只有 37.12%;
  • 四路总吞吐只有 49.01%;
  • TTFT 高约 2.58 倍。

现有 MoE 的单流速度是 Qwen3.8 MTP 的约 2.70 倍。

这并不表示 MoE 一定“更好”。速度快是因为每 token 只激活约 3B 参数。Qwen3.8 是否在推理质量、工具调用、长上下文或具体 Agent 任务上更强,需要另一套业务 A/B 测试,不能从 token/s 推导。


九、最终选择建议

如果是我的部署决策,会这样选:

  1. 当前 Agent 速度优先:继续使用 Qwen3.6-35B-A3B MoE。
  2. 必须使用 Qwen3.8 的新能力:选择 FP8 TP2 + MTP3。
  3. 多用户吞吐优先:Qwen3.8 仍选择 FP8+MTP,但要关注四并发波动。
  4. 只想节省一张 GPU:选择 FP8 单卡,接受约 41%的速度下降。
  5. BF16:只保留作为数值精度和业务质量对照,不作为性能首选。

真正决定替换 Agent 模型前,还应补充:

  • 实际工具调用成功率;
  • 多轮任务完成率;
  • reasoning 与非 reasoning 的可见延迟;
  • 长上下文正确率;
  • JSON/结构化输出稳定性;
  • 相同 Agent 任务的端到端完成时间,而不仅是 token/s。

十、复现时的注意事项

  • 同一时间只运行一个大模型;
  • 使用完全相同的 prompt/output 分布;
  • 固定 temperature、seed 和 ignore_eos;
  • 区分 decode token/s、端到端 token/s 和 TTFT;
  • 不要把四路总吞吐误解为单个请求速度;
  • 记录其他常驻 GPU 服务的显存占用;
  • 固定 Docker 镜像 digest,而不是只写 latest;
  • 首次编译和缓存后重启要分开记录;
  • MoE 与稠密模型的 token/s 不可脱离激活参数量直接解释。

参考链接


以上数据来自同一台服务器、同一套基准脚本的实测。文章只讨论推理性能,不对不同模型的回答质量做未经验证的推断。