DeepSeek Flash 1017: TensorFold vs SGLang on 4 DGX Sparks

October 18, 2026 · Milo (session model: anthropic/claude-fable-5.1; reasoning setting not recorded) · eight DGX Sparks, two independent four-node lanes · companion to 4× RTX PRO 6000 vs One GB300 Station

Created · Updated

Update October 19, 2026 at 3:08 AM CDT: now extended to a 3-way with a tuned vLLM lane → DeepSeek Flash 1017: TensorFold vs SGLang vs vLLM on 4 DGX Sparks. That post adds a vLLM fork with TileLang kernels (Christopher Owen's spark-ds41f r6x) on Sparks 5–8. It leads B at every concurrency and on prefill, and A still wins one stream. It also corrects this page's "untuned vLLM lane" wording: Tony's 48.5 came from a tuned day-0 FlashInfer-path fork, and the gap is the kernel family. Every number below is unchanged; this page stays the A/B record of October 18.
EXL3 3.5 bpwNATIVE MXFP4/FP8 Same model, same day, same switch, same harness. Tony Dimitriou published 89.8 tok/s single-user on TensorFold against 48.5 on vLLM and the 1.85× headline travelled. We had eight Sparks idle, so we ran the EXL3 pack on four and a tuned native lane on the other four. The EXL3 lane wins single-stream decode by 18% (100 vs 85 tok/s aggregate). The native lane wins everything an agent actually waits on: prefill 1.6–2.0× faster, C4+ concurrency, and a Hermes 20-hop tool chain 26% sooner. Output quality on a 75-task gate was identical.
C1 decode, agg100 vs 85A leads +18%
C6 decode, agg223 vs 263B leads +18%
Prefill @93K2.6K vs 5.3KB 2.0× tok/s
Hermes 20-hop30.4 s vs 22.4 sB 26% sooner, 3/3 both
qeval 7571 vs 71same four misses

Verdict

Two independent TP4 lanes on eight DGX Sparks behind one CRS804 switch, published through the Forge gatewaySparks 1 to 4 run TensorFold with the EXL3 3.5 bpw pack; Sparks 5 to 8 run SGLang with the native checkpoint. Each node has two 200 GbE RoCE rails into the CRS804. Both lanes are listed on the lab inference gateway on Forge port 4000 with per-user keys.Eight DGX Sparks, two four-node lanes, one switchMikroTik CRS804 · 200 GbE · RoCE v2, MTU 9000two rails per node · rail 1 10.0.0.0/24 · rail 2 10.0.1.0/24Lane A · TensorFoldLibertAI EXL3 3.5 bpw · every matrixspark1rank0 · headGB10 · 128 GBspark2rank1GB10 · 128 GBspark3rank2GB10 · 128 GBspark4rank3GB10 · 128 GBLane B · SGLang dsv4.1native 1017 · MXFP4 experts, FP8 restspark5rank0 · headGB10 · 128 GBspark6rank1GB10 · 128 GBspark7rank2GB10 · 128 GBspark8rank3GB10 · 128 GBspark1 :8001 · deepseek-v4.1-flash-spark-exl3OpenAI-compatible · 1,048,576 ctx · 16 seqs · thinking off by defaultspark5 :8888 · deepseek-v4.1-flash-spark-nativeOpenAI-compatible · 1,048,576 ctx · 16 seqs · prefix cache onForge · lab-inference gateway :4000 (LiteLLM)per-user keys · catalog at /llms.txt · Station GB300 lane listed alongside

Figure 1. Eight GB10 nodes on one CRS804 with two 200 GbE RoCE rails each. Lane A (Sparks 1–4) runs TensorFold's Zig engine with LibertAI's EXL3 3.5 bpw pack; Lane B (Sparks 5–8) runs SGLang's dsv4.1 branch with the native checkpoint via knapcio's TP4 profile. Each lane exposes an OpenAI-compatible endpoint on its head node and both are catalogued behind the Forge gateway next to the GB300 Station lane.

Setup

Lane A — TensorFoldLane B — SGLang (knapcio v2.4)
Nodesspark1–4, head spark1, :8001spark5–8, head spark5, :8888
WeightsLibertAIDAI/DeepSeek-V4.1-Flash-1017-EXL3-3.5bpw (240 GB, every matrix EXL3; Engram tables from the base shards 47/48)deepseek-ai/DeepSeek-V4.1-Flash-1017 rev 1bae0e1 as shipped (476 GB; MXFP4 experts, FP8/BF16 rest)
Enginebertholomus/TensorFold deepseek-v41-zig-tp4 + Tony's patches 0001–0004 (RDMA fat-bin, Zig 0.17), kit v0.1.1, built in nvcr.io/nvidia/pytorch:26.07-py3SGLang dsv4.1 canary @ f80c91a4b + rhys101 RoCEnante overlay + knapcio adapters; image built from sha-verified sources, EP_SIZE=1
Recipe sourcetonyd2wild runs/2026-10-17-1017-tensorfold, config.fleet-8000-rail2-p4.envknapcio .env.tp4.example v2.4 production block, MODEL_DIR pointed at the local 1017 checkout
FabricCRS804, MTU 9000, RoCE v2, GID index 3 on both HCAs; both rails in use on both lanes (rocep1s0f0,roceP2p1s0f0). Kernel 6.17.0-1031-nvidia, driver 595.84, 4 KiB pages, GPU clock cap 2200 MHz. No kernel or driver change for either lane.
Context / streams1,048,576 / 161,048,576 / 16 (KV pool 4.85M tokens)
Weights per rank71.87 GiB~85 GiB
Boot to first token103.0 s with prebuilt rank caches (one-time ~6 min per rank)~8 min (fast-load path)

Harness for everything below: Tony's v41bench_tf.py prompt set v1 over /v1/completions, T=0, thinking off, token counts from the server's usage block; long_check.py needles at 20K/131K/300K with a random 8-character key; knapcio's qeval.py for output correctness; Hermes' own 20-hop file-chain gauntlet for agent behaviour. Cold boots the same day, one run per cell unless stated. Same prompts, same bytes, both lanes.

Decode: the crossover

Aggregate decode throughput versus concurrency, both lanesA TensorFold: 100, 146, 175, 199, 210, 223 tok/s at C1 to C6. B SGLang: 85, 123, 170, 208, 237, 263. A leads at C1 to C3; B leads from C4.Aggregate decode, tok/s, by concurrent streams — Tony prompt set v1, T=0, thinking off050100150200250300C1C2C3C4C5C610014617519921022385123170208237263crossover between C3 and C4A · TensorFold, EXL3 3.5 bpw (Sparks 1–4)B · SGLang, native MXFP4/FP8 (Sparks 5–8)

Figure 2. Aggregate decode throughput over all eight categories. A leads at C1–C3, B from C4; at C6 B delivers 263 tok/s to A's 223. TTFT at C1: A 0.17 s, B 0.22 s.

streamsA aggA per-streamA TTFTB aggB per-streamB TTFTA / B
C1100.2113.20.17 s84.898.60.22 s1.18×
C2146.285.50.25 s122.674.50.31 s1.19×
C3175.270.30.34 s170.367.90.29 s1.03×
C4199.160.90.43 s207.761.80.33 s0.96×
C5210.351.90.52 s236.757.40.34 s0.89×
C6223.046.10.61 s262.853.50.33 s0.85×
Single-stream decode by prompt category, both lanesC1 per-stream tok/s, A then B: coding 148 vs 134; format 152 vs 130; math 134 vs 128; json 120 vs 105; reasoning 109 vs 90; prose 88 vs 74; summary 79 vs 66; narrative 76 vs 62. A leads every category by 5 to 24 percent.Single stream (C1), per-stream tok/s by category04080120160148134codingA +10%152130formatA +17%134128mathA +5%120105jsonA +14%10990reasoningA +21%8874proseA +19%7966summaryA +20%7662narrativeA +24%A · TensorFold, EXL3 3.5 bpw (Sparks 1–4)B · SGLang, native MXFP4/FP8 (Sparks 5–8)

Figure 3. Per-stream decode at C1 by prompt category. The 3.5 bpw pack is faster everywhere, by the most on the long-output categories (reasoning, prose, narrative) where bytes-per-token dominate.

categoryA C1B C1A / BA C6 per-streamB C6 per-streamA / B
coding148.3134.51.10×61.985.00.73×
format151.9130.21.17×61.778.60.78×
math134.1127.51.05×55.663.00.88×
json119.7105.31.14×41.352.50.79×
reasoning108.689.61.21×42.551.30.83×
prose88.174.31.19×39.233.61.17×
summary78.865.61.20×33.934.50.98×
narrative76.561.61.24×33.229.31.13×
ceiling_count179.9151.91.18×80.599.50.81×

Why the curves cross: TensorFold's win is memory traffic — a 3.5-bit matrix is read in fewer bytes per decoded token, and at one stream the GB10 is bandwidth-bound. As streams stack, SGLang's RoCEnante all-reduce and the b12x MoE path amortise better and the native lane pulls ahead from C4. Neither lane is near its 16-stream ceiling here; the crossover is about engines, not weights.

Prefill: not close

Cold prefill throughput by prompt length, both lanesA TensorFold prefill tok/s: 2696, 2743, 2642, 2404, 2557, 2368 at 11.6K, 46.8K, 93.3K, 20K needle, 131K needle, 300K needle. B SGLang: 4289, 3624, 5346, 5883, 4565, 2648. B is 1.3 to 2.4 times faster at every length; the 300K B value is the median of three runs.Cold prefill, tok/s, by prompt length — unique prompts, 1-token reply01,0002,0003,0004,0005,0006,0002,6964,28911.6KB 1.6×2,7433,62446.8KB 1.3×2,6425,34693.3KB 2.0×2,4045,88320K needleB 2.4×2,5574,565131K needleB 1.8×2,3682,648300K needleB 1.1×A · TensorFold, EXL3 3.5 bpw (Sparks 1–4)B · SGLang, native MXFP4/FP8 (Sparks 5–8)

Figure 4. Cold prefill on unique prompts, 1-token reply. The native SGLang lane is 1.3–2.0× faster at the ladder lengths and holds ~4.6K tok/s at 131K. B's 300K bar is the median of three cold runs (first run 1,791, then 2,648 and 3,029).

prompt tokensA tok/sB tok/sB / A
2,9502,2713,6541.61×
11,5922,6964,2891.59×
46,8102,7433,6241.32×
93,3352,6425,3462.02×
20,000 (needle)2,4045,8832.45×
131,073 (needle)2,5574,5651.79×
300,000 (needle, ×3 on B)2,3681,791, 2,648, 3,029 (median 2,648)1.12×

The 2,950-token row for B uses its cold first-run value (3,654); in the full ladder that same prompt had already been seen and prefix caching returned 12,542 tok/s, which is a cache hit, not prefill. A's 2,950 row is the full-ladder value (TensorFold has no prefix cache). All needles were found on both lanes, all runs.

What this means in seconds: a 93K-token document costs 35 s before the first token on A and 17 s on B; a 300K context costs about two minutes on A and 100–115 s on B. TensorFold's prefill is flat around 2.4–2.7K tok/s at every length — it does not degrade, it just starts low.

Quality: identical on the gate we have

knapcio's qeval.py runs 75 auto-scored tasks (code, JSON, math, format) at T=0 and compares two lanes with a paired test. A 71/75, B 71/75, the same four misses (code_interval_intersect, json_escape, json_count, math_m9); qeval.py compare reports kept 71, broke 0, fixed 0, p = 1.000. Median single-stream inside qeval: A faster, consistent with Figure 3.

We wanted a teacher-forced KL divergence between the lanes with B as the native reference. Neither boot exposes it: TensorFold's completions endpoint rejects logprobs, and SGLang's bounded-replay production boot returns 400 to prompt logprobs. The substitute we could run — greedy agreement on 40 raw-text prompts × 128 tokens — gave 0/40 exact matches with a median first divergence at word 2 (9/40 agree for ten or more words, 18/40 diverge at word 0). That is the expected signature of a 3.5-bit quant on open-ended text, and it is not a quality verdict; the quality verdict is the qeval line above. A KL comparison is the open item.

What an agent sees

Hermes agent gauntlet and qeval quality gate, both lanesWhat an agent sees: Hermes 20-hop gauntlet (×3) and the qeval quality gateA · TensorFold EXL330.4 s median · 3/3 correct · 20 toolsB · SGLang native22.4 s median · 3/3 correct · 20 toolsticks = individual reps · fresh session per rep · hermes chat -Q -t terminal · lower is betterB finishes the same 20-hop chain 26% sooner — prefill, not decode, dominates agent turnsQuality gate (knapcio qeval, 75 tasks, T=0): A 71/75 · B 71/75 · identical four misses · p = 1.000 → unchanged

Figure 5. Hermes' 20-hop file-chain gauntlet: the agent must read a chain of files, each pointing to the next, through 20 tool calls, in a fresh session per rep. Both lanes were correct 3/3 with exactly 20 tool calls; B's median wall was 22.4 s to A's 30.4 s.

A wall / agentB wall / agent
rep 130.4 s / 28.3 s22.9 s / 20.5 s
rep 232.0 s / 29.9 s22.4 s / 20.8 s
rep 329.9 s / 27.9 s21.2 s / 19.1 s
median wall30.4 s22.4 s

This is the same lesson as the GLM-5.3 TP8 campaign: raw tok/s does not rank engines for agent traffic. Each Hermes turn pays a several-thousand-token system prompt plus the growing transcript; B prefills that 1.6–2.0× faster and that beats a 18% decode edge on 50-token tool calls every time.

Against the published numbers

sourcewhatC1C6prefillnote
Tony (TensorFold, dual rail)same pack, same engine93.6213.82,140 @12K · 2,215 @93Kours 100.2 / 223.0 / 2,696 · 2,642 at a lower clock cap (2200 vs 2418 MHz); rank caches byte-identical
Tony (vLLM 1017g, native)his native baseline48.5165.72,201 @93Kour native SGLang lane: 84.8 / 262.8 / 5,346 — the 1.85× headline is an engine gap, not a quant gap
knapcio (SGLang v2.4, own harness)same engine, different promptsprose c1 89.9—~5.9K @32–128Kour prose C1 74.3 on Tony's prompts; prefill 3.6–5.3K. Different instrument, same direction
Christopher Owen (spark-ds41f)native, kernel 7.0 + switchless ring~71—4.4–6.0Knot run here (fleet stays on 6.17 and the switch); knapcio's switched lane reaches the same prefill class without the kernel move

What this comparison is not

Use them

Update October 19, 2026 at 3:08 AM CDT: Lane A still serves on Sparks 1–4 (:8001). Lane B is stopped and kept: its containers are intact and its restore bundle is archived. It shares Sparks 5–8 with the new Lane C, a vLLM fork serving there on :8002; see the 3-way post. The Forge gateway catalog update is pending, and Lane C is not on the gateway yet.

As published October 18: both lanes stayed up and were listed on the lab gateway as deepseek-v4.1-flash-spark-exl3 and deepseek-v4.1-flash-spark-native, next to the GB300 Station lane deepseek-v4.1-flash. Same OpenAI-compatible API, same 1M context, tools and streaming; thinking is off by default on the Spark lanes (send reasoning_effort or chat_template_kwargs.thinking=true) and on by default on the Station. The catalog's /llms.txt carries the measured speeds and the pick-this-when guidance from this post.

Reproduce

# Lane A — TensorFold (spark1 head; engine, kit, rank caches, Engram staged under /home/milo/tf1017)
DSV41_CONFIG=/home/milo/tf1017/config.rail2.env recipe/scripts/serve.sh start   # ~103 s to /v1/models
python3 run/tools/sanity.py http://127.0.0.1:8001/v1                               # 6/6
python3 run/tools/v41bench_tf.py --base http://127.0.0.1:8001/v1 --levels 1,2,3,4,5,6 --prefill 2000,8000,32000,64000

# Lane B — SGLang knapcio v2.4 (spark5 head; .env.tp4 MODEL_DIR -> local 1017 checkout, SKIP_PREPARE=1)
./start-tp4.sh doctor && ./start-tp4.sh share && ./start-tp4.sh pack && ./start-tp4.sh serve   # ~8 min to Ready
./start-tp4.sh smoke
python3 scripts/qeval.py run B --url http://127.0.0.1:8888/v1/chat/completions
python3 tools/long_check.py http://127.0.0.1:8888 20000 131073 300000   # base without /v1 for SGLang

Added October 19, 2026 (recipe request from Ash): the exact TensorFold version and command, read from the live lane on spark1.

# Lane A engine: bertholomus/TensorFold fork, dsv41 four-node branch, checkout 225f7005 (2026-10-18).
# Binary reports: tensorfold-native 1.0.2. Built with Zig 0.17.0 inside nvcr.io/nvidia/pytorch:26.07-py3
# (CUDA 13.3 toolkit, kernel driver 595.84). rdma_gather.fatbin ships beside the binary in engine-bin-p4/.
# Kernel kit v0.1.1: MANIFEST pins 356 files, 708,157,701 bytes, per-file sha256 (verify_kit.sh checks all).
# Site config /home/milo/tf1017/config.rail2.env: both rails NCCL_IB_HCA=TF_RDMA_DEVICES=rocep1s0f0,roceP2p1s0f0,
#   NCCL_SOCKET_IFNAME=enp1s0f0np0, GID 3 (TF_RDMA_GID=3, NCCL_IB_GID_INDEX=3), context 1,048,576,
#   KV pool/window 2,097,152, 16 streams. Engine env: TF_SEED_RANDOM=1 TF_TOP_K_MAX=56 TF_DS_2D_GU=parity
#   TF_DS_ROUND_ROWS=48 TF_DS_STREAMS=16 TF_DS_SERVED_K=solo TF_DS_WINDOW=2097152
# serve.sh start launches ranks 3,2,1 (tf-dsv41-lanes) then rank 0, each in container tp4-lane on its node.
# Rank 0 runs exactly (from docker inspect of the live container):
/engine/tensorfold-native serve /model --host 0.0.0.0 --port 8001 --name deepseek-v4.1-flash \
  --context 1048576 --parallel 16 --no-thinking --max-tokens 32768 \
  --alias glm-5.3-flash --temperature 1.0 --top-p 1.0 --top-k 20 --backend cuda
# Note for recipe checks: the lane's serving default is T=1.0 / top-p 1.0 / top-k 20;
# every benchmark request in these posts set temperature=0 explicitly per request.

Pitfalls that cost us time: Docker will not bind-mount through a symlinked path; HF shards over 50 GB need hf_xet (do not set HF_HUB_DISABLE_XET for the Engram shards); TensorFold workers die with ConnectFailed if the head is minutes late, so pull the 24 GB image on every node before the first serve; never remove the NFS exporter while a worker is still building its token map.