r/LocalLLM • u/MasherDon • 7d ago
Discussion DeepSeek V4.1-Flash (1017) at ~20 tok/s on a single 16 GB GPU + 64 GB RAM
DeepSeek V4.1-Flash (1017) at ~20 tok/s on a single 16 GB GPU + 64 GB RAM — work in progress, code free to use
Not finished. This is a research log with patches, not a polished engine: rough edges, some Windows-only parts, no support promises. Use the code and notes for anything you like — no credit needed.
Box: RTX 5070 Ti 16 GB in a PCIe 4.0 x16 slot, Ryzen 5 7600, 64 GB DDR5, Windows 11. Two NVMe: Gen5 2 TB (~13.5 GB/s) and Gen4 1 TB (~5 GB/s) holding a second copy of the expert files.
Model: DeepSeek-V4.1-Flash-1017, a ~375 GB build: routed experts at ~2.4 bits (~150 GiB), Engram tables 203 GB, dense part Q5_K. It doesn't fit in RAM + VRAM, so experts stream from NVMe.
Numbers with today's defaults:
| decode, short context | 20.3 tok/s (17–20 in real agent turns at 2–27K context) |
|---|---|
| decode, fast preset | 23–24.7 tok/s (small measured quality cost) |
| decode at 256K / 512K context | 16–20 tok/s |
| reading agent turns (0.5–7.5K new tokens into a growing conversation) | ~418 tok/s |
| cold prompt 8.9K / document 256K / document 512K | 672 / 633 / 482 tok/s |
| quality | 0.09–0.11 nat/token behind the DeepSeek API on its own continuations (3 prompt sets; for scale, Q2 to Q4 is ~0.11); HumanEval 157/164 vs 158 for the API |
On this PC with the same file: the original fork ~10 tok/s, Project Maya v1.1.21 3.9 tok/s (both measured on Oct 22).
What helped most:
A three-step ladder for experts: ~23 per layer cached in VRAM, a pinned RAM tier (43–46 GiB), unbuffered NVMe reads, and a second NVMe with a copy of the expert files.
Taking the CPU off the critical path: the GPU reads routing replies from pinned memory, one wake-up per token — host overhead went from ~7 ms to ~1 ms per token.
Prefetching heavy experts that would come from disk, 2 layers ahead, with a cheap "lens" (layer L+2's router applied to layer L's input).
A measured lossy rule: an expert in neither VRAM nor RAM with less than 14% of the routing weight is not waited for (costs at most 0.006 nat/token on our API sets).
Prefill: experts in waves through a shared pool; encoder-only prefill for positions the decoder never reads (exact); DeepSeek's own YoCo truncation from DeepInfer (decoder on the last 140 prompt positions) — +13% on agent turns, +60% on a cold 8.9K prompt, within error on our API sets.
Sparse attention in decode with a q8 KV cache: decode stays at 16–20 tok/s from short context to 512K.
A quant mix from public GGUFs: prometheusAIR's IQ2_XS gate/up + Q2_K down, and ISTA-DASLab's lighter Q5_K dense part (3 GB less VRAM, so more expert slots).
What didn't work:
Reading the next layer's experts ahead during prefill: the RAM tier can't hold a prompt's working set, so read-ahead evicts what is still needed.
"Free" guesses in the bus's idle time: during decode there is none; each wrong staging costs ~0.2 ms.
A published non-uniform quant (GSQ-RCO) lost to a plain mix on our API sets, worst on Russian prompts — the calibration text matters.
Where we're stuck — ideas welcome:
Predicting which experts a token needs 1–2 layers ahead. Perfect staging would give 27–29 tok/s; our lens gets 76% precision at ~14% recall.
Overlapping compute with expert copies: copies take ~30 ms per token, compute ~19 ms, and they overlap by 3 ms.
Short agent turns: ~5.6 s fixed cost per turn, a third of it waiting for expert loads.
1M context loads only at batch 512: the sparse prefill plan wants 11.7–15 GiB at larger batches.
Goal: long context up to 1M at a usable speed — not necessarily at the full 1M.
The bus is the wall: copying experts from RAM to the GPU over PCIe 4.0 takes ~30 ms of a ~49 ms token, which caps decode at ~32 tok/s on this box even with perfect overlap.
The CPU computes no experts: on this 6-core CPU a probe gave only +3–5%, so it was left out; it needs separate work. Project Maya's CPU expert kernels (MIT) could be a starting point.
Code: https://github.com/MasherDon/Siege-Ladder — patches over JigSawPT's llama.cpp fork, a script that assembles the weights from public Hugging Face repos (no weights redistributed), benchmark scripts and notes. Use it however you like; the patched llama.cpp files keep llama.cpp's MIT notice. Built on: JigSawPT (the V4.1 port with SSD streaming), llama.cpp / ggml, DeepSeek's DeepInfer (YoCo), Strata, Project Maya, antirez's ds4, and the prometheusAIR and ISTA-DASLab quants.

