GPU 추론에 최적화된 AWQ와 GPTQ 양자화 기법의 원리, 차이점, 그리고 GGUF와의 비교를 통해 상황별 최적 양자화 전략을 제시합니다.
지난 3장에서 GGUF 포맷과 llama.cpp를 활용한 CPU 기반 추론을 살펴보았습니다. GGUF는 CPU 환경에서 뛰어난 범용성을 제공하지만, GPU를 갖춘 환경에서는 GPU에 최적화된 양자화 기법을 사용하는 편이 성능 면에서 유리합니다. 이번 장에서는 GPU 추론에 특화된 대표적인 양자화 기법인 GPTQ, AWQ, EXL2, 그리고 bitsandbytes NF4를 비교 분석합니다.
GPTQ(GPT Quantization)는 학습이 완료된 모델에 대해 사후적으로(post-training) 양자화를 적용하는 기법입니다. 핵심 아이디어는 가중치를 양자화할 때 발생하는 오차를 Hessian 행렬의 역행렬 정보를 활용하여 최소화하는 것입니다.
GPTQ는 OBQ(Optimal Brain Quantization) 알고리즘을 대규모 언어 모델에 맞게 확장한 기법입니다. 각 가중치를 양자화할 때, 해당 가중치의 중요도를 Hessian 행렬로부터 추정하고, 양자화 오차를 아직 양자화되지 않은 나머지 가중치에 보상(compensation)하는 방식으로 동작합니다.
from transformers import AutoModelForCausalLM, AutoTokenizer, GPTQConfig
model_id = "meta-llama/Llama-3.1-8B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_id)
# Calibration 데이터셋 준비 (128개 샘플 권장)
quantize_config = GPTQConfig(
bits=4, # 4비트 양자화
group_size=128, # 128개 가중치를 하나의 그룹으로
desc_act=True, # Activation order로 양자화 (정확도 향상)
dataset="c4", # Calibration 데이터셋
tokenizer=tokenizer,
)
model = AutoModelForCausalLM.from_pretrained(
model_id,
quantization_config=quantize_config,
device_map="auto",
)
model.save_pretrained("./llama-3.1-8b-gptq-4bit")desc_act=True 옵션은 활성화 크기 순서대로 가중치를 양자화하여 정확도를 높여주지만, 추론 속도가 다소 느려질 수 있습니다. 속도가 중요한 경우 desc_act=False로 설정하는 것이 일반적입니다.
GPTQ는 Calibration 데이터셋의 품질에 민감합니다. 실제 사용 도메인과 유사한 텍스트를 Calibration 데이터로 사용하면 양자화 품질이 크게 향상됩니다. 보통 128~256개의 샘플이면 충분합니다.
AWQ(Activation-aware Weight Quantization)는 MIT에서 제안한 기법으로, 모든 가중치가 동일하게 중요하지 않다는 관찰에서 출발합니다. 활성화(Activation) 분포를 분석하여 출력에 큰 영향을 미치는 **핵심 가중치(salient weights)**를 식별하고, 이 가중치들의 정밀도를 선택적으로 보존합니다.
AWQ는 다음과 같은 단계로 동작합니다.
GPTQ와의 결정적 차이점은 AWQ가 가중치 자체가 아닌 활성화 패턴을 기준으로 중요도를 판단한다는 것입니다. 이 접근 방식은 양자화 속도가 빠르고, Calibration 데이터에 대한 의존도도 상대적으로 낮습니다.
from awq import AutoAWQForCausalLM
from transformers import AutoTokenizer
model_id = "meta-llama/Llama-3.1-8B-Instruct"
quant_path = "./llama-3.1-8b-awq-4bit"
model = AutoAWQForCausalLM.from_pretrained(model_id)
tokenizer = AutoTokenizer.from_pretrained(model_id)
quant_config = {
"zero_point": True, # Zero-point 양자화
"q_group_size": 128, # 그룹 크기
"w_bit": 4, # 4비트 양자화
"version": "GEMM", # GEMM 커널 (범용) vs GEMV (배치 1 최적화)
}
model.quantize(tokenizer, quant_config=quant_config)
model.save_quantized(quant_path)
tokenizer.save_pretrained(quant_path)프로덕션 환경에서는 vLLM과 함께 AWQ 모델을 사용하는 것이 일반적입니다. vLLM은 AWQ 양자화 모델에 대한 네이티브 지원을 제공하며, PagedAttention과 결합하여 높은 처리량을 달성합니다.
from vllm import LLM, SamplingParams
llm = LLM(
model="./llama-3.1-8b-awq-4bit",
quantization="awq",
dtype="half",
gpu_memory_utilization=0.85,
max_model_len=4096,
)
sampling_params = SamplingParams(temperature=0.7, max_tokens=512)
outputs = llm.generate(["온디바이스 AI의 미래에 대해 설명해주세요."], sampling_params)
print(outputs[0].outputs[0].text)ExLlamaV2는 turboderp가 개발한 고성능 GPTQ 추론 엔진으로, 자체적인 양자화 포맷인 EXL2를 지원합니다. EXL2의 가장 큰 특징은 레이어별로 서로 다른 비트 수를 할당하는 혼합 정밀도(mixed-precision) 양자화를 지원한다는 점입니다.
예를 들어, 전체 모델을 평균 4.0비트로 양자화하되, 중요한 레이어에는 5비트를, 덜 중요한 레이어에는 3비트를 할당하는 방식입니다. 이를 통해 동일한 모델 크기에서 더 높은 품질을 달성할 수 있습니다.
EXL2는 목표 평균 비트 수를 소수점 단위(예: 3.5bpw, 4.65bpw)로 세밀하게 지정할 수 있어, VRAM 예산에 맞춰 최적의 품질-크기 균형을 찾기에 용이합니다.
bitsandbytes는 QLoRA 논문과 함께 등장한 라이브러리로, NF4(NormalFloat 4-bit) 양자화를 제공합니다. NF4는 정규 분포를 따르는 가중치에 최적화된 데이터 타입으로, 일반적인 4비트 정수 양자화보다 이론적으로 더 낮은 양자화 오차를 보입니다.
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
import torch
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4", # NF4 양자화
bnb_4bit_compute_dtype=torch.bfloat16, # 연산은 bfloat16
bnb_4bit_use_double_quant=True, # 이중 양자화 (메모리 추가 절약)
)
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-3.1-8B-Instruct",
quantization_config=bnb_config,
device_map="auto",
)bitsandbytes의 주요 장점은 별도의 양자화 과정 없이 로딩 시점에 즉시 양자화가 적용된다는 점입니다. 다만, GPTQ나 AWQ 대비 추론 속도는 느린 편이며, 주로 QLoRA 파인튜닝이나 빠른 프로토타이핑 용도로 사용됩니다.
각 양자화 기법은 고유한 강점과 약점을 가집니다. 다음 표는 주요 항목별로 비교한 결과입니다.
| 항목 | GGUF | GPTQ | AWQ | EXL2 | bitsandbytes |
|---|---|---|---|---|---|
| 주요 타겟 | CPU + GPU | GPU | GPU | GPU | GPU |
| 양자화 속도 | 빠름 | 느림 (수 시간) | 보통 (수십 분) | 느림 | 즉시 (로딩 시) |
| 추론 속도 | 보통 | 빠름 | 매우 빠름 | 매우 빠름 | 느림 |
| 품질 (4bit) | 좋음 | 매우 좋음 | 매우 좋음 | 가장 좋음 | 좋음 |
| Calibration | 불필요 | 필수 | 필수 | 필수 | 불필요 |
| 혼합 정밀도 | 제한적 | 지원 안 함 | 지원 안 함 | 완전 지원 | 지원 안 함 |
| vLLM 지원 | 제한적 | 지원 | 지원 | 미지원 | 미지원 |
양자화 품질 비교는 모델, 태스크, 벤치마크에 따라 달라질 수 있습니다. 위 표는 일반적인 경향을 나타내며, 실제 배포 전에는 반드시 자신의 유스케이스에 맞는 벤치마크를 수행해야 합니다.
양자화 기법의 선택은 운영 환경과 요구사항에 따라 달라집니다.
CPU 전용 또는 하이브리드 환경에서는 GGUF가 여전히 최선의 선택입니다. llama.cpp의 유연한 CPU/GPU 분할 기능은 VRAM이 부족한 환경에서 강력한 장점이 됩니다.
**GPU 서빙 환경(vLLM, TGI)**에서는 AWQ를 우선 고려합니다. 양자화 속도가 빠르고, 추론 성능이 우수하며, vLLM과의 호환성도 뛰어납니다. 최대 품질이 중요한 경우 GPTQ의 desc_act=True 옵션을 검토합니다.
VRAM 최적화가 극도로 중요한 경우 EXL2의 혼합 정밀도를 활용하여 평균 비트 수를 세밀하게 조절하는 것이 효과적입니다.
파인튜닝(QLoRA) 목적이라면 bitsandbytes NF4가 가장 간편한 선택입니다.
이번 장에서는 GPU 중심 양자화 기법들의 원리와 실전 활용법을 살펴보았습니다. 양자화 기법의 선택은 단순히 기술적 우열이 아니라, 배포 환경과 요구사항에 따른 트레이드오프 결정이라는 점을 기억해야 합니다.
다음 5장에서는 서버나 로컬 GPU 없이 웹 브라우저에서 직접 LLM을 추론하는 방법을 다룹니다. WebGPU와 WebLLM을 활용한 브라우저 내 AI 추론의 가능성과 한계를 살펴보겠습니다.
이 글이 도움이 되셨나요?
관련 주제 더 보기
WebGPU를 활용한 브라우저 내 LLM 추론의 원리, WebLLM과 MLC LLM의 아키텍처, 실전 구현, 그리고 브라우저 AI의 가능성과 한계를 다룹니다.
온디바이스 LLM 추론의 핵심인 GGUF 형식과 llama.cpp의 아키텍처, 설치와 사용법, 성능 최적화, 그리고 주요 프론트엔드 도구를 다룹니다.
iOS와 Android에서의 LLM 추론 기법 — Apple MLX, Core ML, MediaPipe, Qualcomm AI Engine, 그리고 모바일 AI 앱 개발 패턴을 다룹니다.