I benchmarked Unsloth's Qwen3.6-27B NVFP4 on 1x/2x 5090s. MTP is great until it really isn't.
摘要
详细基准测试:Unsloth的Qwen3.6-27B NVFP4模型在RTX 5090 GPU上的表现,显示MTP(多令牌预测)在短上下文的单次请求中能显著加速,但在批量并发或长上下文场景下则会带来不利影响。
我使用Qwen3.6-27B的GGUF版本有一段时间了,所以当Unsloth发布NVFP4版本时,我想看看它在vLLM中的表现。先澄清一下:这是Unsloth的Qwen3.6-27B NVFP4版本,不是NVIDIA单独的NVFP4版本。我最想弄清楚的是如何设置num_speculative_tokens参数。另外,我还想知道将模型分到两张5090上是否真的能提升生成速度,以及在加入并发或大上下文后,MTP是否仍然有效。简而言之:对于单个用户、短上下文的情况,nspec=3表现非常好。一旦GPU忙于批处理,或者上下文变大,优势基本消失,反而可能带来明显的速度下降。
https://preview.redd.it/dht5v418ileh1.png?width=2400&format=png&auto=webp&s=f4517815a4db1324b2ba16a4c5bf27ff1c0364aa
### 设置
- **模型**: Unsloth Qwen3.6-27B-NVFP4(压缩张量;NVFP4 MLP,FP8注意力)
- **GPU**: 2× RTX 5090,每张32 GB
- **vLLM**: 0.25.1
- **PyTorch**: 2.11.0+cu130
- **驱动**: 580.159.03
- **注意力后端**: TRITON_ATTN
- **最大模型长度**: 65,536
- **1 GPU**: tensor_parallel_size=1, max_num_seqs=16
- **2 GPU**: tensor_parallel_size=2, max_num_seqs=32
- **MTP方法**: qwen3_5_mtp
对于MTP和并发测试,我使用了Spec-Bench提示数据集,而不是像"数到100"这样的合成提示。
- **单请求测试**: 24个提示,请求512个输出token
- **并发测试**: 256个输出token,并发数1/4/8/12/16下分别有8/16/32/48/64个提示
- **上下文测试**: 每个上下文大小下四个固定长度的随机提示,256个输出token
上下文样本较小,因此我将这些数字视为该配置下的强信号,而非普遍规律。我保留了模型的默认采样参数:temperature=1.0, top_k=20, top_p=0.95。这意味着实际的接受率和MTP速度在不同运行间可能有所波动。对于第1节和第3节,解码速度为1000 / 中位数TPOT。通俗来说,这是首个token之后的生成速度,已排除提示处理时间。第2节则不同,它报告了整个服务器在所有活跃请求上的合计输出吞吐量。
### 1. 单GPU搭配MTP比双GPU更快
| GPU | MTP | 解码tok/s | 与同GPU基线相比的变化 |
|------|------|-------------|------------------------|
| 1× 5090 | 关闭 | 66 | 基线 |
| 1× 5090 | nspec=3 | 120 | +82% |
| 2× 5090 | 关闭 | 99 | 基线 |
| 2× 5090 | nspec=3 | 108 | +9% |
这是第一个让我意外的结果。一张5090搭配nspec=3达到了120 tok/s,而两张5090使用相同的MTP设置仅为108 tok/s。这并不意味着第二张卡毫无用处。它为你提供了更大的KV缓存、上下文、批处理和预填充空间。只是在这个测试中,它对单请求解码速度没有帮助。我猜测是张量并行的通信开销显著改变了MTP的权衡。此外,TP=2时运行间的波动也更大。我较早的一次运行结果是单GPU 117 tok/s,双GPU 118 tok/s。单GPU的结果非常稳定,双GPU则不然。我不建议将108视为每个人应得的固定数值。
### 2. 批处理接管后,MTP优势消失
以下是单张RTX 5090上整个服务器的总输出token数(每秒)。该数值是所有活跃请求的总和,而非每个用户单独看到的。
| 并发请求数 | MTP关闭 | nspec=3 | 变化 |
|------------|----------|---------|------|
| 1 | 64 | 121 | +87% |
| 4 | 228 | 414 | +81% |
| 8 | 453 | 475 | +5% |
| 12 | 638 | 501 | -22% |
| 16 | 789 | 498 | -37% |
在1个请求时,MTP几乎使吞吐量翻倍。在8个请求时几乎没什么帮助。在12和16个请求时,它反而拖慢了服务器。有趣的是,接受率在负载下并未崩溃:并发1时约为73%,并发16时约为71%。我的解读是,常规批处理已经使GPU保持忙碌,因此推测验证变成了额外的工作,不再能节省足够的解码步骤来证明其合理性。这里的异常点是并发4。这次运行测得MTP为414 tok/s,但较早的一次运行只有250 tok/s,并且尾部延迟非常糟糕。基线数值以及并发1/8/12/16的行为都复现得相当一致。在多做几次重复测试之前,我不会对并发4下+81%的数据过于信任。
### 3. 长上下文最终使MTP从加速变为减速
**单张RTX 5090,单一活跃请求**
| 输入长度 | MTP关闭 | nspec=3 | 变化 |
|----------|---------|---------|------|
| 2k | 66 | 107 | +62% |
| 8k | 65 | 100 | +54% |
| 32k | 61 | 62 | +2% |
| 60k | 57 | 46 | -20% |
**两张RTX 5090搭配张量并行,单一活跃请求**
| 输入长度 | MTP关闭 | nspec=3 | 变化 |
|----------|---------|---------|------|
| 2k | 99 | 105 | +6% |
| 8k | 96 | 117 | +22% |
| 32k | 89 | 72 | -19% |
| 60k | 81 | 45 | -44% |
交叉点因GPU配置而异。在单GPU上,MTP在32k时基本持平,60k时慢20%。在TP=2时,32k时已慢19%,60k时慢44%。在双GPU上,接受率从8k时的约71%降至60k时的60%。与此同时,随着KV缓存增长,每次验证传递的成本也越来越高。这种组合似乎很快扼杀了收益。因此我不会使用像"超过16k就始终禁用MTP"这样的一刀切规则。在这台机器上,交叉点出现在8k到32k之间(TP=2时),以及32k到60k之间(单GPU时)。你的提示和接受率会改变这个点的位置。
### 我目前实际使用的设置
- **单个交互用户,短上下文**: num_speculative_tokens=3
- **约八个并发请求**: 两者都测试;这里MTP仅带来+5%
- **单张5090上12+个并发请求**: 关闭MTP
- **TP=2时32k上下文**: 关闭MTP
- **任一配置下60k上下文**: 关闭MTP
另有一个警告来自更大范围的扫描:TP=2搭配nspec=8在并发16时导致vLLM服务器两次崩溃,错误为"CUDA error: an illegal memory access was encountered"。在此特定模型/后端组合下,两次尝试均失败。我并非声称nspec=8在所有地方都有问题。
### 快速质量检查
基准测试数值如果量化模型做不了任何有趣的事情就没什么用,所以我还在自己构建的桌面应用中给了它一个智能体任务:"构建Flappy Bird"。没有后续提示,没有修正,没有提示。它规划了任务,编写了代码,并一次性启动了一个可玩的游戏。
https://reddit.com/link/1v2l1zi/video/lfslklsukleh1/player
显然,一次成功的演示不是质量基准,也不能证明与BF16或GGUF版本相当。我仅将其作为合理性检查,表明该模型在相当复杂的智能体工作流中仍然可用。
### 复现命令
这是单GPU、nspec=3的服务器配置:
```bash
vllm serve /path/to/Qwen3.6-27B-NVFP4 \
--served-model-name qwen \
--tensor-parallel-size 1 \
--attention-backend TRITON_ATTN \
--max-model-len 65536 \
--gpu-memory-utilization 0.90 \
--max-num-seqs 16 \
--reasoning-parser qwen3 \
--speculative-config '{"method":"qwen3_5_mtp","num_speculative_tokens":3}'
```
这是单请求Spec-Bench客户端:
```bash
vllm bench serve \
--backend openai-chat \
--endpoint /v1/chat/completions \
--model /path/to/model \
--served-model-name qwen \
--tokenizer /path/to/model \
--dataset-name spec_bench \
--dataset-path spec_bench_question.jsonl \
--spec-bench-output-len 512 \
--num-prompts 24 \
--max-concurrency 1 \
--ignore-eos \
--percentile-metrics ttft,tpot,itl,e2el
```
有没有其他人测试过这个Unsloth版本在两张5090上的表现?我很好奇,如果换用另一个注意力后端,TP=2下MTP扩展性弱的现象是否仍然复现。我也希望看到有人用确定性采样和更多提示重复长上下文扫描。
相似文章
在4块RTX 5060 Ti上,使用P2P和PP=4,对新的unslooth/Qwen3.6-27B-NVFP4在并发数为1、4、8、12和16下的基准测试
unslooth/Qwen3.6-27B-NVFP4模型在4块RTX 5060 Ti GPU上,使用点对点(P2P)和流水线并行(PP)在不同并发级别下的基准测试结果。
在 2x3090 NVLINK 上对 Qwen 3.6 27B MTP 进行基准测试
对 Qwen 3.6 27B MTP 在 4 张 RTX 3090 GPU 上的基准分析表明,基于 NVLink 的张量并行相较于 PCIe 配置可实现显著的吞吐量提升(最高达 +53%)。
@Snixtp: https://x.com/Snixtp/status/2055734339346768225
某用户使用llama.cpp在单张RTX 3090上对Qwen3.6 27B的MTP变体与普通版本进行了基准测试,发现MTP在长上下文(32k-64k)下生成速度最高可提升2.37倍,但预填充较慢且暂不支持并发。
@superalesha: 别急着埋葬RTX 3090,先读完这个!@UnslothAI本周发布了qwen3.6-35b的两个新4位量化版本。我花了…
对Qwen3.6-35B在RTX 3090上的nvfp4、nvfp4-fast和AWQ 4位量化进行了基准测试,结果显示性能相近,而MTP头技巧将吞吐量提升了41%。
RTX 5080 16GB:Qwen3.6 35B MoE 在 128k 上下文下的表现——56 tok/s,以及 MTP 为何无济于事
Qwen3.6 35B MoE 在 RTX 5080 16GB 上的详细基准测试表明,MTP(多令牌预测)由于显存限制,在 128k 上下文中无法提升推理速度;最佳配置为不带 MTP 的 Q4_K_XL,在 128k 上下文下生成速度约 56 tok/s。