Quantization for Transformer Inference

Reducing precision for faster inference: INT8/INT4 weight quantization, activation quantization, GPTQ, AWQ, SmoothQuant, per-channel vs per-group calibration, and the theory of quantization error bounds.

Advanced

Table of Contents

  1. Learning Objectives
  2. Notation
  3. Core Intuition
  4. Uniform Quantization Theory
  5. Weight-Only Quantization (W4A16)
  6. GPTQ: Optimal Brain Quantization
  7. AWQ: Activation-Aware Weight Quantization
  8. SmoothQuant (W8A8)
  9. Per-Channel vs Per-Group Calibration
  10. Error Analysis and Bounds
  11. Common Pitfalls
  12. Summary
  13. Exercises

Learning Objectives

  1. Derive uniform quantization and compute the reconstruction error.
  2. Explain why weight-only quantization is effective for memory-bound inference.
  3. Derive the GPTQ algorithm from optimal brain surgery.
  4. Explain how AWQ exploits activation magnitudes to protect salient weights.
  5. Prove how SmoothQuant migrates quantization difficulty from activations to weights.

Notation

  • ss — scale factor
  • zz — zero-point
  • bb — bit-width (4 or 8)
  • H\mathbf{H} — Hessian of the layer-wise loss
  • gg — group size for per-group quantization

Core Intuition

A 70B model in FP16 requires 140 GB — too large for most GPUs. Quantization represents the same weights with fewer bits (INT4 = 4 bits per weight → 35 GB). For memory-bound inference, this directly translates to speedup: less data to load from memory means faster generation. The challenge: minimize the accuracy loss from reduced precision.

Interactive: Weight Quantization

FP32 originalQuantizedError

MSE

7.52e-6

Max Error

0.0046

Compression

4.0×

Explore: Reduce bits to see quantization error grow. At 4-bit, you get 8× compression but visible error. At 1-bit (binary), only two values exist. The red lines show individual weight errors — notice outlier weights suffer most.

Uniform Quantization Theory

Forward quantization:

wq=round(ws)+z,wq{0,1,,2b1}.(1)w_q = \text{round}\left(\frac{w}{s}\right) + z, \quad w_q \in \{0, 1, \ldots, 2^b - 1\}. \tag{1}

Dequantization:

w^=s(wqz).(2)\hat{w} = s \cdot (w_q - z). \tag{2}

Scale and zero-point from range [wmin,wmax][w_{\min}, w_{\max}]:

s=wmaxwmin2b1,z=round(wmins).(3)s = \frac{w_{\max} - w_{\min}}{2^b - 1}, \quad z = \text{round}\left(-\frac{w_{\min}}{s}\right). \tag{3}

Symmetric quantization (zero-point = 0): s=max(w)/(2b11)s = \max(|w|) / (2^{b-1} - 1).

Quantization error for a single weight:

ww^s2=wmaxwmin2(2b1).(4)|w - \hat{w}| \leq \frac{s}{2} = \frac{w_{\max} - w_{\min}}{2(2^b - 1)}. \tag{4}

Weight-Only Quantization (W4A16)

Strategy: Quantize weights to INT4; keep activations in FP16.

Why it works for inference: Generation is memory-bound → loading weights is the bottleneck. INT4 weights are 4x smaller → 4x less memory bandwidth → ~4x speedup.

Computation: Dequantize weights on-the-fly during matrix multiply:

y=xdequant(Wint4)=x(s(Wint4z)).(5)\mathbf{y} = \mathbf{x} \cdot \text{dequant}(\mathbf{W}_{\text{int4}}) = \mathbf{x} \cdot (s \cdot (\mathbf{W}_{\text{int4}} - z)). \tag{5}

Modern GPU kernels fuse dequantization with GEMM — negligible overhead.


GPTQ: Optimal Brain Quantization

Problem: Quantize each weight to minimize the output error of the layer:

minW^WXW^XF2.(6)\min_{\hat{\mathbf{W}}} \|\mathbf{WX} - \hat{\mathbf{W}}\mathbf{X}\|_F^2. \tag{6}

Algorithm (column-by-column):

  1. For column jj: quantize weight wjw_j, compute error δj=wjw^j\delta_j = w_j - \hat{w}_j.
  2. Compensate: Distribute the error to remaining unquantized columns:
wj+1:wj+1:δj[H1]jjHj,j+1:1,(7)\mathbf{w}_{j+1:} \leftarrow \mathbf{w}_{j+1:} - \frac{\delta_j}{[\mathbf{H}^{-1}]_{jj}} \cdot \mathbf{H}^{-1}_{j, j+1:}, \tag{7}

where H=XXT\mathbf{H} = \mathbf{X}\mathbf{X}^T is the Hessian of the layer loss.

Intuition: After quantizing one weight with error, adjust remaining weights to compensate, weighted by their sensitivity (Hessian).

Result: Near-lossless INT4 quantization for models up to 175B parameters.


AWQ: Activation-Aware Weight Quantization

Key observation: Not all weights are equally important. Weights that correspond to large activation channels have more impact on the output.

Salient weight identification: For each weight column jj, compute the average activation magnitude:

importance(j)=E[xj]wj.(8)\text{importance}(j) = \mathbb{E}[|x_j|] \cdot |w_j|. \tag{8}

Strategy: Protect important weights by per-channel scaling before quantization:

w^j=quantize(wjαj),x^j=xj/αj.(9)\hat{w}_j = \text{quantize}(w_j \cdot \alpha_j), \quad \hat{x}_j = x_j / \alpha_j. \tag{9}

