Blog
llm-inferencequantizationkv-cacheoptimizationvllmai

LLM 추론 최적화 가이드 - 양자화, KV Cache, 추측적 디코딩

LLM 추론 최적화의 핵심 기법인 양자화(GPTQ, AWQ, GGUF), KV Cache 최적화, 추측적 디코딩, 배치 처리, 텐서 병렬, FlashAttention을 체계적으로 정리합니다.

Data Dynamics2026년 4월 16일16 min read

지하철 출근 시간, 칸마다 사람이 가득 찬 상황을 상상해 보세요. 새 전동차를 사지 않고도 같은 선로에서 더 많은 승객을 실어 나를 수 있다면 어떨까요? LLM 추론 최적화도 꼭 그런 일을 합니다. GPU를 새로 사지 않고, 이미 가진 자원에서 더 많은 요청을 더 빠르게 처리하는 거거든요.

이 글에서 배우는 것

  • 양자화(Quantization)로 모델 크기를 절반 이하로 줄이는 방법
  • KV Cache와 PagedAttention으로 메모리를 아끼는 원리
  • 추측적 디코딩으로 응답 속도를 2배 넘게 높이는 비결
  • Continuous Batching과 FlashAttention 등 서빙 엔진 핵심 기법
  • 상황별로 어떤 최적화를 먼저 적용할지 우선순위 가이드

1. LLM 추론의 이해

추론 과정

여러분이 챗봇에 질문을 입력하면 실제로 무슨 일이 벌어질까요? LLM 추론은 크게 두 단계로 나뉩니다. 질문 전체를 한 번에 읽는 Prefill 단계, 그리고 단어 하나씩 차례차례 뱉어내는 Decode 단계입니다. 이 두 단계의 특성이 서로 달라서, 최적화 전략도 달라집니다.

Loading diagram…

핵심 성능 지표

지표설명영향 요소
TTFT첫 번째 토큰 생성 시간Prefill 속도, 모델 크기
TPS초당 생성 토큰 수Decode 속도, 메모리 대역폭
Throughput전체 처리량 (tok/s)배칭, GPU 활용률
Latency (P95)95번째 백분위 응답 시간큐잉, 스케줄링

GPU 메모리 구성

[7B 모델의 GPU 메모리 사용 (FP16)]

총 GPU 메모리: 24 GB (RTX 4090)

모델 가중치:     ██████████████  14 GB (58%)
KV Cache:       ████████         8 GB (33%)
활성화/임시:     ██               2 GB (9%)
                 ─────────────────────────
                 합계: 24 GB

→ KV Cache가 동시 요청 수를 결정하는 병목

2. 양자화 (Quantization)

양자화란

카메라 사진을 RAW로 저장하면 용량이 크지만, JPEG로 저장하면 크게 줄어들면서도 육안으로는 거의 똑같아 보이죠. 양자화가 바로 그 원리입니다. 모델 가중치의 정밀도를 줄여 메모리 사용량과 연산량을 절감하면서도, 품질 손실은 놀라울 정도로 적습니다.

FP32 (32비트): 0.12345678901234567890  → 4바이트/파라미터
FP16 (16비트): 0.1235                  → 2바이트/파라미터 (2x 절감)
INT8 (8비트):  31                       → 1바이트/파라미터 (4x 절감)
INT4 (4비트):  7                        → 0.5바이트/파라미터 (8x 절감)

주요 양자화 방식 비교

방식비트품질 손실속도추론 환경대표 도구
FP16/BF1616없음기준GPU기본
GPTQ4매우 적음빠름GPU (CUDA)AutoGPTQ
AWQ4매우 적음매우 빠름GPU (CUDA)AutoAWQ
GGUF2~8방식에 따라보통CPU/GPUllama.cpp
BitsAndBytes4/8적음보통GPUHuggingFace
FP88거의 없음빠름H100+vLLM, TRT-LLM
AQLM2중간빠름GPU-

GGUF 양자화 (llama.cpp / Ollama)

# GGUF 양자화 수준별 비교 (LLaMA 3.1 8B)
# Q2_K:   2.7 GB  — 품질 저하 있음, 최소 메모리
# Q4_K_M: 4.1 GB  — 좋은 균형점 (가장 추천)
# Q5_K_M: 4.8 GB  — 우수한 품질
# Q6_K:   5.5 GB  — 높은 품질
# Q8_0:   7.2 GB  — 거의 원본 수준
# FP16:  14.0 GB  — 원본
 
# Ollama에서 양자화 모델 사용
ollama run llama3.1:8b-q4_K_M

AWQ 양자화 (GPU 서빙용)

# AWQ 양자화 모델을 vLLM으로 서빙
python -m vllm.entrypoints.openai.api_server \
    --model TheBloke/Llama-3.1-8B-Instruct-AWQ \
    --quantization awq \
    --max-model-len 4096

양자화 선택 가이드

Loading diagram…

3. KV Cache 최적화

KV Cache란

