DGX Spark · documentation

Qwen3.8-27B 4-bit on a single DGX Spark (GB10 / SM121)

View the repository Last pushed 6 September 2026 9 documents

A measured serving recipe for 4-bit Qwen3.8-27B on one DGX Spark, with a side-by-side comparison of two 4-bit checkpoints and the FP8 baseline they are measured against. Every number in RESULTS.md came from the harness in bench/.

Headline: 75 tok/s single-stream (k=14), or 246 tok/s aggregate at 8-way concurrency (k=7, default batch budget). Those are two different configurations — draft depth trades one against the other, and no single setting wins both. See §3 of RESULTS.

This repository measures speed only. No quality evaluation was performed here; every accuracy figure below is cited from its publisher and unverified. Read LIMITATIONS.md before relying on any of it.

Fresh generation Edit-heavy
FP8 + DSpark k=7 20.00 45.0 – 47.1
MixedInt4-AutoRound + DSpark k=7 29.12 56.7 – 63.7
NVFP4 (Unsloth) + DSpark k=7 29.23 58.6 – 59.1
NVFP4 (Unsloth) + DSpark k=14 29.55 72.6 – 75.0
gain from quantization alone, k=7 1.46× 1.26 – 1.35×

The drafting configuration is identical across the first three rows, so that difference is attributable to the weights alone. The last row adds draft depth, which requires --max-num-batched-tokens 16384.

Read this first: quantization only pays at low concurrency

Measured against FP8 on the same harness, DSpark k=7:

Concurrency FP8 NVFP4 4-bit advantage
c1 46.91 59.79 +27 %
c4 134.21 161.36 +20 %
c8 208.71 229.31 +10 %
c16 256.08 256.47 +0.2 %

Single-stream decode is memory-bandwidth-bound, so fewer weight bytes is decisive. As the batch grows, one weight read serves many sequences, the workload turns compute-bound, and byte count stops mattering.

If you serve a fleet at c16, this entire repository buys you nothing — FP8 matches it and carries no quantization quality question. Quantize for interactive latency and low concurrency; do not quantize for fleet throughput.

4-bit also costs 7–9 % of prefill throughput at 32K–100K prompts (§4), because Marlin dequantization is compute-bound work that prefill pays for.

DFlash 2 does not run on either 4-bit checkpoint

DFlash 2 (Inco AI, August 2026) is the strongest drafter currently available for this model. Under vLLM it cannot be used with either checkpoint in this repo — it requires an unquantized target LM head, and both 4-bit builds fail the check (NVFP4 quantizes the head; AutoRound stores it in bf16 but vLLM still assigns it a quantized method). FP8 is the only build that works.

llama.cpp has no such restriction, and there it is the fastest single-stream configuration measured anywhere in this work:

engine · config generative edit-heavy
llama.cpp Q4_K_M, no spec 10.84 10.84
llama.cpp Q4_K_M + MTP k=7 30.38
llama.cpp Q4_K_M + DFlash2 k=7 37.58 60.89
vLLM FP8 + DFlash2 k=7 31.72 49.20

But llama.cpp saturates at ~77 tok/s aggregate and its TTFT p50 reaches 4.0 s at c16, against vLLM's 220 tok/s and 1.1 s. The rule this repo already argues for quantization extends to the engine: llama.cpp for one interactive user, vLLM for anything else.

Separately — the drafter in most 4-bit recipes is the wrong one. On identical NVFP4 weights, free in-checkpoint MTP k=3 beats the Doopeworld DSpark k=7 drafter at every concurrency, by +15% at c1 rising to +49% at c16, while saving a 2.6 GiB drafter.

Full detail, the c1-c16 curves, the block-size ceiling and quality measurements: DFLASH2.md. References: SOURCES.md.

Read this next if you are choosing a quantization

GB10 has no native FP4 compute path. SM121 lacks the tensor-core support the FP4 GEMM kernels need, so 4-bit weights are dequantized through Marlin and multiplied in higher precision. Three consequences:

  1. W4A4 buys nothing here. You pay the accuracy cost of quantized activations and receive no compute benefit, because the activation path is not executed in FP4. Prefer W4A16 — weight-only. The speedup on this device comes entirely from reading fewer bytes per token, not from faster math.
  2. CUTLASS FP4 kernels are reported to emit silent garbage on this architecture. Not an error — wrong output. Keep them out of the path.
  3. VLLM_MARLIN_USE_ATOMIC_ADD=1 is required. There is a documented race condition in the Marlin kernel on SM121 that produces incorrect output without it. Since 4-bit weights go through Marlin here, this sits directly in your critical path — and a kernel race looks exactly like "this quantization is bad quality".

Checkpoints compared

