SmoothQuant: W8A8 Quantization
Quantizing both weights AND activations to INT8: the activation outlier problem, SmoothQuant's migration strategy, per-channel scaling, and achieving 2x speedup via INT8 tensor core acceleration.
Prerequisites
Table of Contents
- Learning Objectives
- Notation
- Core Intuition
- Why W8A8 Matters
- The Activation Outlier Problem
- SmoothQuant: Migrating Difficulty
- Choosing the Migration Strength
- Per-Token vs Per-Tensor Activation Quantization
- Implementation & Speedup
- LLM.int8(): Mixed-Precision Decomposition
- Common Pitfalls
- Summary
- Exercises
Learning Objectives
- Explain why activation quantization is harder than weight quantization.
- Derive SmoothQuant's channel-wise scaling transformation.
- Analyze the migration strength parameter and its optimal value.
- Compare W8A8 with W4A16 in terms of actual inference speedup.
- Describe LLM.int8()'s mixed-precision approach for outlier channels.
Notation
- — per-channel smoothing factors
- — migration strength
- WA — -bit weights, -bit activations
Core Intuition
Weight-only quantization (W4A16, W8A16) reduces memory but doesn't speed up computation — activations are still in FP16, and the matmul itself uses FP16 arithmetic. For actual COMPUTE speedup, both weights AND activations must be quantized to INT8, enabling INT8 tensor cores (2x throughput on A100/H100). The challenge: activations have outlier channels that make direct quantization catastrophic.
SmoothQuant Migration
Why W8A8 Matters
Memory bandwidth vs compute:
- W4A16: Reduces weight loading (memory-bound regime). No compute speedup.
- W8A8: Both operands in INT8 → use INT8 tensor cores → 2x compute throughput.
When compute-bound (large batch, long sequence): W8A8 provides actual speedup. When memory-bound (batch=1, short prompt): W4A16 is sufficient.
Hardware support:
- NVIDIA A100: INT8 tensor cores (624 TOPS vs 312 TFLOPS FP16).
- NVIDIA H100: INT8 at 1979 TOPS vs 989 TFLOPS FP16.
- 2x peak throughput for quantized operations.
The Activation Outlier Problem
Discovery (Dettmers et al., 2022): In LLMs above 6B parameters, specific hidden dimensions develop extreme outlier activations.
Properties:
- Systematic: same channels are outliers across ALL tokens and layers.
- Magnitude: 10-100x larger than other channels.
- Sparse: only 1-5% of channels are outliers (but they're critical).
Impact on quantization: One outlier channel at magnitude 100 with other channels at magnitude 1:
- Per-tensor scale: .
- Non-outlier channels quantized to: → rounded to 1.
- Effective precision: 2-3 levels for 99% of channels.
SmoothQuant: Migrating Difficulty
Key insight (Xiao et al., 2023): Activations are hard to quantize (outliers); weights are easy (smooth distribution). Migrate the quantization difficulty from activations to weights via per-channel scaling.
Transformation:
Effect:
- : Outlier channels divided by large → smoothed.
- : Corresponding weight columns scaled up → slightly harder to quantize, but weights can handle it.
Result: Both and are easy to quantize to INT8.
Choosing the Migration Strength
Smoothing factor:
where is column of activations and is row of weights.
controls migration:
- : No smoothing (original problem).
- : Equal difficulty for both (geometric mean).
- : All difficulty on weights.
Optimal: for most LLMs. For very outlier-heavy models (OPT-175B): .
Calibration: Compute over a small calibration dataset (128 samples typical).
Per-Token vs Per-Tensor Activation Quantization
Per-tensor: One scale for entire activation matrix. Cheapest but most error.
Per-token (per-row): One scale per token (row of activation matrix).
Why per-token works: Different tokens have different magnitudes (e.g., special tokens vs content tokens). Per-token handles this without extra kernel overhead.
Combined with SmoothQuant: Per-token activation scaling + per-channel weight scaling = good W8A8 quality.
Implementation & Speedup
Inference pipeline:
- Offline: Compute smoothing factors from calibration data. Pre-multiply weights by .
- Online: Quantize activation (per-token scale). INT8 matmul. Dequantize output.
Actual speedups (A100, OPT-175B):
- W8A8 SmoothQuant: 1.56x speedup over FP16.
- Memory: 2x reduction (both weights and activations in INT8).
- Quality: less than 0.5% accuracy loss on downstream tasks.
Supported frameworks: TensorRT-LLM, vLLM (with CUTLASS INT8 kernels), FasterTransformer.
LLM.int8(): Mixed-Precision Decomposition
Alternative approach (Dettmers et al., 2022): Instead of smoothing, handle outliers separately:
- Identify outlier dimensions (magnitude exceeds threshold 6.0).
- Extract outlier columns → compute in FP16.
- Remaining columns → compute in INT8.
- Sum the two results.
Tradeoff vs SmoothQuant:
- LLM.int8(): No calibration needed; slightly slower (two matmuls).
- SmoothQuant: Needs calibration; faster (single INT8 matmul).
Common Pitfalls
Pitfall 1. Assuming W8A8 always gives 2x speedup. Speedup depends on being compute-bound. At batch=1 (memory-bound), W4A16 may be faster than W8A8.
Pitfall 2. Using per-tensor activation quantization without SmoothQuant. Outliers will dominate the scale and destroy quality. Always smooth first.
Pitfall 3. Calibrating smoothing factors on unrepresentative data. The outlier pattern depends on the input domain. Use data similar to deployment inputs.
Summary
- W8A8 enables INT8 tensor cores → 2x compute speedup (when compute-bound).
- Activation outlier problem: 1-5% of channels have 100x magnitude → destroys naive quantization.
- SmoothQuant: Migrate difficulty from activations to weights via per-channel scaling.
- : Equal difficulty split (optimal for most models).
- LLM.int8(): Handle outliers separately in FP16 (no calibration needed).
- Choose based on: compute-bound vs memory-bound, calibration feasibility, framework support.
Exercises
Exercise 1. For activations with channel magnitudes and weights with column magnitudes : compute the SmoothQuant factors with .
Exercise 2. After smoothing with the factors from Exercise 1: compute the new activation and weight magnitudes. Verify both are now quantizable.
Exercise 3. Compare the wall-clock speedup of W8A8 vs W4A16 on an A100 for batch sizes 1, 16, and 128 (use roofline model).
Exercise 4. For LLM.int8(): if 3% of channels are outliers, what fraction of compute remains in FP16? Is this significant?
Exercise 5. Design an experiment to find the optimal for a specific model. What metric should you optimize?