Study · Quantization
What actually happens when you quantize a KV cacheKV cache를 quantize하면 실제로 무슨 일이 일어나는가
Not the cartoon version. A step-through of the real dataflow — actual tensor shapes, actual scale/zero arithmetic on an 8-value group, actual bytes packed into HBM, and the roofline arithmetic that explains why 4× fewer bytes is (almost) 4× faster decode attention. Every number on this page can be recomputed by hand. 만화 버전이 아니다. 실제 dataflow를 한 단계씩 따라간다 — 실제 tensor shape, 8개 값 그룹에 대한 실제 scale/zero 산술, HBM에 실제로 패킹되는 바이트, 그리고 바이트가 4× 줄면 decode attention이 (거의) 4× 빨라지는 이유를 설명하는 roofline 산술까지. 이 페이지의 모든 숫자는 손으로 다시 계산할 수 있다.
Before you start: you should know roughly what a decoder-only transformer does at inference time, and that attention lets each new token consult the keys and values of every earlier token — Attention-head anatomy covers this, plus the MHA/GQA/MLA distinction used below. §6 leans on the HBM → L2 → SM picture from GPU memory hierarchy; a skim is enough. 시작하기 전에: decoder-only transformer가 inference 시에 대략 무엇을 하는지, 그리고 attention이 새 토큰마다 앞선 모든 토큰의 key와 value를 참조하게 한다는 것 정도는 알고 있어야 한다 — Attention-head anatomy가 이 내용과 아래에서 쓰는 MHA/GQA/MLA 구분을 다룬다. §6은 GPU memory hierarchy의 HBM → L2 → SM 그림에 기대고 있다 — 훑어보는 것으로 충분하다.
§1The itch: the cache outgrows the model문제의식: 캐시가 모델보다 커진다
A language model generates text one token per step, and every step has to look back at all the tokens before it. The state that makes that look-back affordable — the KV cache — is remembered per token, per head, per layer, so it grows with context length and with batch size. For the 7B-class model used throughout this page the bill comes to 512 KiB per token (§3 derives it): a single 4,096-token sequence drags 2.0 GiB of cache behind it, and a batch of 8 drags 16 GiB — more than the ~13 GiB the model's own weights occupy in FP16. Language model은 스텝마다 토큰 하나를 생성하고, 매 스텝은 그 앞의 모든 토큰을 돌아봐야 한다. 그 돌아보기를 감당 가능하게 만드는 상태 — KV cache — 는 토큰마다, head마다, layer마다 기억되므로 context 길이와 batch 크기에 따라 자란다. 이 페이지에서 내내 쓰는 7B급 모델 기준 청구서는 토큰당 512 KiB다 (§3에서 유도한다): 4,096-토큰 시퀀스 하나가 2.0 GiB의 캐시를 끌고 다니고, batch 8이면 16 GiB — 모델 자신의 weight가 FP16으로 차지하는 ~13 GiB보다 크다.
On a 40 GB A100 it is the cache, not the weights, that caps batch size — that is the capacity half of the problem, and the entire motivation in one sentence. The speed half is worse: to produce each new token, the GPU must re-read the whole cache (§2 explains why that read is the clock). Bytes are both rent and toll. 40 GB A100에서 batch 크기를 제한하는 것은 weight가 아니라 캐시다 — 이것이 문제의 용량 절반이고, 한 문장으로 요약한 동기의 전부다. 속도 절반은 더 나쁘다: 새 토큰 하나를 만들 때마다 GPU는 캐시 전체를 다시 읽어야 한다 (§2에서 왜 그 읽기가 시계인지 설명한다). 바이트는 임대료이자 통행료다.
FP16 spends 16 bits per cached value — what actually happens if we spend 4?FP16은 캐시된 값 하나에 16 bit를 쓴다 — 4 bit만 쓰면 실제로 무슨 일이 일어나는가?
§2Foundations: the cache, the clock, and the grid기초: 캐시, 시계, 그리드
Why a cache exists at all. Attention at step t scores the new token's query against the key of every earlier token and takes a weighted average of their values. Those K and V vectors were already computed once, when their tokens were generated; recomputing them every step would cost a full forward pass per token. So we store them and reuse them — FLOPs traded for memory. The KV cache is that stored memory, and this page is about what it costs. 애초에 왜 캐시가 존재하는가. 스텝 t의 attention은 새 토큰의 query를 앞선 모든 토큰의 key와 비교해 점수를 매기고, 그들의 value를 가중 평균한다. 그 K와 V 벡터는 각 토큰이 생성될 때 이미 한 번 계산된 것들이다; 매 스텝 다시 계산하면 토큰당 full forward pass 비용이 든다. 그래서 저장해 두고 재사용한다 — FLOPs를 memory와 맞바꾸는 것이다. KV cache가 그 저장된 memory이고, 이 페이지는 그 비용에 관한 것이다.
The running configuration is a Llama-2-7B-shaped decoder: 32 layers, multi-head attention with 32 KV heads of dimension 128, FP16 weights and activations. Every byte count on this page follows from those four numbers. (Grouped-query models divide the cache by the head-count ratio — 4× for Llama-3-8B — but change nothing structural.) 기본 설정은 Llama-2-7B 모양의 decoder다: 32 layer, dimension 128의 KV head 32개를 가진 multi-head attention, FP16 weight와 activation. 이 페이지의 모든 바이트 수는 이 네 숫자에서 따라 나온다. (Grouped-query 모델은 head-count 비율만큼 캐시를 나눈다 — Llama-3-8B는 4× — 하지만 구조적으로는 아무것도 바뀌지 않는다.)
Why bytes are the clock. An A100 can execute ~312 TFLOP/s of FP16 math but read only ~1.55 TB/s from HBM — the compute units stay busy only if the kernel does roughly 200 floating-point operations per byte it reads. Decode attention does about 2 FLOPs per 2 bytes of cache. It is not close: the GPU spends essentially the whole step waiting on memory, so a decode step takes bytes ÷ bandwidth, almost independent of arithmetic. Any bytes you remove come straight off the wall clock. (§6 turns this sketch into a receipt.) 왜 바이트가 시계인가. A100은 FP16 연산을 ~312 TFLOP/s로 수행하지만 HBM에서는 ~1.55 TB/s밖에 읽지 못한다 — 읽는 byte당 대략 200번의 부동소수점 연산을 해야 compute unit이 놀지 않는다. Decode attention은 캐시 2 byte당 약 2 FLOPs를 한다. 비교가 되지 않는다: GPU는 사실상 스텝 전체를 memory를 기다리며 보내므로, decode 한 스텝의 시간은 bytes ÷ bandwidth이고 산술량과는 거의 무관하다. 바이트를 줄이면 그대로 벽시계 시간이 줄어든다. (§6에서 이 스케치를 영수증으로 만든다.)
What “quantize” means here. Replace each FP16 number by a small integer index into a uniform grid: pick 16 evenly spaced levels (4 bits), record where the grid sits using two shared numbers — a scale (the step width) and a zero-point (which level decodes to 0.0) — and round every value to its nearest level. The data becomes tiny integers plus a tiny shared header; the price is a rounding error of at most half a step per value. Everything in §3 is this one idea, executed carefully on real numbers. 여기서 “quantize”란 무엇인가. 각 FP16 숫자를 uniform grid의 작은 정수 index로 바꾸는 것이다: 균등 간격의 level 16개(4 bit)를 고르고, grid의 위치를 공유 숫자 두 개 — scale(스텝 폭)과 zero-point(0.0으로 decode되는 level) — 로 기록한 뒤, 모든 값을 가장 가까운 level로 반올림한다. 데이터는 작은 정수들과 작은 공유 header가 되고, 대가는 값당 최대 반 스텝의 rounding error다. §3의 전부가 이 아이디어 하나를 실제 숫자 위에서 조심스럽게 실행한 것이다.
A token arrives and becomes 16 KiB of FP16 per layer — what exactly happens to it on the way down to 4 bits?토큰 하나가 도착해 layer당 16 KiB의 FP16이 된다 — 4 bit로 내려가는 길에 정확히 무슨 일이 일어나는가?
§3The dataflow, step by stepDataflow, 한 단계씩
We now have the problem (§1) and the vocabulary (§2). What follows is the whole pipeline run on real numbers — one token's key row, eight FP16 values, followed all the way into packed HBM bytes and back out through the read path. Use the pips, the arrow keys, or Play; every number can be checked by hand. 이제 문제(§1)와 어휘(§2)가 갖춰졌다. 다음은 파이프라인 전체를 실제 숫자 위에서 돌린 것이다 — 한 토큰의 key row, FP16 값 8개를 HBM에 패킹되는 바이트까지, 그리고 read path를 따라 다시 나올 때까지 끝까지 따라간다. pip 버튼, 방향키, Play를 써 보라; 모든 숫자는 손으로 검산할 수 있다.
1One decode step, two tensors디코드 한 스텝, 두 개의 텐서
2Zoom in: one quantization group확대: quantization group 하나
Quantizers never see the whole tensor — they work on small groups that share
one scale and one zero-point. Below: the first 8 channels of K[3, :], real FP16
values. (8 is a toy size so the math fits on screen; production kernels use g = 32–128.
Step 5 does the storage arithmetic at g = 128.)
Quantizer는 tensor 전체를 보지 않는다 — scale 하나와 zero-point 하나를 공유하는
작은 그룹 단위로 동작한다. 아래는 K[3, :]의 처음 8개
channel, 실제 FP16 값이다. (8은 수식이 화면에 들어오도록 고른 toy 크기이고,
production kernel은 g = 32–128을 쓴다. Step 5에서 g = 128로 저장 산술을 한다.)
Group total in FP16: 8 × 2 B = 16 B. The goal of the next three steps is to
rewrite these 16 bytes as 4 bytes of codes plus a small shared header —
while keeping every value within half a grid step of where it started.
FP16 기준 그룹 합계: 8 × 2 B = 16 B. 다음 세 단계의 목표는 이
16바이트를 code 4바이트와 작은 공유 header로 다시 쓰는 것이다 —
모든 값이 원래 자리에서 grid 반 스텝 이내에 머물게 하면서.
3Two numbers summarize the group숫자 두 개가 그룹을 요약한다
min = −0.28 (c4) max = 0.87 (c2) range = 1.15 One pass over the 8 values.8개 값을 한 번에 스캔.
s = range / (2⁴ − 1) = 1.15 / 15 = 0.07667 The width of one grid step: 16 codes ⇒ 15 steps between them.grid 한 스텝의 폭: code 16개 ⇒ 그 사이 스텝은 15개.
z = round(−min / s) = round(3.652) = 4 The integer code that decodes to ≈ 0.0 — this is what makes it asymmetric.≈ 0.0으로 decode되는 정수 code — 이것이 asymmetric의 핵심이다.
q = clamp( round(x / s) + z, 0, 15 ) dequantizex̂ = (q − z) × s Why asymmetric? A concrete comparison왜 asymmetric인가? 구체적 비교
A symmetric INT4 quantizer centers its grid at zero and must cover
max(|min|, |max|) = 0.87 on both sides:
s = 0.87 / 7 = 0.124. This group is skewed positive
(max = 0.87 vs |min| = 0.28), so the asymmetric grid's step of 0.0767 is
38% finer for the same 4 bits — the zero-point simply slides the grid
to hug [min, max]. KV activations are routinely skewed, which is why asymmetric is
the default for cache quantization.
Symmetric INT4 quantizer는 grid를 0에 중심 맞추고
max(|min|, |max|) = 0.87을 양쪽 모두 커버해야 한다:
s = 0.87 / 7 = 0.124. 이 그룹은 양수 쪽으로 치우쳐 있어
(max = 0.87 vs |min| = 0.28), 같은 4 bit로도 asymmetric grid의 스텝 0.0767이
38% 더 촘촘하다 — zero-point는 grid를 [min, max]에 밀착하도록
밀어줄 뿐이다. KV activation은 으레 치우쳐 있으므로, cache quantization에서는
asymmetric이 기본값이다.
4Snap every value to the 16-level grid모든 값을 16-level grid에 스냅
| ch | x (FP16) | x / s | round | +z → q | bits | x̂ = (q−z)·s | error |
|---|---|---|---|---|---|---|---|
| c0 | 0.42 | 5.478 | 5 | 9 | 1001 | 0.3833 | −0.0367 |
| c1 | −0.13 | −1.696 | −2 | 2 | 0010 | −0.1533 | −0.0233 |
| c2 | 0.87 | 11.348 | 11 | 15 | 1111 | 0.8433 | −0.0267 |
| c3 | 0.05 | 0.652 | 1 | 5 | 0101 | 0.0767 | +0.0267 |
| c4 | −0.28 | −3.652 | −4 | 0 | 0000 | −0.3067 | −0.0267 |
| c5 | 0.61 | 7.957 | 8 | 12 | 1100 | 0.6133 | +0.0033 |
| c6 | 0.17 | 2.217 | 2 | 6 | 0110 | 0.1533 | −0.0167 |
| c7 | −0.02 | −0.261 | 0 | 4 | 0100 | 0.0000 | +0.0200 |
5Pack nibbles, pay the header, count the bytesnibble 패킹, header 비용, 바이트 계산
Two 4-bit codes share one byte — even channel in the low nibble, odd in the high nibble.4-bit code 두 개가 1 byte를 나눠 쓴다 — 짝수 channel은 low nibble, 홀수 channel은 high nibble.
8 values · 16 B of FP16 → 4 B of codes값 8개 · FP16으로 16 B → code 4 B
On HBM, each group also stores its header. One 128-channel group (the production size used below) as a logical record — widths not to scale; real kernels usually keep scales/zeros in separate contiguous arrays for coalesced loads: HBM에는 각 그룹의 header도 함께 저장된다. 아래 저장 산술에 쓰는 production 크기인 128-channel 그룹 하나를 논리적 record로 그리면 — 폭은 비례가 아니고, 실제 kernel은 coalesced load를 위해 scale/zero를 보통 별도의 연속 배열에 둔다:
68 B where FP16 needed 256 B → 3.76×, i.e. 4.25 effective bits per value.FP16이 256 B 쓰던 것을 68 B로 → 3.76×, 즉 값당 4.25 effective bits.
| per token (K+V, 32 layers) | FP16 | INT4, g=128 |
|---|---|---|
| element data | 524,288 B | 131,072 B |
| scales + zeros (2,048 groups × 4 B) | — | 8,192 B |
| total per token | 512 KiB | 136 KiB |
| 4,096-token sequence | 2.0 GiB | 544 MiB |
| bits per value | 16.0 | 4.25 → 3.76× |
| group size g | header per value | effective bits | ratio |
|---|---|---|---|
| 32 | 1.00 bit | 5.00 | 3.20× |
| 64 | 0.50 bit | 4.50 | 3.56× |
| 128 | 0.25 bit | 4.25 | 3.76× |
| whole tensor | ≈ 0 | 4.00 | 4.00× (worst error) |
The group-size dialgroup-size 다이얼
Smaller groups hug their local min/max, so the step s shrinks and rounding error falls — but every group pays the 4-byte header, so effective bits rise. g = 64–128 is the usual sweet spot for the KV cache: the header cost drops to 0.25–0.5 bits per value while each group still spans only a narrow slice of the distribution. 그룹이 작을수록 로컬 min/max에 밀착해 스텝 s가 줄고 rounding error도 떨어진다 — 하지만 그룹마다 4-byte header를 내야 하므로 effective bits는 올라간다. KV cache에서는 g = 64–128이 통상의 sweet spot이다: header 비용이 값당 0.25–0.5 bit로 떨어지면서도 각 그룹은 여전히 분포의 좁은 조각만 커버한다.
6Decode: the cache streams back, and bytes are the bill디코드: 캐시가 다시 스트리밍되고, 청구서는 바이트다
The roofline receipt (per decode step, 4,096 ctx, batch 1)roofline 영수증 (decode step당, 4,096 ctx, batch 1)
- bytes read, FP16읽는 바이트, FP16
4,096 × 512 KiB = 2.0 GiB - bytes read, INT4 + headers읽는 바이트, INT4 + headers
4,096 × 136 KiB = 544 MiB - stream time @ 1.55 TB/s스트리밍 시간 @ 1.55 TB/s
1.39 ms → 0.37 ms - extra dequant work추가 dequant 연산
1.07 G elems × 1 FMA ≈ 2.1 GFLOP - …which costs…의 비용
≈ 27 µs on CUDA cores (≈ 7 µs fused) - arithmetic intensity
1 → ≈ 7.5 FLOP/B · ridge ≈ 200 FLOP/B
7Where the clean picture breaks깔끔한 그림이 깨지는 곳
K outliers A few key channels run ~10× hot일부 key channel은 ~10× 뜨겁게 달린다
Keys have persistent outlier channels — a structure tied to rotary position embeddings and “massive activation” channels (documented in KVQuant and the massive-activations literature). One hot channel inside a group inflates the range, and the scale is range/15. Toy group with one outlier: Key에는 지속적인 outlier channel이 있다 — rotary position embedding과 “massive activation” channel에 결부된 구조다 (KVQuant와 massive-activations 문헌에 기록됨). 그룹 안의 뜨거운 channel 하나가 range를 부풀리는데, scale은 range/15다. outlier 하나가 든 toy 그룹:
[0.03, −0.05, 0.02, −0.01, 0.04, 0.01, −0.02, 4.80]
s = 4.85 / 15 = 0.323 · z = 0
every normal value: round(x / 0.323) = 0 → decodes to exactly 0.0
Seven of eight channels are erased. The outlier is fine; everything near it dies.8개 중 7개 channel이 지워진다. outlier는 멀쩡하고, 그 주변의 모든 값이 죽는다.
axis choice K per-channel, V per-token
Because K's outliers align along channels, group K per-channel: each group collects one channel across consecutive tokens, so a hot channel shares a scale only with itself. V shows no persistent channel structure, so per-token grouping (one group inside each token's 128-dim vector) works and keeps the append-only streaming layout trivial — this K/V asymmetry is the central observation of KIVI. The cost of per-channel K: you must buffer a few tokens before a channel-group fills, so systems keep a small FP16 residual window of the newest tokens anyway. K의 outlier는 channel 방향으로 정렬되어 있으므로 K는 per-channel로 그룹화한다: 각 그룹이 연속된 토큰들에 걸쳐 channel 하나를 모으므로, 뜨거운 channel은 자기 자신하고만 scale을 공유한다. V는 지속적인 channel 구조가 없어 per-token 그룹화(각 토큰의 128-dim 벡터 내부에서 그룹 하나)로 충분하고 append-only streaming 레이아웃도 그대로 단순하게 유지된다 — 이 K/V 비대칭이 KIVI의 핵심 관측이다. per-channel K의 비용: channel-group이 찰 때까지 토큰 몇 개를 버퍼링해야 하므로, 시스템들은 어차피 최신 토큰의 작은 FP16 residual window를 유지한다.
2-bit cliff 4 levels is where uniform grids dielevel 4개, uniform grid가 죽는 지점
At 2 bits a group has 4 codes → 3 steps; round-to-nearest noise per value is ~4× the INT4 case, and accuracy falls off a cliff rather than degrading gracefully — long-context retrieval and multi-step reasoning go first. Working 2-bit systems are never “the same recipe, smaller grid”: they add non-uniform (quantile/learned) levels, isolate outliers into a sparse FP16 side-band (KVQuant), tighten groups, and keep a recent-token FP16 window (KIVI). Textbook INT4 is nearly free; 2-bit is a research area. 2 bit에서는 그룹당 code 4개 → 스텝 3개; 값당 round-to-nearest 노이즈가 INT4의 ~4×이고, 정확도는 완만히 저하되는 대신 절벽처럼 떨어진다 — long-context retrieval과 multi-step reasoning이 먼저 무너진다. 동작하는 2-bit 시스템은 결코 “같은 레시피에 grid만 축소”가 아니다: non-uniform (quantile/learned) level을 더하고, outlier를 sparse FP16 side-band로 분리하고 (KVQuant), 그룹을 조이고, 최근 토큰 FP16 window를 유지한다 (KIVI). 교과서식 INT4는 거의 공짜지만, 2-bit는 연구 분야다.
sinks The first tokens are load-bearing첫 토큰들이 하중을 받치고 있다
Softmax needs somewhere to park attention mass, and it picks the first few positions — the “attention sink” effect (StreamingLLM). Their K vectors are also outlier-heavy. Quantizing them aggressively damages every future step's attention distribution, so implementations routinely keep the first handful of tokens (and the newest 32–128) in FP16. The overhead is constant while the cache grows linearly — at 4,096 tokens, a 128-token FP16 window costs 3% of the cache for most of the accuracy back. Softmax는 attention mass를 세워둘 곳이 필요하고, 처음 몇 개 위치를 고른다 — “attention sink” 효과다 (StreamingLLM). 이 토큰들의 K 벡터는 outlier도 많다. 이들을 공격적으로 quantize하면 이후 모든 스텝의 attention 분포가 손상되므로, 구현들은 으레 처음 몇 개 토큰을 (그리고 최신 32–128개를) FP16으로 유지한다. 캐시는 선형으로 자라는 반면 이 오버헤드는 상수다 — 4,096 토큰에서 128-토큰 FP16 window는 캐시의 3% 비용으로 정확도 대부분을 되찾는다.
The clicks showed what happens. Written as math, why is the error bounded — and by exactly how much?클릭으로 무엇이 일어나는지는 봤다. 수식으로 쓰면, 왜 오차가 유계이고 정확히 얼마인가?
§4The math on paper수식으로 다시 쓰기
You have clicked through the pipeline; now pin it down. Steps 2–4 of the explorer — group, scale, snap — compress into four lines you can carry away. 파이프라인을 클릭으로 통과했으니, 이제 못을 박자. explorer의 Step 2–4 — 그룹, scale, 스냅 — 는 들고 다닐 수 있는 네 줄로 압축된다.
Group-wise asymmetric INT4 stores, per group, 4-bit codes plus one FP16 scale and one
zero-point. The scale is s = (max − min) / 15 — the grid step; the zero-point
z = round(−min / s) is the code that decodes to zero. Encoding is
q = clamp(round(x/s) + z, 0, 15), decoding is x̂ = (q − z) · s.
Two properties do all the work: round-to-nearest bounds every element's error by
s/2 (0.038 in the worked group — check the table), and the asymmetric grid
hugs [min, max] so a skewed group wastes no codes. Nothing is learned; two reduction passes
and a rounding, cheap enough to run inline as tokens are generated.
Group-wise asymmetric INT4는 그룹마다 4-bit code와 FP16 scale 하나, zero-point 하나를
저장한다. scale은 s = (max − min) / 15 — grid 스텝이고, zero-point
z = round(−min / s)는 0으로 decode되는 code다. 인코딩은
q = clamp(round(x/s) + z, 0, 15), 디코딩은 x̂ = (q − z) · s.
두 성질이 모든 일을 한다: round-to-nearest는 모든 element의 error를
s/2로 유계 짓고 (위 그룹에서 0.038 — 표에서 확인), asymmetric grid는
[min, max]에 밀착해 치우친 그룹도 code를 낭비하지 않는다. 학습되는 것은 없다;
reduction 두 번과 rounding 한 번, 토큰이 생성되는 동안 인라인으로 돌 만큼 싸다.
Codes are 4 bits, but the scale and zero-point are extra bytes — what does the cache honestly cost now?code는 4 bit지만 scale과 zero-point는 추가 바이트다 — 이제 캐시의 정직한 비용은 얼마인가?
§5Packing and the honest byte count패킹과 정직한 바이트 계산
Integer codes are not yet bytes in HBM. Two bookkeeping details — nibble packing and the per-group header — decide the number you are allowed to quote. 정수 code가 곧 HBM의 바이트인 것은 아니다. 부기 항목 두 개 — nibble 패킹과 그룹당 header — 가 인용해도 되는 숫자를 결정한다.
Two codes per byte (low nibble = even channel), so 128 values pack into 64 B; the header adds 4 B. 68 B versus 256 B in FP16 is 3.76×, or 4.25 effective bits per value — the honest number to quote, since the scale/zero overhead is real traffic and real capacity. Group size is a dial: g = 32 costs a full extra bit per value but quantizes tighter slices; g = 128 pays 0.25 bit. Per token, the model's cache line shrinks from 512 KiB to 136 KiB. byte당 code 두 개 (low nibble = 짝수 channel), 그래서 128개 값이 64 B로 패킹되고 header가 4 B를 더한다. FP16의 256 B 대비 68 B는 3.76×, 즉 값당 4.25 effective bits — scale/zero 오버헤드는 실제 트래픽이자 실제 용량이므로 이것이 정직하게 인용할 숫자다. group size는 다이얼이다: g = 32는 값당 온전히 1 bit를 더 내는 대신 더 좁은 조각을 quantize하고, g = 128은 0.25 bit를 낸다. 토큰당 모델의 cache line은 512 KiB에서 136 KiB로 줄어든다.
Smaller at rest is nice — but the claim was faster. Where does the speed actually come from?저장이 작아지는 건 좋다 — 하지만 주장은 빨라진다였다. 속도는 실제로 어디서 오는가?
§6Deep water: why fewer bytes means faster깊은 물: 왜 바이트가 줄면 빨라지는가
This is the hardest section of the page — take it slowly. Everything so far was bookkeeping; this is the argument that turns bookkeeping into wall-clock time, and it is the argument the whole field stands on. 이 페이지에서 가장 어려운 섹션이다 — 천천히 가자. 지금까지는 전부 부기였다; 여기는 그 부기를 벽시계 시간으로 바꾸는 논증이고, 이 분야 전체가 딛고 선 논증이다.
Decode attention must read the K and V of every cached token to produce one new token: ~2 FLOPs per cached element against 2 bytes read. That is an arithmetic intensity of ~1 FLOP/B on hardware that breaks even near 200 — the definition of memory-bound, so runtime is bytes ÷ bandwidth and nothing else. Quantization cuts the bytes 3.76×; the added dequant is one fused multiply-add per element (~2.1 GFLOP per step at 4K context, ~30 µs) executed in registers while the next block streams in. You trade a millisecond of DRAM stall for microseconds of arithmetic. The same logic explains why weight-only quantization speeds up decode at batch 1: whenever the roofline says memory, compression is a latency optimization wearing a capacity costume. Decode attention은 새 토큰 하나를 만들기 위해 캐시된 모든 토큰의 K와 V를 읽어야 한다: 캐시된 element당 ~2 FLOPs에 2 byte 읽기. break-even이 200 근처인 하드웨어에서 arithmetic intensity ~1 FLOP/B — memory-bound의 정의 그 자체이므로, runtime은 bytes ÷ bandwidth이고 그 외의 어떤 것도 아니다. Quantization은 바이트를 3.76× 줄인다; 추가되는 dequant는 element당 fused multiply-add 하나로 (4K context에서 스텝당 ~2.1 GFLOP, ~30 µs), 다음 블록이 스트리밍되는 동안 register에서 실행된다. 1 밀리초의 DRAM stall을 수십 마이크로초의 산술과 맞바꾸는 셈이다. 같은 논리가 batch 1에서 weight-only quantization이 decode를 빠르게 하는 이유도 설명한다: roofline이 memory라고 말하는 한, 압축은 용량이라는 의상을 입은 latency 최적화다.
If INT4 is this close to free, why isn't everyone already at 2 bits — what breaks first?INT4가 이렇게 거의 공짜라면, 왜 모두가 이미 2 bit를 쓰지 않는가 — 무엇이 먼저 깨지는가?
§7The caveats that define the field이 분야를 정의하는 주의사항들
Because the clean picture assumed the values are tame — and real K tensors are not. Panel 7 of the explorer showed four failure modes; here is why they, together, are the map of the field. 깔끔한 그림은 값들이 얌전하다고 가정했기 때문이다 — 그리고 실제 K tensor는 그렇지 않다. explorer의 panel 7이 네 가지 failure mode를 보여줬다; 그 넷이 합쳐져 왜 이 분야의 지도가 되는지가 여기 있다.
The textbook recipe survives contact with K's outlier channels only if the grouping axis respects them (per-channel K, per-token V), survives long contexts only if sink and recent tokens keep full precision, and does not survive 2 bits without non-uniform levels or outlier side-bands. Those three caveats are, roughly, the table of contents of the post-2023 KV-quantization literature (KIVI, KVQuant, and their descendants). 교과서 레시피는 grouping 축이 K의 outlier channel을 존중할 때만 (per-channel K, per-token V) 그와의 접촉에서 살아남고, sink와 최근 토큰이 full precision을 유지할 때만 long context에서 살아남으며, non-uniform level이나 outlier side-band 없이는 2 bit에서 살아남지 못한다. 이 세 가지 주의사항이 대략 2023년 이후 KV-quantization 문헌의 목차다 (KIVI, KVQuant, 그리고 그 후손들).
Those exceptions were the 2023–24 papers. What is the field pushing on now?그 예외들이 2023–24년의 논문들이었다. 지금 이 분야는 무엇을 밀고 있는가?
§8Where this goes여기서 어디로 가는가
You can now read a KV-quantization paper the way its authors do: as a response to one of the caveats in §7, priced by the arithmetic of §5 and §6. Here is where the field is pushing. 이제 KV-quantization 논문을 저자들처럼 읽을 수 있다: §7의 주의사항 중 하나에 대한 응답으로, §5와 §6의 산술로 가격이 매겨진 것으로. 이 분야가 밀고 있는 방향은 다음과 같다.
The live frontier is below 4 bits. §7 said uniform grids die at 2 bits; the working answers so far are non-uniform levels plus sparse outlier side-bands (KVQuant), axis-aware grouping with a small FP16 residual window (KIVI), and — more recently — rotating the tensor before quantizing so outliers smear into ordinary coordinates (see the TurboQuant and LiftQuant reviews on this site). 살아 있는 최전선은 4 bit 아래다. §7에서 uniform grid는 2 bit에서 죽는다고 했다; 지금까지의 동작하는 답은 non-uniform level과 sparse outlier side-band (KVQuant), 작은 FP16 residual window를 곁들인 축 인식 grouping (KIVI), 그리고 — 더 최근에는 — quantize 전에 tensor를 회전시켜 outlier를 평범한 좌표로 번지게 하는 것이다 (이 사이트의 TurboQuant, LiftQuant 리뷰 참고).
Quantization is also only one lever on the same byte bill. Eviction keeps fewer tokens rather than cheaper ones (H2O); some heads need the full cache while others stream (DuoAttention); and architectural changes — GQA, MLA — shrink the cache before any compression runs. The open questions are old-fashioned ones: how these levers compose, and how to measure quality honestly, since long-context retrieval and multi-step reasoning degrade well before perplexity notices. Quantization은 같은 바이트 청구서에 대한 여러 레버 중 하나일 뿐이기도 하다. eviction은 토큰을 싸게 만드는 대신 더 적게 유지하고 (H2O), 어떤 head는 full cache가 필요하지만 다른 head는 streaming으로 충분하며 (DuoAttention), 아키텍처 변화 — GQA, MLA — 는 압축이 돌기 전에 캐시 자체를 줄인다. 열린 질문들은 고전적인 것들이다: 이 레버들이 어떻게 합성되는가, 그리고 품질을 어떻게 정직하게 측정하는가 — long-context retrieval과 multi-step reasoning은 perplexity가 눈치채기 한참 전에 무너지기 때문이다.
Going deeper더 깊이
Primary sources1차 자료
KIVI — Liu et al., 2024
Tuning-free 2-bit KV quantization; source of the per-channel-K / per-token-V asymmetry and the FP16 residual window.Tuning-free 2-bit KV quantization; per-channel-K / per-token-V 비대칭과 FP16 residual window의 출처.
arXiv 2401.18079KVQuant — Hooper et al., 2024
Non-uniform quantization levels plus sparse outlier isolation; what it takes to push below 3 bits at long context.Non-uniform quantization level과 sparse outlier 분리; long context에서 3 bit 아래로 내려가는 데 필요한 것들.
arXiv 2309.17453StreamingLLM — Xiao et al., 2023
Attention sinks: why the first tokens absorb attention mass and must be treated gently by any cache compression.Attention sink: 왜 첫 토큰들이 attention mass를 흡수하며, 어떤 cache compression이든 이들을 조심히 다뤄야 하는 이유.
arXiv 2211.05102Pope et al., 2022
Efficiently Scaling Transformer Inference — the memory-bound decode arithmetic this whole page rests on.Efficiently Scaling Transformer Inference — 이 페이지 전체가 기대고 있는 memory-bound decode 산술.