18 분 소요

LLM은 놀라운 기능을 가능하게 했지만 매우 큰 모델 크기 때문에 실제 운영 환경에서 많은 문제가 생긴다. 고성능 GPU는 가격이 비싸고 확보하기도 어렵다. 크고 비싼 모델을 더 많은 사용자가 쓸 수 있게 하려면 모델의 핵심 성능을 지키면서 크기를 줄여야 한다. 이때 모델 압축 기법을 사용한다. 단순한 임시방편이 아니라 성능을 유지하면서 모델 크기와 연산 부하를 줄이는 운영 전략이다.

1. 모델 압축

모델 압축은 일반적으로 세 가지 범주로 나뉜다.

  • 양자화(quantization): 모델 매개변수의 정밀도를 높은 비트 형식에서 낮은 비트 형식으로 줄인다. 같은 메모리에 더 많은 매개변수를 넣고 행렬 연산 속도를 높인다.
  • 증류(distillation): 큰 교사 모델(teacher model)의 지식을 더 작고 빠른 학생 모델(student model)에 전달해 교사 모델의 동작을 모방하게 한다.
  • 가지치기(pruning): 중복된 가중치(weight)나 어텐션 헤드를 선택적으로 제거한다. 모델 용량 중 사용되지 않는 부분을 줄인다.

이 글에서는 각 기법의 원리, 절충점, 실제 적용 방법을 살펴본다. 세 가지 주요 압축 기법 중 실용성이 가장 높은 것은 양자화다. 빠르고 효과적이며 모델 학습 파이프라인을 거의 수정하지 않아도 된다. 이런 장점 때문에 운영 환경에서 LLM을 압축하고 가속할 때 가장 먼저 선택하는 기법이 됐다.

양자화 모델은 예상보다 훨씬 널리 운영에 사용된다. 지연 시간이 짧고 처리량이 높아야 하거나, 자원이 제한된 엣지 장치(edge device)에서 모델을 실행해야 하는 경우에 특히 유용하다. 영향력과 보급 정도가 큰 만큼 이 절에서는 다른 두 기법보다 양자화를 더 자세히 다룬다.

1-1. 양자화

양자화는 가중치, 활성화(activation), KV 캐시 같은 모델 매개변수의 정밀도를 낮추는 과정이다. 32비트 FP32, 16비트 FP16 또는 BF16 같은 고정밀 부동소수점 형식을 8비트 FP8 또는 INT8, 4비트 FP4 또는 INT4 같은 저비트 표현으로 바꾼다. 모델 데이터의 정확도를 어느 정도 양보하고 더 나은 서빙 성능을 얻는 방식이다.

1-2. 양자화 오차

양자화는 모델 매개변수의 수치 정밀도를 높은 수준에서 낮은 수준으로 줄인다. 이 과정에서 반올림 오차(rounding error)와 클램핑 오차(clamping error)가 발생해 모델의 추론 정확도가 낮아질 수 있다.

반올림 오차는 FP32의 숫자를 INT8 같은 대상 형식으로 정확히 표현할 수 없을 때 가장 가까운 값으로 반올림해서 생긴다. 원래 값과 변환된 값의 차이가 반올림 오차다. 예를 들어 FP32 값 7.6을 소수를 저장할 수 없는 INT8로 바꾸면 가장 가까운 정수 8이 된다. 반올림 오차는 8 - 7.6 = 0.4다.

클램핑 오차는 숫자가 대상 형식의 표현 범위보다 너무 크거나 작을 때 생긴다. 숫자를 표현 가능한 최댓값이나 최솟값으로 제한한다. FP8과 FP16 같은 형식은 지수(exponent) 범위가 제한되어 있기 때문이다.

예를 들어, FP8이 -448에서 +448까지만 표현할 수 있다고 가정하자. 1,000은 FP8로 표현할 수 없으므로 FP32에서 FP8로 압축할 때 허용되는 최댓값 448로 제한해야 한다. 4,096를 FP8의 448로 바꾸는 것처럼 클램핑은 큰 왜곡을 만들 수 있다. 최신 양자화 기법은 가능한 한 강제 클램핑을 피한다. 일부 반올림 오차가 생기더라도 대상 범위 안에서 값의 상대적 크기를 더 잘 보존하도록 스케일링 전략(scaling strategy)을 사용한다.

양자화할 때 스케일링 계수(scaling factor)를 적용해 원본 데이터의 값 범위를 압축한다. 극단의 값을 갑자기 잘라 내는 대신 더 많은 값이 INT8이나 FP8 같은 저정밀 형식의 표현 범위에 들어오게 한다. 널리 사용하는 방법에는 대칭 스케일링(symmetric scaling)비대칭 스케일링(asymmetric scaling)이 있다.

이제 LLM 매개변수를 저장하는 여러 데이터 형식을 자세히 살펴보자.

1) 숫자 저장 형식

