Skip to content
Published on

LLM 양자화 기법 비교 가이드 — GPTQ, AWQ, GGUF, bitsandbytes 실전 적용

Authors
  • Name
    Twitter
LLM 양자화 기법 비교 가이드

들어가며

70B 파라미터 LLM을 FP16으로 로딩하면 약 140GB의 VRAM이 필요하다. A100 80GB 2장으로도 빠듯하며, 추론 비용은 시간당 수십 달러에 달한다. 하지만 **양자화(Quantization)**를 적용하면 동일한 모델을 단일 GPU에서 운용할 수 있고, 추론 속도도 2~4배 향상된다. INT4 양자화를 적용하면 70B 모델이 약 35GB로 줄어 A100 한 장에 올릴 수 있다.

2024~2026년 사이 양자화 기법은 급격히 발전했다. GPTQ, AWQ, GGUF, bitsandbytes 등 다양한 방법이 등장했고, 각각 정확도-속도-메모리의 트레이드오프가 다르다. 이 글에서는 각 기법의 원리를 깊이 분석하고, 실전 코드와 벤치마크를 통해 상황별 최적의 선택지를 안내한다.

양자화의 필요성과 기본 원리

왜 양자화가 필요한가

LLM의 파라미터 수가 기하급수적으로 늘어나면서, 모델을 로딩하고 추론하는 데 필요한 GPU 메모리와 연산 비용이 핵심 병목이 되었다. 양자화는 모델 가중치의 수치 정밀도를 낮춰 메모리 사용량을 줄이고, 연산 속도를 높이는 기법이다.

FP32에서 INT4까지의 데이터 타입 변환

양자화란 높은 정밀도의 부동소수점(FP32/FP16) 가중치를 낮은 비트의 정수(INT8/INT4)로 변환하는 과정이다. 비트 수가 줄어들수록 메모리 절감은 크지만, 표현할 수 있는 값의 범위와 정밀도가 감소한다.

데이터 타입비트 수표현 범위70B 모델 메모리품질 영향
FP3232bit약 +/-3.4 x 10^38~280GB기준 (100%)
FP16/BF1616bit약 +/-6.5 x 10^4~140GB거의 동일
INT88bit-128 ~ 127~70GB2% 미만 손실
INT44bit-8 ~ 7~35GB2~8% 손실

핵심은 정밀도 손실을 최소화하면서 비트 수를 줄이는 것이다. 단순히 반올림하면 정확도가 크게 떨어지므로, 각 양자화 기법은 오차를 보상하는 고유한 전략을 사용한다.

양자화의 기본 수학

가장 기본적인 양자화 방식인 Absmax와 Zero-Point 양자화를 살펴보자.

import torch
import numpy as np

def absmax_quantize(tensor: torch.Tensor, bits: int = 8) -> tuple:
    """Absmax 양자화: 절대 최대값 기준 대칭 스케일링"""
    qmax = 2 ** (bits - 1) - 1  # INT8이면 127, INT4이면 7
    scale = tensor.abs().max() / qmax
    quantized = torch.round(tensor / scale).clamp(-qmax, qmax).to(torch.int8)
    return quantized, scale

def zeropoint_quantize(tensor: torch.Tensor, bits: int = 8) -> tuple:
    """Zero-Point 양자화: 비대칭 분포 대응"""
    qmin = -(2 ** (bits - 1))
    qmax = 2 ** (bits - 1) - 1
    scale = (tensor.max() - tensor.min()) / (qmax - qmin)
    zero_point = qmin - torch.round(tensor.min() / scale)
    quantized = torch.round(tensor / scale + zero_point).clamp(qmin, qmax).to(torch.int8)
    return quantized, scale, zero_point

# 예시: 양자화 오차 비교
weight = torch.randn(4096, 4096, dtype=torch.float32)
q_abs, scale_abs = absmax_quantize(weight, bits=4)
restored_abs = q_abs.float() * scale_abs
error_4bit = (weight - restored_abs).abs().mean()

q_abs8, scale_abs8 = absmax_quantize(weight, bits=8)
restored_abs8 = q_abs8.float() * scale_abs8
error_8bit = (weight - restored_abs8).abs().mean()

print(f"INT8 평균 양자화 오차: {error_8bit:.6f}")
print(f"INT4 평균 양자화 오차: {error_4bit:.6f}")
# INT8 평균 양자화 오차: 0.003127
# INT4 평균 양자화 오차: 0.048915

