Field Log · Entry

저정밀 LLM 추론: FP8·INT8·INT4·FP4 Kernel과 Calibration (8/10)

BF16에서 W8A8·W4A16·W4A8KV4·FP8·FP4로 정밀도를 낮추며 scale, outlier, fused GEMM, 정확도와 SLO gate를 비교하는 저정밀 LLM 추론 구조

오늘의 결론

  • “4-bit model”이라는 이름만으로는 시스템을 설명할 수 없습니다. Weight·activation·KV cache·accumulator·collective의 dtype과 scale 단위를 각각 적어야 합니다.
  • 이론상 byte 감소는 출발점입니다. Pack·unpack, scale·zero-point, padding, dequantization, layout conversion이 fused kernel 안에 들어가지 않으면 더 작은 model이 오히려 느릴 수 있습니다.
  • INT4 weight-only는 decode의 weight bandwidth를 줄이기 좋은 현실적 시작점이고, W8A8·FP8은 activation까지 낮춰 GEMM fast path를 노립니다. FP4는 더 세밀한 block scale과 hardware·kernel 일치가 특히 중요합니다.
  • Calibration은 대표 문장 몇 개를 통과시키는 의식이 아닙니다. Production prompt·언어·도메인·context length·tool JSON을 층화하고, tensor별 range와 quality regression을 재현 가능한 artifact로 남기는 과정입니다.
  • Release 기준은 checkpoint size가 아니라 실제 resident byte + TTFT·ITL SLO goodput + task quality입니다. Quantization recipe와 kernel·GPU 조합을 하나의 배포 단위로 버전 관리합니다.

앞 글에서는 model을 여러 rank에 나누고 collective와 topology를 설계했습니다. 이번 글은 각 rank에서 weight·activation·KV byte를 줄이되, 실제 low-precision kernel과 서비스 품질까지 연결하는 방법을 다룹니다.

production tensors
  → choose W / A / KV / accumulator precisions
  → collect representative ranges
  → select scale granularity and outlier policy
  → quantize, pack, and lay out for the target kernel
  → verify numerical quality and real memory
  → benchmark SLO goodput on the target GPU

이 글에서 답하는 질문

  1. INT quantization의 scale·zero-point·group size는 실제 byte와 오차를 어떻게 바꾸는가?
  2. FP8의 E4M3·E5M2와 FP4의 block scaling은 무엇이 다른가?
  3. W4A16, W8A8, W4A8KV4는 어떤 병목을 줄이는가?
  4. GPTQ·AWQ·SmoothQuant·rotation은 어떤 outlier 문제를 다루는가?
  5. 작은 checkpoint가 실제 GPU에서 빨라지지 않는 이유는 무엇인가?
  6. RAG Agent 품질과 SLO를 함께 지키는 calibration·release gate는 어떻게 만드는가?

BF16 tensor에서 INT8·INT4·FP8·FP4 표현과 scale 단위를 선택하고 calibration, outlier 처리, packing을 거쳐 aligned fused kernel fast path와 fallback dequantization 경로를 비교한 뒤 실제 memory, task quality, TTFT·ITL goodput으로 release하는 저정밀 LLM 추론 파이프라인

그림 1. Quantization은 파일 변환이 아니라 숫자 형식·scale metadata·packed layout·kernel·quality gate의 계약이다. 저장 byte만 줄고 target kernel이 열리지 않으면 service gain은 실현되지 않는다.


1. 먼저 “무엇을” 낮췄는지 쓴다

다음 표기는 서로 다른 시스템입니다.

표기WeightActivationKV cache대표 목적
BF1616-bit16-bit16-bitBaseline·넓은 지원
W8A8INT8/FP8INT8/FP8별도GEMM compute·memory 감소
W4A16INT4FP16/BF16별도Weight bandwidth·capacity 감소
W4A8INT4INT8/FP8별도Weight와 activation 모두 감소
W4A8KV4INT4INT8INT4Weight·GEMM·long-context KV 동시 최적화

Accumulator는 보통 input보다 넓은 형식을 사용합니다. LayerNorm, softmax, residual add, logits도 별도 precision일 수 있습니다. 따라서 “INT4 추론” 대신 다음처럼 manifest를 적습니다.

