Introduction

Modern neural networks are heavy. A large language model can carry billions of weights, each stored as a 32-bit floating-point number — four bytes that encode a real value somewhere between 3.4×1038-3.4 \times 10^{38} and +3.4×1038+3.4 \times 10^{38}. That precision is great during training, but at inference time it is mostly wasted.

INT8 quantization is the idea that most of those billions of numbers actually cluster inside a modest range — say [2.0,2.0][-2.0,\, 2.0] — and that you can represent each one faithfully enough with just an 8-bit integer (one of 256 values from 128-128 to 127127). The trick is to record two small constants alongside the weights: a scale ss and a zero-point zz. They let you go back and forth:

q=round ⁣(ws)+z,w^=s(qz)q = \operatorname{round}\!\left(\frac{w}{s}\right) + z, \qquad \hat{w} = s \cdot (q - z)

The reconstructed value w^\hat{w} is slightly off — that error is called quantization noise — but for well-trained models the accuracy drop is surprisingly small, often less than 1%. Meanwhile the model shrinks , fits in less RAM, and runs faster on the integer arithmetic units that every modern CPU and GPU ships with.

Related compression ideas appear in dimensionality reduction and neural-network training; quantization sits at the very end of the pipeline, between training and deployment.

Try It: Weight Quantization

The demo below generates a small set of toy model weights drawn from a realistic distribution. Choose a bit-width with the slider — from 8 bits (INT8) down to 2 bits — and watch the histogram of quantization errors change.

<!-- {{c_html_intro}} -->
<div class="controls">
  <label for="bits-slider">{{label_bits}} <strong id="bits-val">8</strong> {{label_bits_unit}}</label>
  <input type="range" id="bits-slider" min="2" max="8" step="1" value="8" title="{{label_slider_title}}">
</div>
<div class="stats" id="stats"></div>
<canvas id="chart" width="420" height="180" aria-label="{{label_chart_aria}}"></canvas>
<div class="legend">
  <span class="dot dot-orig"></span> {{legend_weights}}
  <span class="dot dot-err"></span> {{legend_errors}}
</div>
<div class="info" id="info"></div>
<button id="resample" type="button">{{btn_resample}}</button>
/* {{c_css_intro}} */
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; padding: .5rem; background: #f8f9fb; }
.controls { display: flex; flex-direction: column; gap: .25rem; margin-bottom: .6rem; font-size: .9rem; }
label { font-weight: 600; color: #1d3557; }
input[type=range] { width: 100%; accent-color: #1d3557; cursor: pointer; }
.stats { font-size: .82rem; color: #444; min-height: 1.3em; margin-bottom: .35rem; }
canvas { display: block; background: #fff; border: 1px solid #dde3ea; border-radius: 8px;
         width: 100%; max-width: 420px; }
.legend { font-size: .8rem; color: #555; margin: .4rem 0; display: flex; gap: 1rem; }
.dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; vertical-align: middle; margin-right: 3px; }
.dot-orig { background: #457b9d; }
.dot-err { background: #e63946; }
.info { font-size: .85rem; color: #2d6a4f; font-weight: 600; min-height: 1.4em; margin: .35rem 0; }
button { font: 600 13px system-ui; padding: .4rem .85rem; border: 1px solid #1d3557;
         background: #1d3557; color: #fff; border-radius: 8px; cursor: pointer; }
button:hover { background: #163048; }
// Code not found

Notice that at 8 bits the errors are tiny and evenly spread. Drop to 4 bits and the error bars widen noticeably. At 2 bits — only 4 discrete levels — the reconstruction can be badly wrong for weights near the edges of the range. This is why 8 bits became the practical sweet spot: enough levels to keep errors sub-percent, cheap enough to halve or quarter model size and inference cost.

The Real Complexity

The formula looks simple, but several choices shape how well it works.

Choosing scale and zero-point. Given weights in [wmin,wmax][w_{\min},\, w_{\max}] and 2b2^b integer levels, the scale is:

s=wmaxwmin2b1s = \frac{w_{\max} - w_{\min}}{2^b - 1}

and the zero-point anchors where floating-point zero lands in integer space. Symmetric quantization forces the range to be [wmax,wmax][-w_{\max},\, w_{\max}] and sets z=0z = 0; it is simpler but wastes levels when the distribution is lopsided. Asymmetric quantization uses the actual [wmin,wmax][w_{\min},\, w_{\max}] interval and can be more accurate.

Per-tensor vs. per-channel. Using one (s,z)(s, z) pair for an entire weight matrix is fastest but coarser. Using one pair per output channel — a technique called per-channel quantization — keeps accuracy much closer to the full-precision baseline, at the cost of a few extra stored constants.

Calibration. The scale must be tuned on a small sample of real inputs (post-training quantization, PTQ) or learned during training (quantization-aware training, QAT). PTQ is faster; QAT is more accurate, especially at 4 bits or below.

The real trade-off. At 8 bits the quantization error is typically s/2\sim s/2, which is tiny relative to the weight range. The maximum relative error is bounded by 1/(2b1)1/(2^b - 1): roughly 0.4%0.4\% at INT8, 6.7%6.7\% at INT4. Once you go below 4 bits, most models degrade noticeably without QAT. Eight bits is the threshold where "almost free" becomes "actually expensive."

Where It Matters

INT8 quantization is not a research curiosity — it is the default mode for shipping neural networks at scale:

  • On-device AI: smartphone cameras, voice assistants, and autocomplete all run quantized models on dedicated neural-processing units (NPUs) that speak only in integers.
  • LLM inference: serving billion-parameter models would require server-sized memory without quantization. The LLM.int8() paper (Dettmers et al., 2022) showed that BLOOM-176B could run on a single 80 GB GPU after INT8 quantization — impossible at float32.
  • Browser and WebAssembly: WebNN and ONNX Runtime Web quantize to INT8 to make models fast enough to run client-side without a server round-trip.
  • Real-time video and speech: latency-sensitive pipelines on edge devices — surveillance cameras, hearing aids, industrial robots — depend on INT8 to meet tight timing budgets.
  • Data-center efficiency: INT8 GEMM throughput on modern GPUs (Tensor Cores) is 2–4× higher than FP16, halving inference cost at the same hardware.

The same efficiency obsession shows up in neural-network training and in dimensionality reduction, but quantization is unique: it is the final, often irreversible step between a trained model and a deployed product.

Conclusion

INT8 quantization is elegant in its simplicity: two numbers — a scale and a zero-point — transform each 32-bit weight into an 8-bit integer and back. The reconstruction is imperfect, but the imperfection is small enough that billions of users never notice it in the AI features they use every day.

The deeper lesson is that most information in a trained model is redundant at inference time. The weights do not need the full dynamic range of a float. Noticing that — and acting on it with a careful scale — is how modern AI fits into a phone, a browser tab, and a data center at once.

The same question of "how much precision do you actually need?" runs through neural-network training, compression, and every other place where computation meets a tight budget.

Share this article

Pick a channel — or use your device's native share sheet.

Comments

Loading comments...

https://www.kipuhub.com/en/article/model-quantization-int8/Content licensed under CC BY-NC 4.0.