PTQ vs QAT: 양자화 시점에 따른 분류

양자화는 적용 시점에 따라 크게 두 가지로 나뉜다.

PTQ (Post-Training Quantization)

학습이 완료된 모델에 양자화를 적용하는 방식이다. 추가 학습이 필요 없어 빠르고 간편하지만, 극단적인 저비트(3bit 이하)에서는 품질 손실이 클 수 있다. GPTQ, AWQ, GGUF 변환이 모두 PTQ에 해당한다.

  • 장점: 추가 학습 불필요, 빠른 적용, 기존 모델 활용
  • 단점: 극단적 저비트에서 품질 저하 가능

QAT (Quantization-Aware Training)

학습 과정에서 양자화를 시뮬레이션하여, 모델이 양자화된 환경에 적응하도록 훈련하는 방식이다. PTQ보다 높은 품질을 유지할 수 있지만, 전체 학습 파이프라인이 필요해 비용이 크다.

  • 장점: PTQ 대비 우수한 품질 유지, 극단적 저비트에서도 효과적
  • 단점: 전체 학습 파이프라인 필요, 높은 연산 비용
비교 항목PTQQAT
적용 시점학습 후학습 중
소요 시간수 분~수 시간수 일~수 주
품질 유지4bit까지 양호2~3bit에서도 양호
적용 난이도낮음높음
대표 기법GPTQ, AWQ, RTNEfficientQAT, BitNet

실무에서는 대부분 PTQ를 사용한다. QAT는 모델을 처음부터 학습하거나, 극단적 압축이 필요한 경우에 고려한다.

GPTQ: Hessian 기반 레이어별 최적 양자화

원리

GPTQ(Generative Pre-trained Transformer Quantization)는 2022년 Frantar 등이 제안한 PTQ 기법으로, OBQ(Optimal Brain Quantization) 알고리즘을 대규모 모델에 효율적으로 적용할 수 있도록 개선한 것이다.

핵심 아이디어는 다음과 같다:

  1. 레이어별 처리: 모델의 각 레이어를 독립적으로 양자화한다
  2. 열(column) 단위 순차 처리: 가중치 행렬의 열을 순차적으로 양자화하며, 양자화 오차를 아직 처리하지 않은 열로 보상한다
  3. Hessian 기반 오차 보상: 2차 근사(Hessian 행렬)를 이용해 양자화가 레이어 출력에 미치는 영향을 최소화하도록 나머지 가중치를 조정한다
  4. Lazy Batch 업데이트: 128개 열을 한 배치로 처리해 GPU 연산 효율을 높인다

실전 적용: AutoGPTQ

from transformers import AutoModelForCausalLM, AutoTokenizer
from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig

# 1. 원본 모델 로딩
model_id = "meta-llama/Llama-3.1-8B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_id)

# 2. 양자화 설정
quantize_config = BaseQuantizeConfig(
    bits=4,                   # 4bit 양자화
    group_size=128,           # 128개 가중치 단위로 스케일 공유
    desc_act=True,            # Activation order 사용 (정확도 향상)
    damp_percent=0.1,         # Hessian 안정화를 위한 댐핑 비율
    sym=True,                 # 대칭 양자화
)

# 3. 캘리브레이션 데이터 준비 (128~256 샘플 권장)
calibration_data = [
    tokenizer(text, return_tensors="pt", max_length=2048, truncation=True)
    for text in calibration_texts[:128]
]

# 4. 양자화 실행
model = AutoGPTQForCausalLM.from_pretrained(
    model_id, quantize_config=quantize_config
)
model.quantize(calibration_data)

# 5. 양자화된 모델 저장
model.save_quantized("./llama-3.1-8b-gptq-4bit")
tokenizer.save_pretrained("./llama-3.1-8b-gptq-4bit")

GPTQ 장단점

구분내용
장점GPU 추론 최적화, Marlin 커널로 741 tok/s 달성, HuggingFace 생태계 통합
단점양자화 시간이 길다(8B 모델 기준 1~2시간), 캘리브레이션 데이터 품질에 민감
적합한 경우GPU 서버 기반 프로덕션 서빙, vLLM 배포

AWQ: 활성화 기반 가중치 양자화

원리

AWQ(Activation-aware Weight Quantization)는 MIT의 Han 연구진이 2023년에 제안한 기법이다. 핵심 통찰은 모든 가중치가 동등하게 중요하지 않다는 것이다.

