Quantization, in depth
Quantization shrinks weights from 16-bit floats to fewer bits, trading a little quality for a lot of memory. The one-line version (Q8 โ lossless, Q4_K_M โ sweet spot, below Q3 hurts) is enough to get running. This page goes one level down: what the tags actually do, how K-quants and I-quants differ, and where quality loss shows up first.
Why 4-bit works at all
Trained weights are not uniform noise. Values in each tensor cluster in a narrow, roughly bell-shaped distribution, and the network's behavior is carried by the shape of that distribution โ not by the last decimal digit of any single weight. That makes weights compressible: store each weight as a small integer plus a shared scale factor, and you lose only fine detail.
One real complication: outlier channels. A small fraction of channels carry activations far larger than the rest. A single scale for the whole tensor spends its entire range on those outliers and crushes everything else into mud. Every serious quant scheme is fundamentally an outlier-handling scheme โ per-block scales, activation-aware protection (AWQ), or calibration against real data (imatrix).
Block quantization mechanics
The core trick: chop each tensor into small blocks that share one scale. Dequantizing a weight is a single multiply:
w โ s ยท q # s: block scale, q: stored integer
Q4_0: block = 32 weights โ 1รfp16 scale + 32ร4-bit ints โ 4.5 bpw
K-quants: super-block = 256 weights
1รfp16 super-scale + 8รfp8 sub-scales + ints โ 4.8 bpw
bpw = bits per weight, including scale overhead. That overhead is why nothing is exactly 4.0: a 4-bit weight is half a byte, and a 2-byte scale spread over 32 weights adds 0.5 bpw. K-quants amortize the cost with two-level scaling โ 256-weight super-blocks whose 8 sub-blocks get cheap fp8 scales โ and land at ~4.8 bpw with better quality than Q4_0 at similar size.
K-quants and the _M / _S suffixes
Q4_K_M is not "Q4_K with a hat" โ the suffix is a mix. The quantizer bumps specific tensors up to a higher quant while the bulk stays at Q4_K: typically attention projections (wv, wo) and sometimes the token embedding table go to Q6_K. The suffix ranks the mix:
_S(small) โ fewest tensors bumped, smallest file_M(medium) โ the default recommendation, best size/quality balance_L(large) โ more tensors at higher precision, diminishing returns
The mix exists because layers degrade unevenly: attention projections and embeddings are more sensitive than the big feed-forward matrices. A few hundred extra MB there buys real quality โ which is why _M is the community default rather than plain Q4_K.
I-quants: calibrated, smaller, CPU-slow
IQ quants (IQ4_XS, IQ3_XXS, IQ2_XSโฆ) add a calibration step. First compute an importance matrix (imatrix) by running the model over a sample of representative text; then place the quantization levels where the weights that matter actually live. The payoff: a given quality at smaller size than the equivalent K-quant โ IQ4_XS undercuts Q4_K_S at equal-or-better quality, and IQ2/IQ3 make sub-3 GB 7โ8B models possible at all.
The tradeoff is decode speed. I-quant dequantization is not a plain multiply โ it needs non-power-of-two lookups and structured reconstruction. On CPU that extra math is visible in tokens/sec; on GPU it hides behind memory latency and costs almost nothing. Rule of thumb: K-quants for CPU boxes, I-quants fine on GPU, IQ2/IQ3 only when VRAM forces your hand.
The quality ladder, honestly
Approximate file sizes for a 7โ8B model. Scale roughly linearly with parameters โ a 14B is about double:
| Quant | Size | bpw | Honest quality note |
|---|---|---|---|
| Q8_0 | 8.5 GB | 8.5 | transparent; survives blind A/B against FP16 |
| Q6_K | 6.6 GB | 6.6 | near-transparent; the last stop before paranoia |
| Q5_K_M | 5.7 GB | 5.7 | slight loss, hard to notice in chat |
| Q4_K_M | 4.9 GB | 4.8 | the sweet spot; low-single-digit % benchmark drop |
| IQ4_XS | 4.5 GB | 4.25 | โ Q4_K_S quality, smaller; prefer on GPU |
| Q3_K_M | 3.9 GB | 3.9 | noticeable on factual recall and math |
| IQ3_XXS | 3.2 GB | 3.1 | fluent chat, shaky facts; realistically GPU-only |
| Q2_K | 3.2 GB | 3.4 | last resort โ personality survives, precision doesn't |
Treat exact percentages as folklore-grade: the loss depends on the model, the language, and the task. The ordering is stable even when the magnitudes aren't.
Where quantization hurts first
Damage is not uniform across capabilities. Roughly in order of falling:
- Factual recall โ names, dates, numbers drift first. A Q3 model misattributes confidently.
- Math and multi-step reasoning โ small errors compound through the chain.
- Long-context coherence โ retrieval from deep in a long prompt gets shakier than short-prompt behavior suggests.
- Lower-resource languages โ Korean degrades earlier than English at heavy quants; Korean tokens were rarer in training, so there is less precision slack. If Korean matters to you, hold Q5+ where you can.
- Chat fluency and style โ barely shows at all. A Q2 model still sounds fine, which is the trap: fluency is a bad proxy for damage.
Small models suffer more
Quantization error eats redundancy, and small models have the least of it. A 70B at Q4 loses nearly nothing; a 3B at Q4 loses visibly more; below ~2B, heavy quants can gut the model. Practical rule: Q6_K or Q8_0 for anything under ~4B parameters โ the absolute GB saved by crushing a small model are tiny anyway. Get the size-vs-capability baseline in parameters before deciding where to spend bits.
The KV cache is a separate decision
Quantizing the weights does nothing to the KV cache โ that is its own memory line (fp16 by default, separately quantizable to q8_0/q4_0 in llama.cpp). At long context the cache can rival the weights in size; budget it independently in KV cache.
A practical decision ladder
Worked example โ 12 GB card, 8B dense model, 8k context:
weights Q4_K_M 4.9 GB
KV cache 8k tokens, fp16 1.0 GB (8B GQA โ 128 KiB/token)
overhead compute buffers + ctx ~1.5 GB
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
total ~7.4 GB โ fits with room to spare
Given VRAM math, the ladder:
- Budget: VRAM โ context โ overhead = what's left for weights.
- Q6_K fits โ run Q6_K. Only Q4_K_M fits โ run Q4_K_M without guilt.
- Drop to IQ4_XS/Q3 only to fit context or avoid CPU offloading โ offload costs more speed than one quant step costs quality.
- If your target model doesn't fit at Q4, drop a size class rather than quantizing to Q2: a solid 8B at Q4 usually beats a crushed 14B in practice.
Related: VRAM math ยท KV cache ยท Parameters ยท Model formats