Skip to content

benchmarks/stock: llama.cpp with its own DFlash2 drafter (and why it doesn't speed up here) - #52

Merged
nathansutton merged 2 commits into
mainfrom
docs/llamacpp-dflash2-42
Sep 11, 2026
Merged

nathansutton merged 2 commits into
mainfrom
docs/llamacpp-dflash2-42

Conversation

@nathansutton

@nathansutton nathansutton commented Sep 11, 2026

Copy link
Copy Markdown
Owner

Closes #42 — and instead of only relabelling the llama.cpp row, measures llama.cpp with its own DFlash2 drafter.

What was out of date

The stock-engine table said llama.cpp's speculation was "none for this model", and docs/benchmarks.md said there was no DFlash2 head in GGUF form. Both were true for build 10470, the build measured, and are not now:

The new measurement

stock.py llama-dflash runs llama-server (build 10917) on the same UD-Q3_K_XL GGUF twice — serial, then with the Q4_K_M drafter (-md … --spec-type draft-dflash --spec-draft-n-max 7, chad's draft width) — on the same 512-token filler chad-bench tiles (tokenized by the server itself), greedy, cache_prompt off, 3 reps each after a warmup. It also records a llama-bench verify-width probe. M4 Pro 24 GB, nothing else resident, run twice (the numbers below are the committed second run; the first agreed within 0.1 tok/s).

Engine Prefill (512-tok prompt) Decode (128 tok) Speculative decoding
llama.cpp llama-bench (stock, build 10470) 102 tok/s 10.9 tok/s off in this benchmark
llama.cpp llama-server (build 10917), serial 97 tok/s 11.3 tok/s off
llama.cpp llama-server (build 10917) 95 tok/s 11.1 tok/s DFlash2 drafter (Q4_K_M GGUF)
chad, serial (CHAD_NO_DFLASH=1) 99 tok/s 18.1 tok/s off
chad, default 98 tok/s 62 tok/s DFlash2 block drafter

The drafter works and the speedup doesn't arrive. 96.5% of drafted tokens are accepted (110 / 114 per run, ~7.5 committed per round), and decode is 11.1 tok/s against 11.3 serial. The verify pass is why: llama.cpp's Metal path runs a batch of 1 / 2 / 4 / 8 / 16 tokens at 11.2 / 12.8 / 13.5 / 14.0 / 45.5 tok/s on this GGUF, so the 8-token verify alone costs ~6.4 serial steps and no acceptance rate can pay for the round. The jump at 16 is a kernel switch the round sits just below. chad's whole round at the same width, drafter included, costs ~2.2 serial steps (mlx_dflash.BLOCK_ROUND_COSTS).

I checked it isn't a measurement fault before writing it down: the drafter loaded and engaged (common_speculative_impl_draft_dflash: n_max=7 … block_size=8, acceptance from the server's own counters), all 128 tokens were generated on every rep, and round time (~0.67 s) is the probe's 0.57 s verify plus ~0.1 s — not a CPU-bound drafter.

Scope, as the docs now say it

This is this GGUF on this Mac, not llama.cpp's DFlash2 in general — llama.cpp's PR reports ~1.8× on an M5 Pro with a Q4_K_M target, and a different quant or chip can land on the other side of that kernel switch. Both drafted rows are ceilings on tiled code; the real-session numbers for chad stay in the footnote. Ollama is now described as measured without speculative decoding, not as lacking it.

Changes

  • README.md, docs/benchmarks.md: the two new rows, the relabelled build-10470 row, the Ollama wording, and the stale "no GGUF head" explanation replaced with the measurement.
  • benchmarks/stock/stock.py: the llama-dflash arm, table() renders it and prints the llama-bench build, STOCK_LLAMA_BIN so a newer build runs from an unpacked release without replacing the brew install the matrix grid's llama.cpp rows are pinned to. Server logs go to the temp dir, not _runs/.
  • benchmarks/stock/_runs/llama-dflash.json: the record (per-rep timings, probe, flags).
  • benchmarks/stock/README.md: the new command and how to point it at a build.

The chad rows are unchanged (chad 2.0.0, same machine); nothing since touched the decode path. ruff clean on stock.py.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Qsqne39Q9TQuEoKWukmSpT

nathansutton and others added 2 commits September 11, 2026 17:34
…doesn't speed up here

The stock-engine table labelled llama.cpp's speculation "none for this model" and the docs
said there was no DFlash2 head in GGUF form. Both stopped being true after the measured run:
llama.cpp gained DFlash2 in build 10658 (#27816, the master landing of #27342), and
incoai/Qwen3.8-27B-DFlash2-GGUF publishes the drafter.

New `stock.py llama-dflash` arm: llama-server on the same UD-Q3_K_XL GGUF, serial and with
the Q4_K_M DFlash2 drafter (--spec-type draft-dflash, draft width 7), same 512-token filler
chad-bench tiles, greedy, cache_prompt off, 3 reps, plus a llama-bench verify-width probe.
On build 10917, M4 Pro 24 GB:

  serial   97 tok/s prefill, 11.3 tok/s decode
  DFlash2  95 tok/s prefill, 11.1 tok/s decode, 96.5% of drafted tokens accepted
  batch of 1/2/4/8/16 tokens: 11.2 / 12.8 / 13.5 / 14.0 / 45.5 tok/s

The drafter works; the 8-token verify costs ~6.4 serial steps on llama.cpp's Metal path for
this quant, so acceptance cannot pay for the round. chad's whole round at that width costs
~2.2. The docs scope this to this GGUF on this Mac: llama.cpp's own PR reports ~1.8x on an
M5 Pro with a Q4_K_M target.

The build-10470 llama-bench row stays as recorded, relabelled "off in this benchmark".
STOCK_LLAMA_BIN runs a newer build from an unpacked release without touching the brew
install the matrix grid is pinned to.

Closes #42.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qsqne39Q9TQuEoKWukmSpT
The README footnote now states the result and links to docs/benchmarks.md, where the
verify-width numbers already live. The drafter always downloads from the pinned repo, so
the STOCK_DRAFT override and its one-use helper go.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qsqne39Q9TQuEoKWukmSpT
@nathansutton
nathansutton marked this pull request as ready for review September 11, 2026 21:43
@nathansutton
nathansutton merged commit cf70a4b into main Sep 11, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: update llama.cpp DFlash2 availability in the stock-engine comparison

1 participant