AWQ는 활성화(activation) 분포를 관찰하여 중요한 가중치 채널을 식별한다. 전체 가중치의 약 1%만이 모델 출력에 결정적인 영향을 미치며, 이 1%의 **돌출 가중치(salient weights)**를 보호하면 양자화 품질을 크게 향상시킬 수 있다.

GPTQ와의 핵심 차이점:

  1. 가중치 중요도 판별: GPTQ는 Hessian 행렬(2차 정보)로 오차를 보상하지만, AWQ는 활성화 크기를 기준으로 중요한 가중치를 식별한다
  2. 스케일링 기반 보호: 중요한 채널에 스케일 팩터를 적용해 양자화 오차를 줄인다
  3. 캘리브레이션 강건성: AWQ는 캘리브레이션 데이터와 평가 도메인이 달라도 성능 저하가 적다 (퍼플렉시티 증가 0.50.6 vs GPTQ의 2.34.9)

실전 적용: AutoAWQ

from awq import AutoAWQForCausalLM
from transformers import AutoTokenizer

# 1. 모델 및 토크나이저 로딩
model_id = "meta-llama/Llama-3.1-8B-Instruct"
model = AutoAWQForCausalLM.from_pretrained(model_id)
tokenizer = AutoTokenizer.from_pretrained(model_id)

# 2. AWQ 양자화 설정
quant_config = {
    "zero_point": True,       # Zero-Point 양자화 사용
    "q_group_size": 128,      # 그룹 크기
    "w_bit": 4,               # 4bit 양자화
    "version": "GEMM",        # GEMM 커널 사용 (범용)
    # "version": "Marlin",    # Marlin 커널 (A100/H100에서 최적)
}

# 3. 양자화 실행 (GPTQ보다 빠름)
model.quantize(tokenizer, quant_config=quant_config)

# 4. 저장
model.save_quantized("./llama-3.1-8b-awq-4bit")
tokenizer.save_pretrained("./llama-3.1-8b-awq-4bit")

GPTQ vs AWQ 품질 비교

항목GPTQ (4bit)AWQ (4bit)
Llama-2-70B 퍼플렉시티3.423.41
HumanEval Pass@146.0%51.8%
캘리브레이션 도메인 불일치 시 퍼플렉시티 증가+2.3~4.9+0.5~0.6
양자화 소요 시간 (8B 모델)1~2시간10~20분
Marlin 커널 출력 처리량712 tok/s741 tok/s

AWQ가 전반적으로 더 높은 품질을 유지하면서 양자화 속도도 빠르다. 특히 캘리브레이션 데이터 강건성에서 큰 차이를 보인다.

GGUF: llama.cpp 생태계의 범용 포맷

원리

GGUF(GPT-Generated Unified Format, 원래 Georgi Gerganov Unified Format)는 양자화 알고리즘이 아니라 양자화된 모델을 저장하는 파일 포맷이다. llama.cpp의 개발자 Georgi Gerganov가 설계했으며, 모델 아키텍처 정보, 토크나이저, 양자화 파라미터, 가중치를 단일 파일에 패키징한다.

GGUF 포맷의 양자화 타입은 다양하다:

양자화 타입비트 수8B 모델 크기품질권장 용도
Q2_K2bit~2.5GB낮음극단적 메모리 제약
Q3_K_M3bit~3.3GB보통메모리 제한 환경
Q4_K_M4bit~4.1GB양호범용 권장
Q5_K_M5bit~4.8GB우수품질 중시
Q6_K6bit~5.5GB매우 우수고품질 필요 시
Q8_08bit~7.0GB최상품질 최우선

Q4_K_M과 Q5_K_M이 가장 많이 사용된다. K-Quant 방식은 레이어별로 다른 정밀도를 적용해 핵심 레이어(attention의 value, FFN의 down projection 등)에 더 높은 비트를 할당한다.

실전 적용: llama.cpp로 GGUF 변환

# 1. llama.cpp 빌드
git clone https://github.com/ggml-org/llama.cpp
cd llama.cpp
cmake -B build -DLLAMA_CUDA=ON  # GPU 가속 활성화
cmake --build build --config Release -j$(nproc)

# 2. HuggingFace 모델을 GGUF FP16으로 변환
python convert_hf_to_gguf.py \
    ./models/Llama-3.1-8B-Instruct/ \
    --outfile ./models/llama-3.1-8b-f16.gguf \
    --outtype f16