부동소수점(floating-point, FP)은 3.14, -42.7, 1e9 같은 실수를 컴퓨터에서 표현하는 표준 방식이다. 일반적인 구조는 다음과 같다.

전체 비트 수 = 부호 비트 1개 + 가수 비트 + 지수 비트

숫자를 세 부분으로 표현한다.

  • 부호 비트(sign bit) 1개는 양수와 음수를 구분한다.
  • 가수(mantissa 또는 significand)는 숫자 표현의 정밀도, 즉 세밀함을 결정한다.
  • 지수(exponent)는 값의 규모를 결정하며 얼마나 크거나 작은 숫자를 표현할 수 있는지를 정한다.

부동소수점 형식에는 여러 종류가 있지만 FP32, FP16, BF16이 가장 일반적이다.

표 6-1. 일반적인 부동소수점 형식과 비트 배분 비교

정밀도 형식 전체 비트 부호 비트 지수 가수 대략적인 범위
FP32 32 1 8 23 ±10³⁸
FP16 16 1 5 10 ±10⁻⁵
BF16 16 1 8 7 ±10³⁸

FP32는 완전 정밀도(full precision) 형식으로 간주하며 총 32비트를 사용한다. 부호 1비트, 지수 8비트, 가수 23비트다. 표현 범위가 넓고 정밀도도 좋아 딥러닝 모델 학습의 표준 형식으로 사용해 왔다.

FP16과 BF16은 모두 16비트로 FP32의 절반 크기다. 지수와 가수 중 어느 쪽에 더 많은 비트를 배분하느냐에 따라 표현 범위와 정밀도가 달라진다.

BF16은 FP16보다 지수에 더 많은 비트를 배분한다. FP16은 5비트, BF16은 8비트다. 가수 비트 수를 줄여 정밀도를 일부 포기하는 대신 수치 표현 범위를 크게 넓힌다.

BF16과 FP32는 모두 지수에 8비트를 사용하므로 표현 범위가 같다. FP32에서 BF16으로 변환하는 과정은 FP16으로 변환할 때보다 단순하다. 표현 범위 때문에 클램핑이 발생할 위험은 없고, 가수가 짧아져 정밀도만 낮아진다.

이 특성 때문에 BF16은 세밀한 정밀도보다 동적 범위(dynamic range)가 더 중요한 딥러닝 학습에 적합하다. 메모리와 연산 오버헤드도 줄일 수 있다. 그림 6-14는 FP32, BF16, FP16을 시각적으로 비교한다.

현재 LLM 서빙에서는 FP32를 사용하는 경우가 줄었으며 대부분의 모델 체크포인트(model checkpoint)는 FP16 또는 BF16으로 제공된다.

그림 6-14. FP32, BF16, FP16의 정밀도와 표현 범위 그림 6-14. FP32, BF16, FP16의 정밀도와 표현 범위 비교.

이제 양자화 숫자 형식을 살펴보자. 양자화 표현에는 INT8, INT4 같은 정수 기반 형식과 FP8, FP4 같은 부동소수점 기반 형식이 있다. 이 책을 집필하는 동안에도 부동소수점 기반 저비트 형식의 사용이 늘었다.

두 형식의 핵심 차이는 데이터 지점을 배치하는 방식이다. 정수 형식은 전체 값 범위에서 데이터 지점 사이의 간격이 일정한 균일 분포(uniform distribution)를 사용한다. 값의 정밀도가 범위에 따라 변하지 않는다.

반면 부동소수점은 비균일 분포(nonuniform distribution)를 사용한다. 0 주변에는 데이터 지점이 더 많고 절댓값이 매우 큰 영역에는 더 적다. FP 값이 로그 방식으로 표현되기 때문에 이런 밀도 차이가 생긴다. FP8 값은 다음과 같이 계산한다.

$$
\text{Value} = (-1)^{\text{sign}} \times (1 + \text{mantissa}) \times 2^{\text{exponent} - \text{bias}}
$$

지수가 커질수록 표현 가능한 숫자 사이의 간격도 커진다. 1.0과 2.0 사이에서는 1.01, 1.001처럼 많은 값을 표현할 수 있지만 1,000,000과 2,000,000 사이에서는 최소 간격이 128 이상으로 커질 수 있다. 그림 6-15가 INT8과 FP8의 데이터 지점 분포를 보여준다.

그림 6-15. INT8과 FP8의 데이터 지점 분포 그림 6-15. INT8과 FP8 형식의 데이터 지점 분포.

모델 가중치와 활성화 값 같은 매개변수의 실제 데이터 분포에 따라 정확도를 가장 잘 유지하는 형식을 선택해야 한다.

2) 양자화가 모델 서빙에 주는 이점

사용 사례에 맞는 양자화 방식을 고르려면 양자화가 어떤 이유와 방식으로 처리량을 높이고 지연 시간을 줄이는지 이해해야 한다.

첫 번째 이유는 데이터 크기다. 매개변수당 8비트를 쓰는지 16비트를 쓰는지에 따라 디스크와 GPU 메모리에서 모델이 차지하는 공간이 직접 달라진다. FP16은 매개변수마다 2바이트를 사용한다. 7B 모델의 크기는 다음과 같다.