linear: W4A8 → accumulate INT32/FP32 → output BF16 or FP16
attention KV: INT4 with per-group scales
norm / softmax / logits: BF16 or FP32 as configured
collective payload: BF16

2. Uniform Integer Quantization

실수 xb-bit integer q로 바꾸는 기본 형태는 다음과 같습니다.

$$ q=\operatorname{clamp}\left(\operatorname{round}\left(\frac{x}{s}\right)+z, q_{min}, q_{max}\right) $$

$$ \hat{x}=s(q-z) $$

  • s: scale
  • z: zero-point
  • q_min, q_max: integer 표현 범위
  • : 복원된 근삿값

Signed INT8은 보통 256개 code, INT4는 16개 code만 사용합니다. Bit가 줄수록 한 scale이 담당하는 값의 범위를 작게 만들거나 outlier를 별도로 처리해야 오차를 줄일 수 있습니다.

3. Symmetric과 Asymmetric

Symmetric

Zero-point를 0으로 두고 절댓값 최대치에 맞춥니다.

$$ s=\frac{\max(|x|)}{q_{max}} $$

연산과 metadata가 단순하고 GEMM kernel에 유리합니다. 그러나 분포가 한쪽으로 치우치면 code range 일부를 낭비합니다.

Asymmetric

관측한 최소·최대 범위를 이용해 scale과 zero-point를 둡니다. 비대칭 분포를 더 촘촘히 표현할 수 있지만 zero-point 보정과 metadata가 추가됩니다.

Weight에는 symmetric, KV처럼 분포 특성이 다른 tensor에는 asymmetric가 유리할 수 있습니다. 정답은 tensor 이름이 아니라 target kernel과 측정 오차가 함께 결정합니다.

4. Scale Granularity가 핵심이다

한 scale이 담당하는 범위가 작을수록 local range에 잘 맞지만 metadata와 reduction이 늘어납니다.

coarse                                      fine
per-tensor → per-channel → per-row/token → per-group/block
metadata ↓          quantization error ↓          kernel complexity ↑

Per-tensor

Tensor 전체가 scale 하나를 공유합니다. Outlier 하나가 나머지 값을 좁은 code range에 몰아넣을 수 있습니다.

Per-channel

Weight output 또는 input channel마다 scale을 둡니다. Channel별 범위 차이를 흡수하면서도 정적 weight에 미리 계산할 수 있습니다.

Per-token / Per-row

Runtime activation의 각 token row에 scale을 계산합니다. 동적 범위에 적응하지만 amax reduction과 scale 적용이 critical path가 될 수 있습니다.

Per-group / Per-block

예를 들어 weight 128개마다 scale 하나를 둡니다. INT4 정확도를 높이기 좋지만 group size와 GEMM tile·packed layout이 맞아야 합니다.

5. “4-bit”의 실제 Bit 수

Group size G, element bit b, group당 scale metadata m bit라면 padding과 zero-point를 제외한 effective bit는:

$$ b_{eff}=b+\frac{m}{G} $$

INT4 weight 128개마다 FP16 scale 하나면:

$$ 4+\frac{16}{128}=4.125\ \text{bits/weight} $$

Zero-point, tensor header, row alignment, shard padding, duplicated scales가 더해집니다. Model file size가 아니라 device에 올라온 packed weight와 metadata allocation을 측정합니다.

6. Clipping은 Range와 Resolution의 교환이다

Outlier까지 모두 포함하면 saturation은 줄지만 대부분 값의 quantization step이 커집니다. 반대로 percentile이나 error objective로 range를 자르면 중심부는 정밀해지지만 큰 값이 clamp됩니다.

wide range  → few clipped outliers, coarse steps for common values
narrow range → fine common values, more saturated outliers

Calibration은 단순 max(abs(x)) 수집을 넘어 clipping threshold가 downstream error에 미치는 영향을 탐색할 수 있습니다.

7. FP8은 작은 Floating Point다

FP8도 8-bit지만 INT8과 range 배치가 다릅니다.

