Research 13 min read

DeepSeek V4.1 Flash on Two DGX Sparks: 2.9-Bit, 1.9× Faster Than V4 Flash, and What the Bits Cost

ai.rs Oct 26, 2026
DeepSeek V4.1 Flash on Two DGX Sparks: 2.9-Bit, 1.9× Faster Than V4 Flash, and What the Bits Cost illustration

In September we sized DeepSeek-V4.1-Flash against our two GB10 boxes and said no: 475 GiB of weights against 242 GB of memory, and the only way in, a re-quantisation to two or three bits, would "give back concurrency and the KV pool, move us to a forked vLLM, and decode no faster than today, with no published quality table". Nine days ago we repeated the verdict for the 1017 retrain: two Sparks, V4-Flash only.

We were wrong on two of those four counts, and this article is the measurement that shows it. On 25 October we ran V4.1-Flash-1017 at 2.9 bits per weight on the same two DGX Sparks, tensor parallel over both RoCE rails, with a native serving engine instead of vLLM. It decodes 1.5 to 1.9× faster per token than the V4-Flash that has served us since August. It ties V4-Flash on every quality harness we own, beats it on hard code, and finds a needle at 976,000 tokens. The two counts we had right are the costs: it gives back most of the memory headroom and the concurrency, and it draws about 1.6× DS4's typical busy power under sustained load. It also reads documents, which DS4 cannot.

Test rig. Two GB10 workstations, one 200 Gb cable, both RoCE rails. "DS4" is DeepSeek-V4-Flash-0731 in NVIDIA's NVFP4 DSpark build on vLLM, tensor parallel 2, the pair's engine since August; its quality rows are the August and September runs. "The lane" is DeepSeek-V4.1-Flash-1017 in LibertAI's EXL3 pack at 2.9 bits per weight, served by TensorFold tensor parallel 2 following tonyd2wild's two-Spark recipe of 18 October, with the 196B Engram lookup tables read from each node's NVMe; measured 25 October with the same harnesses, prompts and haystacks. "The API" is DeepSeek's own deepseek-flash endpoint, which serves the same 1017 weights unquantised: the control that separates "the newer model" from "the 2.9-bit quantisation". Every number is ours.

What runs on each box

Row DS4, V4-Flash-0731 the lane, V4.1-Flash-1017
parameters 304B, 13B active 763B: 552B backbone + 196B Engram tables; 8B active prefill, 16B decode
precision NVFP4, NVIDIA's DSpark build EXL3 at 2.9 bpw: routed experts 3 bits (2 on five layers), attention 5, head 6, drafter 4; Engram FP8 on NVMe
engine vLLM, tensor parallel 2 TensorFold native, tensor parallel 2 over both RoCE rails
weights resident per node ~78 GiB 105 GiB
memory left per node, of ~121 GB usable ~43 GB, as a 2,873,231-position KV pool 5.8 and 7.8 GiB; pool 1,048,576 positions
streams 6 4
window per request 1M 1M
load time minutes 30 s per rank
vision no yes: the pack carries the vision tower, and it reads documents

The pack was not made for this engine; LibertAI built it for a vLLM-based two-Spark kit, and its card reports perplexity 1.8% worse than the unquantised model on code and 0.4% on prose. The fit arithmetic from September still holds, which is why the experts had to go to 3 bits: at their native 4 bits they alone exceed the pair.

Speed: the bigger model is the faster one

One stream, nothing else running, through the same chat front end both engines serve:

prompt DS4 the lane ratio
count to 300, structured, drafter hits 88 tok/s 138 tok/s 1.6×
350-word story, prose 33 tok/s 61 tok/s 1.9×
two Serbian sentences, Cyrillic 33 tok/s 52 tok/s 1.6×
time to first token, short prompt 0.2 s 0.15 to 0.3 s
prefill, 269K-token haystack 1,505 tok/s 2,070 tok/s 1.4×
prefill, 538K-token haystack 1,170 tok/s 1,860 tok/s 1.6×
prefill, 976K-token haystack not run 1,620 tok/s

With four prose streams in flight the lane aggregates 106 tok/s at 29 per stream; the recipe's own four-stream figure on a mixed set with code in it is 136. DS4 has served six streams at about 148 aggregate on structured prompts, so at full concurrency the two are closer than the single-stream rows suggest; per user, the lane is faster at every count it allows.

The same V4.1 under vLLM on Sparks, in tonyd2wild's measurements, decodes at 27 prose and 40 code. The lane doubles that on the same boxes. None of this is the model being smaller, because it is not. It is the serving path.

Why

