모델 저장소에 -AWQ, -FP8, -GGUF가 줄줄이 붙어 있으면 무엇을 내려받아야 할지 막막하시죠? 결론부터 말하면 형식은 "어디서 돌리나"가 먼저 정하고, 그다음은 "가중치를 올리고 KV 캐시가 얼마나 남나"로 정해요. 맥·CPU·게임용 GPU라면 GGUF, Ada·Hopper 서버 GPU라면 FP8, 그보다 앞 세대 GPU이거나 메모리가 빠듯하면 AWQ·GPTQ 4비트가 기본값이에요. 품질은 8비트면 사실상 그대로, 4비트면 작은 모델일수록 눈에 띄게 떨어져요.
이 글은 양자화 수식 대신 고를 때 필요한 숫자만 다뤄요. 기준 모델은 네 형식을 공식 저장소에 모두 올려 둔 Qwen3-32B예요. 파일 크기는 Hugging Face 저장소에서 직접 합산했고, GPU 요금은 2026-10-26에 공식 가격표에서 확인했어요.
양자화 형식 한눈에 — 엔진과 GPU가 먼저 정해요
같은 4비트라도 GGUF는 llama.cpp 계열에서, AWQ·GPTQ는 vLLM·SGLang 같은 서버 엔진에서 제 속도가 나요. 형식은 "어느 엔진이 어느 GPU에서 빠르게 돌리나"의 문제예요.
vLLM 양자화 지원 하드웨어 표에서 고를 때 걸리는 칸만 추리면 이래요.
| 형식 | Volta (V100) | Turing (T4) | Ampere (A100·A10·A6000) | Ada (L4·L40S) | Hopper (H100) |
|---|---|---|---|---|---|
| AWQ | ✕ | ○ | ○ | ○ | ○ |
| GPTQ | ○ | ○ | ○ | ○ | ○ |
| FP8 W8A8 (llm-compressor) | ✕ | ✕ | ✕ | ○ | ○ |
| GGUF | ○ | ○ | ○ | ○ | ○ |
여기서 바로 갈리는 지점이 두 개 있어요.
- FP8 가중치·활성값 연산은 Ada·Hopper부터예요. A100은 FP8 연산 유닛이 없어요. Marlin 커널로 가중치만 FP8로 읽는 길은 있지만 4비트보다 읽는 양이 두 배예요.
- vLLM의 GGUF는 보조 수단이에요. vLLM GGUF 문서는 지원이 "매우 실험적이고 최적화가 덜 됐다"고 경고하고, 별도 플러그인이 필요해요.
같은 모델, 형식별 실제 파일 크기
"파라미터 수 × 비트 ÷ 8"로 어림하면 대개 모자라요. Qwen3-32B(파라미터 32.8B) 공식 저장소의 .safetensors·.gguf 크기를 합산했어요(10⁹바이트 = 1GB).
파일 크기를 파라미터 수로 나누면 파라미터당 실제 비트가 나와요.
| 형식 | 크기 | 파라미터당 실제 비트 | BF16 대비 |
|---|---|---|---|
| BF16 | 65.5GB | 15.98 | 100% |
| FP8 (128×128 블록 스케일) | 34.3GB | 8.37 | 52.4% |
| GGUF Q8_0 | 34.8GB | 8.49 | 53.1% |
| GGUF Q6_K | 26.9GB | 6.56 | 41.0% |
| GGUF Q5_K_M | 23.2GB | 5.66 | 35.4% |
| GGUF Q4_K_M | 19.8GB | 4.82 | 30.2% |
| AWQ (4비트, group 128) | 19.3GB | 4.71 | 29.5% |
AWQ 저장소의 config.json은 bits: 4, group_size: 128, FP8 저장소는 fmt: e4m3, weight_block_size: [128, 128], 활성값 dynamic이에요. 4비트인데 4.7비트가 나오는 건 128개마다 붙는 스케일·영점과, 임베딩처럼 16비트로 남는 텐서 몫이에요. VRAM을 어림할 땐 이름의 비트 대신 실제 파일 크기를 쓰세요.
llama.cpp 문서는 크기를 GiB로, 위 표는 GB로 적어요. 1GiB는 1.074GB라 숫자가 7% 다르게 보이니, 섞여 있으면 데이터 용량 변환기로 기준을 맞추세요.
남는 메모리가 동시 요청 수를 정해요
서빙 엔진은 가중치를 올리고 남은 메모리를 KV 캐시로 써요. 그 크기가 동시에 몇 명을 받을지 정해요.
Qwen3-32B의 config.json은 64층, KV 헤드 8개, 헤드 차원 128이에요. 토큰 하나의 KV 캐시는 2(K·V) × 64 × 8 × 128 × 2바이트 = 262,144바이트, 즉 256KiB예요. 32K 토큰 문맥 하나면 약 8.6GB예요.
남는 메모리는 vLLM gpu_memory_utilization 기본값 0.92에 맞춰 GPU 메모리의 92%에서 가중치와 활성값 몫 2GB(가정값)를 뺐어요. GPU 요금은 Lambda 가격표의 1장짜리 인스턴스 시간당 요금(세금 별도), 한 달은 730시간이에요.
| GPU (시간당 / 월) | 형식 | KV 캐시 자리 | 32K 요청 동시 수 | 요청 자리 1개당 월 비용 |
|---|---|---|---|---|
| H100 SXM 80GB ($4.29 / 약 $3,132) | BF16 | 약 6.1GB | 0.7개 | 약 $4,427 |
| 〃 | FP8 | 약 37.3GB | 4.3개 | 약 $722 |
| 〃 | AWQ | 약 52.3GB | 6.1개 | 약 $515 |
| A100 40GB ($1.99 / 약 $1,453) | AWQ | 약 15.5GB | 1.8개 | 약 $806 |
| A6000 48GB ($1.09 / 약 $796) | AWQ | 약 22.8GB | 2.7개 | 약 $299 |
| A10 24GB ($1.29 / 약 $942) | AWQ | 약 0.8GB | 0.1개 | 사실상 불가 |
표에서 읽을 점은 이래요.
- BF16 32B는 H100 한 장에 "들어가기만" 해요. 32K 요청 하나도 다 못 담아요.
- FP8로 바꾸면 받는 요청이 약 6배예요. 품질 손실이 가장 작은 형식이라 H100이 있다면 첫 선택지예요.
- A6000 + AWQ가 요청 자리당 가장 싸요. 다만 HBM을 쓰는 H100과 달리 GDDR6 메모리라 대역폭이 낮아서, 한 명이 체감하는 속도는 느려요. 사내 도구에 맞아요.
- 24GB 카드에 32B 4비트는 무리예요. KV 캐시 자리가 없어서 14B 이하 모델이 맞아요.
KV 캐시 자체도 줄일 수 있어요. vLLM 양자화 KV 캐시 문서의 kv_cache_dtype="fp8"을 쓰면 KV가 절반이 되어 H100 FP8 구성의 32K 동시 요청이 약 8.7개로 늘어요. 문서는 보정 데이터로 스케일을 구하는 방식을 권장해요. 자세한 계산은 vLLM KV 캐시 용량 계산에 정리해 두었어요.
속도 — 파일이 작은 만큼 빨라지진 않아요
생성 단계는 대개 가중치를 읽는 시간이 병목이라 이론상 속도는 파일 크기에 반비례해요. H100 SXM의 대역폭은 NVIDIA 사양표 기준 3.35TB/s이니, 배치 1의 초당 토큰 상한은 BF16 약 51, FP8 약 98, AWQ 약 173이에요.
실측은 Qwen 공식 속도 벤치마크에 있어요. NVIDIA H20 96GB, SGLang, 배치 1로 2,048토큰을 생성했고, 입력 1토큰 조건은 생성 속도로 읽으면 돼요.
AWQ는 파일이 FP8보다 훨씬 작은데 속도는 비슷했어요. 4비트를 곱하기 직전에 16비트로 푸는 비용이 이득 일부를 먹어요.
프롬프트가 길어지면 순위가 바뀌어요. 같은 표의 Qwen3-32B 값이에요(속도 = 입력+출력 토큰 ÷ 걸린 시간).
| 입력 길이 | FP8 | AWQ | AWQ ÷ FP8 |
|---|---|---|---|
| 1토큰 | 46.17 | 47.67 | 1.03 |
| 6,144토큰 | 165.71 | 159.99 | 0.97 |
| 30,720토큰 | 436.59 | 366.84 | 0.84 |
| 63,488토큰 | 532.18 | 425.23 | 0.80 |
| 129,042토큰 | 491.45 | 395.96 | 0.81 |
긴 프롬프트를 처리하는 단계는 읽기보다 계산이 병목이라, FP8 행렬곱을 그대로 쓰는 FP8이 유리해요. RAG·긴 문서 요약처럼 입력이 긴 서비스라면 FP8, 짧은 질문에 짧게 답하는 챗봇이라면 AWQ도 손해가 없어요.
llama.cpp 쪽도 같은 경향이에요. llama.cpp quantize 문서의 Llama-3.1-8B 표에서 생성 속도(128토큰)는 F16 29.17, Q8_0 50.93, Q6_K 58.67, Q4_K_M 71.93토큰/초예요. 파일은 3.27배 작아졌는데 속도는 2.47배예요. 프롬프트 처리(512토큰)는 오히려 약 11% 느려졌어요(923.49 → 821.81). 측정 장비가 적혀 있지 않으니 비율만 참고하세요.
품질 — 몇 비트까지 내려도 되나
품질 손실은 모델과 평가마다 달라요. 공개된 측정 두 가지로 방향만 잡아요.
첫째, llama.cpp perplexity 문서의 Llama 3 8B 점수표예요(RTX 4090, Wikitext-2). FP16 대비 퍼플렉서티가 몇 % 나빠졌는지 계산했어요.
같은 문서에는 "원본과 1순위 토큰이 같은 비율"도 있어요. Q8_0 97.7%, Q6_K 96.0%, Q4_K_M 91.9%, Q2_K 71.1%예요. Q4_K_M이면 100번 중 8번꼴로 원본과 다른 토큰을 1순위로 골라요.
같은 Q4_K_M도 Llama 2 7B는 1.4%, Llama 3 8B는 2.8% 나빠졌어요. 모델마다 견디는 정도가 달라요.
둘째, Qwen 공식 양자화 성능표예요. Qwen3용은 "업데이트 예정"이라 Qwen2 결과예요(MMLU·C-Eval·IFEval 평균).
| 모델 | BF16 | GPTQ-Int8 | GPTQ-Int4 | AWQ |
|---|---|---|---|---|
| Qwen2-72B-Instruct | 81.3 | 80.7 | 81.2 | 80.4 |
| Qwen2-7B-Instruct | 66.9 | 66.2 | 64.1 | 64.1 |
| Qwen2-1.5B-Instruct | 48.4 | 48.1 | 45.0 | 46.5 |
72B는 4비트로 내려도 0.1~0.9점 차이인데, 7B는 2.8점이 빠져요. 큰 모델은 4비트로, 작은 모델은 8비트나 6비트로가 무난한 출발점이에요.
GGUF는 imatrix(중요도 행렬) 판이 있으면 그쪽을 쓰세요. 파일 크기는 같은데 Q4_K_M 악화율이 2.82%에서 2.43%로, Q2_K는 56.5%에서 38.8%로 줄었어요.
상황별 추천 — 어떤 형식을 어디에
| 상황 | 추천 | 이유 |
|---|---|---|
| 맥북·데스크톱에서 혼자 쓰기 | GGUF Q4_K_M (여유 있으면 Q5_K_M·Q6_K) | llama.cpp 계열이 잘 돌고 악화율 3% 안쪽 |
| H100·L40S, 긴 입력(RAG·문서 요약) | FP8 | 품질 손실이 가장 작고, 3만 토큰 넘는 입력에서 AWQ가 16~20% 느렸어요 |
| H100, 짧은 질의응답·동시 요청 많음 | AWQ 또는 FP8 + FP8 KV 캐시 | AWQ는 KV 자리를 가장 많이 남기고, FP8 KV면 FP8도 요청 수가 두 배 |
| A100·A10·A6000 같은 Ampere | AWQ·GPTQ 4비트 | FP8 W8A8 연산이 없어요 |
| 7B 이하 작은 모델 | 8비트(FP8·Q8_0) 또는 Q6_K | 4비트에서 점수 하락이 커요 |
| 원본 품질이 계약 조건 | BF16, GPU 장수 늘리기 | 32B는 H100 두 장부터 현실적이에요 |
지연을 더 줄이려면 투기적 디코딩을 겹칠 수 있고, MoE 모델은 MoE 모델 VRAM·비용 계산처럼 전체 파라미터로 메모리를 잡아야 해요.
도입 체크리스트
- 엔진과 GPU 세대부터 확인해요. vLLM 지원 표에서 형식 × GPU 칸이 ○인지 봐요. Ampere에 FP8 W8A8은 안 돼요.
- 공식 양자화본부터 찾아요. 직접 만들면 보정 데이터를 서비스 입력과 비슷하게 골라야 해요.
- VRAM은 실제 파일 크기로 계산해요. 파라미터 × 4 ÷ 8로 어림하면 Qwen3-32B에서 16.4GB가 나와 실제(19.3~19.8GB)보다 15% 넘게 모자라요.
- KV 캐시 몫을 계산해요. 동시 요청 수 × 문맥 길이 × 토큰당 KV 바이트가 남은 메모리에 들어가야 해요.
- 입력 길이별로 속도를 재요. 짧은 입력과 가장 긴 입력에서 초당 토큰·첫 토큰 지연을 기록해요.
- 자기 평가 세트로 BF16과 나란히 돌려요. 숫자·코드·한국어가 섞인 정답 있는 문제로요.
- 생성 설정을 다시 맞춰요. Qwen3 AWQ 모델 카드는 양자화 모델에서 끝없는 반복을 막으려면
presence_penalty를 1.5로 두라고 강하게 권해요.
자주 묻는 질문
FP8과 AWQ 중 무엇이 더 빠른가요?
Qwen 공식 측정에서 배치 1·짧은 입력이면 Qwen3-32B 기준 AWQ 47.67, FP8 46.17토큰/초로 비슷했어요. 입력이 3만 토큰을 넘으면 AWQ가 FP8보다 16~20% 느렸어요. 대신 AWQ는 파일이 작아 KV 캐시 자리가 더 남아요.
4비트 모델이면 VRAM이 원본의 4분의 1이면 되나요?
아니요. Qwen3-32B 기준 AWQ는 원본의 29.5%, Q4_K_M은 30.2%예요. 스케일과 16비트로 남는 텐서 때문에 파라미터당 4.7~4.8비트가 돼요. 여기에 KV 캐시와 활성값 메모리가 따로 들어요.
GGUF 파일을 vLLM 서버에서 써도 되나요?
돌아가긴 하지만 vLLM 문서가 "매우 실험적"이라고 적었고 별도 플러그인이 필요해요. 서버에서는 같은 모델의 AWQ·GPTQ·FP8 판이 속도와 기능 호환에서 나아요.
Q4_K_M과 Q5_K_M 중 무엇을 받아야 하나요?
메모리가 남으면 Q5_K_M이에요. llama.cpp의 Llama 3 8B 측정에서 퍼플렉서티 악화가 Q4_K_M 2.82%, Q5_K_M 0.91%였고, 파일은 Qwen3-32B 기준 19.8GB와 23.2GB로 3.4GB 차이예요. 문맥을 길게 쓸 거라 KV 캐시 자리가 아쉬우면 Q4_K_M(imatrix 판)이 균형이 좋아요.
정리
- 형식은 엔진과 GPU가 먼저 정해요. 로컬은 GGUF, Ada·Hopper 서버는 FP8, Ampere나 메모리가 빠듯한 서버는 AWQ·GPTQ예요.
- VRAM은 실제 파일 크기로, 동시 요청 수는 남는 KV 캐시로 계산해요. Qwen3-32B를 H100 한 장에 올리면 32K 요청이 BF16 0.7개, FP8 4.3개, AWQ 6.1개예요.
- 속도는 파일 크기만큼 빨라지지 않아요. 짧은 입력에선 FP8·AWQ가 비슷하고, 긴 입력에선 FP8이 앞서요.
- 품질은 8비트면 사실상 그대로, 4비트는 큰 모델에서 무난하고 작은 모델에서 눈에 띄게 떨어져요. 마지막 판단은 자기 평가 세트로 하세요.
더 깊이 읽기
이 글은 실무에서 판단할 때 필요한 것 위주로 정리했어요. 같은 주제의 내부 동작 원리는 devboi 기술 블로그의 LLM 양자화 원리 — INT8·INT4·GGUF, GPTQ·AWQ에서 도식과 코드로 단계별로 풀었어요.