형식SignExponentMantissa성격
E4M3143더 많은 유효 정밀도, 상대적으로 좁은 범위
E5M2152더 넓은 동적 범위, 더 거친 정밀도

Micikevicius 등의 FP8 형식 제안은 E4M3와 E5M2를 구분합니다. 단, special value와 최대값의 세부 encoding은 구현 variant에 따라 달라질 수 있으므로 dtype 이름과 engine 정의를 artifact에 고정해야 합니다.

FP8은 exponent 덕분에 INT8보다 값 크기 변화에 유연하지만 scale이 필요 없다는 뜻은 아닙니다. Tensor range를 FP8 representable range에 배치하는 scaling recipe가 여전히 중요합니다.

8. FP8 Scale Recipe

Current Scaling

현재 tensor의 amax로 scale을 계산합니다. 최신 범위를 반영하지만 reduction·synchronization 비용이 생깁니다.

Delayed Scaling

이전 step의 amax history로 다음 scale을 정합니다. Scale 계산을 pipeline하기 쉽지만 갑작스러운 분포 변화에 margin과 history policy가 필요합니다.

Block Scaling

Tensor를 작은 block으로 나눠 각각 scale을 둡니다. Per-tensor outlier 영향을 줄이는 대신 scale metadata와 layout constraint가 증가합니다.

x_real ≈ x_fp8 × scale_block
scale_block = amax_block / max_representable_fp8

공식 Transformer Engine 문서의 blockwise recipe처럼 block shape·scale type·power-of-two 제약은 hardware generation과 library revision에 따라 다릅니다.

9. E4M3와 E5M2를 이름만으로 고르지 않는다

E4M3는 같은 8-bit 안에서 mantissa가 하나 더 있어 일반적으로 forward의 weight·activation에 유리하고, E5M2는 exponent가 하나 더 있어 넓은 range가 필요한 tensor에 쓰일 수 있습니다. 그러나 inference에서 어떤 operand와 output이 native kernel을 지원하는지는 GPU와 library가 결정합니다.

확인할 계약:

  • Input A·B format과 scale mode
  • Accumulator·output dtype
  • Per-tensor 또는 block scale shape
  • Transpose 시 scale layout
  • Saturation·NaN handling
  • GEMM epilogue와 bias·activation fusion

10. FP4는 Element보다 Block Format을 본다

대표 FP4 element인 E2M1은 sign 1, exponent 2, mantissa 1 bit를 사용합니다. Code가 매우 적어 element 단독 표현력보다 몇 개 element가 어떤 scale을 공유하는가가 중요합니다.

OCP MX specification은 MXFP4 같은 microscaling format을 정의합니다. MX 계열은 block element와 shared scale을 하나의 data format으로 봅니다. NVFP4처럼 vendor-specific recipe는 같은 E2M1 element를 사용해도 block size와 scale 계층이 다를 수 있습니다.

따라서 다음은 같은 의미가 아닙니다.

FP4 element type
MXFP4 block format
NVFP4 scaling recipe
arbitrary software-packed 4-bit float

Checkpoint의 label만 보고 kernel 호환성을 가정하지 않습니다.

11. Weight-only INT4: W4A16

Weight를 INT4로 저장하고 activation은 BF16/FP16으로 유지합니다.

packed INT4 weights
  → load fewer bytes
  → unpack / dequantize with scales
  → multiply with BF16/FP16 activations
  → accumulate and write output

Decode의 작은 batch GEMM은 weight load가 병목이기 쉬워 W4A16이 효과적인 시작점입니다. Activation과 KV는 그대로이므로 prefill compute나 long-context KV capacity가 같은 비율로 줄지는 않습니다.

12. GPTQ가 최적화하는 것

GPTQ는 calibration activation에서 얻은 approximate second-order information을 이용해 weight를 순차 quantize하고, 앞선 quantization error를 남은 weight에 보상하는 one-shot PTQ 방법입니다.

직관적으로 단순 nearest rounding보다 layer output reconstruction error에 민감한 방향을 고려합니다. 하지만 다음은 별개입니다.

  • Quantized checkpoint의 정확도
  • Target engine이 이해하는 group·packing format
  • GPU에서 실행되는 실제 kernel