약 70억 매개변수 × 매개변수당 2바이트 = 140억 바이트 = 14GB

이 모델을 INT8로 양자화하면 크기가 곧바로 절반인 7GB가 된다. 양자화하지 않은 모델을 담을 만큼 GPU 메모리가 크지 않을 때 큰 이점이 된다.

큰 모델을 서빙할 때도 양자화를 통해 여러 노드 대신 한 대의 머신 또는 노드에 모델을 넣을 수 있다. 노드 간 통신을 피할 수 있다. 메모리 사용량이 줄어들면 KV 캐시에 더 많은 공간을 배정할 수 있으므로 동시 요청 수와 전체 처리량도 늘어난다. 특히 디코드 단계는 데이터 이동이 병목이므로 GPU 메모리 대역폭이 LLM 성능 최적화의 핵심이다. 양자화로 모델을 작게 만들면 이동해야 하는 데이터가 직접 줄어 추론 지연 시간이 크게 단축된다.

마지막으로 낮은 정밀도는 연산 자체도 더 빠르게 할 수 있다. 표 6-2는 정밀도별 H100 성능을 비교한다. 일반적으로 비트 수를 16비트에서 8비트로 절반으로 줄이면 FLOPS가 두 배가 된다. 가중치를 4비트로 양자화할 때도 같은 원리가 적용된다.

표 6-2. 정밀도별 H100 SXM 성능

정밀도 H100 SXM 성능
FP64 34 teraFLOPS
FP64 Tensor Core 67 teraFLOPS
FP32 67 teraFLOPS
TF32 Tensor Core 989 teraFLOPS
BFLOAT16 Tensor Core 1,979 teraFLOPS
FP16 Tensor Core 1,979 teraFLOPS
FP8 Tensor Core 3,958 teraFLOPS
INT8 Tensor Core 3,958 TOPS

양자화는 모델 크기와 연산 중 데이터 이동량을 줄이고 연산 속도를 높인다.

3) 가중치 전용 양자화와 가중치-활성화 양자화

가장 흔한 양자화 전략은 모델 가중치만 양자화하는 방식과 가중치와 활성화를 모두 양자화하는 방식이다. W4A16, W8A8 같은 표기는 모델 가중치(weight, W)와 중간 단계 입력 및 출력인 활성화(activation, A)에 사용하는 비트 폭을 나타낸다.

  • W4A16: 모델 가중치 4비트, 활성화 16비트
  • W8A8: 모델 가중치 8비트, 활성화 8비트

가중치 전용 양자화(weight-only quantization)는 모델 가중치만 양자화하고 활성화는 양자화하지 않는다. 모델 크기는 줄어들지만 실행 중에는 저비트 가중치를 다시 고비트 형식으로 역양자화(dequantization)한다. 모델 크기와 데이터 이동량이 줄어드는 이점은 있지만 연산 속도 자체가 빨라지지는 않는다. 연산 전에 가중치를 역양자화해야 하므로 약간의 오버헤드도 생긴다.

추론 중 역양자화를 피하려면 혼합 정밀도 커널(mixed-precision kernel)을 사용할 수 있다. NVIDIA Ampere 세대 A100에서는 Marlin 커널을, Hopper 세대 H100에서는 Machete 커널을 예로 들 수 있다. 이런 커널은 양자화 가중치 접근을 융합해 행렬 곱셈을 효율적으로 처리한다. 예를 들어 INT4 행렬과 FP16 행렬의 곱셈을 별도의 역양자화 없이 한 번에 수행한다. 실제로 여러 LLM 서빙 엔진은 가중치 전용 양자화 LLM을 서빙할 때 이 커널을 기본으로 활성화한다.

가중치-활성화 양자화(weight-and-activation quantization)는 모델 크기와 데이터 이동량을 줄이는 데 그치지 않는다. 활성화도 양자화하므로 연산 병목 워크로드에서 더 높은 FLOPS를 얻는다. 다만 활성화 값은 계속 바뀌는 모델 입력에 따라 달라지므로 가중치만 양자화할 때보다 복잡하다. 활성화를 양자화할 때는 스케일링 시점을 정해야 한다.

  • 동적 스케일링(dynamic scaling): 추론하는 동안 스케일링 계수를 즉석에서 계산한다.
  • 정적 스케일링(static scaling): 모델 배포 전에 보정 데이터셋(calibration dataset)으로 스케일링 계수를 추정하고 미리 계산한다.

동적 스케일링은 정확도가 더 높지만 실제 추론 중 계수를 계산하므로 정적 스케일링보다 성능이 낮다. 가중치 전용 양자화에서는 GPTQ 또는 AWQ 방식의 W4A16이 대규모 운영 환경에서 가장 흔하다. 가중치-활성화 양자화에서는 이 책을 쓰는 시점에 W8A8이 가장 흔하다. 과거에는 주로 INT8을 사용했지만 최근에는 FP8로 옮겨가고 있다.

