| granularity | scale 수 | 용도 |
|---|---|---|
| per-tensor | 1 | 가장 단순 · outlier 취약 |
| per-channel | Cout | weight 표준 (row/col 별) |
| per-token | Ntok | activation (batch·seq 축) |
| per-group | N/G | INT4/FP4 weight · G∈{32,64,128} |
| block-scale | N/G | FP8/FP4 microscaling (MX/NV) |
group-wise는 outlier 흡수 ↔ scale 메모리 trade-off.
| 축 | Symmetric | Asymmetric |
|---|---|---|
| zp | 0 | ≠0 가능 |
| range 활용 | 분포 대칭시 full, 비대칭시 낭비 | 항상 full |
| matmul 비용 | 낮음 (zp 항 없음) | zp cross-term 2개 추가 |
| 적합 | weight | activation · ReLU 출력 |
∴ weight symmetric + activation asymmetric 조합이 흔한 choice.
| 대상 | 자주 쓰는 설정 |
|---|---|
| Weight | per-channel sym INT8 / per-group INT4 |
| Activation | per-token asym INT8 / FP8 E4M3 |
| KV cache | per-token (V) · per-channel (K) · INT8/INT4/FP8 |
| Gradient | FP8 E5M2 (wider range) |
| Accumulator | 항상 FP32 유지 |
acc는 항상 FP32 이다.
실무: activation INT8에 q=99.9% 이 기본값.
TensorRT 기본 entropy calibrator의 수학적 근거.
| 방법 | 장 | 단 |
|---|---|---|
| min-max | 단순·완전 cover | outlier 민감 |
| percentile | robust | q 선택 hyperparam |
| MSE | L2 최적 | grid search 비용 |
| KL | 분포 보존 | bin 수 감도 |
for batch in calib_set:
y = model(batch) # FP forward
for tensor t in acts:
hist[t].update(t.values)
for t in tensors:
s[t] = argmin_KL(hist[t]) # or MSE / minmax
sample 수 ~512면 LLM activation 분포 근사에 충분.
| tensor | 분포 특성 | 권장 |
|---|---|---|
| weight | 평균 0, 얇은 tail | sym · minmax·MSE |
| pre-GeLU act | mild asym | asym · percentile |
| post-LayerNorm | heavy outlier (ch별) | per-channel · SmoothQuant |
| attn logits | long tail | percentile 99.9 |
| 축 | PTQ | QAT |
|---|---|---|
| 데이터 | calib 수백 sample | full training set |
| gradient | 불필요 (GPTQ 제외) | 필수 |
| 비용 | 분~시간 | 수일~수주 |
| bit 하한 | INT4 (세심히) | INT2/INT3 가능 |
| accuracy | −0.1~−1 PPL | ≈ FP baseline |
| LLM 적용 | 주류 | 드묾 (비용) |
| 시점 | 방법 | 특징 |
|---|---|---|
| 학습 완료 후 | RTN / minmax PTQ | 가장 빠름 |
| + calib 수백 | percentile / KL | activation INT8 |
| + Hessian | GPTQ / AdaRound | per-layer 최적화 |
| + act 분석 | AWQ / SmoothQuant | outlier 대응 |
| Retrain | QAT | 최종 수단 |
| 유형 | 대상 | 대표 |
|---|---|---|
| W-only INT8 | weight만 | 기본 PTQ |
| W-only INT4 | weight group-q | GPTQ, AWQ |
| W8A8 | weight + act INT8 | SmoothQuant, LLM.int8() |
| W4A8 | mixed bit | SpQR, QServe |
| W4A4 | 둘 다 INT4 | Atom, QuaRot |
FP ckpt │ ├─ RTN (baseline) │ ├─ GPTQ ← weight INT4 │ ├─ SmoothQ ← act outlier migrate │ └─ AWQ ← scale per-channel ↓ W4A8 / W4A16 / W8A8 deploy
X = X_reg (대부분 ch, INT8) + X_out (~0.1% ch, FP16) Y = W_reg · X_reg (INT8 GEMM) + W_out · X_out (FP16 GEMM)
Dettmers et al. (2022) — bitsandbytes `int8_linear`.
| model | INT8 speedup | PPL Δ |
|---|---|---|
| OPT-6.7B | ~1.0× (offload 존재시 ↑) | ≈0 |
| OPT-13B | ~1.2× | ≈0 |
| OPT-175B | ~2× (fit on 1 node) | ≈0 |
소형 model은 outlier 없음 → PTQ INT8 그대로 OK.
X (B·N·d)
├── ch∈outlier ──► FP16 path
└── ch∈regular ──► INT8 (vec-scale)
│ │
▼ ▼
W_f16·X_f16 + Dq(W_q·X_q)
▼
Y (FP16)
dampening: H ← H + λ·diag(H) · I, λ=1% (수치 안정).
1. H = 2·X X^T + λ·diag
2. L = Cholesky(H^{-1})
3. for block B in columns (stride 128):
for j in B:
wq[j] = quant(w[j])
err = (w[j]-wq[j]) / L[j,j]
W[:, j+1:B_end] -= err · L[j, j+1:B_end]
W[:, rest] -= err_block · L[B, rest]
| 모델 | 시간 (A100) | 메모리 |
|---|---|---|
| LLaMA-7B | ~1h | ~25 GB |
| LLaMA-13B | ~2h | ~35 GB |
| LLaMA-65B | ~20h | ~160 GB |
| OPT-175B | ~4d | multi-GPU |
cf. RTN은 분 단위지만 INT4에서 PPL +3 이상.
| 설정 | PPL Δ (WikiText) |
|---|---|
| LLaMA-7B FP16 | base 5.68 |
| W4 RTN | +0.3~+0.6 |
| W4 GPTQ | +0.1~+0.2 |
| W3 GPTQ | +0.4~+0.9 |
Frantar et al. (2022) · 값은 논문 표 기준, 세부는 버전 의존.
| 축 | GPTQ | AWQ |
|---|---|---|
| 근거 | Hessian H=2XXT | activation magnitude |
| 최적화 | column 순 block update | per-ch scale s 탐색 |
| calib 시간 | 시간 단위 | 분 단위 |
| runtime fuse | 불필요 (weight only) | prev-layer fuse |
| W4A16 | 강점 | 강점 (양립 가능) |
1. calib forward → per-ch |x|_mean
2. α grid: {0, 0.1, …, 1.0}
3. for each α:
s = |x|_mean^α / geomean
W' = W·diag(s)
loss = ‖W·X − Q(W')·(X/s)‖
4. α* = argmin
5. fuse s^{-1} into prev layer
| 모델 | W4 RTN | W4 AWQ |
|---|---|---|
| LLaMA-7B | +0.6 | +0.1 |
| LLaMA-13B | +0.4 | +0.08 |
| LLaMA-65B | +0.3 | +0.05 |
Lin et al. (2023) · group=128, sym. vLLM 통합 ↗ V16 §7.
before: X : ───|▇▇▇|─── (outlier ch 극단) W : ──▂▂▂▂▂── (균일) after (s fused): X' : ──▃▃▃▃▃── (평탄화) W' : ──▃▅▅▅▃── (약간 커짐) → 둘 다 INT8에 안전
| 위치 | fuse 대상 |
|---|---|
| QKV proj 앞 | LayerNorm γ |
| FFN up 앞 | LayerNorm γ |
| Out proj 앞 | 별도 div op (추가) |
| FFN down 앞 | element-wise scale |
out-proj 앞은 fuse 지점이 없어 작은 runtime overhead 발생.
| 축 | SmoothQuant | AWQ |
|---|---|---|
| 목표 | W8A8 | W4A16 |
| 이전 방향 | act → weight | weight → act (역) |
| scale 식 | max|x|α/max|w|1−α | |x|meanα |
| primary 용도 | activation int8 가능화 | weight int4 보호 |
| 모델 | W8A8 baseline | W8A8 SQ |
|---|---|---|
| OPT-6.7B | +2.1 | +0.1 |
| OPT-66B | +12.5 | +0.2 |
| BLOOM-176B | +3.2 | +0.1 |
Xiao et al. (2022) · 대형 model에서 효과 두드러짐.
1. FP16 forward on calib
2. per-ch:
a_max[j] = max |X[:,:,j]|
w_max[j] = max |W[j,:]|
3. sweep α:
s(α) = a_max^α / w_max^{1-α}
fuse s, quant W', quant X'
eval loss
4. pick α* minimizing PPL
| 축 | INT8 | INT4 |
|---|---|---|
| granularity | per-token | per-token + group=128 |
| sym/asym | asym | asym |
| 실효 speed | ~1.8× | ~3.2× |
| PPL Δ | ≈0 | +0.1~+0.3 |
asym 선택 이유는 §4에서 설명.
dequant를 matmul에 fuse하면 extra load 없음 (load·dequant·mma).
K[t, h, :] size d_head=128 group_size = 32 → 4 group/token s_K[t, h, g] × 4 z_K[t, h, g] × 4 quant: K_q[t, h, g·32:(g+1)·32] ∈ [0,15]
group=32가 PPL-overhead 균형점 (Atom).
| 축 | per-channel (head dim) | per-token |
|---|---|---|
| scale 저장 | H·d (static) | seq·H (dynamic) |
| K에 적합 | ○ (ch별 bias) | △ |
| V에 적합 | △ | ○ (token별 magnitude) |
| 메모리 | 고정 overhead | seq 비례 |
int8_e4m3, fp8 옵션| 축 | K (Key) | V (Value) |
|---|---|---|
| 출처 | LN·WK·x | LN·WV·x |
| 채널 bias | 큼 (ch별 fixed offset) | 작음 |
| token variance | 작음 | 큼 |
| 최적 scale | per-channel | per-token |
per-token sym은 ch shift를 scale로 흡수 못 함.
K tensor : [L, H, d_head, seq]
↑ scale 축
V tensor : [L, H, seq, d_head]
↑ scale 축
→ K / V의 스토리지를 서로 다른
stride로 유지하면 per-axis scale이
coalesced load와 맞음.
| scheme | K | V | bit |
|---|---|---|---|
| naive | per-token sym | per-token sym | 8 |
| vLLM FP8 | per-tensor | per-tensor | 8 (FP8) |
| KIVI | per-ch asym | per-tok asym | 4/2 |
| Atom | per-ch asym | per-tok asym | 4 |
| 설정 | PPL Δ |
|---|---|
| LLaMA-7B KV8 per-tok sym | +0.05 |
| LLaMA-7B KV4 per-tok sym | +1.1 |
| LLaMA-7B KIVI INT4 | +0.2 |
| LLaMA-7B KIVI INT2 | +0.5 |
Liu et al. (2024) · WikiText-2 PPL.
| 축 | INT8 | FP8 |
|---|---|---|
| 표현 | uniform [-127, 127] | exp+mant (E4M3/E5M2) |
| dynamic range | 고정 (s로 이동만) | ~107 (E4M3) |
| calibration | 필수 | 필수 (amax) |
| outlier | clip or scale | exp가 일부 흡수 |
| bit layout | int | ↗ V09 §4 |
hist = [amax_{t-N}, …, amax_{t-1}]
s_t = max(hist) / FP8_max
amax_t = measure(x_t / s_t … ) ← 기록만, 다음에 씀
hist.shift_and_insert(amax_t)
forward:
1. load s (from prev hist)
2. x_fp8 = cast(x / s)
3. y = GEMM_fp8(x_fp8, w_fp8, acc=fp32)
4. amax_t = max|x| (비동기)
5. hist[t] = amax_t
6. s_{t+1} = max(hist) / 448
backward:
gradient는 E5M2 (range 넓음)
| 대상 | dtype | 이유 |
|---|---|---|
| weight | E4M3 | 정밀 우선, range 충분 |
| forward act | E4M3 | 정밀 우선 |
| backward grad | E5M2 | range 넓음 |
| accumulator | FP32 | 누적 오차 방지 |
load_fp16 → cast_fp8 → mma_fp8
│
FP32 accumulator ←─────────┘
│
cast_fp16 or fp8 ← epilogue
WGMMA는 FP8 operand · FP32 acc (Hopper). 상세 ↗ V04 §8.
| 경로 | Fake (simulated) | Real |
|---|---|---|
| dtype | FP32/FP16 내부 | INT8/FP8 실제 |
| 연산 | quant → dequant → FP matmul | low-prec matmul |
| 속도 | baseline과 유사 | ~2× / ~4× |
| 용도 | accuracy 평가, QAT | 실제 배포 |
| 오차 | round+clip만 | + accumulator error |
| 연산 | acc dtype | saturate? |
|---|---|---|
| INT8·INT8 TC | INT32 | K≤216이면 안전 |
| FP8·FP8 TC | FP32 | 항상 안전 |
| INT4·INT4 | INT32 | 안전 |
| FP4·FP4 | FP32 | 안전 (block-scale과 결합) |
fake:
FP(W·X) → +bias → GeLU → next quant
real:
INT(W_q·X_q)
↓ dequant (s_w·s_x)
↓ +bias (FP)
↓ GeLU (FP, approximated)
↓ quant (next layer)
| 벤치 | 측정 | 특징 |
|---|---|---|
| MMLU | 다분야 지식 zero-shot accuracy | knowledge tail 민감 |
| GSM8K | 수학 체인오브소트 | reasoning 누적 오차 반영 |
| BBH / HumanEval | reasoning / code | task 세분 |
PPL은 통과하지만 MMLU·GSM8K에서 점수 drop하는 quant 흔함.
per-layer εY 를 plot하면 문제 layer가 드러남.
activation은 magnitude보다 방향이 downstream에 중요.
| quant 목적 | 필수 지표 |
|---|---|
| W8 (min loss) | PPL |
| W4 (W-only) | PPL + MMLU |
| W4A8 | PPL + MMLU + GSM8K |
| W4A4 | 전부 + humaneval |
| KV quant | long-context PPL |
for L in layers: run with L quantized, others FP measure ΔPPL → sort layers by impact → 최악 top-k는 FP16 유지 (mixed-bit)
| 상황 | 지표 |
|---|---|
| sweep 중 빠른 비교 | PPL (WikiText-2) |
| release gating | MMLU + GSM8K + PPL |
| per-layer debug | εY, cos |
| long-context | RULER / needle |
| RL·code | HumanEval / pass@k |
| 방법 | W | A | KV | bit | sym/asym | granularity |
|---|---|---|---|---|---|---|
| RTN | ○ | × | × | 8 | sym | per-ch |
| LLM.int8() | ○ | ○ | × | 8 | sym (vec) | per-tok (A) · per-ch (W) |
| GPTQ | ○ | × | × | 4/3 | sym | per-group 128 |
| AWQ | ○ | × | × | 4 | sym | per-group 128 |
| SmoothQuant | ○ | ○ | × | 8 | sym+asym | per-ch/tok |
| FP8 (TE) | ○ | ○ | △ | 8 (FP) | sym | per-tensor |
| MX / NVFP4 | ○ | ○ | × | 4/8 (FP) | sym | block (16/32) |
| KIVI | × | × | ○ | 4/2 | asym | per-ch K + per-tok V |
| Atom | ○ | ○ | ○ | 4 | asym | group 128 + KV mixed |
Q: accuracy 예산 ΔPPL?
├─ ≤0.05 ──► FP16 유지 (no quant)
├─ ≤0.2 ──► W8 RTN / FP8 (E4M3)
│ └ A8도 원함 → SmoothQuant
├─ ≤0.5 ──► W4 AWQ or GPTQ (g=128)
│ └ KV도 줄임 → +KIVI INT4
└─ ≤1.0 ──► W4A4 Atom / MXFP4
└ 학습 가능? → QAT
| GPU | 지원 low-prec TC |
|---|---|
| A100 (Ampere) | INT8 / INT4 / BF16 |
| H100 (Hopper) | + FP8 E4M3/E5M2 + TE |
| B200 (Blackwell) | + FP4 / MX / NVFP4 block-scale |
arch 상세 ↗ V02 §7.
| 모델 | latency 중요 | throughput 중요 |
|---|---|---|
| <3B | W8 / FP8 | FP16 batch ↑ |
| 7–13B | W4 AWQ + KV8 | W4A8 SmoothQuant |
| 30–70B | W4 AWQ + KV4 KIVI | W4A4 Atom / MXFP4 |
| 175B+ | W4 GPTQ + FP8 + TP | 동일 + EP |
| Do | Don't |
|---|---|
| weight: per-ch sym | per-tensor sym on large LLM |
| act: per-tok asym (or SQ) | per-tensor act without smoothing |
| accumulator FP32 | low-prec accumulator |
| RTN baseline 측정 선행 | RTN 건너뛰고 GPTQ |
| MMLU·GSM8K 최종 검증 | PPL만 믿기 |
| FP8 delayed scaling | current-batch amax block |