GPTQ label이 붙어 있어도 runtime이 매번 큰 BF16 buffer로 dequantize하면 memory capacity만 얻고 latency는 잃을 수 있습니다.

13. AWQ는 중요한 Weight를 Activation으로 찾는다

AWQ는 activation 관측으로 salient weight channel을 식별하고 per-channel scaling을 탐색하는 weight-only PTQ입니다. 원 논문은 극소수의 salient weight를 보호하는 것이 중요하다는 관찰에서 출발합니다.

Calibration data에 backpropagation으로 맞추는 방식은 아니지만 activation statistics를 사용하므로 calibration workload의 대표성은 여전히 중요합니다. Instruction·한국어·산업 용어 분포가 production과 다르면 protected channel 선택도 달라질 수 있습니다.

14. W8A8은 Activation Outlier를 만난다

Weight와 activation을 모두 8-bit로 낮추면 low-precision tensor core GEMM을 사용할 가능성이 커지고 activation traffic도 줄어듭니다. 하지만 LLM activation에는 일부 channel의 매우 큰 값이 나타날 수 있습니다.

Per-tensor INT8 scale 하나가 큰 outlier에 맞춰지면 일반 값은 몇 개 code에 몰립니다. Per-token·per-channel scale은 오차를 줄이지만 kernel과 metadata 비용이 늘어납니다.

15. SmoothQuant의 등가 변환

SmoothQuant는 activation의 quantization difficulty를 offline weight 쪽으로 이동합니다. Linear layer Y=XW에 diagonal scale S를 넣으면:

$$ Y=(XS^{-1})(SW) $$

수학적 output은 같지만 activation channel의 큰 값을 줄이고 weight channel 범위를 키울 수 있습니다. S는 calibration statistics와 smoothing strength에서 정해져 static weight에 fold됩니다.

핵심은 “outlier 제거”가 아니라 같은 함수 안에서 quantization하기 쉬운 operand로 range를 재배치하는 것입니다. 그 뒤 W8A8 GEMM kernel이 실제로 사용돼야 성능 이득이 완성됩니다.

16. Mixed-precision Outlier Path

LLM.int8()는 outlier feature를 higher precision 경로로 분리하고 나머지를 INT8로 계산하는 관점을 제시했습니다.

common channels  → INT8 GEMM
outlier channels → FP16/BF16 side path
sum partial outputs

정확도는 지킬 수 있지만 side path가 불규칙하거나 비율이 커지면 launch와 gather overhead가 커집니다. Outlier threshold, side-path density, fused support를 profile합니다.

17. Rotation은 Outlier를 퍼뜨린다

QuaRot은 model function을 보존하는 rotation을 적용해 hidden-state outlier를 여러 dimension으로 분산시키고 end-to-end W4A4·KV4 quantization을 가능하게 하는 방향을 보였습니다.

Rotation은 coarse scale 하나에 걸린 극단값 문제를 줄일 수 있지만 공짜가 아닙니다.

  • 정적 rotation을 weight에 fold할 수 있는가?
  • Online rotation이 어떤 kernel에 fusion되는가?
  • Attention·RoPE·KV layout과 정확히 호환되는가?
  • Distributed shard 사이 추가 collective가 생기는가?

논문의 quality result와 production engine의 realized speedup을 분리해 검증합니다.

18. KV Cache Quantization은 별도 문제다

Weight는 request 사이에 공유되는 정적 tensor지만 KV는 request·layer·token마다 증가하는 동적 state입니다.

weight quantization:
  offline statistics → pack once → reuse across requests

KV quantization:
  generate every token → compute scales → write packed KV
  → read/dequantize inside attention every future step

KV4는 capacity와 attention memory bandwidth를 줄이지만 scale 계산·pack write·attention dequant가 매 request critical path에 들어갑니다.

19. Key와 Value는 같은 Scale 단위가 아닐 수 있다

KIVI는 Key cache와 Value cache의 분포가 다르다는 관찰에서 asymmetric 2-bit quantization을 제안했습니다. 논문은 Key에는 per-channel, Value에는 per-token granularity를 사용합니다.

이 예가 주는 일반 원칙은 명확합니다.