Checkpoint Size Scheme Published evaluation
Qwen/Qwen3.8-27B-FP8 28.5 GiB FP8 (official) — (reference)
…-MixedInt4-AutoRound 20.8 GB int4 W4A16 g128 on decoder Linears; in_proj_a/in_proj_b and vision tower BF16 MMLU recovery 99.32 %
unsloth/Qwen3.8-27B-NVFP4 22.6 GB NVFP4 with 8-bit groups for sensitive modules none published
…-NVFP4A16 (MLP-only) 28.8 GiB 4-bit MLP only; attention, SSM, vision, lm_head BF16 ppl +3.0 %, lower divergence than official FP8
ModelOpt / NVIDIA recipe ~21 GB 193 W4A16_NVFP4 (MLP + lm_head, g16) + 208 FP8 attention/GDN + 257 BF16 GSM8K 81.25 %, HumanEval 39/40, IFEval 38/40

Two things worth noting from that table.

The MLP-only NVFP4A16 build is a quality upgrade, not a speed one. At 28.8 GiB it is the same size as FP8, so decode throughput is unchanged. Sparing attention, SSM, vision and lm_head is what keeps its divergence low — and what eliminates the size advantage.

The ModelOpt recipe has the strongest published evidence, and it is the only one of these reporting a code benchmark. If you need to justify a quantization to someone, HumanEval 39/40 is a better argument than an MMLU delta.

Which layers must not be quantized

Qwen3.8-27B is hybrid: 48 GatedDeltaNet (linear-attention) layers and 16 full-attention layers. Independent evaluation of the same-generation 27B found that NVFP4 builds which quantize the linear-attention path "consistently and significantly underperform", while builds keeping it in 16-bit show only subtle degradation.

The specific fix: linear attention can be quantized as long as in_proj_a and in_proj_b stay in higher precision. These are two tiny per-layer recurrence-control projections. Miss them and the model degrades in ways benchmarks may not surface but real work will.

If you quantize this model yourself, that is the single most important line in the recipe.

Quickstart

./serve.sh                      # NVFP4 + DSpark k=7 by default
MODEL=<int4-repo> ./serve.sh    # or the AutoRound int4 build
python bench/edit_bench.py
python bench/conc_bench.py

Where the speed actually comes from

Only a minority of the total speedup on this device is the quantization:

Change Edit-heavy Cumulative
Stock FP8, no speculation, no prefix caching 7.88 1.0×
+ speculative decoding (DSpark k=7) 47.1 6.0×
+ 4-bit weights 59.1 7.5×
+ draft depth (k=14) 75.0 9.5×

Six of the 9.5× is decode strategy on unchanged FP8 weights — speculative decoding is output-preserving by construction. Establish that baseline before reaching for quantization: it is free, reversible, and carries no accuracy question at all.

Quantization contributes the remaining 1.6×, and it is the only step here that changes what the model knows. Treat it accordingly — see Evaluation.

Evaluation

Published benchmark scores are necessary but not sufficient. A same-family checkpoint in this model line passed standard benchmarks and then failed a real code task badly enough to justify a blanket "16-bit weights only" policy for months. Benchmarks did not predict that; a concrete task did.

Before promoting any 4-bit build, run your own representative task — ideally a multi-file change or an API-precise piece of work, since that is where quantization damage shows up first, rather than one-shot generation which tends to look fine.

The speculative-decoding and prefix-caching configuration needs no such gate. It cannot change output.

License

MIT for the scripts and documentation in this repository. Model weights remain under their upstream licenses.

§Documentation

01

Measurements — Qwen3.8-27B 4-bit on one DGX Spark

Measured against a live vLLM v0.27.1-aarch64 server on a DGX Spark (GB10 / SM121, 128 GB unified, 273 GB/s), sole occupant, gpu-memory-utilization 0.85, max-model-len 262144, temperature=0,…

02

DFlash 2 on 4-bit Qwen3.8-27B

The headline is a negative result with a workaround: DFlash 2 cannot be served on either 4-bit checkpoint in this repo under vLLM.

03

Findings and gotchas — 4-bit on SM121

SM121 lacks the tensor-core support the FP4 GEMM kernels require. vLLM's actual path is:

04

Limitations and methodology caveats

Everything in RESULTS.md is a real measurement taken on real hardware.

05

DFlash2 benchmark harness

The suite that produced every number in ../../DFLASH2.md. It is kept separate from the sibling bench/ scripts because it uses different prompts and output lengths — the two are internally…

06

Prompt — Orbital mechanics

Build a single self-contained HTML file called index.html containing a three.js N-body orbital mechanics simulation.

07

Prompt — GPU flow field

Build a single self-contained HTML file called index.html containing a three.js GPU particle flow-field simulation.

08

Prompt — Double pendulum

Build a single self-contained HTML file called index.html containing a three.js double-pendulum chaos simulation.

09

Sources

Published figures cited for comparison (Inco AI, H200, SGLang, block size 8, temperature 1.0 with xhigh reasoning): acceptance length 4.80 mean for Qwen3.8-27B against MTP 4.28 and a…

Read it where it lives, and open an issue if a number looks wrong.

Back to DGX Spark