LLM 추론 최적화 - 양자화와 KV 캐시
LLM을 직접 서빙해보면 학습보다 추론(inference) 이 더 골치 아프다는 걸 금방 알게 됩니다. GPU 메모리는 순식간에 꽉 차고, 토큰은 느리게 나오고, 비용은 요청량에 비례해 불어납니다. 다행히 추론을 가볍게 만드는 두 가지 핵심 기술이 있습니다. 바로 양자화(Quantization) 와 KV 캐시(KV Cache) 입니다.
이 글에서는 추론이 왜 무거운지부터 시작해, 이 둘이 각각 무엇을 해결하는지, 그리고 배치·연속 배치 같은 서빙 기법과 실무 선택 기준까지 정리합니다.
1. LLM 추론은 왜 무거운가
LLM이 답을 만드는 과정은 토큰을 하나씩 순차적으로 생성하는 일입니다. "안녕하세요"를 만들려면 "안" → "녕" → ... 이렇게 한 토큰씩, 매번 모델 전체를 다시 통과시켜야 합니다.
여기서 두 가지 병목이 생깁니다.
- 메모리 병목: 70B 모델을 fp16으로 올리면 가중치만 약 140GB입니다. 여기에 실행 중 상태까지 더해져 GPU VRAM을 압박합니다.
- 대역폭 병목: 토큰 하나를 만들 때마다 수십~수백 GB의 가중치를 메모리에서 읽어와야 합니다. 연산보다 메모리에서 데이터를 옮기는 시간이 더 큽니다. 그래서 추론은 흔히 memory-bound 라고 부릅니다.
비유하자면, 요리 실력(연산)이 아니라 냉장고에서 재료를 꺼내오는 왕복 시간(메모리 이동) 이 전체 속도를 결정하는 상황입니다.
이 두 병목을 각각 공략하는 것이 양자화(메모리 크기)와 KV 캐시(중복 연산 제거)입니다.
2. 양자화 - 숫자를 더 적은 비트로
모델 가중치는 기본적으로 실수(float)입니다. 이 실수를 더 적은 비트로 표현해 용량과 대역폭을 줄이는 것이 양자화입니다.
| 정밀도 | 비트 | 상대 크기 | 특징 |
|---|---|---|---|
| fp32 | 32bit | 4배 | 학습 기본, 서빙엔 과함 |
| fp16 / bf16 | 16bit | 2배 | 추론 표준 |
| int8 | 8bit | 1배 | 품질 거의 유지, 흔한 선택 |
| int4 (4bit) | 4bit | 0.5배 | 메모리 최소, 품질 저하 감수 |
핵심 감각은 이렇습니다. fp16 → int8 로 가면 가중치 용량이 절반이 되고, 그만큼 메모리에서 읽어올 양도 줄어 속도도 빨라집니다. int4까지 내리면 소비자용 GPU에서도 큰 모델을 굴릴 수 있게 됩니다.
2-1. 품질 트레이드오프
공짜는 아닙니다. 비트를 줄이면 숫자를 표현하는 해상도가 낮아져 미세한 정보가 뭉개집니다.
- int8: 대부분의 작업에서 품질 손실이 거의 체감되지 않습니다. 실무 기본값으로 안전합니다.
- int4: 용량은 매력적이지만, 복잡한 추론·코딩에서 미묘하게 품질이 떨어질 수 있습니다.
그래서 실무에서는 정밀도를 무작정 낮추지 않고, 자신의 태스크로 직접 평가해서 허용 가능한 지점을 찾습니다. 요약 챗봇은 int4로 충분해도, 코드 생성은 int8을 유지하는 식입니다.
참고로 GPTQ, AWQ 같은 기법은 "품질에 덜 중요한 가중치는 과감히, 중요한 가중치는 보수적으로" 양자화해 4bit에서도 손실을 최소화합니다.
3. KV 캐시 - 이미 계산한 건 다시 안 한다
토큰을 하나 만들 때마다 모델은 지금까지의 모든 토큰을 다시 본다고 했습니다. 그런데 이전 토큰들에 대한 내부 계산 결과(어텐션의 )는 매번 똑같습니다. 매번 다시 계산하면 낭비죠.