# 3. Q4_K_M 양자화 적용
./build/bin/llama-quantize \
    ./models/llama-3.1-8b-f16.gguf \
    ./models/llama-3.1-8b-Q4_K_M.gguf \
    Q4_K_M

# 4. (선택) Importance Matrix를 활용한 고품질 양자화
# 먼저 imatrix 데이터 생성
./build/bin/llama-imatrix \
    -m ./models/llama-3.1-8b-f16.gguf \
    -f calibration_data.txt \
    -o imatrix.dat

# imatrix 기반 양자화
./build/bin/llama-quantize \
    --imatrix imatrix.dat \
    ./models/llama-3.1-8b-f16.gguf \
    ./models/llama-3.1-8b-Q4_K_M-imat.gguf \
    Q4_K_M

# 5. 여러 양자화 타입 일괄 생성
for QTYPE in Q4_K_M Q5_K_M Q6_K Q8_0; do
    ./build/bin/llama-quantize \
        ./models/llama-3.1-8b-f16.gguf \
        "./models/llama-3.1-8b-${QTYPE}.gguf" \
        ${QTYPE}
    echo "완료: ${QTYPE}"
done

GGUF 장단점

구분내용
장점CPU/Apple Silicon 지원, 단일 파일 배포, GPU 오프로딩 가능, Ollama/LM Studio 호환
단점GPU 전용 서빙에서는 GPTQ/AWQ보다 느림, 양자화 알고리즘 자체의 정교함은 떨어짐
적합한 경우로컬 환경 추론, CPU 기반 서빙, 엣지 디바이스 배포

bitsandbytes: 온더플라이 양자화

원리

bitsandbytes는 Tim Dettmers가 개발한 라이브러리로, 모델 로딩 시점에 실시간으로 양자화를 수행한다. 사전 양자화 체크포인트가 필요 없다는 것이 가장 큰 장점이다.

핵심 기술인 **NF4(Normalized Float 4)**는 정규분포를 따르는 가중치에 대해 정보 이론적으로 최적인 4비트 데이터 타입이다. QLoRA 논문에서 소개되었으며, 양자화된 모델에 LoRA 파인튜닝을 적용하는 데 핵심적으로 사용된다.

실전 적용

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig

# 1. 4-bit 양자화 설정 (NF4 + Double Quantization)
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,                    # 4bit 양자화 활성화
    bnb_4bit_quant_type="nf4",            # NF4 데이터 타입 (FP4 대비 우수)
    bnb_4bit_compute_dtype=torch.bfloat16, # 연산은 BF16으로 수행
    bnb_4bit_use_double_quant=True,        # 이중 양자화 (0.4bit 추가 절감)
)

# 2. 양자화된 모델 로딩 (사전 양자화 체크포인트 불필요!)
model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-3.1-8B-Instruct",
    quantization_config=bnb_config,
    device_map="auto",
)
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3.1-8B-Instruct")

# 3. 8-bit 양자화도 간단히 적용 가능
bnb_config_8bit = BitsAndBytesConfig(
    load_in_8bit=True,
    llm_int8_threshold=6.0,   # 아웃라이어 탐지 임계값
)

model_8bit = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-3.1-8B-Instruct",
    quantization_config=bnb_config_8bit,
    device_map="auto",
)

# 4. QLoRA 파인튜닝을 위한 설정 예시
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training

model = prepare_model_for_kbit_training(model)

lora_config = LoraConfig(
    r=16,
    lora_alpha=32,
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
)

model = get_peft_model(model, lora_config)
print(f"학습 가능 파라미터: {model.print_trainable_parameters()}")

bitsandbytes 장단점

구분내용
장점사전 양자화 불필요, HuggingFace 완벽 통합, QLoRA 지원, 가장 낮은 퍼플렉시티 손실(6.67 vs 기준 6.56)
단점추론 속도 느림(168 tok/s), GPU 전용, 서빙 프레임워크 호환성 제한
적합한 경우파인튜닝(QLoRA), 빠른 프로토타이핑, 연구/실험

종합 벤치마크 비교

주요 지표 비교 (Llama-3.1-8B, H200 GPU 기준)

지표FP16 (기준)GPTQ 4bitAWQ 4bitGGUF Q4_K_Mbitsandbytes 4bit
퍼플렉시티6.566.826.716.746.67
HumanEval Pass@156.1%46.0%51.8%49.5%50.2%
출력 처리량 (tok/s)67712 (Marlin)741 (Marlin)320 (GPU)168
VRAM 사용량16.0GB5.2GB5.1GB5.0GB (GPU)5.8GB
양자화 소요 시간-1~2시간10~20분5~10분0분 (즉시)
CPU 추론 지원XXXOX
파인튜닝 지원O제한적제한적XO (QLoRA)