Decode on a GB10 is bound by memory bandwidth and by how many scheduler steps a second the engine completes; the tokens per step come from the DSpark drafter, which both models have. The chat's own statistics give both numbers for each run:

Row DS4 the lane
bytes read per step, active weights 13B at ~4.5 bits with scales, ~7 GB 16B at 2.9 bits, ~6 GB
steps per second ~14 23 on the count, 32 on the story
tokens accepted per step ~6.3 structured, ~2.4 prose 5.9 structured, 1.9 prose
tokens per second 88 / 33 138 / 61

Acceptance is the same or a little lower. The whole gain is in the step, which the native engine finishes in 31 to 43 ms where vLLM takes about 70. Four reasons, in order of weight:

  1. CUDA graphs. On GB10, vLLM must run eager, because the NVFP4 mixture-of-experts kernels crash on this chip with graphs enabled, a fix we recorded in August. Every DS4 step is launched kernel by kernel from Python. The lane replays one captured graph per step.
  2. A native engine. Zig and CUDA, no Python in the decode loop, the all-reduce over RDMA on both rails, fused kernels compiled ahead of time for exactly these bit widths.
  3. Fewer bytes per step at 2.9 bits, despite more active parameters: about 6 GB against 7, so the bandwidth-bound part is a little shorter, not longer.
  4. A quarter of the KV per token, 890 bytes against 3,514, so attention reads less per step, and V4.1's sparse indexer reads only selected blocks at long context. That is also why prefill at 538K is 1.6× faster and why the 976K prompt still runs at 1,620 tok/s.

This is the correction to our September sentence. We assumed a re-quantised V4.1 would inherit vLLM's step time. The step time was vLLM's, not the model's.

Quality: three columns, with the unquantised model as the control

Row DS4 on the pair, NVFP4 V4.1 lane, 2.9 bpw V4.1 unquantised, API
code, 10 tasks with hidden tests 10/10 10/10 10/10
LiveCodeBench v6, 175 problems, thinking off, 6K budget 95, 54.3% 104, 59.4% 118, 67.4%
of which hard, 80 problems 20 27 37
LiveCodeBench, thinking on, 16K budget not run 119, 68.0% 127, 72.6%
of which hard, thinking on 33 40
GSM8K strict, 1,319 problems 96.59% 96.59% 96.82%
Serbian recall, 16 facts 16/16 16/16 16/16
false premises, 5 traps 5/5, 0 fabricated 5/5, 0 fabricated 5/5, 0 fabricated
deep knowledge, 3 explanations, 30 facts 25/30 24/30 24/30
Serbian prose, stops on its own 6/6 6/6 6/6
prose, Cyrillic share 0.952 0.989 0.978
prose, length accuracy 0.94 0.79 0.78
agent repair, 7 broken repos 7/7, 5.0 turns, 3,069 tokens 7/7, 4.0 turns, 2,107 tokens 7/7, 4.4 turns, 4,151 tokens
degraded Serbian invoice, 13 money fields cannot read images 91.5% content, 13/13 fields, 6.8 s 90.6%, 13/13, 3.2 s
single needle, 90K to 807K, three depths 12/12 12/12 12/12
two-needle sums 3/3 to 540K 4/4 to 807K 4/4 to 807K
needle at 976,402 tokens not run found not run

Three readings. The newer model's gain over DS4 is real in one place, code: unquantised, V4.1 solves 23 more LiveCodeBench problems, 17 of them hard. Everywhere else the two models tie, and V4.1 writes shorter prose than asked, at the API as much as on the lane, so that is the model and not the bits. And the quantisation shows in exactly one row, hard code: the lane equals the API on deep knowledge, prose length, GSM8K, recall, traps and every needle, and is 10 hard problems behind it with thinking off.

Reading past the counts: the lane's deep-knowledge misses are the same facts the unquantised model misses, Milanković's insolation cycles, Enigma's daily keys, H.265's tiles, not new errors. The agent loop is tighter by one turn per repair and a third fewer tokens, which is where DeepSeek says the 1017 retrain's gains are, and that arrives on the pair intact. And the invoice row is new for the pair: DS4 cannot read an image at all, so until now a document went to the API or to a Qwen3-VL 32B on the desktop, which scored 88.4% on the same fixture in 92 s. The lane reads it in 6.8 s with every critical field exact, and nothing leaves the network.

What the 2.9 bits cost, taken apart

