15장. 모델 경량화: 양자화, 프루닝, 지식증류
우리 GPU 에 맞추기
트럭에 짐을 실을 때 짐만 생각하면 안 되고, 짐을 고정할 끈과 사람이 들어갈 틈도 남겨야 합니다. GPU 에는 가중치 말고도 KV 캐시와 계산 중간값이 들어갑니다. 특히 KV 캐시는 글이 길수록, 동시에 받는 사용자가 많을수록 커집니다.
네 카드는 GPU 메모리를 나눠 쓰는 것들입니다. 가중치는 모델 크기와 비트로 정해지고, KV 캐시는 층 수, 키·값의 크기, 글 길이, 동시 사용자 수에 비례하며, 계산 중간값과 여유는 프로그램과 드라이버가 씁니다. Ollama 는 모델이 다 들어가지 않으면 남는 층을 CPU 로 보냅니다. 여기서 끈과 틈이 KV 캐시와 여유입니다.
KV 캐시 어림
| 칸 | Qwen2.5-0.5B | Qwen2.5-3B |
|---|---|---|
| 층 수 | 24 | 36 |
| KV 머리 수 × 머리 크기 | 2 × 64 | 2 × 128 |
| 글 4,096토큰, fp16 의 KV 캐시 | 약 50MB | 약 151MB |
KV 캐시 계산하기
def kv_cache_mb(layers, kv_heads, head_dim, tokens, users=1, bytes_per=2):
"""키와 값(2) × 층 × KV 머리 × 머리 크기 × 토큰 × 사용자 × 바이트"""
return 2 * layers * kv_heads * head_dim * tokens * users * bytes_per / 1e6
print("0.5B, 4,096토큰:", round(kv_cache_mb(24, 2, 64, 4096)), "MB")
print("3B, 4,096토큰:", round(kv_cache_mb(36, 2, 128, 4096)), "MB · 사용자 8명:", round(kv_cache_mb(36, 2, 128, 4096, users=8)), "MB")코드에 나오는 함수
| 코드 | 쉬운 뜻 |
|---|---|
def kv_cache_mb(layers, kv_heads, head_dim, tokens, users=1, bytes_per=2): | 층 수, KV 머리 수, 머리 크기, 토큰 수, 사용자 수, 숫자 하나의 바이트로 KV 캐시를 MB 로 계산한다. users 와 bytes_per 는 주지 않으면 1, 2(fp16)를 쓴다 |
2 * layers * ... | 맨 앞의 2 는 키(Key)와 값(Value) 두 가지를 저장한다는 뜻이다 |
kv_heads, head_dim | KV 머리(head)의 수와 머리 하나의 크기(dimension, 차원)다 |
/ 1e6 | 바이트를 MB 로 바꾼다 |
users=8 | 인자 이름을 적어 사용자 수만 8 로 바꾼다 |
이 코드가 뜻하는 것
식당에서 손님마다 주문 메모지를 쌓아 두는 것에 견줄 수 있습니다. 메모지는 요리 단계(층)마다, 주문이 길수록(토큰), 손님이 많을수록(사용자) 늘어납니다. 여기서 메모지 더미가 KV 캐시입니다.
| 줄 | 하는 일 | 쉽게 말하면 |
|---|---|---|
return 2 * layers * kv_heads * head_dim * tokens * users * bytes_per / 1e6 | 모든 칸을 곱해 MB 로 바꾼다 | 단계 × 주문 길이 × 손님 수만큼 메모지 |
kv_cache_mb(24, 2, 64, 4096) | 0.5B 모델, 4,096토큰, 혼자 | 작은 식당, 손님 한 명 |
kv_cache_mb(36, 2, 128, 4096, users=8) | 3B 모델, 4,096토큰, 8명 | 큰 식당, 손님 여덟 명 |
결과는 0.5B 가 50MB, 3B 가 151MB, 3B 에 사용자 8명이면 1208MB 입니다. 사용자가 8배면 KV 캐시도 정확히 8배가 됩니다. 3B 를 4비트로 줄인 가중치(약 1.5GB)에 버금가는 크기입니다.
주의할 점
- 서비스에서는 동시 사용자 수만큼 KV 캐시가 늘어납니다. 혼자 시험할 때 들어갔다고 서비스에서도 들어간다는 보장은 없습니다(16장).
- 모델의 일부가 CPU 로 넘어가면 속도가 크게 떨어집니다.
ollama ps의 PROCESSOR 칸이 "100% GPU" 인지 봅니다.