같은 “KV cache”라도 K와 V의 outlier axis를 측정한 뒤 granularity를 고른다.

GQA·RoPE·head dimension·residual window가 바뀌면 분포와 kernel layout도 다시 확인합니다.

20. QServe의 W4A8KV4가 보여 주는 것

QServe는 algorithm만 낮은 bit로 바꾸지 않고 W4A8KV4와 GPU kernel을 함께 설계합니다. 원 논문은 기존 INT4 경로에서 dequantization이 큰 runtime overhead가 될 수 있음을 지적하고, progressive quantization·weight reordering·register-level optimization과 KV4 attention을 결합합니다.

중요한 교훈은 특정 speedup 숫자가 아니라 다음 식입니다.

realized gain
  = byte reduction + native low-bit throughput
  - scale / pack / dequant / reorder / padding overhead
  - accuracy recovery and fallback cost

21. 모든 연산을 같은 Bit로 낮추지 않는다

다음은 높은 precision에 남기는 후보입니다.

  • Embedding·LM head
  • LayerNorm·RMSNorm statistics
  • Softmax와 attention score reduction
  • Residual accumulation
  • 최종 logits와 sampling probability
  • 첫·마지막 layer 또는 sensitivity가 큰 projection
  • Adapter merge·dynamic LoRA path

“예민한 layer” 목록을 관습으로 복사하지 말고 layerwise error·ablation으로 결정합니다.

22. Accumulator Precision

Input이 4-bit여도 dot product에는 많은 항이 더해집니다. Accumulator까지 좁으면 rounding·overflow가 누적됩니다.

input storage: INT4 / FP4 / INT8 / FP8
multiply path: hardware-specific
accumulator: INT32 / FP16 / BF16 / FP32
output cast: scaled FP8/INT8 or BF16/FP16

Kernel 문서에서 input dtype만 보지 말고 accumulation mode, reduction order, output scale과 epilogue를 확인합니다. Tensor parallel all-reduce가 어느 dtype으로 전달·누적되는지도 별도 계약입니다.

23. Fused Kernel이 성능을 결정한다

느린 경로:

packed W4 in HBM
  → standalone unpack kernel
  → materialize BF16 weights in HBM
  → ordinary BF16 GEMM
  → separate bias / activation kernel

빠른 경로:

load packed W4 + scales into tile
  → dequantize in register/shared-memory path
  → tensor-core-compatible MMA
  → fused epilogue
  → write output once

두 경로는 checkpoint 크기가 같아도 HBM traffic과 launch 수가 완전히 다릅니다.

24. Kernel Eligibility Checklist

Low-bit kernel은 shape와 layout에 조건이 있습니다.

  • GPU compute capability가 해당 dtype·MMA를 지원하는가?
  • M/N/K, head dimension, group size가 tile alignment를 만족하는가?
  • Weight packing order가 kernel이 기대하는 order인가?
  • TP shard 뒤 dimension도 alignment를 유지하는가?
  • Scale tensor가 contiguous하고 기대 shape인가?
  • Bias·activation·LoRA epilogue가 fusion되는가?
  • Small batch와 large prefill에 각각 다른 kernel이 선택되는가?
  • Unsupported shape에서 어떤 fallback이 발생하는가?

Profiler trace에 kernel name, input dtype, tensor shape, fallback reason을 남깁니다.

25. Padding도 실제 Memory와 Compute다

Hidden dimension 11008을 kernel tile 128에 맞추려고 padding하면 quantized zero라도 저장·load·compute할 수 있습니다. TP shard별로 다시 padding되면 전체 overhead가 커질 수 있습니다.

logical bytes
  = elements × nominal bits / 8

resident bytes
  = padded packed data
  + scales / zero-points
  + reordered copies
  + dequant workspace
  + graph and communication buffers

2편의 memory ledger에 logical과 resident를 따로 기록합니다.

26. Prefill과 Decode의 이득은 다르다

Decode

작은 M의 GEMM은 weight bandwidth가 지배하기 쉬워 W4 weight-only의 byte 감소가 바로 도움이 될 수 있습니다. 긴 KV를 읽는 attention에는 KV precision이 중요합니다.