표 6-3. W4A16과 W8A8 비교

항목 W4A16 W8A8
모델 크기 및 데이터 이동 감소 75%, 원본의 1/4 50%, 원본의 1/2
연산 FLOPS 변화 없음 2배
프리필 단계, 연산 병목 변화 없음 개선
디코드 단계, 메모리 대역폭 병목 개선, 작은 배치에 유리 개선, 큰 배치에 유리
적합한 환경 긴 생성, 지연 시간 민감, 작은 배치 긴 컨텍스트, 높은 처리량, 큰 배치

W4A16은 모델 크기를 W8A8보다 두 배 더 많이 줄인다. GPU 메모리 사용량과 필요한 메모리 대역폭이 더 작으므로 디코드 단계에서 큰 효과가 있다.

W8A8은 긴 컨텍스트의 프리필처럼 연산 병목인 워크로드와 큰 배치로 높은 처리량을 내는 환경에 유리하다. 큰 배치에서는 디코드도 연산 병목에 가까워지기 때문이다.

양자화 전략 선택 기준 실제 운영 배포에서 모델을 단일 GPU에 넣어 GPU 간 통신을 피하거나 단일 머신의 GPU들에 넣어 노드 간 통신을 피하려면 모델 크기를 4분의 1로 줄이는 W4A16이 적합하다. 반면 큰 배치에서는 활성화를 양자화해 연산 효율을 높이는 이점이 메모리 절감보다 커지는 경우가 많다. 모델 실행 병목도 메모리 대역폭에서 연산으로 이동한다. W8A8로 지연 시간 SLA를 만족할 수 있다면 모델 인스턴스당 유효 배치를 더 키워 처리량을 높이고 비용을 줄이는 방향을 우선할 수 있다.

이제 데이터 형식을 다시 살펴보자. 과거의 W8A8 양자화는 단순성과 하드웨어 호환성을 위해 가중치와 활성화를 고정된 -127에서 +127 범위로 제한하는 INT8 형식을 주로 사용했다. 최근에는 E4M3, E5M2 같은 FP8 변형 모델의 운영 배포가 크게 늘었다.

NVIDIA는 2022년 논문에서 FP8 E4M3 형식을 소개했다. INT8처럼 정확도 유지를 위한 보정이 필요하지 않으면서 FP16보다 정확도 손실을 작게 유지하고 서빙 성능을 높일 수 있음을 보였다.

FP8의 두 변형 중 추론에서는 E4M3을 더 많이 사용한다. E5M2보다 동적 범위가 작아 스케일링이 필요할 수 있지만 더 높은 정밀도를 유지하기 때문이다.

표 6-4. FP8 부동소수점 형식의 비트 배분

정밀도 형식 전체 비트 부호 비트 지수 가수
FP8 E4M3 8 1 4 3
FP8 E5M2 8 1 5 2

FP8을 항상 사용할 수 있는 것은 아니다 모든 GPU나 가속기가 FP8을 지원하지 않는다. NVIDIA GPU 중에서는 Hopper와 Blackwell만 FP8을 지원한다. A100 또는 더 오래된 GPU만 있다면 FP8을 실행해도 기대한 전체 성능 향상을 얻지 못할 수 있다.

이 책은 엔지니어링에 초점을 맞추므로 양자화 과정 자체를 깊이 다루지는 않는다.

4) 양자화 실습

이제 양자화를 실제로 적용하는 예를 살펴보자. 제공되는 Google Colab 노트북에는 Qwen/Qwen2.5-7B-Instruct 모델을 다음 세 가지 형태로 vLLM 서버에 올리는 코드가 있다.

  • 원본 모델
  • GPTQ W4A16 양자화 모델
  • W8A8 양자화 모델

각 모델에 서로 다른 동시성(concurrency)으로 벤치마크를 실행한다. TTFT, 출력 토큰당 시간(time per output token, TPOT) 또는 ITL, 처리량을 기록해 성능 향상과 절충점을 비교한다.

양자화 모델 찾기. 노트북에서는 원본 모델과 양자화 모델을 각각 독립 실행 서버로 실행한다. 모델을 실행하려면 로컬이나 클라우드 위치에 저장하거나 Hugging Face의 모델을 직접 참조해야 한다.

널리 쓰이는 기반 모델(foundation model)과 그 양자화 변형은 Hugging Face에서 바로 찾을 수 있는 경우가 많다. 직접 양자화하지 않아도 된다. 그림 6-16처럼 Hugging Face 모델 페이지 오른쪽에는 이미 업로드된 양자화 변형이 표시된다.

그림 6-16. Hugging Face에서 제공되는 양자화 모델 변형 그림 6-16. Hugging Face에서 제공되는 양자화 모델 변형.

모델 직접 양자화하기. 단순히 모델 ID Qwen/Qwen2.5-7B-Instruct를 서버 시작 명령의 인수로 넘길 수 있다. 필요하면 모델 ID를 모델 경로로 바꾼다.