품질 보존율 비교

기법품질 보존율메모리 절감주요 강점
AWQ95%75%최고 품질 + 최고 속도
GGUF Q4_K_M92%75%CPU/GPU 유연성
bitsandbytes93%70%즉시 적용 + QLoRA
GPTQ90%75%GPU 서빙 최적화

모델 크기별 양자화 영향

모델이 클수록 양자화에 의한 품질 손실이 적다.

모델 크기4bit 양자화 퍼플렉시티 증가권장 최소 비트
1~3B8~15%6bit 이상
7~8B3~8%4bit
13B2~5%4bit
30~34B1~3%4bit
65~70B1~2%3~4bit

실무 양자화 적용 가이드

단계 1: 용도별 기법 선택

용도 판별
  |
  +-- GPU 서버 프로덕션 서빙? --> AWQ (Marlin 커널) 또는 GPTQ (Marlin 커널)
  |
  +-- 로컬/엣지 배포? --> GGUF (Q4_K_M 또는 Q5_K_M)
  |
  +-- 파인튜닝(QLoRA)? --> bitsandbytes (NF4)
  |
  +-- 빠른 프로토타이핑? --> bitsandbytes (설정 2줄로 즉시 적용)

단계 2: vLLM으로 양자화 모델 서빙

# AWQ 모델을 vLLM으로 서빙
pip install vllm

# AWQ Marlin 커널로 최적 성능 달성
python -m vllm.entrypoints.openai.api_server \
    --model ./llama-3.1-8b-awq-4bit \
    --quantization awq_marlin \
    --dtype auto \
    --max-model-len 8192 \
    --gpu-memory-utilization 0.9 \
    --port 8000

# GPTQ 모델 서빙
python -m vllm.entrypoints.openai.api_server \
    --model ./llama-3.1-8b-gptq-4bit \
    --quantization gptq_marlin \
    --dtype auto \
    --max-model-len 8192 \
    --port 8000

# Ollama로 GGUF 모델 서빙 (로컬 환경)
ollama create my-llama -f Modelfile
# Modelfile 내용:
# FROM ./llama-3.1-8b-Q4_K_M.gguf
# PARAMETER num_ctx 8192
# PARAMETER temperature 0.7

단계 3: 양자화 품질 검증

양자화 후 반드시 품질을 검증해야 한다. 퍼플렉시티만으로는 부족하고, 실제 태스크 기반 평가가 필요하다.

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

def evaluate_quantized_model(model, tokenizer, test_prompts: list) -> dict:
    """양자화 모델 품질 평가"""
    results = {
        "total": len(test_prompts),
        "coherent": 0,
        "avg_length": 0,
    }

    total_length = 0
    for prompt in test_prompts:
        inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
        with torch.no_grad():
            outputs = model.generate(
                **inputs,
                max_new_tokens=256,
                temperature=0.7,
                do_sample=True,
            )
        response = tokenizer.decode(outputs[0], skip_special_tokens=True)
        generated = response[len(prompt):]
        total_length += len(generated)

        # 기본 일관성 검사
        if len(generated.strip()) > 20 and not generated.strip().endswith(generated.strip()[:10]):
            results["coherent"] += 1

    results["avg_length"] = total_length / len(test_prompts)
    results["coherence_rate"] = results["coherent"] / results["total"]
    return results

# 평가 실행 예시
test_prompts = [
    "Python으로 이진 탐색 알고리즘을 구현하세요:",
    "머신러닝에서 과적합을 방지하는 방법 3가지를 설명하세요:",
    "REST API와 GraphQL의 차이점을 비교하세요:",
]
# results = evaluate_quantized_model(model, tokenizer, test_prompts)
# print(f"일관성: {results['coherence_rate']:.1%}")

트러블슈팅과 운영 주의사항

자주 발생하는 문제와 해결책

1. GPTQ 양자화 시 CUDA OOM

RuntimeError: CUDA out of memory
  • 원인: 캘리브레이션 과정에서 전체 레이어를 GPU에 로딩
  • 해결: --use_cpu 옵션 사용, 또는 max_memory 설정으로 GPU 메모리 제한
  • group_size를 128에서 64로 줄이면 메모리 절감 (품질 소폭 저하)

