본문으로 건너뛰기

[vLLM] GPTQ: 2차 정보 기반 후훈련 양자화

들어가며

대규모 언어 모델(LLM)을 실제 서비스에 배포할 때 가장 큰 병목은 GPU 메모리이다. 70B 파라미터 모델을 FP16으로 로드하면 약 140GB가 필요한데, 이를 단일 GPU에 올리기란 현실적으로 불가능하다. GPTQ(Generative Pre-Trained Transformer Quantization)는 이 문제를 **후훈련 양자화(Post-Training Quantization)**로 해결한다. 핵심 아이디어는 헤시안(Hessian) 행렬의 2차 정보를 활용하여, 양자화로 인한 출력 오차를 최소화하는 방식으로 가중치를 압축하는 것이다.

공식 문서

vLLM 공식 문서: GPTQModel Quantization

핵심 구조/코드 분석

GPTQConfig: 양자화 설정

vLLM의 GPTQ 구현은 vllm/model_executor/layers/quantization/gptq.py에 위치한다. 설정 클래스인 GPTQConfig가 양자화의 모든 파라미터를 관리한다.

class GPTQConfig(QuantizationConfig):
    """Config class for GPTQ.
    Reference: https://arxiv.org/abs/2210.17323
    """
    def __init__(
        self,
        weight_bits: int,
        group_size: int,
        desc_act: bool,
        lm_head_quantized: bool,
        dynamic: dict[str, dict[str, int | bool]],
        ...
    ) -> None:
        self.weight_bits = weight_bits
        self.group_size = group_size
        self.desc_act = desc_act
        self.pack_factor = Fraction(32, self.weight_bits)
        if self.weight_bits not in [2, 3, 4, 8]:
            raise ValueError(
                "Currently, only 2/3/4/8-bit weight quantization is "
                f"supported for GPTQ, but got {self.weight_bits} bits."
            )

핵심 파라미터를 정리하면 다음과 같다:

파라미터 설명
weight_bits 양자화 비트 수 (2, 3, 4, 8)
group_size 같은 스케일/제로포인트를 공유하는 가중치 그룹 크기
desc_act 활성화 순서 기반 재배열 (Activation Order) 사용 여부
pack_factor 32비트 정수에 몇 개의 가중치를 패킹하는지 (e.g., 4비트면 8개)

dynamic 필드는 GPTQModel 프로젝트에서 도입한 기능으로, 모듈별로 다른 양자화 설정을 적용할 수 있게 해준다. 정규식 기반 매칭을 통해 레이어별 비트 수나 그룹 크기를 다르게 지정한다.

GPTQLinearMethod: 실제 연산

양자화된 가중치의 생성과 추론은 GPTQLinearMethod이 담당한다. create_weights 메서드에서 INT32로 패킹된 가중치 텐서들을 생성한다:

class GPTQLinearMethod(LinearMethodBase):
    def create_weights(self, layer, input_size_per_partition, ...):
        qweight = PackedvLLMParameter(
            data=torch.empty(
                input_size_per_partition // self.quant_config.pack_factor,
                output_size_per_partition,
                dtype=torch.int32,
            ),
            input_dim=0, output_dim=1,
            packed_dim=0,
            packed_factor=self.quant_config.pack_factor,
        )

4비트 GPTQ의 경우 pack_factor가 8이므로, 하나의 INT32 값에 8개의 4비트 가중치가 패킹된다. qweight, qzeros, scales, g_idx 네 개의 파라미터가 레이어에 등록된다.

추론 경로: Exllama 커널

실제 추론 시에는 apply 메서드에서 ops.gptq_gemm 커널을 호출한다:

def apply(self, layer, x, bias=None):
    output = ops.gptq_gemm(
        reshaped_x,
        layer.qweight,
        layer.qzeros,
        layer.scales,
        layer.g_idx,
        layer.exllama_state == ExllamaState.READY,
        self.use_v2_format,
        self.quant_config.weight_bits,
    )