hf_model_id = "Qwen/Qwen2.5-7B-Instruct"
!vllm serve {hf_model_id}

다른 보정 데이터셋으로 기반 모델을 양자화하거나 직접 미세 조정한 모델을 양자화하려면 GPTQModel, AutoAWQ, LLMCompressor 같은 라이브러리를 사용할 수 있다. 다음은 GPTQ 양자화 예제다.

from transformers import AutoModelForCausalLM, AutoTokenizer, GPTQConfig

tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-7B-Instruct")
dataset = [
    "Gptq is an easy-to-use model quantization library with user-friendly APIs, "
    "based on the GPTQ algorithm."
]  # calibration dataset
gptq_config = GPTQConfig(bits=4, dataset=dataset, tokenizer=tokenizer)

quantized_model = AutoModelForCausalLM.from_pretrained(
    "Qwen/Qwen2.5-7B-Instruct",
    device_map="auto",
    quantization_config=gptq_config
)

벤치마크 실행: vLLM 서버가 시작되면 요청을 보내 서로 다른 방식으로 양자화한 모델의 성능을 관찰할 수 있다. 벤치마크는 vLLM 저장소에 포함된 스크립트를 사용한다.

성능 분석: 세 모델 변형의 벤치마크 결과를 그림 6-17, 6-18, 6-19에 나타냈다.

동시성이 낮은 환경에서는 GPTQ W4A16의 성능이 가장 좋다. 원본 모델보다 지연 시간과 처리량이 약 300% 향상된다. FP8 W8A8도 약 150%의 성능 향상을 제공한다.

작은 배치에서는 GPU 메모리 대역폭이 병목이다. GPTQ는 가중치를 4분의 1 크기인 INT4로 줄이므로 이 환경에서 특히 효과가 크다. 챗봇이나 여러 번 모델을 호출해 누적 지연 시간을 줄이는 것이 중요한 AI 에이전트 흐름처럼 최저 지연 시간이 필요하다면 W4A16 가중치 전용 양자화가 적합하다.

그림 6-17. 요청 동시성에 따른 TTFT 비교 그림 6-17. Qwen2.5-7B-Instruct 원본, GPTQ-INT4 W4A16, FP8 W8A8 모델의 요청 동시성별 TTFT 비교.

그림 6-18. 요청 동시성에 따른 TPOT와 ITL 비교 그림 6-18. Qwen2.5-7B-Instruct 원본, GPTQ-INT4 W4A16, FP8 W8A8 모델의 요청 동시성별 TPOT 및 ITL 비교.

각 그래프의 x축을 왼쪽에서 오른쪽으로 이동하며 동시성을 높이면 큰 배치 처리에서의 특성이 나타난다. GPTQ W4A16은 가중치 전용 양자화이므로 연산 자체는 여전히 16비트다. 이때 약점이 드러난다. GPTQ W4A16의 TTFT 증가가 가장 크며 원본 모델보다 느려지기도 한다.

연산량을 줄이지 못하는 데다 역양자화 오버헤드까지 생기기 때문이다. 반면 FP8 W8A8은 활성화도 FP8로 양자화해 연산이 빨라지므로 큰 배치에서 훨씬 좋은 성능을 낸다. W8A8의 지연 시간이 사용 사례의 SLA를 이미 만족한다면 배치를 더 키워 모델 인스턴스 하나가 더 많은 요청을 병렬 처리하게 하고 비용을 줄일 수 있다.

그림 6-19. 요청 동시성에 따른 처리량 비교 그림 6-19. Qwen2.5-7B-Instruct 원본, GPTQ-INT4 W4A16, FP8 W8A8 모델의 요청 동시성별 처리량 비교.

5) 다른 양자화 방식

지금까지 설명한 가중치와 활성화 양자화는 주로 어텐션 계층이 아니라 FFN을 대상으로 한다. FFN이 매개변수와 연산의 대부분을 차지하지만 일부 환경에서는 어텐션 메커니즘과 KV 캐시도 양자화한다.

KV 캐시 양자화와 어텐션 양자화: 첫 단계는 KV 캐시를 양자화하는 것이다. 가중치 전용과 가중치-활성화 양자화 모두 일반적으로 KV 캐시는 고정밀 형식으로 남겨 둔다. 그러나 KV 캐시는 GPU 메모리를 상당히 많이 차지할 수 있다.

KV 캐시를 양자화하면 GPU 메모리를 더 확보할 수 있다. 배치 크기를 키워 처리량을 높일 수 있고, 더 많은 프리픽스를 다시 계산하거나 로드하지 않고 저장할 수 있으므로 프리픽스 캐싱에도 도움이 된다.