글을 읽다가 "앞 문장에서 누가 나왔더라?"를 매번 처음부터 다시 읽어서 확인한다면 엄청나게 비효율적이겠죠. KV Cache는 이 문제를 해결합니다. Transformer가 Self-Attention을 계산할 때, 이미 처리한 토큰의 Key/Value를 메모리에 저장해 두어 중복 계산을 방지합니다.

[KV Cache 없이]
토큰 1 생성: K,V 계산 (토큰 0)
토큰 2 생성: K,V 계산 (토큰 0, 1)        ← 토큰 0 재계산!
토큰 3 생성: K,V 계산 (토큰 0, 1, 2)     ← 토큰 0, 1 재계산!
→ O(n²) 연산

[KV Cache 사용]
토큰 1 생성: K,V 계산 (토큰 0) → 캐시 저장
토큰 2 생성: 캐시(토큰 0) + K,V 계산 (토큰 1) → 캐시 업데이트
토큰 3 생성: 캐시(토큰 0,1) + K,V 계산 (토큰 2) → 캐시 업데이트
→ O(n) 연산

KV Cache 메모리 계산

KV Cache 크기 = 2 × num_layers × num_heads × head_dim × seq_len × dtype_bytes

LLaMA 3.1 8B 예시:
= 2 × 32 × 32 × 128 × 4096 × 2(FP16)
= 2,147,483,648 bytes ≈ 2 GB (시퀀스 1개당)

→ 동시 10개 요청: ~20 GB의 KV Cache 필요!

PagedAttention (vLLM)

[기존: 연속 메모리 할당]
요청 1: [████████░░░░░░░░░░]  ← 최대 길이만큼 예약, 낭비 발생
요청 2: [██████░░░░░░░░░░░░]
요청 3: [메모리 부족]

[PagedAttention: 페이지 단위 할당]
요청 1: [█][█][█][█]          ← 필요한 만큼만 블록 할당
요청 2: [█][█][█]
요청 3: [█][█]                ← 남은 블록 활용!

→ 메모리 낭비 60~80% 감소
→ 동시 처리 가능 요청 수 2~4배 증가

MQA / GQA (Multi-Query / Grouped-Query Attention)

KV Cache 크기를 줄이는 아키텍처 수준의 최적화:

방식KV 헤드 수Cache 크기적용 모델
MHA (Multi-Head)Q=K=V 동일기준GPT-3
MQA (Multi-Query)K=V=11/32PaLM, Falcon
GQA (Grouped-Query)K=V 그룹1/4~1/8LLaMA 3, Gemma

4. 추측적 디코딩 (Speculative Decoding)

원리

인턴 사원이 초안을 빠르게 작성하면, 시니어 엔지니어가 한 번에 검토하고 수정하는 방식을 생각해 보세요. 추측적 디코딩도 마찬가지입니다. 작은 Draft 모델이 여러 토큰을 빠르게 생성하고, 큰 Target 모델이 이를 한 번에 검증합니다. 틀린 토큰만 골라내서 다시 만들면 되니, 전체 속도가 크게 빨라지죠.

[일반 디코딩]
Target(70B): 토큰 1 → 토큰 2 → 토큰 3 → 토큰 4 → 토큰 5
             (5 스텝, 각 스텝 느림)

[추측적 디코딩]
Draft(8B):   토큰 1,2,3,4,5 빠르게 생성 (1 스텝)
Target(70B): 5개 토큰을 한 번에 검증 → 4개 수락, 1개 재생성 (1 스텝)
             → 총 2 스텝으로 4개 토큰 생성 (2.5x 가속)

vLLM에서의 사용

# 추측적 디코딩 활성화
python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Llama-3.1-70B-Instruct \
    --speculative-model meta-llama/Llama-3.1-8B-Instruct \
    --num-speculative-tokens 5 \
    --speculative-draft-tensor-parallel-size 1

성능 효과

시나리오일반추측적 디코딩가속비
코드 생성 (반복 패턴 많음)30 tok/s75 tok/s2.5x
일반 대화30 tok/s55 tok/s1.8x
창작 글쓰기 (예측 어려움)30 tok/s40 tok/s1.3x

참고: 예측 가능성이 높은 태스크(코드, 형식화된 출력)에서 가속 효과가 큽니다.


5. 배치 처리와 스케줄링

Continuous Batching

[Static Batching]
배치 1: [요청A(100tok), 요청B(50tok), 요청C(200tok)]
→ 가장 긴 요청(C) 완료까지 전체 대기
→ A, B 완료 후에도 GPU 유휴

[Continuous Batching]
시점 1: [A, B, C] 동시 처리
시점 2: B 완료 → D 즉시 추가 [A, D, C]
시점 3: A 완료 → E 즉시 추가 [E, D, C]
→ GPU 유휴 시간 최소화

처리량 최적화 설정