Choose αj\alpha_j larger for salient channels → reduces their quantization error at the expense of less important channels.

Optimal scaling: αj=E[xj2]/max(wj)\alpha_j^* = \sqrt{\mathbb{E}[x_j^2] / \max(|w_j|)} (balances activation and weight quantization ranges).


SmoothQuant (W8A8)

Problem: Activations have outlier channels (values 100x larger than average), making activation quantization difficult. Weights are well-behaved.

Solution: Migrate the quantization difficulty from activations to weights:

Y=XW=(Xdiag(s)1)(diag(s)W),(10)\mathbf{Y} = \mathbf{X} \cdot \mathbf{W} = (\mathbf{X}\text{diag}(\mathbf{s})^{-1}) \cdot (\text{diag}(\mathbf{s})\mathbf{W}), \tag{10}

where sj=max(xj)α/max(wj)1αs_j = \max(|x_j|)^\alpha / \max(|w_j|)^{1-\alpha} balances the ranges.

Effect: Smoothed activations X^=Xdiag(s)1\hat{\mathbf{X}} = \mathbf{X}\text{diag}(\mathbf{s})^{-1} have smaller outliers (easier to quantize). Scaled weights W^=diag(s)W\hat{\mathbf{W}} = \text{diag}(\mathbf{s})\mathbf{W} absorb the outlier magnitude.

Result: Enables INT8 quantization for both weights AND activations (W8A8) → can use INT8 tensor cores for 2x compute speedup.


Per-Channel vs Per-Group Calibration

Per-tensor: One (s,z)(s, z) for the entire weight matrix. Coarse; high error.

Per-channel: One (s,z)(s, z) per output channel. Better accuracy; standard for INT8.

Per-group: One (s,z)(s, z) per group of gg weights (e.g., g=128g=128). Fine-grained; standard for INT4.

Overhead=2×FP16 values (s, z)group size=4 bytesg×b/8 bytes.(11)\text{Overhead} = \frac{2 \times \text{FP16 values (s, z)}}{\text{group size}} = \frac{4 \text{ bytes}}{g \times b/8 \text{ bytes}}. \tag{11}

For g=128,b=4g=128, b=4: overhead = 4/(128×0.5)=6.25%4/(128 \times 0.5) = 6.25\% additional storage.

Tradeoff: Smaller gg → better accuracy, more overhead. g=128g=128 is the standard for INT4; g=32g=32 for INT3.


Error Analysis and Bounds

Layer-wise error: The output error from quantizing layer ll:

Δy=ΔWxΔWFx.(12)\|\Delta\mathbf{y}\| = \|\Delta\mathbf{W} \cdot \mathbf{x}\| \leq \|\Delta\mathbf{W}\|_F \cdot \|\mathbf{x}\|. \tag{12}

Error accumulation across layers: Errors compound:

ΔyLl=1LΔWlk>l(Wk+ΔWk).(13)\|\Delta\mathbf{y}_L\| \leq \sum_{l=1}^L \|\Delta\mathbf{W}_l\| \cdot \prod_{k>l} \|(\mathbf{W}_k + \Delta\mathbf{W}_k)\|. \tag{13}

Empirical observation: INT8 quantization typically adds <0.1%< 0.1\% perplexity increase. INT4 with GPTQ/AWQ: <1%< 1\% perplexity increase for models 7B\geq 7B.

Smaller models are harder to quantize: The relative error ΔW/W\|\Delta\mathbf{W}\|/\|\mathbf{W}\| is larger when there are fewer weights to distribute the error across.


Common Pitfalls

Pitfall 1. Quantizing small models (<3B< 3B) to INT4. The quality degradation is substantial — INT8 is safer for small models.

Pitfall 2. Ignoring calibration data quality. GPTQ and AWQ require representative calibration data. Using random data or a mismatched domain leads to poor quantization.

Pitfall 3. Assuming W4A16 provides 4x compute speedup. It provides 4x memory bandwidth reduction (faster weight loading) but activations are still FP16, so tensor core utilization doesn't improve. W8A8 (SmoothQuant) provides actual compute speedup via INT8 tensor cores.


Summary

  • W4A16 (GPTQ, AWQ): 4x memory reduction → 4x bandwidth speedup. Near-lossless for large models.
  • W8A8 (SmoothQuant): 2x memory + 2x compute speedup via INT8 tensor cores.
  • GPTQ: Hessian-aware error compensation; optimal per-column quantization.
  • AWQ: Protect salient weights via activation-aware scaling.
  • SmoothQuant: Migrate quantization difficulty from activations to weights.
  • Per-group quantization (g=128g=128) is standard for INT4 quality.

Exercises

Exercise 1. Compute the memory size of LLaMA-70B in FP16, INT8, and INT4 (with per-group g=128g=128 overhead).

Exercise 2. Derive the optimal scale factor ss that minimizes MSE for symmetric quantization of a uniform distribution wU[a,a]w \sim U[-a, a].

Exercise 3. Explain why GPTQ processes columns in order and compensates remaining columns, rather than quantizing all independently.

Exercise 4. For SmoothQuant with α=0.5\alpha = 0.5: compute the smoothing factor sjs_j given max(xj)=100\max(|x_j|) = 100 and max(wj)=0.5\max(|w_j|) = 0.5.

Exercise 5. Compute the effective bits-per-weight for INT4 quantization with group size 128, accounting for the FP16 scale and zero-point overhead.