Prefill

큰 token batch의 GEMM은 compute-bound가 될 수 있어 activation까지 낮춘 native W8A8·FP8·FP4 MMA가 유리할 수 있습니다. Weight-only dequant overhead가 compute gain을 상쇄할 수도 있습니다.

따라서 같은 recipe를 다음 shape에서 따로 benchmark합니다.

prefill: M = 128, 1K, 8K tokens
decode:  M = active sequences 1, 8, 32, 128
context: 1K, 8K, 32K, 128K KV

27. Distributed Inference에서 Dtype 경계

앞 글의 TP·PP·EP에 quantization을 더하면 경계가 늘어납니다.

  • Rank별 weight scale이 같은 global channel을 의미하는가?
  • Reduce-scatter 전 output은 어떤 dtype인가?
  • Collective payload를 FP8로 낮추면 scale을 rank마다 또는 group마다 공유하는가?
  • PP activation send 전에 quantize하고 받은 뒤 dequantize하는가?
  • EP all-to-all token의 scale metadata는 함께 이동하는가?
  • P/D KV transfer가 packed form을 보존하는가?

통신 byte를 줄여도 quantize/dequantize와 scale synchronization이 exposed되면 ITL이 악화됩니다.

28. CUDA Graph와 Dynamic Scale

Activation·KV의 current scale은 runtime reduction과 metadata update를 요구할 수 있습니다. Captured graph에서 pointer·workspace·shape가 안정적인지 확인합니다.

Graph-friendly 후보

  • Static quantized weight와 preallocated scale
  • Fixed bucket shape
  • Device-side scale update
  • Capture 가능한 fused quantize/GEMM op

Graph break 후보

  • Host가 읽는 amax
  • Token마다 달라지는 allocation
  • Unsupported shape의 JIT compilation
  • Rare outlier fallback의 다른 control flow

Quantization 적용 전후 graph coverage와 launch 수를 비교합니다.

29. Calibration Dataset을 설계한다

Calibration sample은 production traffic의 작은 복제본이어야 합니다.

포함할 구간
언어한국어·영어·혼합·코드
Prompt 길이짧은 질의·일반 RAG·긴 문서
Output 형태자연어·JSON·코드·citation
도메인일반·반도체·PHM·사내 약어
Agent 단계계획·검색·tool call·검증·요약
난이도일반·수치 계산·long-tail entity
Safety거절·민감 정보·권한 오류

Random public text만 쓰면 production outlier와 구조화 output failure를 놓칩니다. 개인정보는 원문 저장 대신 승인된 redaction·synthetic replay policy를 사용합니다.

30. Calibration은 Holdout 평가가 아니다

한 데이터로 scale을 고르고 같은 데이터에서 품질을 보고하면 과적합을 감지하기 어렵습니다.

calibration split
  → range, clipping, smoothing, scale selection

quality holdout
  → perplexity / tasks / RAG / tools / long context

load replay
  → real shapes, memory, TTFT, ITL, goodput

Model family·revision·tokenizer·prompt template가 바뀌면 calibration artifact를 새로 만듭니다.

31. Quantization Artifact Manifest

model:
  id: "<model>"
  revision: "<sha>"
  tokenizer_revision: "<sha>"
recipe:
  weights: int4
  activations: int8
  kv_cache: int4
  accumulator: int32
  group_size: 128
  symmetric: true
  algorithm: "<gptq|awq|smoothquant|custom>"
calibration:
  dataset_revision: "<sha>"
  samples: "<count>"
  token_histogram: "<artifact>"
  clipping_policy: "<policy>"
runtime:
  engine_commit: "<sha>"
  kernel_pack_format: "<version>"
  gpu_arch: "<target>"
  fallback_policy: "fail-closed"
quality:
  report: "<artifact>"
performance:
  report: "<artifact>"

Quantized weight만 배포하지 말고 이를 해석하는 recipe와 engine version을 함께 서명·보존합니다.

32. Numerical Error를 Layer부터 본다

End-task 점수가 떨어졌을 때 전체 model만 보면 원인을 찾기 어렵습니다.

