Iβve been following the @Albond thread on the 122B model optimisations but for me the Intel autoround quant is not usable for agentic tasks like using OpenCode because of a bug with that quant where it just stops generating in the middle of tool calls. There is also a lot of talk recently about how the dense 27B model can perform better than the 122B MoE so I was keen to try it out.
Initially I found the performance is unacceptably slow for 27B. I went through osoleve/Qwen3.5-27B-Text-NVFP4-MTP and got around 20 t/s with MTP but that one is text only and I regularly use the great vision capabilities of Qwen3.5. I tried the Intel/Qwen3.5-27B-int4-AutoRound but that one does not have MTP enabled and it is a lot slower than osoleve at ~13 t/s.
Now I see the recent DFlash speculative decoding https://huggingface.co/z-lab/Qwen3.5-27B-DFlash and decided to give it a try with spark-vllm-docker and found it is working quite well with Intel/Qwen3.5-27B-int4-AutoRound.
hf download z-lab/Qwen3.5-27B-DFlash
Note their suggested vllm parameters, particularly the βmodelβ property refers to their speculative decoding model:
vllm serve Intel/Qwen3.5-27B-int4-AutoRound \
--speculative-config '{"method": "dflash", "model": "z-lab/Qwen3.5-27B-DFlash", "num_speculative_tokens": 15}' \
--attention-backend flash_attn \
--max-num-batched-tokens 32768
Iβm getting about 30 T/s with general queries but the degree of speculative decoding at 15 means it is quite variable. I did some benchmarks, firstly I used the bench_qwen35.sh from the albond github https://github.com/albond/DGX_Spark_Qwen3.5-122B-A10B-AR-INT4/blob/master/bench_qwen35.sh
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Qwen3.5-27B-Intel-int4-DFlash Benchmark: test
β Wed 8 Apr 11:24:33 UTC 2026
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββ Run 1/2 ββββββββββββββββββββββββββββββββββββββ
[Q&A] 256 tokens in 5.69s = 44.9 tok/s (prompt: 23)
[Code] 507 tokens in 7.80s = 65.0 tok/s (prompt: 30)
[JSON] 1024 tokens in 22.25s = 46.0 tok/s (prompt: 48)
[Math] 64 tokens in 1.76s = 36.3 tok/s (prompt: 29)
[LongCode] 2048 tokens in 31.45s = 65.1 tok/s (prompt: 37)
ββ Run 2/2 ββββββββββββββββββββββββββββββββββββββ
[Q&A] 256 tokens in 5.69s = 44.9 tok/s (prompt: 23)
[Code] 507 tokens in 7.81s = 64.9 tok/s (prompt: 30)
[JSON] 1024 tokens in 22.18s = 46.1 tok/s (prompt: 48)
[Math] 64 tokens in 1.76s = 36.3 tok/s (prompt: 29)
[LongCode] 2048 tokens in 31.46s = 65.0 tok/s (prompt: 37)
You can see that fairly predictable text like coding perform very well, 60+ t/s.
I also ran llama-benchy to see the hit that the speculative decoding makes on the underlying t/s:
| model | test | t/s | peak t/s | ttfr (ms) | est_ppt (ms) | e2e_ttft (ms) |
|:---------------------------------|----------------:|---------------:|-------------:|------------------:|------------------:|------------------:|
| Intel/Qwen3.5-27B-int4-AutoRound | pp2048 | 1004.03 Β± 3.08 | | 2191.17 Β± 6.74 | 2041.12 Β± 6.74 | 2191.28 Β± 6.73 |
| Intel/Qwen3.5-27B-int4-AutoRound | tg32 | 8.71 Β± 0.58 | 10.18 Β± 0.69 | | | |
| Intel/Qwen3.5-27B-int4-AutoRound | pp2048 @ d4096 | 1032.69 Β± 0.74 | | 6100.56 Β± 4.27 | 5950.51 Β± 4.27 | 6100.63 Β± 4.27 |
| Intel/Qwen3.5-27B-int4-AutoRound | tg32 @ d4096 | 9.15 Β± 0.83 | 11.05 Β± 1.20 | | | |
| Intel/Qwen3.5-27B-int4-AutoRound | pp2048 @ d8192 | 1030.67 Β± 2.35 | | 10086.03 Β± 23.07 | 9935.98 Β± 23.07 | 10086.17 Β± 23.07 |
| Intel/Qwen3.5-27B-int4-AutoRound | tg32 @ d8192 | 8.40 Β± 0.70 | 9.84 Β± 1.02 | | | |
| Intel/Qwen3.5-27B-int4-AutoRound | pp2048 @ d16384 | 1014.41 Β± 1.18 | | 18320.31 Β± 21.74 | 18170.26 Β± 21.74 | 18320.41 Β± 21.71 |
| Intel/Qwen3.5-27B-int4-AutoRound | tg32 @ d16384 | 8.14 Β± 0.43 | 9.36 Β± 0.41 | | | |
| Intel/Qwen3.5-27B-int4-AutoRound | pp2048 @ d32768 | 921.86 Β± 6.12 | | 37919.98 Β± 252.11 | 37769.93 Β± 252.11 | 37920.08 Β± 252.12 |
| Intel/Qwen3.5-27B-int4-AutoRound | tg32 @ d32768 | 7.45 Β± 0.01 | 8.00 Β± 0.00 | | | |
Some vllm output of the speculative decoding acceptance rates for 16 tokens:
(APIServer pid=55) INFO: 172.19.0.2:42192 - "POST /v1/chat/completions HTTP/1.1" 200 OK
(APIServer pid=55) INFO 04-08 10:47:03 [loggers.py:259] Engine 000: Avg prompt throughput: 511.5 tokens/s, Avg generation throughput: 28.8 tokens/s, Running: 0 reqs, Waiting: 0 reqs, GPU KV cache usage: 0.0%, Prefix cache hit rate: 0.0%
(APIServer pid=55) INFO 04-08 10:47:03 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 5.74, Accepted throughput: 23.70 tokens/s, Drafted throughput: 79.99 tokens/s, Accepted: 237 tokens, Drafted: 800 tokens, Per-position acceptance rate: 0.940, 0.840, 0.780, 0.560, 0.380, 0.260, 0.260, 0.240, 0.200, 0.080, 0.040, 0.040, 0.040, 0.040, 0.020, 0.020, Avg Draft acceptance rate: 29.6%
(APIServer pid=55) INFO 04-08 10:47:13 [loggers.py:259] Engine 000: Avg prompt throughput: 797.9 tokens/s, Avg generation throughput: 16.3 tokens/s, Running: 1 reqs, Waiting: 0 reqs, GPU KV cache usage: 6.1%, Prefix cache hit rate: 0.0%
(APIServer pid=55) INFO 04-08 10:47:13 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.68, Accepted throughput: 11.80 tokens/s, Drafted throughput: 70.40 tokens/s, Accepted: 118 tokens, Drafted: 704 tokens, Per-position acceptance rate: 0.773, 0.591, 0.455, 0.227, 0.182, 0.136, 0.114, 0.114, 0.045, 0.023, 0.023, 0.000, 0.000, 0.000, 0.000, 0.000, Avg Draft acceptance rate: 16.8%
(APIServer pid=55) INFO 04-08 10:47:23 [loggers.py:259] Engine 000: Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 33.5 tokens/s, Running: 1 reqs, Waiting: 0 reqs, GPU KV cache usage: 6.1%, Prefix cache hit rate: 0.0%
(APIServer pid=55) INFO 04-08 10:47:23 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 4.24, Accepted throughput: 25.60 tokens/s, Drafted throughput: 126.39 tokens/s, Accepted: 256 tokens, Drafted: 1264 tokens, Per-position acceptance rate: 0.810, 0.570, 0.443, 0.380, 0.304, 0.203, 0.139, 0.127, 0.114, 0.063, 0.038, 0.038, 0.013, 0.000, 0.000, 0.000, Avg Draft acceptance rate: 20.3%
(APIServer pid=55) INFO 04-08 10:47:33 [loggers.py:259] Engine 000: Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 32.8 tokens/s, Running: 1 reqs, Waiting: 0 reqs, GPU KV cache usage: 6.3%, Prefix cache hit rate: 0.0%
(APIServer pid=55) INFO 04-08 10:47:33 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 4.15, Accepted throughput: 24.90 tokens/s, Drafted throughput: 126.39 tokens/s, Accepted: 249 tokens, Drafted: 1264 tokens, Per-position acceptance rate: 0.823, 0.608, 0.418, 0.342, 0.278, 0.253, 0.228, 0.089, 0.063, 0.013, 0.013, 0.013, 0.013, 0.000, 0.000, 0.000, Avg Draft acceptance rate: 19.7%
(APIServer pid=55) INFO 04-08 10:47:43 [loggers.py:259] Engine 000: Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 33.9 tokens/s, Running: 1 reqs, Waiting: 0 reqs, GPU KV cache usage: 6.3%, Prefix cache hit rate: 0.0%
Recipe:
description: vLLM serving Intel/Qwen3.5-27B-int4-AutoRound with DFlash
model: Intel/Qwen3.5-27B-int4-AutoRound
container: vllm-node-tf5
build_args:
- '--tf5'
mods:
- mods/fix-qwen3.5-chat-template
defaults:
port: 8000
host: 0.0.0.0
tensor_parallel: 1
gpu_memory_utilization: 0.75
max_model_len: 262144
max_num_seqs: 10
env:
command: |
vllm serve Intel/Qwen3.5-27B-int4-AutoRound \
--tensor-parallel-size {tensor_parallel} \
--max-num-seqs {max_num_seqs} \
--enable-prefix-caching \
--gpu-memory-utilization {gpu_memory_utilization} \
--max-model-len {max_model_len} \
--enable-auto-tool-choice \
--dtype auto \
--tool-call-parser qwen3_coder \
--reasoning-parser qwen3 \
--chat-template unsloth.jinja \
--load-format fastsafetensors \
--attention-backend flash_attn \
--max-num-batched-tokens 32768 \
--trust-remote-code \
--host {host} \
--port {port}
recipe_version: '1'
name: Intel/Qwen3.5-27B-int4-AutoRound-DFlash
cluster_only: false
solo_only: false
Run command:
./run-recipe.sh qwen3.5-27b-int4-autoround --solo --speculative-config '{"method": "dflash", "model": "z-lab/Qwen3.5-27B-DFlash", "num_speculative_tokens": 16}'
Iβm not an expert on python, I come from a dotnet background so Iβm hoping some of the guruβs here will be able to tweak this even further. I donβt think people on spark give 27B much of a look because of the speed. Hopefully this DFlash speculative decode will ignite some renewed interest in the 27B dense here. For me it is currently the optimum on a single spark with DFlash.
Any ideas on how to improve on this Intel autoround + DFlash?