다만 KV 캐시 양자화만으로 지연 시간이 크게 줄지는 않는다. 어텐션 연산이 계속 고정밀 형식을 사용한다면 KV 캐시 크기만 작아질 뿐 연산 중 더 많은 FLOPS를 얻지는 못한다. 가중치 전용 양자화와 마찬가지로 어텐션을 계산할 때 KV 캐시를 다시 역양자화해야 한다. KV 캐시 양자화의 이점을 모두 얻으려면 양자화 어텐션 커널과 함께 사용해야 한다.

일반적으로는 가중치 전용 또는 가중치-활성화 양자화부터 시작한다. 예를 들어 가중치와 활성화를 모두 FP8로 바꾼다. 그 뒤 제한된 GPU 메모리에서 긴 컨텍스트를 처리하거나 디코드 비중이 큰 워크로드의 처리량을 더 높여야 할 때 FP8 KV 캐시 양자화와 FP8 어텐션 커널을 추가한다.

GGUF 양자화: GPT-Generated Unified Format(GGUF)은 성격이 매우 다른 양자화 방식이다. 고성능 GPU가 없을 때 로컬, 이동 가능, 저자원 배포를 원하는 사용자에게 인기가 있다. GPU 대신 CPU와 Apple Silicon의 Metal에서 LLM을 실행하는 데 초점을 맞추며, GPU가 있으면 필요에 따라 일부 작업을 GPU로 오프로딩(offloading)한다. GGUF는 다양한 양자화 수준과 형식을 제공한다. Hugging Face의 GGUF 모델을 llama.cpp로 로컬 실행할 수 있다.

6) 정확도 절충

양자화를 적용할 때 가장 중요한 절충은 모델 정확도와 서빙 성능, 즉 처리량 및 지연 시간 사이에서 일어난다. 양자화 모델이 원본 모델에 가까운 정확도와 충분한 품질을 유지하지 못하면 운영 제품에 배포할 수 없으므로 성능 향상도 의미가 없다. 다행히 모델 정확도를 유지하기 위한 실험과 연구가 많이 진행됐다. GPTQ W4A16, AWQ, 가중치와 활성화를 모두 양자화하는 FP8은 실제 정확도 지표에서 손실이 작다는 결과를 보였다. 그림 6-20이 이를 보여준다.

양자화로 얻은 성능 덕분에 더 큰 모델의 양자화 버전을 실행할 수도 있다. 예를 들어 FP16 8B 모델 대신 FP8 12B 모델을 배포하면 비슷한 지연 시간에서 더 높은 처리량과 더 좋은 모델 정확도를 얻을 수 있다.

그림 6-20. 모델 크기와 양자화 방식별 OpenLLM Leaderboard 점수 그림 6-20. Neural Magic이 비교한 모델 크기와 양자화 방식별 OpenLLM Leaderboard 점수.

연구 결과는 모델 크기와 컨텍스트 길이에 따라 양자화 방식이 미치는 영향에도 일정한 패턴이 있음을 보여준다. 이 패턴은 만족할 만한 정확도를 유지하는 양자화 수준과 방식을 찾는 데 도움이 된다. 예를 들어 더 공격적인 가중치 전용 양자화와 긴 컨텍스트 서빙을 시도할 수 있다. 모델이 클수록 가중치 및 KV 캐시 양자화에 따른 정확도 변화에 더 민감하다. KV 캐시 양자화는 정확도에 미치는 영향이 비교적 작지만 성능 향상도 크지 않다. KV 캐시 공간과 ITL이 문제라면 좋은 방법이지만 우선순위는 상대적으로 낮다.

양자화 후에는 모델 정확도가 요구 수준을 유지하는지 평가해야 한다. LM Eval은 다양한 구성을 지원하는 대표적인 도구다. 다음은 정확도 평가 예제다.

lm_eval --model {hf|vllm|sglang} \
  --model_args Qwen/Qwen2-7B-Instruct \
  --tasks gsm8k_cot \
  --device cuda:0 \
  --batch_size auto

최근 연구는 NVIDIA Blackwell 세대 GPU를 이용한 FP4, FP6, W4A8처럼 더 낮은 비트의 양자화로 이동하고 있다. 아직 좋은 모델 정확도를 유지하기가 상당히 어렵다. 그러나 텐서별 스케일링(per-tensor scaling), 채널별 스케일링(per-channel scaling), 이상치 인식 클리핑(outlier-aware clipping) 등 새로운 기법을 함께 사용해 양자화 오차를 줄이고 있으므로 가까운 시기에 저비트 형식의 운영 사용이 늘어날 것으로 예상된다.

7) 양자화 인식 학습

매우 낮은 비트에서 양자화 정확도 문제를 완화하는 강력하지만 복잡한 방법이 양자화 인식 학습(quantization-aware training, QAT)이다. 지금까지 설명한 방식은 모두 학습 후 양자화(post-training quantization, PTQ)에 초점을 맞췄다. PTQ는 학습 파이프라인에 접근할 필요가 없다. 직접 학습하지 않았더라도 접근할 수 있는 기반 모델이나 사용자 학습 모델을 양자화할 수 있다. 사용하기 쉽고 정확도도 충분히 좋기 때문에 실무에서는 QAT보다 PTQ가 훨씬 널리 쓰인다.

