The author optimized DeepSeek V4.1 Flash for Apple M3 Ultra, achieving up to 40 t/s decode speed with DSpark speculative decoding while maintaining byte-identical accuracy to the upstream model.
I liked DeepSeek V4.1 Flash as an agent model but at 16 t/s on ds4 it was painful to sit through a real turn. It seemed some redditors and m3 ultra owners appreciated my glm 53 flash optimizations, so I forked antirez/ds4 for V4.1 Flash to see how much I learned optimizing GLM for the M3 Ultra could apply here. A lot did, but not as much as I had hoped. The screenshot is a real 91 minute agent turn in my UI: 101k tokens decoded, 4.6M tokens prefilled at 99.5% cache hit, 56 tool calls (no mistakes), context growing from 3k to 127k. https://github.com/IngeniousIdiocy/ds4-v41-m3ultra#v41 Upstream ds4 vs this branch, same Mac, Q4 weights: Decode, 8k context: 16.6 → 31.3 t/s Decode, 300k context: 14.0 → 28.3 t/s Prefill, 62k prompt: 737 → 813 t/s TTFT, 23k system prompt: 35.8 s → 31.1 s Same prompt restored w/ disk KV cache: 0.23 s DSpark on code, serial → speculative: 32.1 → 40.5 t/s DSpark on agent turns, answer phase: 31.3 → 41.3 t/s Output is byte-identical to upstream under greedy decode, including with DSpark on. SHA-256 manifests and the scripts to re-run them are in the repo. Decode: The model reads ~14 GB of weights per token. At 700 GB/s that caps decode around 50 t/s. Upstream was at 16.6. The loss was hundreds of small dispatches per token, not the matmuls. All layers go in one command buffer. Engram row fetches run in a worker pool instead of on the critical path. The 384-expert router is one dispatch instead of nine. Shared expert gate+up+SwiGLU is one kernel. BF16 rounding is done inside the producing kernels, which removed ~770 re-round dispatches. Hyper-connection prediction runs inside the projection kernels. Decode at depth: V4.1's compressed attention picks 512 blocks per layer out of the whole context. That selection chain was 98% of the slowdown at long context. Layers now score only the blocks their mask admits, compact the admitted index once per row, and select the top 512 with a bounded radix select. 300k decodes at 90% of the 8k rate. Prefill: Prefill only gained 10%, and that is about what was there. Prefill is compute bound. Matrix work is half the wall and upstream's GEMM kernels already ran at 95-100% of their measured ceiling. The M3's Metal GEMM tops out around 23-24 TFLOPS on these shapes, and the Metal 4 TensorOps path that would raise it is disabled on hardware before M5. The gain came from the attention core, the Engram disk waits, and the glue. Every 8k chunk now writes a continuable checkpoint so a long prompt resumes instead of starting over. DSpark: V4.1 ships its own multi-token drafter. With it on, the decode step is a 6-row verify, not one row. So the target stopped being serial t/s and became weight bytes per committed token. The 6 verify rows share one weight stream through paired Q8 projections. Engram fetches for all 6 rows overlap. Verify chunks submit independently. Verify went from 177 ms to 112 ms per block and weight bandwidth from 213 to 337 GB/s. The admission controller is ported from my GLM-5.3 branch. It measures wall time per request, declines drafts the drafter is not confident in, and backs off where drafting loses. Leave it on. At temperature > 0 it does exact speculative sampling. A drafter fault disables DSpark for that session instead of guessing. Disk KV cache: Full-prefix snapshots at every chunk boundary. Restore is 0.23 s vs 31 s cold. Eviction keeps a ladder of waypoints and decays the score of old entries so a long chat does not evict its own history. Same design as my GLM branch. Accuracy: none of this changes what the model computes. Every kernel does the same math in the same order as the upstream kernel it replaces, so the output is identical, not close. Under greedy decode the branch produces the same bytes as upstream on every fixture, with DSpark on or off, and the manifests in the repo let you check that yourself. Nothing here trades quality for speed. Also in the repo: a per-dispatch bandwidth ledger, an A/B fixture that runs two configs in one resident server, and the fidelity manifest. CHANGES-V41.md lists what was tried and rejected, with the numbers. This branch is M3 Ultra only. These weights need about 300 GB of RAM, and for now the 512 GB M3 Ultra is the only Apple machine with the memory. Beyond that, the optimizations depend on detailed measurements of this specific chip: its two-die memory behavior, per-core residency and bandwidth, and how Metal schedules dispatches and threadgroups across its 80 GPU cores. We're optimizing one model's actual execution on one machine, with one set of weights (Q4), and checking that the predicted kernel savings survive in full decoding or prefill. Weights are not redistributed. The target is upstream's published Q4 GGUF via its download script. The drafter GGUF is 7.8 GB and you build it yourself from the mtp tensors in three shards of the official checkpoint. Commands in the README. Thanks to antirez for ds4.
The author achieved a 12x speedup for DeepSeek V4 Flash on a Mac Studio M3 Ultra by optimizing kernels and implementing effective caching strategies, reducing chat turn latency from 6-20 seconds to 1.6 seconds.
A user shares experiments running a 4-bit quantized DeepSeek v4 Flash on a 32GB M5 MacBook Air, achieving roughly 50 tokens/s prefill and 1 token/s decode using streamed experts and other tricks.
A GitHub patch allows running DeepSeek V4 Flash in LM Studio on 128GB Macs by sideloading antirez's llama.cpp fork, working around struct-layout drift, decoding splits, and code-signing issues.
DeepSeek released DSpark, a speculative decoding method that boosts throughput by 51% to 400% for V4 Flash & Pro, along with the open-source DeepSpec codebase for training and evaluating draft models.
The article details a customized quantized version of DeepSeek-V4-Flash with MTP self-speculation enabled, achieving significant speedups on dual RTX PRO 6000 Max-Q GPUs using a patched vLLM setup.