On one RTX PRO 6000 with SGLang and DFlash2 (8 draft tokens), ukisai’s Swift 1.5 NVFP4 scores the same as stock Qwen3.8-27B NVFP4 on GSM8K and a 205-case BFCL subset (97.04% vs 96.82%, 168 vs 168) and decodes at about the same speed per token. At reasoning_effort=medium it spends 14–19% fewer thinking tokens on GSM8K and SPEED-Bench, so a response is 8–10% shorter and finishes about 10% sooner.
Results
Stock RadixArk/Qwen3.8-27B-NVFP4 vs Swift ukisai/Swift-1.5-Qwen3.8-27b-NVFP4, both with DFlash2 8, reasoning_effort=medium.
| Benchmark | Stock NVFP4 | Swift NVFP4 | Δ |
|---|---|---|---|
| GSM8K, all 1,319, correct | 1,277 (96.82%) | 1,280 (97.04%) | +3 |
| GSM8K, mean output tokens | 348 | 320 | −8% |
| GSM8K, mean thinking tokens | 214 | 184 | −14% |
| GSM8K, mean request time (32 in flight) | 11.4 s | 10.2 s | −10.5% |
| BFCL subset, correct of 205 | 168 | 168 | 0 |
| BFCL, mean output tokens per call | 146 | 134 | −9% |
| SPEED-Bench qualitative, mean output tokens | 1,455 | 1,308 | −10% |
| SPEED-Bench qualitative, mean thinking tokens¹ | 622 | 502 | −19% |
| SPEED-Bench qualitative, out tok/s | 203.3 | 203.5 | 0% |
| SPEED-Bench qualitative, accept length | 4.35 | 4.36 | 0% |
| Chat, 1 user (12 prompts), out tok/s (fixed length) | 177.8 | 170.4 | −4% |
| Chat, 4 users (32 prompts), out tok/s (fixed length) | 591.2 | 593.7 | 0% |
| 20k prompt, 1 user, out tok/s (fixed length) | 98.4 | 99.2 | +1% |
¹ The 125 of 142 turns where both models stopped on their own; the output-token row counts all 142.
Accept length on the five sets of the DFlash2 model card, with its protocol (xhigh, temperature 1.0, top-p 0.95, top-k 20, max 4096 new tokens), 32 prompts per set, 1 user. “8 draft tokens” is SGLang’s --speculative-num-draft-tokens 8, DFlash2’s block size 8 (7 drafted per step):
| Set | DFlash2 card (H200) | Stock NVFP4 | Swift NVFP4 |
|---|---|---|---|
| GSM8K | 5.46 | 5.29 ± 0.11 | 5.57 ± 0.11 |
| MATH-500 | 5.28 | 5.18 ± 0.14 | 5.22 ± 0.11 |
| HumanEval | 4.39 | 4.24 ± 0.13 | 4.45 ± 0.11 |
| MBPP | 4.79 | 4.61 ± 0.10 | 4.79 ± 0.12 |
| MT-Bench | 4.10 | 4.13 ± 0.18 | 4.33 ± 0.21 |
Mean thinking tokens per answer on the same sets, on the prompts where both models stopped on their own. At medium that’s 30–32 of 32 prompts; at xhigh 31 (MATH-500), 26 (MBPP), 24 (MT-Bench) and 21 (HumanEval), with GSM8K at 32.
| Set | Stock, xhigh | Swift, xhigh | Stock, medium | Swift, medium |
|---|---|---|---|---|
| GSM8K | 312 | 167 (−47%) | 204 | 186 (−9%) |
| MATH-500 | 759 | 517 (−32%) | 768 | 478 (−38%) |
| HumanEval | 845 | 700 (−17%) | 685 | 652 (−5%) |
| MBPP | 762 | 545 (−28%) | 342 | 306 (−10%) |
| MT-Bench | 416 | 243 (−42%) | 499 | 425 (−15%) |
Mean tokens per answer, thinking plus answer, all 32 prompts (answers cut off at 4096 count as 4096):
| Set | Stock, xhigh | Swift, xhigh | Stock, medium | Swift, medium |
|---|---|---|---|---|
| GSM8K | 438 | 296 (−32%) | 371 | 368 (−1%) |
| MATH-500 | 1,052 | 864 (−18%) | 1,276 | 833 (−35%) |
| HumanEval | 2,042 | 1,454 (−29%) | 1,196 | 1,131 (−5%) |
| MBPP | 1,551 | 899 (−42%) | 977 | 895 (−8%) |
| MT-Bench | 1,475 | 1,163 (−21%) | 1,113 | 1,002 (−10%) |
Takeaways
- Same speed per token; the time saved is the shorter answers. Median time per output token on SPEED-Bench is 4.49 vs 4.47 ms. Swift finishes the 110 prompts in 913 s instead of 1,016 s because it writes 10% fewer tokens. Both runs hit the 4,096-token cap on some turns (11% of stock’s, 9% of Swift’s). Cut-off answers count as 4,096, so the real gap is probably a bit larger.
- Chat at 1 user is the exception: 4% slower, accept length 3.27 vs 3.44. One run on 12 prompts, so I can’t say whether it’s real. The other serving rows in the repo (4 users, 20k, 80k, 120k) are within 1%; 40k at 1 user is +4% for Swift (4 prompts).
- The saving is mostly thinking. At
mediumSwift thinks 5–38% less on the DFlash2 card’s sets and 14–19% less on GSM8K and SPEED-Bench; atxhigh, 17–47% less. Total minus thinking (an estimate:completion_tokensagainst re-tokenized reasoning) is about the same on full GSM8K (134 vs 136) and atxhighon GSM8K and MATH-500, but it moves elsewhere: MT-Bench atxhigh−29%, HumanEval atxhigh+26%, and MBPP atmediumsaves 82 tokens of which only 36 are thinking. Swift’s model card claims 24.8% fewer thinking tokens atmediumand 41.9% atxhigh(card @b4c84d42, checked 2026-10-30). That is BF16 on vLLM; thexhighfigure is its GPQA-Diamond row and the table doesn’t name a benchmark formedium. - On three of five sets
xhighcosts Swift about whatmediumdoes. Whole responses atxhighvsmedium: GSM8K 296 vs 368 tokens, MATH-500 864 vs 833, MBPP 899 vs 895. MT-Bench (1,163 vs 1,002) and HumanEval (1,454 vs 1,131) cost 16–29% more. Stock pays more forxhighon four of five (HumanEval 2,042 vs 1,196). I didn’t measure accuracy atxhigh, and the 4,096 cap hides the longest answers. - Stock accept length holds up on Swift. It is within 2 standard errors of stock on every set and SPEED-Bench domain, and slightly higher on all five DFlash2 card sets at
xhigh. So the fine-tune didn’t hurt the stock drafter. I didn’t test a drafter tuned on Swift. - The DFlash2 model card’s numbers reproduce here. On its prompts and protocol, stock NVFP4 lands within 0.18 of the DFlash2 card on every set, and output tok/s at 1 user is within 7% of the H200 (180–240 vs 184–236). The 3.4 in the spec-decode post is ShareGPT chat at
medium. Prompts, sampling, effort and max length all differ from the DFlash2 card’s runs, so the gap is most likely the workload. - BFCL ties at 168. Stock NVFP4 scored 174 and 176 on this config in the earlier posts, so the same config already moves by 8 cases between runs. By category, Swift gains
multi_turn_base(14 → 16 of 20) and losesirrelevance(15 → 11); with 20 cases each, neither is outside noise. - Quality here is two benchmarks. GSM8K is near ceiling and BFCL is a 205-case subset, so “same” means no difference I could see. Swift’s model card shows 82.22% vs 84.14% for the base at
medium, on a benchmark it doesn’t name. I ran nothing harder.
Setup
Serving stack:
- Image:
lmsysorg/sglang:nightly-dev-cu13-20261010-961bcf48. - Checkpoints:
RadixArk/Qwen3.8-27B-NVFP4@319f741c,ukisai/Swift-1.5-Qwen3.8-27b-NVFP4@25482027(ukisai’s own NVFP4 build). - Drafter:
z-lab/Qwen3.8-27B-DFlash2@50307d4c, 8 draft tokens, on every run. - Flags: the launch command from the NVFP4 vs FP8 post (
scripts/args/qwen38-27b.sh) with--mem-fraction-static 0.41. Both get a 236,864-token KV pool and 43.8 GB of GPU memory after load.
Benchmarks, all at reasoning_effort=medium unless noted:
- GSM8K: the full test split, sgl-eval’s prompt and grader (last
\boxed{}), the model’s own sampling, max 32,768 tokens, 32 requests in flight. No answer was cut off. - BFCL:
bfcl-eval2026.3.23, theQwen/Qwen3-32B-FChandler, the same fixed 205-case subset as the earlier posts (case ids). - DFlash2 card sets: GSM8K, MATH-500, HumanEval, MBPP, MT-Bench (first turn), prompt formats and shuffle from
z-lab/dflashat07ebd93, 32 prompts per set, 1 user. Once with the DFlash2 card’s protocol (xhigh), once atmediumwith the same sampling. - SPEED-Bench: the qualitative split, 10 prompts per domain (110 prompts, 142 turns), max 4096 tokens, 1 user, server-default sampling.
- Serving:
python3 -m sglang.benchmark.serving --backend sglang-oai-chat --flush-cache --warmup-requests 2 --seed 1, the same chat and 20k scenarios as the first post.
Caveats
- One run per config, 32 prompts per DFlash2 card set and 10–26 turns per SPEED-Bench domain. Gaps under about 2 standard errors can’t be told from noise, and every Swift-vs-stock accept-length gap is under that. Chat at 1 user is 12 prompts; the 20k–120k rows are 4 prompts each (8 at 4 users).
- “Output tokens” and “tokens per answer” are
completion_tokens, i.e. thinking plus answer; answers cut off at 4096 count as 4096. “Thinking tokens” is the saved reasoning text of each response, tokenized with the model’s tokenizer, counted only on prompts where both models stopped on their own (thinking_tokens.pyin the repo). - The DFlash2 model card doesn’t say how many prompts it ran or at what precision; its launch example serves BF16
Qwen/Qwen3.8-27B. Mine is NVFP4 on an RTX PRO 6000 at 400 W. - The serving rows use fixed output lengths (
ignore_eos), so they measure speed only and can’t show the token savings. The 20k prompt is SGLang’srandomdataset (one ShareGPT prompt repeated to length). - BFCL uses its own Qwen3 FC prompt, not the model’s chat template. Compare these scores with each other, not with the public leaderboard.
Raw data
- Scripts, configs and raw results: adcostanza/benchmarks.
run.shthere reruns all four configs, about two and a half hours. - The scripts on
mainkeep changing. To rerun with them exactly as these runs had them, check out50fa2ce. results/stock-nvfp4-quality/andresults/swift-nvfp4-quality/: GSM8K and BFCL, every response included.results/dflash8/(stock) andresults/swift-dflash8/(Swift):accept-sets/,speed-bench/(one line per request, generated text included),bench-serving.jsonlandserver.log.thinking_tokens.py: the thinking-token tables, from the saved responses.
Test system
- GPU: NVIDIA RTX PRO 6000 Blackwell Workstation Edition, 96 GB, power limit 400 W (default 600 W). Nothing else on the GPU, one config at a time.
- PCIe: Gen 4 x16 (the card supports Gen 5;
nvidia-smireports Gen 4 as this system’s maximum). - CPU: AMD Ryzen 9 7950X, 16 cores, 32 threads.
- RAM: 250 GiB DDR5.
- OS: Ubuntu 24.04.2, kernel 6.8.0-147.
- NVIDIA: driver 580.178.04, CUDA 13.0.
- Containers: rootless Docker 28.0.4, NVIDIA Container Toolkit 1.18.1, GPU through CDI.
- Full list: hardware.md at the commit these runs used.