Tensor-level

  • Saturation ratio
  • Zero ratio·code utilization
  • Scale·amax histogram
  • MSE·cosine similarity
  • Outlier channel·token 비율

Layer-level

  • BF16 대비 output cosine·relative error
  • Attention logits·softmax divergence
  • Residual error accumulation
  • Layer별 mixed-precision ablation

Model-level

  • Perplexity
  • Knowledge·reasoning·code task
  • Long-context retrieval
  • Structured output validity

Layer error가 작아도 autoregressive step마다 누적될 수 있으므로 실제 generation을 평가합니다.

33. RAG Agent 품질 Gate

일반 benchmark 평균만 통과해도 Agent 계약은 깨질 수 있습니다.

  • Retrieval query rewriting의 entity·숫자 보존
  • Citation source ID 정확도
  • 근거 없는 답변의 abstention
  • Tool name·argument JSON exact match
  • Decimal·단위·날짜 계산
  • Multi-turn state reference
  • Long retrieved context의 needle recall
  • Safety·ACL 관련 거절 일관성
  • Parallel branch 결과의 merge 판단

특히 logits의 작은 변화가 JSON delimiter, tool 선택, citation ID를 바꿀 수 있습니다. Field별 exact-match와 semantic quality를 모두 둡니다.

34. 8B Model 사고 실험

8B parameter dense model의 이상적인 weight byte만 보면:

BF16: 8B × 2 bytes   ≈ 16 GB
INT8: 8B × 1 byte    ≈ 8 GB
INT4: 8B × 0.5 byte  ≈ 4 GB

그러나 INT4 deployment 총량은 4GB가 아닙니다.

total resident
  = packed W4 + scales + padding / reordered copies
  + KV cache dtype and capacity
  + activations + workspaces
  + CUDA graph pools + communication buffers

Weight가 12GB 줄어도 더 큰 batch·context로 KV가 그 공간을 채웁니다. 절약된 byte를 어떤 goodput으로 바꿀지 scheduler 설정까지 함께 변경합니다.

35. Benchmark Matrix

Baseline

  • 동일 model·tokenizer·prompt template
  • BF16 또는 검증된 FP16 engine
  • 같은 scheduler·parallelism·memory reservation

Recipe Sweep

  • W8A8 INT8
  • FP8 tensorwise·blockwise
  • W4A16 GPTQ·AWQ
  • W4A8와 KV8·KV4 조합
  • FP4 native path가 있는 target에서만 FP4

Shapes

  • Prompt·output joint distribution
  • Batch와 active sequence sweep
  • Short·long context
  • Dense·MoE·adapter workload

Measure

  • Packed·resident·peak memory
  • Prefill time·TTFT
  • Decode step·ITL
  • Input/output token/s와 SLO goodput/GPU
  • Kernel별 time·fallback count
  • Power·energy·cost per accepted request
  • Quality holdout와 RAG Agent contract

Checkpoint마다 scheduler를 고정한 비교와, 절약된 memory를 활용해 각각 최적화한 deployment 비교를 둘 다 제공합니다.

36. Quantization 선택 순서

  1. BF16 baseline의 weight·KV·activation·workspace byte를 측정합니다.
  2. Prefill은 compute, decode는 weight·KV 중 무엇이 병목인지 분리합니다.
  3. Target GPU와 engine의 native low-bit kernel matrix를 확인합니다.
  4. W·A·KV·accumulator precision을 각각 명시합니다.
  5. Scale granularity와 group size가 kernel tile에 맞는지 확인합니다.
  6. Production-stratified calibration set과 독립 holdout을 고정합니다.
  7. GPTQ·AWQ·SmoothQuant·rotation 등 필요한 error-control만 선택합니다.
  8. Packed file과 resident allocation의 실제 byte를 측정합니다.
  9. Profiler에서 fused kernel과 fallback reason을 확인합니다.
  10. Prefill·decode·long-context shape를 따로 benchmark합니다.
  11. Distributed collective·KV transfer dtype 경계를 검증합니다.
  12. RAG Agent quality와 SLO goodput을 함께 release gate로 사용합니다.