# vLLM 최적화 설정
python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Llama-3.1-8B-Instruct \
    --max-num-seqs 256 \            # 최대 동시 시퀀스
    --max-num-batched-tokens 8192 \ # 배치당 최대 토큰
    --gpu-memory-utilization 0.9 \  # GPU 메모리 활용률
    --enable-chunked-prefill \      # 청크 프리필 활성화
    --max-model-len 4096

6. 추가 최적화 기법

FlashAttention

GPU는 빠르지만, GPU 메모리와 연산 코어 사이를 데이터가 오가는 것 자체가 병목이 됩니다. FlashAttention은 이 이동 횟수를 획기적으로 줄이는 방식으로 Attention 연산의 메모리 접근 패턴을 최적화하여 속도를 향상시킵니다. 알고리즘 자체를 바꿔서 수학적으로 같은 결과를 훨씬 빠르게 구하는 거예요.

버전속도 향상메모리 절감지원 GPU
FlashAttention-12~4xO(N) → O(√N)A100+
FlashAttention-25~9x (FP16)동일A100+
FlashAttention-31.5~2x (추가)FP8 지원H100

Prefix Caching

같은 회사 소개를 100명의 사용자에게 100번 읽히는 것은 낭비입니다. Prefix Caching은 동일한 시스템 프롬프트를 공유하는 모든 요청에서 프리픽스 KV Cache를 재사용하여, 이미 처리한 공통 부분을 다시 계산하지 않습니다.

요청 1: [시스템 프롬프트 (공통)] + [사용자 질문 A]
요청 2: [시스템 프롬프트 (공통)] + [사용자 질문 B]
요청 3: [시스템 프롬프트 (공통)] + [사용자 질문 C]

→ 시스템 프롬프트의 KV Cache를 1번만 계산, 3번 재사용
→ TTFT 50~80% 감소 (시스템 프롬프트가 긴 경우)
# vLLM에서 Prefix Caching 활성화
python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Llama-3.1-8B-Instruct \
    --enable-prefix-caching

텐서 병렬 (Tensor Parallelism)

# 4개 GPU로 70B 모델 실행
python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Llama-3.1-70B-Instruct \
    --tensor-parallel-size 4
병렬 전략분할 대상적합 상황
Tensor Parallel레이어 내부 (가중치)단일 노드 멀티 GPU
Pipeline Parallel레이어 간 (깊이)멀티 노드
Data Parallel요청 (복제)동일 모델 N개 인스턴스

7. 최적화 전략 요약

시나리오별 최적화 가이드

목표핵심 기법기대 효과
모델 메모리 절감양자화 (AWQ/GGUF Q4)모델 크기 75% 감소
동시 처리량 증가PagedAttention + Continuous Batching처리량 2~4배
첫 토큰 속도 향상Prefix Caching + FlashAttentionTTFT 50~80% 감소
토큰 생성 속도 향상추측적 디코딩TPS 1.5~2.5배
대형 모델 실행텐서 병렬70B+ 모델 서빙 가능
비용 절감양자화 + 소형 모델GPU 비용 60~80% 절감

적용 우선순위 (권장)

Loading diagram…

참고: 최적화 기법들은 대부분 조합하여 사용할 수 있습니다. 양자화 + PagedAttention + Continuous Batching + Prefix Caching을 함께 적용하면 최대 효과를 얻을 수 있습니다.


마치며 — 핵심 요약

  • 양자화는 가장 쉽고 효과가 큰 첫 번째 선택지입니다. AWQ(GPU 서빙)나 GGUF Q4_K_M(CPU/로컬)으로 메모리를 최대 75%까지 줄일 수 있습니다.
  • PagedAttention + Continuous Batching은 vLLM의 핵심으로, GPU 메모리 낭비를 막고 동시 처리량을 2~4배 높여줍니다.
  • Prefix Caching은 시스템 프롬프트가 긴 서비스에서 TTFT를 50~80% 줄이는 즉효약입니다.
  • 추측적 디코딩은 코드 생성처럼 예측 가능성이 높은 태스크에서 토큰 생성 속도를 최대 2.5배 높입니다.
  • FlashAttention은 대부분의 최신 서빙 프레임워크에 이미 내장되어 있으니, 활성화 여부만 확인하면 됩니다.
  • 이 기법들은 대부분 조합해서 쓸 수 있습니다. 하나씩 차근차근 적용하다 보면 어느새 GPU 비용이 확연히 줄어 있을 거예요.

References

  • Kwon, W. et al. (2023). "Efficient Memory Management for Large Language Model Serving with PagedAttention." SOSP
  • Dao, T. (2024). "FlashAttention-2: Faster Attention with Better Parallelism and Work Partitioning." ICLR
  • Leviathan, Y. et al. (2023). "Fast Inference from Transformers via Speculative Decoding." ICML
  • Frantar, E. et al. (2023). "GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers." ICLR
  • Lin, J. et al. (2024). "AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration." MLSys
  • Ainslie, J. et al. (2023). "GQA: Training Generalized Multi-Query Transformer Models." EMNLP

— Data Dynamics 엔지니어링 팀