ExllamaState는 세 가지 상태를 가진다: UNUSED, UNINITIALIZED, READY. Exllama 커널 사용 시 가중치 로딩 후 gptq_shuffle로 가중치를 재배열해야 하며, 이 과정은 process_weights_after_loading에서 한 번만 실행된다.

왜 이 설계인가

1. 패킹 전략: INT32에 여러 저비트 가중치를 패킹하는 이유는 GPU 메모리 대역폭 효율성이다. 4비트 가중치 8개를 한 번에 읽으면 메모리 접근 횟수가 8분의 1로 줄어든다.

2. Group Quantization: 전체 행렬에 하나의 스케일을 적용하면 정밀도 손실이 크다. group_size로 채널을 그룹화하여 각 그룹마다 별도의 스케일과 제로포인트를 유지함으로써, 양자화 오차를 그룹 단위로 제한한다.

3. Activation Order (desc_act): GPTQ 논문의 핵심 기여 중 하나다. 헤시안의 대각 원소가 큰 순서대로 가중치를 양자화하면, 중요한 가중치에 대한 보정이 더 많은 자유도를 가지게 된다. g_idx 텐서가 이 재배열 정보를 저장한다.

4. Marlin 커널 우선: 코드에서 4비트 gptq_gemm 커널에 버그가 있다는 경고를 볼 수 있다. 실제로 vLLM은 GPTQ 모델에 대해 가능하면 gptq_marlin 커널을 자동 선택한다. Marlin은 NVIDIA GPU에 최적화된 GEMM 커널로, GPTQ보다 더 높은 처리량을 달성한다.

5. MoE 호환성: get_quant_method에서 FusedMoE 레이어를 감지하면 MoeWNA16Config로 폴백한다. 이는 MoE 모델의 전문가 레이어에도 GPTQ 양자화를 적용할 수 있게 하는 유연한 설계이다.

논문 핵심 내용

GPTQ 논문의 핵심은 OBS(Optimal Brain Surgeon) 프레임워크를 대규모 모델에 적용할 수 있도록 확장한 것이다. 기존 OBS는 헤시안 역행렬 계산의 O(n^3) 복잡도 때문에 수십억 파라미터 모델에 적용이 불가능했다. GPTQ는 행 단위 양자화와 lazy batch update를 결합하여 OPT-175B (1750억 파라미터)를 약 4시간 만에 양자화할 수 있게 만들었다.

핵심 벤치마크

OPT-175B 모델 기준으로, GPTQ는 3-4비트 양자화에서 무시할 수 있는 수준의 정확도 저하만 보였다. 이전 최고 방법 대비 2배 이상의 압축률 개선을 달성했다.

항목 수치
지원 비트 수 3비트, 4비트
OPT-175B 양자화 시간 ~4 GPU 시간
정확도 저하 무시할 수 있는 수준 (negligible)
A100 GPU 추론 속도 향상 3.25배
A6000 GPU 추론 속도 향상 4.5배
이전 방법 대비 압축률 2배 이상 개선

GPTQ의 핵심 트릭은 Activation Order(desc_act)이다. 헤시안의 대각 원소가 큰 순서(즉, 활성화가 큰 순서)대로 가중치를 양자화하면, 중요한 가중치를 먼저 처리할 때 나머지 가중치에 대한 보정 자유도가 최대화된다. 이 간단한 순서 변경이 특히 3비트처럼 극단적인 양자화에서 perplexity를 크게 개선한다.

실용적 관점에서 GPTQ의 가장 큰 장점은 재학습이 전혀 필요 없다는 것이다. 소량의 캘리브레이션 데이터(128개 샘플 정도)만 있으면 되고, 모델 아키텍처 수정도 불필요하다. 이 때문에 Hugging Face에서 가장 널리 사용되는 양자화 포맷 중 하나가 되었다.

마무리

GPTQ는 후훈련 양자화의 대표적 기법으로, vLLM에서는 Exllama/Marlin 커널과 결합하여 실질적인 추론 가속을 달성한다. 2/3/4/8비트를 모두 지원하며, 모듈별 동적 양자화 설정까지 가능한 점이 프로덕션 환경에서 강점이다.

댓글

관련 포스트

vLLM 의 다른글