Pick the Quant on Quality, Then Tune It for Speed
Speed is the easiest thing to measure about a local model, so it is usually the
first thing measured, and often the only thing. llama-bench will hand you a
prompt-processing and a generation number in a couple of minutes. Quality takes
an afternoon of actually using the thing.
That asymmetry quietly decides which model you run. Over a run of quant swaps on one 16GB card, the two-pass order below produced better outcomes than ranking candidates by throughput, and it is worth writing down because the first pass is the one everyone skips.
Pass one: pick the quant on quality. Compare candidate files against each other on the work you actually do, and choose a winner.
Pass two: tune that winner for speed and context. Flags, batch sizes, context length, offload — all of it, on the one file that already won.
The rule that makes it work is that pass two never reopens pass one. Once a quant has won on quality, a faster alternative is not a reason to go back and re-litigate; it is a reason to make the winner faster.
Speed-first would have picked the wrong file
Two community quants of the same 27B model, both nominally IQ4_XS, both built to fit a 16GB card. On throughput they were close enough to call a tie:
| Quant | Size | Generation | Prompt processing | VRAM free |
|---|---|---|---|---|
| A | 13.5GB | ~82 tok/s | ~1,544 tok/s | 378MB |
| B | 12.8GB | ~80-99 tok/s | ~1,180-1,624 tok/s | 230MB |
Ranked on speed alone, A arguably wins: comparable throughput and 148MB more headroom, which on a card this tight is the difference between local speech-to-text fitting on the GPU or falling back to the CPU.
B was adopted anyway, because its published divergence from the full-precision model was materially lower — a KLD of 0.035 against 0.055. That is a quality difference the throughput columns cannot see, on two files that a speed-ranked table would have called equivalent.
The headroom cost was real and was accepted deliberately: speech-to-text now runs on CPU. That is the shape of the trade this method keeps making — pay a measurable cost in pass two to keep a quality win from pass one.
Benchmark the workload, not the benchmark
The comparison above was not run on llama-bench. It was run by giving both
candidates the same real agentic tasks — write a script and run it, diagnose a
failing test suite and fix it — and watching which one completed them.
Synthetic numbers are still useful, but they answer a narrower question than they appear to. The clearest evidence of that came from thread count.
An early tuning pass A/B'd -t 6, 8, 12 and 16 on live requests. -t 8
and -t 6 tied at roughly 74-77 tok/s, both beating -t 12 and -t 16.
Neither the physical core count nor the thread count was the clean winner, which
was already a warning against the folk rule of matching physical cores.
Then the model changed — from a mixture-of-experts model with layers offloaded
to CPU, to a dense model that fits entirely on the GPU. Thread count went
completely flat from -t 2 to -t 12. There were no longer any CPU-side layers
for the threads to work on, so the setting that had been worth several percent
became worth nothing, and the right value became whatever left the most cores
free for other processes.
A tuning result is only valid for the workload shape it was measured on. Not the model, the shape — where the compute actually happens. Change that and your tuning notes become folklore.
The model card is a starting point, not a measurement
Both candidate quants advertised 95K and 128K context. Neither held on a 16GB card; the real ceiling, found by bisection, was 76,000, with a hard performance cliff immediately above it.
The winning quant's own card also recommended a batch and micro-batch size of
384. Measured on this hardware, that recommendation halved generation speed and
quartered prompt processing against -b 2048 -ub 512.
None of this means the card was dishonest. It means a quant's author measured on their hardware and you have different hardware. Treat every published number as a hypothesis with a free test attached.
A quality win can be worth a measured speed loss
Earlier, on a 12B model, the choice was between a Q4 and a Q6 quant of the same weights:
| Quant | File | Generation | VRAM free at 64K context |
|---|---|---|---|
| Q4_K_XL | 7.37GB | 89.8 tok/s | comfortable |
| Q6_K_XL | 10.69GB | 64.4 tok/s | ~2GB |
Q6 is a 28% generation regression and leaves little room for the speech-to-text and text-to-speech processes sharing the card. Every number on that table argues for Q4.
Q6 was kept, after using both, because its answers were perceptibly more detailed. That is not a rigorous measurement and it is not presented as one — but it is the judgement the first pass exists to allow. A process that ranks purely on the numbers cannot make this call at all, which is precisely why the numbers should not be the only pass.
There may be more than one winner
The most useful outcome of a quality pass was discovering there was no single answer.
A 20B mixture-of-experts model measured roughly six times the generation speed of the 27B dense model, with about 2GB of VRAM to spare instead of 230MB. On throughput it is not close.
It still did not replace the 27B for agentic work, where the dense model produced better results. It became the pick for retrieval and voice, where latency dominates and the reasoning demands are lighter. Same card, same endpoint, two different winners for two different jobs.
This only surfaces if the quality pass is run against the workload you actually have. A single aggregate score would have picked one and quietly made the other job worse.
Quality failures are task-shaped
When quality problems do appear, they are rarely uniform, and the first report of one is often wrong about what it is.
A model was reported as "failing word counting." Fifteen tasks failed to reproduce it: a 44-word passage counted correctly, exact-length constraints from 7 to 25 words all hit exactly, hyphenated words and contractions handled correctly.
The real weakness was next door. Asked for five fruits containing no letter "a", it answered "blackberry." Exclusion constraints, not counting. Raising the reasoning effort fixed every case, at a cost of a few seconds on hard turns and no change to generation speed.
Two things worth taking from that. A vague quality complaint is a starting point for a search, not a finding. And a model that fails one narrow class of task is not a bad model — it is a model with a boundary you now know how to route around.
Two ways to get a wrong number
Both of these produced misleading measurements before they were understood.
Contention. Prompt-processing figures taken while another consumer was holding the same single-slot server were meaningless, and one latency probe was inflated to 28-37 seconds purely by cache thrash from a second client. Stop everything else before you measure.
Mismatched cache types. If the key and value cache quantisation types do not match, prompt processing collapses by five to eight times, and nothing reports an error — flash attention silently drops off its fast path. A configuration that looks reasonable and benchmarks terribly is worth checking here before anywhere else.
The method, compressed
- Two passes. Quality decides the file; speed and context tune it afterwards.
- Pass two does not reopen pass one.
- Run the quality pass on the work you actually do, not on a synthetic benchmark.
- Treat model-card numbers — context, batch size, throughput — as hypotheses with a free test attached.
- A tuning result belongs to the workload shape it was measured on. Re-measure after any change to where the compute happens.
- Accept a measured speed loss for a quality gain when you have used both. Write down that you did it on purpose.
- Expect more than one winner if you have more than one kind of job.
- Stop other clients before benchmarking, and check that your cache types match.