2. AWQ 양자화 후 반복 텍스트 생성

  • 원인: 캘리브레이션 데이터가 너무 적거나 편향됨
  • 해결: 최소 128개 이상의 다양한 도메인 캘리브레이션 샘플 사용
  • temperaturerepetition_penalty 조정으로 추론 시 완화 가능

3. GGUF 변환 시 "unknown tensor" 에러

error: unknown tensor 'model.layers.0.self_attn.rotary_emb.inv_freq'
  • 원인: llama.cpp 버전과 모델 아키텍처 불일치
  • 해결: llama.cpp를 최신 버전으로 업데이트, 또는 convert_hf_to_gguf.py의 모델 지원 목록 확인

4. bitsandbytes "No GPU found" 에러

RuntimeError: No GPU found. A GPU is needed for quantization.
  • 원인: CUDA 드라이버 또는 bitsandbytes 빌드 문제
  • 해결: pip install bitsandbytes --force-reinstall, CUDA toolkit 버전 확인 (nvcc --version)

5. vLLM에서 양자화 모델 로딩 실패

ValueError: The quantization method is not supported
  • 원인: vLLM 버전이 해당 양자화 포맷을 지원하지 않음
  • 해결: pip install vllm --upgrade, 또는 --quantization 파라미터를 awq_marlin, gptq_marlin 등 명시적으로 지정

운영 시 주의사항

메모리 관리

  • 양자화 모델이라도 KV 캐시는 FP16으로 유지되므로, 긴 컨텍스트에서는 KV 캐시가 병목이 된다
  • max_model_len을 실제 필요한 수준으로 제한해야 한다
  • vLLM의 gpu_memory_utilization은 0.85~0.9 범위를 권장한다 (1.0은 OOM 위험)

품질 모니터링

  • 양자화 모델은 특정 태스크에서 예상보다 큰 성능 저하를 보일 수 있다
  • 코드 생성, 수학 문제 풀이에서 특히 취약하다 (HumanEval 기준 4bit에서 최대 10% 하락)
  • 프로덕션 배포 전 반드시 도메인별 평가를 수행해야 한다

장애 복구

  • 양자화 모델의 가중치는 원본으로 복원할 수 없다. 원본 FP16 모델을 반드시 보관해야 한다
  • GGUF 파일 손상 시 llama-quantize --allow-requantize 옵션으로 재양자화 가능
  • 양자화 중 프로세스가 중단되면 출력 파일이 불완전하므로 삭제 후 재시작해야 한다

기법 선택 의사결정 트리

시작: LLM 양자화가 필요한가?
  |
  +-- 파인튜닝이 목적인가?
  |     |
  |     +-- Yes --> bitsandbytes NF4 + QLoRA
  |     +-- No --> 다음 단계
  |
  +-- 서빙 환경은?
        |
        +-- GPU 서버 (A100/H100)
        |     |
        |     +-- 속도 최우선 --> AWQ + Marlin 커널 (741 tok/s)
        |     +-- 품질 최우선 --> AWQ 또는 bitsandbytes 8bit
        |
        +-- 소비자 GPU (RTX 3090/4090)
        |     |
        |     +-- GGUF Q4_K_M (CPU 오프로딩 가능)
        |     +-- AWQ 4bit (VRAM 충분 시)
        |
        +-- CPU / Apple Silicon
              |
              +-- GGUF Q4_K_M 또는 Q5_K_M (유일한 선택지)

마치며

LLM 양자화는 단순한 최적화가 아니라 프로덕션 배포의 필수 기술이다. 2026년 현재 AWQ + Marlin 커널 조합이 속도와 품질 모두에서 최적의 성능을 보이며, GGUF는 로컬 환경의 사실상 표준으로 자리잡았다. bitsandbytes는 QLoRA 파인튜닝에서 여전히 핵심적인 역할을 한다.

선택 기준을 요약하면:

  • 프로덕션 GPU 서빙: AWQ + Marlin 커널 (최고 속도 + 높은 품질)
  • 로컬/엣지 배포: GGUF Q4_K_M (CPU/GPU 유연성)
  • 파인튜닝: bitsandbytes NF4 + QLoRA (즉시 적용)
  • 빠른 실험: bitsandbytes (사전 양자화 불필요)

양자화 기법은 계속 발전하고 있다. 최신 동향을 주시하면서, 자신의 서빙 환경과 품질 요구사항에 맞는 최적의 조합을 찾아 적용하길 바란다.

참고 자료