QAT는 학습 단계, 더 구체적으로는 미세 조정이나 정렬 단계에서 가짜 양자화(fake quantization)를 수행해 정확도를 더 잘 보존한다. 학습 중 모델이 정밀도 손실을 보정하도록 가중치를 조정할 수 있으므로 정확도가 더 높다. 단순히 학습 후 반올림하면 모델이 제대로 동작하지 않을 수 있는 4비트 수준의 공격적인 압축에서는 QAT가 유일하게 신뢰할 만한 선택인 경우가 많다.

표 6-5. PTQ와 QAT 비교

항목 학습 후 양자화(PTQ) 양자화 인식 학습(QAT)
적용 시점 정적 가중치의 학습이 완전히 끝난 뒤 양자화 효과를 모사하며 학습 또는 미세 조정 중
난이도 낮음, 변환과 일부 보정 필요 높음, 학습 파이프라인에 추가 연산 필요
8비트 이상 정확도 좋음 좋음
4비트 이하 정확도 일반적으로 수용하기 어려움 더 좋고 수용 가능
유연성 사용자 모델에 쉽게 적용하고 다양한 하드웨어에 배포 가능 특정 양자화 방식에 묶여 추가 미세 조정과 다른 하드웨어 배포의 유연성이 낮음

실제 사례로 OpenAI가 공개한 오픈 소스 GPT-OSS 모델 계열이 있다. FP4 E2M1 기반 MXFP4 형식의 QAT를 사용해 모델 크기를 공격적으로 줄였다. OpenAI 문서에 따르면 gpt-oss-120b는 핵심 사고 벤치마크에서 OpenAI o4-mini와 거의 같은 수준의 성능을 내면서 80GB GPU 한 장에서 효율적으로 실행된다. gpt-oss-20b는 일반 벤치마크에서 OpenAI o3-mini와 비슷한 결과를 내며 메모리 16GB인 엣지 장치에서도 실행할 수 있다.

FP4는 매개변수당 0.5바이트만 사용한다. OpenAI가 공개한 매개변수 수를 기준으로 gpt-oss-120b는 1,170억 개, gpt-oss-20b는 210억 개다. 단순하게 모델 크기를 계산하면 다음과 같다.

약 1,170억 매개변수 × 0.5바이트/매개변수 = 585억 바이트
= 58.5GB < 80GB

약 210억 매개변수 × 0.5바이트/매개변수 = 105억 바이트
= 10.5GB < 16GB

GPT-OSS의 모든 매개변수가 FP4로 양자화되는 것은 아니다. 양자화는 제7장에서 설명할 전문가 혼합(mixture of experts, MoE) 계층에만 적용된다. 그러나 전체 매개변수의 90% 이상이 MoE 계층에 있으므로 위의 추정은 여전히 유효하다.

GPT-OSS 계열은 정확도와 추론 속도 때문에 큰 인기를 얻었다. 바로 실행할 수 있는 양자화 모델 형식으로 배포되므로 사용자가 양자화 알고리즘과 정밀도를 직접 고르지 않아도 된다. 배포 과정의 반복 작업을 크게 줄인다.

다만 이 장점을 얻으려면 하드웨어와 추론 스택이 모델의 MXFP4 형식을 네이티브로 실행할 수 있어야 한다. 모든 GPU가 FP4를 같은 수준으로 지원하는 것은 아니므로 성능은 사용 가능한 GPU에 크게 좌우된다.

블랙웰(Blackwell)의 B200 등은 NVFP4 E2M1과 MXFP4 같은 블록 스케일 FP4 형식을 포함해 전용 4비트 부동소수점 연산을 지원한다. 반면 Hopper의 H100과 H200 등은 네이티브 FP4가 아니라 FP8 E4M3 및 E5M2 Tensor Core 중심으로 설계됐다.

Blackwell GPU를 사용할 수 있다면 GPT-OSS 배포에 가장 이상적이다. Hopper도 혼합 정밀도 커널의 사용자 정의 소프트웨어 지원을 이용하면 충분히 쓸 수 있다. Ampere의 A100, A10 또는 더 오래된 GPU만 있다면 Qwen 같은 다른 모델 아키텍처를 선택하고 직접 양자화하는 편이 나을 수 있다.

1-3. 증류

모델 압축의 또 다른 기법인 모델 증류(model distillation)를 살펴보자. 세 가지 기법 중 지연 시간과 처리량을 개선할 잠재력이 가장 크다.

증류는 원본 모델의 크기를 줄이는 양자화나 가지치기와 다르다. 새로운 작은 모델을 학습한다. 큰 원본 교사 모델에 들어 있는 지식을 더 작은 학생 모델로 옮기고 학생 모델이 교사의 동작을 모방하게 한다. 그림 6-21은 교사 모델의 출력을 사용해 훨씬 작은 학생 모델을 학습하는 과정을 보여준다. 교사 모델의 출력은 보통 하드 레이블(hard label)이라고 부르는 출력 토큰에만 한정되지 않는다. 예측 확률 분포의 로짓(logit)과 손실(loss)도 포함할 수 있다. 따라서 증류 학생 모델을 만들려면 출력 토큰만 받는 API 호출이 아니라 원본 교사 모델에 완전히 접근할 수 있어야 한다.