실전 체크리스트

  • W·A·KV·accumulator·collective precision을 각각 적었다.
  • Symmetric/asymmetric와 scale·zero-point 식을 알고 있다.
  • Per-tensor·channel·token·group 중 granularity를 근거로 골랐다.
  • Scale·zero-point·padding을 포함한 effective bit를 계산했다.
  • FP8 variant와 scale recipe를 engine version에 고정했다.
  • FP4 element·block format·vendor recipe를 구분했다.
  • Weight-only가 activation·KV까지 줄이지 않는다는 점을 반영했다.
  • Activation과 KV outlier axis를 실제 tensor에서 측정했다.
  • Calibration과 quality holdout을 분리했다.
  • Production 언어·도메인·길이·tool format이 calibration에 포함됐다.
  • Layer별 saturation·cosine·mixed-precision ablation을 저장했다.
  • Packed layout과 TP shard alignment를 확인했다.
  • 실제 profiler에서 fused low-bit kernel을 확인했다.
  • Dequantized full-weight temporary allocation이 없는지 확인했다.
  • Prefill·decode·long context를 별도로 benchmark했다.
  • Dynamic scale 적용 후 CUDA Graph coverage를 확인했다.
  • Distributed collective와 P/D KV transfer dtype을 적었다.
  • Resident·peak memory를 allocator 기준으로 측정했다.
  • RAG citation·tool JSON·숫자·abstention regression을 통과했다.
  • Peak token/s가 아니라 SLO goodput/GPU로 release했다.

스스로 확인하기

Q1. INT4 checkpoint가 BF16보다 네 배 작으면 네 배 빨라지는가?

아닙니다. Weight byte의 이론상 비율일 뿐입니다. Scale·padding·packing이 추가되고, unpack·dequant가 fused되지 않거나 target shape가 kernel 조건을 벗어나면 latency gain이 사라질 수 있습니다. Activation·KV·workspace도 그대로일 수 있습니다.

Q2. W4A16과 W4A8은 무엇이 다른가?

W4A16은 weight만 4-bit로 저장하고 activation 계산은 주로 16-bit를 유지합니다. W4A8은 activation까지 8-bit로 낮춰 native low-precision GEMM을 노리지만 activation range와 outlier 처리, scale 계산이 추가됩니다.

Q3. FP8이면 calibration이 필요 없는가?

아닙니다. Exponent가 있어 INT8보다 range가 유연하지만 tensor 값을 representable range에 배치하는 scale recipe가 필요합니다. Static PTQ라면 대표 range를 수집하고, dynamic scaling이라면 amax policy와 runtime overhead를 검증해야 합니다.

Q4. KV cache는 weight와 같은 group quantization을 쓰면 되는가?

반드시 그렇지 않습니다. KV는 token마다 생성되고 attention에서 반복해서 읽히며 K와 V의 outlier 축도 다를 수 있습니다. KIVI처럼 Key per-channel, Value per-token이 유리한 사례가 있으므로 model·RoPE·head layout에서 다시 측정합니다.

Q5. Quantization 품질은 perplexity 하나면 충분한가?

아닙니다. RAG Agent는 citation ID, tool JSON, 숫자·단위, abstention처럼 작은 logit 변화에도 깨지는 이산 계약이 있습니다. 일반 task와 함께 실제 generation 기반 field-level regression을 통과해야 합니다.

다음 글

이번 글은 한 worker가 더 적은 byte와 빠른 kernel로 request를 처리하게 했습니다. 다음 글 LLM Serving SLO 운영: Admission Control·Fairness·Autoscaling에서는 burst와 tenant 경쟁 속에서 TTFT·ITL deadline을 지키도록 요청을 받아들이고, queue와 replica를 제어하는 방법을 다룹니다.

참고문헌

검증 메모 — 개념과 문헌은 2026년 7월 16일 확인했습니다. Low-precision dtype·scale mode·packing·native kernel 지원은 GPU architecture와 engine revision에 따라 빠르게 달라집니다. 본문의 bit·group·shape는 원리를 설명하는 예시값이며 target model·hardware에서 resident memory, profiler fast path, RAG Agent quality와 TTFT·ITL SLO goodput을 다시 측정해야 합니다.