On the 80 hard problems: DS4 20, the lane 27, the API 37. The newer model is worth 17 hard problems over DS4 at full precision; the lane delivers 7 of them. Where did the other 10 go?

  • Noise. At temperature 0.2 the lane and the API disagreed on 34 problems. Rerun on those 34, the API went from 24 to 21 and flipped on 17 of them; the lane went from 10 to 14 and flipped on 22. Averaging both runs gives lane 106 against API 116.5 on the full set, a six-point gap with a standard error near 3.6 per run. One run on 80 hard problems carries a standard error of about four, so the lane's +7 over DS4 is at the edge of what a single run proves; the two-run estimate on the whole set points the same way.
  • Budget, not loops. The lane hit the 6,000-token cap on 38 problems, the API on 27. Those answers are not degenerate; they are the model working the problem out in prose before writing code, which V4.1 does with thinking off and DS4 does not, median 1,200 output tokens against 356. Rerun at a 16,000-token budget, the lane solved 6 of its 38; the same 38 on the API at 6,000 tokens gave 7. These are problems both endpoints mostly fail, and given the room, the lane reaches the API on them. That is worth five to six problems of the gap.
  • One missing kernel. One problem fails in 0.13 s on every no-thinking run with a kit error: the ahead-of-time kernel set has no recorded variant for that prompt shape, and the engine errors instead of falling back. It is counted as a fail in every lane number above. With thinking on, a different prompt shape, the same problem passed, which confirms the fault is the kernel table and not the model.
  • The rest, seven problems or so, is spread over the other 137 problems, inside one run's noise. That is the most the bits themselves can be shown to cost here.

With thinking on the picture is the same but closer: lane 119, API 127, a gap of 8 instead of 14. Per problem the two agree on 161 of 175; the API alone passes 11, the lane alone 3. Against DS4, the lane with thinking on solves 24 more problems, 13 of them hard, on the same two boxes.

What thinking costs on the pair. The decode rate does not change; the answer gets longer, and the time follows the tokens exactly: median output per problem 1,223 tokens against 3,943, wall for 175 problems on four streams 2,623 s against 8,415 s, both 3.2×. A coding question that answered in a quarter of a minute takes a minute, and scores better. On short Serbian questions the reasoning ran to a few hundred tokens and the cost is small.

The needle grid, to a million

Same filler as the pair's August grid and the API's September one, byte for byte: one needle at three depths, then two needles 90% apart whose sum is the answer, then one needle at a million.

prompt tokens depth 0.1 depth 0.5 depth 0.9 wall, prefill DS4, August API, September
89,744 exact exact exact 40 s 3/3 3/3
269,015 exact exact exact 130 s 3/3 3/3
538,050 exact exact exact 289 s 3/3 3/3
806,909 exact exact exact 474 s 3/3 3/3
976,402 exact 603 s not run not run

Twelve of twelve single needles to 807K, the needle at a million found, and the two-needle sums 4/4 to 807K where the pair had been run to 540K. Recall precision is unchanged by the 2.9-bit backbone and by the sparse indexer at every length tested, up to the full window. DS4 ran the 538K haystack in 460 s and the 269K in 179 s; the lane did them in 289 and 130.

What it costs

These are the whole case against, and the tables above are the case for.

  1. Memory headroom of 6 to 8 GiB per node. The model takes 105 of the 121 GiB. Nothing else fits beside it, and the page cache for the Engram rows is small, so those reads go to NVMe every step, 2 to 3 ms each.
  2. Fewer people in the window. Four streams against six, and a pool of 1,048,576 positions shared by all of them against 2,873,231. Every request on either engine is capped at the model's 1M; the pool is the total in flight. DS4 holds two full-window requests at once with room to spare; the lane holds one, or four averaging 260K. A fifth request waits. For a household chat that is no constraint; several concurrent agents each resending 140K would feel it as queueing.
  3. No scheduler priority. vLLM takes a per-request priority and the chat used it to put interactive turns ahead of long document reads. TensorFold serves in arrival order.
  4. No engine metrics. No Prometheus endpoint, so the decode, KV and acceptance charts stay dark while it runs.
  5. Shorter prose than asked, a property of V4.1 itself: the business letter came in at 47% of the asked length, the argument essay at 50%. A length that matters needs saying twice.
  6. More power under sustained load. 165 W for the pair at four busy decoding streams, 82 W per node at 95% GPU and 84 to 85 °C. DS4 over two months of snapshots draws about 100 W whenever anything is running, with peaks of 165 to 170 W during long prefills. So the lane runs at DS4's peak continuously under full load, about 1.6× DS4's typical busy draw, because the native engine keeps both GPUs busy where vLLM's eager loop left them waiting. Per token of decode it is less efficient, 0.64 tokens per joule on prose against DS4's 1.08 to 1.67; per answer it is faster. Idle is the same, 22.4 W against 23.1.
  7. A younger stack. A community engine at a pinned commit with three patches, measured in hours of uptime against DS4's seventy-one days. Rollback is DS4's own start script, two minutes.