그림 6-21. 교사 모델에서 학생 모델로 이어지는 증류 파이프라인 그림 6-21. 교사 모델의 출력으로 학생 모델을 학습하는 모델 증류 파이프라인.

DeepSeek의 증류 모델을 예로 들자. 원본 DeepSeek R1은 매개변수 6,710억 개와 MoE 아키텍처를 사용한다. DeepSeek는 Llama와 Qwen 계열의 오픈 소스 밀집 모델(dense model)에서 증류한 15억-700억 매개변수 모델도 여러 개 공개했다. 서빙 관점에서는 모델 크기가 10분의 1 이하로 줄어 지연 시간과 처리량이 크게 개선될 수 있다.

표 6-6. DeepSeek R1 원본과 70B 증류 모델의 평가 결과

벤치마크 DeepSeek-R1-671B DeepSeek-R1-Distill-Llama-70B
MATH-500 pass@1 97.3 94.5
GPQA Diamond pass@1 71.5 65.2
LiveCodeBench Pass@1 65.9 57.5

서빙 성능을 높이기 위해 이미 증류된 모델을 사용할지 직접 모델을 증류할지 판단할 때는 쉽고 비용이 낮은 방법부터 시작하는 것이 좋다. 예를 들어 DeepSeek-R1-671BDeepSeek-R1-Distill-Llama-70B 중 하나를 배포한다고 하자. 증류 모델이 이미 있다면 먼저 정확도 벤치마크를 실행한다. 요구 수준을 만족하면 증류 모델을 선택한다. 여기에 양자화를 추가해 서빙 성능을 더 높이고 비용을 줄일 수도 있다.

그러나 실제로는 바로 쓸 수 있는 증류 모델이 없는 경우가 많다. 직접 증류하는 비용이 높고 정확도 손실도 더 크므로 이런 경우에는 양자화를 먼저 적용하는 것이 좋다.

표 6-7. 양자화와 증류 비교

항목 양자화 증류
정확도 하락 낮음, 일반적으로 3% 이하 양자화보다 훨씬 큼
속도 향상 1.5-3배 훨씬 크지만 정확도와 절충 필요
사용 편의성 PTQ는 매우 쉬우며 원본 가중치만 필요 완성된 증류 모델이 없으면 어렵고, 학습 비용이 원본 모델 비용의 10%에 이를 수 있음. 일반적으로 원본 모델을 학습한 연구자가 수행

1-4. 가지치기

마지막 모델 압축 기법은 모델 가지치기(model pruning)다. 이 책의 기준 시점인 2025년 중반에는 운영 환경에서 제대로 활용하려면 더 많은 연구가 필요해 세 기법 중 사용 빈도가 가장 낮다. 핵심 아이디어는 모델이 일반적으로 과매개변수화(overparameterized)되어 있다는 점이다. 중복 요소를 제거하면 압축률을 높이고 서빙 성능을 개선할 수 있다.

가지치기는 구조적 가지치기(structured pruning)와 비구조적 가지치기(unstructured pruning)로 구분한다. 구조적 가지치기는 모델의 일정 부분을 통째로 제거한다. 비구조적 가지치기는 개별 가중치를 더 유연하게 제거한다. 둘 사이에는 반구조적 희소성(semi-structured sparsity)이 있다. 2:4 구조적 희소성(2:4 structured sparsity)이라고도 하며 연속된 원소 4개마다 2개를 제거한다.

Neural Magic의 Sparse Llama 3.1은 반구조적 희소성 모델의 예다. vLLM에서 희소성만으로 정확도의 98%를 복원하고 처리량을 30% 높이며 지연 시간을 20% 줄였다고 설명한다. 그림 6-22에서 왼쪽 원본 행렬의 연속된 값 네 개마다 두 값을 0으로 만든다. 흰색으로 표시한 값이다. 원래 네 값 중 녹색으로 표시한 두 값만 남으므로 희소도는 2:4, 즉 50%다. 오른쪽의 압축 후 행렬은 연산을 위해 여전히 밀집 행렬 형태를 이룬다.

Ampere와 Hopper 같은 NVIDIA GPU 아키텍처에는 이런 구조적 희소성 연산을 가속하는 희소 Tensor Core(sparse Tensor Core)가 있다. 50% 희소성은 행렬 곱셈 속도를 직접 두 배로 높일 수 있어 성능 향상이 크다.

그림 6-22. 2:4 구조적 희소성 패턴과 압축 그림 6-22. 2:4 구조적 희소성 패턴과 압축.

2. 더 읽어 볼 내용

댓글남기기