Gemma 4 on edge: Multi-Token Prediction unlocks 2× decode speedup — in one specific runtime.
Google released MTP drafters for Gemma 4 on May 5. The technique was already a known win on datacenter GPUs and Android phones; the open question for Gemma 4 on edge was whether it would land at batch=1 on Apple Silicon — the workload shape that defines every on-device LLM that runs on a laptop. A controlled benchmark across all three runtimes that can run Gemma 4 on a Mac shows it does, with caveats most posts will miss.
- Google's MTP announcement claims up to 3×. For Gemma 4 on edge at batch=1, the realistic ceiling is ~2×, in one specific runtime.
- That runtime is LiteRT-LM v0.11.0 + Metal GPU. Gemma 4 E4B real prompts: 2.03× speedup, ~100 tok/s.
- Hugging Face
transformers+ MPS gives 1.04–1.24×.llama.cppcan't engage MTP at all (nogemma4_assistantarch upstream). - One gotcha hides the win: the bundled synthetic benchmark uses random tokens, drafter acceptance is ~0%, MTP reads as a regression. Use real prompts.
- Source & commands → github.com/iprajax/gemma4-mtp
01What Multi-Token Prediction is
Standard language-model decoding is strictly sequential. The target generates one token, feeds it back through the network, generates the next. Each token costs one full forward pass through a multi-billion-parameter model. The dependency chain cannot be parallelized — token n+1 needs token n to exist first.
The sequential bottleneck
Visualized as a timeline of GPU work, every output token is the same big block of compute. Five tokens cost five full passes:
MTP: parallelize verification, not generation
MTP pairs the target with a small drafter (78M parameters in Gemma 4's case — about 1% of the target's compute). The drafter proposes k candidate tokens cheaply, in sequence. The target then verifies all k in a single parallel forward pass. Every accepted token is a full token gained at the cost of one drafter step instead of one target step.
The same five tokens, with MTP at k=4, look like this on the timeline:
The verification cycle, animated
Inside one MTP step: drafter emits 4 token proposals (gold), they flow into the target, target verifies in one shot, accepted tokens (sage) flow into the output stream, the first rejected token (rose) stops the chain. The next cycle starts from there.
How acceptance rate translates to real speedup
The drafter doesn't always agree with the target. Real-world acceptance rates depend on prompt predictability — code and JSON predict cleanly, freeform prose less so. Each cycle yields between 1 token (worst case: drafter wrong on first token, target falls back to its own next-token output) and k+1 tokens (best case: full agreement plus the bonus token). The cost is always ~1 target pass plus k tiny drafter passes:
The throughput math is exactly:
Why MTP is lossless
At temperature=0, MTP is provably identical-output to running the target alone. The trick is the verification step: the target is shown the prompt plus all k draft tokens at once and produces its own next-token logits at every position. A draft is only accepted if the target's top-1 token at that position matches the drafted token. The first mismatch is replaced by the target's own choice and the chain halts. So the output is exactly what the target would have produced step by step — just produced in fewer wall-clock units.
This is what "up to 3× decode for free" actually means: free in tokens-per-second, free in quality, paid for only in the small extra drafter compute and slightly larger KV-cache footprint.
02Why MTP matters for Gemma 4 on edge
Running Gemma 4 locally on a phone, laptop, or Pi instead of through an API has four advantages that compound: privacy (prompts stay on the device), cost (free after the model download), latency (no network round-trip), and availability (works offline). The block was always speed — Gemma 4 on edge has been 5–10× slower per token than hosted equivalents.
MTP closes that gap most cleanly at exactly the regime edge deployments care about: single user, batch size 1, no API quota. Which is exactly the regime Google flagged as hardest in their announcement. That made batch=1 Apple Silicon the most interesting cell in the table to actually measure.
"the 26B mixture-of-experts model presents unique routing challenges at a batch size of 1 on Apple Silicon... batch sizes of 4 to 8 unlock up to a ~2.2× speedup locally."
That phrasing implies muted on-edge gains at batch=1. The data below shows the ceiling holds at batch=1 too — for the smaller Gemma 4 sizes most edge devices will run, in the runtime Google shipped specifically for it.
03The benchmark setup
One representative on-edge Mac. Three runtimes that can run Gemma 4 locally on it. Real prompts at temperature=0. Paired baseline / +MTP runs with the program cache primed. Output tokens counted via the matching Hugging Face tokenizer to compute true tok/s.
Two scripts (both in the repo) produce every number that follows: bench_mtp.py for the transformers + MPS path, bench_litertlm.py for the LiteRT-LM path. Each reports paired baseline / +MTP rates and a hash check on output equality at greedy.
04The result, on one machine
Same hardware. Same prompts. Real-prompt decode tok/s, end-to-end:
| Runtime | Model | Baseline | + MTP | Speedup |
|---|---|---|---|---|
| LiteRT-LM Metal GPU | E4B | 44.6 | 82.8 | 1.86× 2.03× best |
| LiteRT-LM Metal GPU | E2B | 84.2 | 144.3 | 1.71× |
| transformers + MPS | E4B | 12.1 | 15.1 | 1.24× |
| transformers + MPS | E2B | 21.9 | 22.9 | 1.04× |
| llama.cpp Q8_0 | E4B | 39.0 | no MTP | — |
LiteRT-LM Metal GPU + MTP is 2.6× faster than transformers+MPS+MTP and 2.1× faster than llama.cpp Q8_0 on E4B. Three runtimes, identical technique, identical hardware — and one delivers the headline while the others land between a fifth and a quarter of it.
05The benchmark trap
The single most common reason MTP looks broken on Apple Silicon: the default measurement tool is the wrong tool for the job.
The bundled litert-lm benchmark command decodes random tokens. Drafter acceptance rate on random sequences is ≈ 0%, which makes MTP pure verification overhead — and reads as a regression. A correctly engaged MTP path scored 0.93× through this tool versus 1.79–2.03× through real prompts. Use litert-lm run with externally-timed real prompts. bench_litertlm.py in the repo does this in 110 lines.
The fix is in the script repo: bench_litertlm.py spawns litert-lm run per prompt, times wall-clock externally, and counts output tokens with the matching Hugging Face tokenizer to compute true tok/s. That's the measurement that produces the 2.03× result above.
06Reproduce in 5 minutes
# Clone the bench scripts and install the LiteRT-LM CLI
git clone https://github.com/iprajax/gemma4-mtp
cd gemma4-mtp
uv tool install litert-lm
# Run the headline benchmark on E2B (smaller, ~1 min)
python bench_litertlm.py --model e2b
# Verify the engine flag flips (proves MTP is engaged)
litert-lm run \
--from-huggingface-repo=litert-community/gemma-4-E2B-it-litert-lm \
--backend=gpu \
--enable-speculative-decoding=true \
--temperature=0 --verbose \
--prompt="Hello" 2>&1 | grep "Speculative decoding"
# Expected: Speculative decoding : true
07What to do, what to skip
- Use LiteRT-LM v0.11.0 Metal GPU + MTP for fastest Gemma 4 on edge
- Re-download bundles dated before 2026-05-05
- Pick E4B over E2B if the RAM allows — bigger speedup
- Run real prompts to measure speed;
--verboseto confirm
- Trust
litert-lm benchmarkfor any MTP measurement - Expect the headline 2× through transformers+MPS — it's 1.04–1.24×
- Wait for llama.cpp + MTP —
gemma4_assistantisn't merged yet - Use MTP on E2B in transformers — on a small target it can be a net loss
08Why one runtime wins
The technique is identical across runtimes — same drafter weights, same verification step. The runtime carries the rest. Three structural differences explain the gap:
- int4 weights instead of bf16. Each target step is faster, leaving more headroom for accepted-draft savings to register.
- Purpose-built Metal kernel chain. WebGPU sampler + drafter pipeline are designed for this exact pattern.
- No Python in the hot loop.
transformers'assistant_modelwrapper pays per-step Python and bf16-on-MPS overhead. LiteRT-LM stays in compiled C++.
The single most useful takeaway from the experiment: for Gemma 4 on edge, runtime choice is at least as important as model choice. Two runtimes, identical hardware, identical model, identical technique — one delivers the headline, the other delivers a fifth of it.
On-device Gemma 4 inference just crossed a real threshold this week. ~100 tok/s on E4B at batch=1 on a 24 GB MacBook is hosted-API-grade speed with zero network. The conditions are specific — one runtime, one model size, real-prompt measurement — but they're documented, reproducible, and they hold today. The narrative most posts will run with next week is "MTP doesn't work on Mac." The data says it works better on Mac than any other path.