The lever on the first two, if it ever matters, is bits: the recipe's newer version serves a 2.5 bpw pack with 2,097,152 positions and eight streams on the same pair, because smaller weights give the pool its room back. Whether 2.5 bits still passes the harnesses is a test like this one, not a given.

The verdict

  • V4.1-Flash fits two DGX Sparks, at 2.9 bits per weight with a native engine, and it is the faster model on them: 1.6 to 1.9× per token, 1.4 to 1.6× on prefill. We said otherwise in September and October; the fit was right, the speed was not.
  • The bits cost hard code and nothing else we can measure. The lane keeps 7 of the 17 hard problems V4.1 gains over DS4 with thinking off, 13 of 20 with thinking on, and ties the unquantised model on every other row, the invoice included.
  • The price is headroom: four streams and one million positions in flight instead of six and 2.87 million, and about 1.6× the power when busy. One user with a million-token window loses nothing; a busy multi-user box loses a third of its seats.
  • If you run one or two people on a pair of Sparks, this is now the engine to run. If you run six, DS4 on vLLM still holds more of them, and the day vLLM gets CUDA graphs on GB10 and a sub-3-bit expert format, that arithmetic changes again.

Frequently Asked Questions

Does DeepSeek V4.1 Flash fit two DGX Sparks? +

Yes, at 2.9 bits per weight. LibertAI's EXL3 pack of V4.1-Flash-1017 keeps the routed experts at 3 bits (2 on five layers), attention at 5 and the head at 6, 196 GiB in total, and TensorFold serves it tensor parallel across two GB10s with the 196B Engram lookup tables read from each node's NVMe. Each node holds 105 GiB of model and keeps 6 to 8 GiB free. The native 4-bit checkpoint, 475 GiB, still does not fit; that needs four Sparks.

How fast is DeepSeek V4.1 Flash on a dual DGX Spark? +

Measured 25 October 2026, one stream: 138 tok/s on structured output and 61 tok/s on prose, against V4-Flash's 88 and 33 on the same two boxes; prefill 1,860 tok/s on a 538K-token prompt against 1,170, and 1,620 tok/s at 976K. Four prose streams aggregate 106 tok/s. The same model under vLLM on Sparks decodes at 27 prose / 40 code in tonyd2wild's measurements.

Why is the 763B V4.1 faster than the 304B V4 Flash on the same hardware? +

The serving path, not the model. On GB10, vLLM must run eager because the NVFP4 MoE kernels crash with CUDA graphs, so every V4 step is launched kernel by kernel from Python at about 14 steps a second. TensorFold replays one captured graph per step in a native Zig and CUDA engine with RDMA all-reduce over both RoCE rails, reaching 23 to 32 steps a second. At 2.9 bits the active weights read per step are also smaller, about 6 GB against 7, and V4.1's KV cache is a quarter the size per token.

What does the 2.9-bit quantisation cost in quality? +

Hard code, and nothing else we can measure. Against the same model unquantised on DeepSeek's API, the lane ties on GSM8K (96.59 vs 96.82%), deep knowledge (24/30 both), Serbian recall and false premises, prose length and script, and every needle to 807K. On LiveCodeBench it scores 104 against the API's 118 with thinking off (27 vs 37 of the 80 hard problems) and 119 against 127 with thinking on. Five to six of those problems are the 6K token budget, one is a missing kernel in the kit, the rest is inside one run's noise.

What does the pair give up by running V4.1 instead of V4 Flash? +

Headroom and concurrency: 6 to 8 GiB free per node instead of about 43 GB, four streams sharing a pool of 1,048,576 positions instead of six sharing 2,873,231, no per-request priority, no engine metrics, and 165 W sustained at four busy streams against DS4's typical 100 W when busy (DS4 peaks at 165 to 170 W during long prefills). Per token of decode it is less efficient (0.64 tokens per joule on prose against 1.08 to 1.67); per answer it is faster. Idle power is the same, 22 to 23 W. Vision is not a cost: the lane reads documents, 13/13 on our invoice fixture.

Does V4.1 Flash on two Sparks still handle 1M-token context? +

Yes. One needle was exact at three depths at 89,744, 269,015, 538,050 and 806,909 tokens, two-needle sums were 4/4 to 806,909, and a needle at 976,402 tokens was found, with prefill at 1,620 tok/s at that length. The window per request is 1M; the pool of positions in flight across all streams is 1,048,576, so one user can use the full window or four users can share it.

Wondering if this fits your business?

The benchmarks and architectures we cover here power real production AI assistants. See where your business stands in 2 minutes.

Take the AI Readiness Check
Share: Post Share

Read next