KV 캐시 최적화: 프로덕션 LLM을 위한 메모리 효율성
2025년 12월 11일 업데이트
2025년 12월 업데이트: 기존 추론 방식은 단편화로 인해 KV 캐시 메모리의 60-80%를 낭비합니다. vLLM의 PagedAttention은 낭비를 4% 미만으로 줄여 2-4배의 처리량 향상을 가능하게 합니다. 8K 컨텍스트를 가진 70B 모델은 요청당 약 20GB의 캐시가 필요하며, 배치 크기 32의 경우 약 640GB가 필요합니다. 현재 KV 캐시는 메모리 소비량에서 모델 가중치를 초과하는 경우가 많습니다. 최적화 기술을 통해 기존 하드웨어에서 더 긴 컨텍스트와 더 큰 배치를 처리할 수 있습니다.
LLM 추론 시스템은 단편화와 과도한 할당으로 인해 할당된 KV 캐시 메모리의 60-80%를 낭비합니다.¹ 이러한 낭비는 처리량 감소, 비용 증가, 컨텍스트 길이에 대한 인위적인 제한으로 직결됩니다. vLLM이 도입한 PagedAttention은 KV 캐시 낭비를 4% 미만으로 줄여 프로덕션 추론 경제성을 혁신하는 2-4배의 처리량 향상을 실현했습니다.² KV 캐시 최적화 기술을 이해하면 조직은 GPU 활용도를 극대화하고 기존 인프라에서 더 많은 사용자에게 서비스를 제공할 수 있습니다.
KV 캐시 관리는 프로덕션 LLM 배포에서 가장 중요한 병목 지점이 되었습니다. 메모리 소비량은 시퀀스 길이와 배치 크기에 따라 선형적으로 증가하여 H100, H200과 같은 고용량 메모리 GPU도 금세 소진됩니다. 캐시 최적화 기술을 마스터하면 더 긴 컨텍스트, 더 큰 배치, 그리고 대규모에서 더 비용 효율적인 추론이 가능해집니다.
KV 캐싱이 중요한 이유
Transformer 모델은 각 새로운 토큰을 생성할 때 이전의 모든 토큰에 대해 어텐션을 계산합니다. 캐싱이 없으면 1,000개의 토큰을 생성하려면 어텐션을 처음부터 1,000번 다시 계산해야 하며, 이는 시퀀스 길이에 따라 비용이 이차적으로 증가합니다.
KV 캐싱 솔루션: 이전 토큰의 key와 value 텐서를 저장하고 이후 어텐션 계산에 재사용합니다. 각 새로운 토큰은 값을 재생성하는 대신 캐시된 값에 대해 어텐션을 계산합니다.
메모리 영향: 배치 크기 32로 8,192개의 토큰을 생성하는 70B 파라미터 모델은 KV 캐시 메모리만 약 40-50GB가 필요하며, 이는 종종 모델 가중치 자체를 초과합니다.³
스케일링 문제: KV 캐시 메모리는 다음과 같이 증가합니다:
Memory = batch_size × seq_length × num_layers × 2 × hidden_dim × precision_bytes
FP16을 사용하는 Llama 3.1-70B의 경우: - 토큰당 캐시: ~2.5MB - 8K 컨텍스트: 요청당 ~20GB - 배치 32: 총 KV 캐시 ~640GB
PagedAttention: 기본적인 최적화
vLLM의 PagedAttention은 운영 체제의 가상 메모리처럼 GPU 메모리를 처리하여 KV 캐시 관리를 혁신했습니다:⁴
작동 방식
기존 할당: 최대 가능한 시퀀스 길이에 대해 연속된 메모리 블록을 예약합니다. 4K 최대 컨텍스트는 100토큰 요청에도 4K 분량의 캐시를 할당하여 예약된 메모리의 97.5%를 낭비합니다.
페이지 할당: KV 캐시를 고정 크기 블록(페이지)으로 나눕니다. 시퀀스가 증가함에 따라 필요에 따라 페이지를 할당합니다. 시퀀스가 완료되면 페이지를 해제합니다.
블록 테이블 매핑: OS 페이지 테이블처럼 PagedAttention은 논리적 시퀀스 위치와 물리적 메모리 위치 간의 매핑을 유지합니다. 시퀀스는 연속적인 메모리를 보지만 물리적 저장소는 비연속적으로 유지됩니다.
성능 영향
- 메모리 낭비: 60-80% → 4% 미만
- 처리량: 기존 할당 대비 2-4배 향상
- 메모리 단편화: 사실상 제거⁵
vLLM에서의 구현
from vllm import LLM, SamplingParams
# PagedAttention은 기본적으로 활성화됨
llm = LLM(
model="meta-llama/Llama-3.1-70B-Instruct",
tensor_parallel_size=4,
gpu_memory_utilization=0.90, # GPU 메모리의 90% 사용
max_model_len=32768,
)
vLLM은 명시적인 설정 없이 페이지 할당, 해제, 메모리 공유를 자동으로 관리합니다.
접두사 캐싱과 메모리 공유
PagedAttention은 공통 접두사를 가진 요청 간에 효율적인 메모리 공유를 가능하게 합니다:
공유 시스템 프롬프트: 여러 요청이 동일한 시스템 프롬프트를 사용할 때, 해당 토큰을 저장하는 물리적 페이지는 복제되지 않고 공유됩니다.
자동 접두사 캐싱: vLLM의 Automatic Prefix Caching(APC)은 요청 간 공통 접두사를 감지하고 KV 캐시 블록을 자동으로 공유합니다:
llm = LLM(
model="meta-llama/Llama-3.1-8B-Instruct",
enable_prefix_caching=True,
)
프로덕션 영향: 일관된 시스템 프롬프트나 반복되는 컨텍스트(공통 문서를 사용하는 RAG, few-shot 예제)가 있는 애플리케이션은 상당한 메모리 절감과 지연 시간 감소를 경험합니다. 잘 구조화된 프롬프트로 87% 이상의 캐시 적중률을 달성할 수 있습니다.⁶
KV 캐시 양자화
KV 캐시 값을 압축하면 약간의 정확도 저하를 감수하고 메모리 요구 사항을 줄일 수 있습니다:
FP8 KV 캐시
Hopper와 Blackwell GPU는 네이티브 FP8 KV 캐시를 지원합니다:
# vLLM FP8 KV 캐시
llm = LLM(
model="meta-llama/Llama-3.1-70B-Instruct",
kv_cache_dtype="fp8",
)
FP8은 대부분의 애플리케이션에서 품질 영향을 최소화하면서 FP16 대비 KV 캐시 메모리를 절반으로 줄입니다. 이 최적화는 캐시가 메모리 소비를 지배하는 긴 컨텍스트 추론에서 필수적입니다.
INT4 KV 캐시
실험적인 4비트 KV 캐시 지원으로 메모리를 더욱 줄일 수 있습니다:⁷ - 메모리 감소: FP16 대비 4배 - 품질 영향: 작업에 따라 다름, 평가 필요 - 최적 용도: 메모리 제약이 있는 긴 컨텍스트 애플리케이션
양자화 선택
| 정밀도 | 메모리 절감 | 품질 영향 | 사용 사례 |
|---|---|---|---|
| FP16 | 기준선 | 없음 | 기본값, 품질 중요 |
| FP8 | 50% | 최소 | 프로덕션 추론 |
| INT8 | 50% | 낮음 | 비용 민감한 배포 |
| INT4 | 75% | 보통 | 극단적인 메모리 제약 |
캐시 축출 전략
메모리 압박이 가용 용량을 초과하면 캐시 축출 정책이 어떤 토큰을 삭제할지 결정합니다:
슬라이딩 윈도우 어텐션
캐시에 최근 토큰만 유지하고 오래된 컨텍스트는 삭제합니다:
# 개념적 슬라이딩 윈도우
def sliding_window_cache(kv_cache, window_size):
if len(kv_cache) > window_size:
kv_cache = kv_cache[-window_size:]
return kv_cache
최근 컨텍스트가 가장 중요한 애플리케이션에 간단하지만 효과적입니다. 아키텍처 슬라이딩 윈도우(Mistral과 같은)는 이를 기본적으로 구현합니다.
어텐션 기반 축출
어텐션 점수가 가장 낮은 토큰을 제거하고 중요한 컨텍스트를 유지합니다:
PagedEviction (2025): CUDA 커널을 수정하지 않고 중요도가 낮은 블록을 식별하고 제거하는 PagedAttention에 맞춤화된 블록 단위 축출 알고리즘입니다.⁸
엔트로피 기반 캐싱: 레이어 어텐션 엔트로피를 기반으로 캐시 예산을 할당합니다. 더 넓은 어텐션 패턴을 가진 레이어는 더 많은 캐시를 받고, 집중된 레이어는 더 적게 받습니다.⁹
Streaming LLM
무한 길이 생성을 위해 Streaming LLM은 다음을 유지합니다: - 초기 "어텐션 싱크" 토큰(첫 4-8개 토큰) - 슬라이딩 윈도우 내의 최근 토큰 - 중간 컨텍스트 삭제
이 접근 방식은 고정 메모리로 이론적으로 무제한 생성을 가능하게 하지만, 장거리 의존성이 필요한 작업에서는 품질이 저하됩니다.
KV 캐시 오프로딩
GPU 메모리가 부족할 때 캐시를 더 느린 스토리지 계층으로 오프로드합니다:
CPU 오프로딩
비활성 시퀀스 캐시를 시스템 RAM으로 이동합니다:
# 오프로딩을 위한 LMCache 통합
from lmcache import LMCacheEngine
cache_engine = LMCacheEngine(
backend="cpu",
max_gpu_cache_size="20GB",
cpu_cache_size="100GB",
)
지연 시간 영향: CPU-GPU 전송은 캐시 검색당 10-50ms를 추가합니다. 배치 워크로드나 GPU 메모리 제한으로 인해 서비스가 불가능한 경우에 적합합니다.
성능: vLLM과 함께 사용하는 LMCache는 재생성 대신 CPU 메모리에 캐싱하여 3-10배의 지연 시간 감소를 달성합니다.¹⁰
디스크 오프로딩
극단적인 경우 NVMe 스토리지에 캐시합니다: - 지연 시간: 검색당 100-500ms - 사용 사례: 그렇지 않으면 불가능한 매우 긴 컨텍스트 - 대화형 애플리케이션에는 적합하지 않음
계층형 캐싱
프로덕션 시스템은 종종 다중 계층 캐싱을 구현합니다:
- GPU HBM: 활발하게 생성 중인 핫 시퀀스
- CPU RAM: 최근 활성화된 웜 시퀀스
- NVMe SSD: 잠재적 재사용을 위한 콜드 시퀀스
지능형 승격 및 강등 정책이 접근 패턴에 따라 계층 간에 캐시를 이동시킵니다.
KV 캐시 인식 라우팅
분산 추론은 관련 캐시를 보유한 파드로 요청을 라우팅하면 이점을 얻습니다:
llm-d 프레임워크
KV 캐시 인식 라우팅을 갖춘 Kubernetes 네이티브 프레임워크:¹¹
# llm-d 캐시 라우팅 구성
routing:
strategy: kv_cache_aware
cache_hit_weight: 0.8
load_balance_weight: 0.2
성능 결과: - 접두사가 많은 워크로드에서 87% 캐시 적중률 - 웜 캐시 적중 시 첫 토큰까지의 시간 88% 단축 - 클러스터 전체에서 중복 계산 상당히 감소
구현 패턴
스티키 세션: 동일한 대화의 요청을 동일한 파드로 라우팅합니다.
접두사 해싱: 시스템 프롬프트를 해시하여 파드 라우팅을 결정하고, 접두사 캐시 적중을 보장합니다.
부하 인식 라우팅: 핫스팟을 방지하기 위해 캐시 지역성과 파드 활용률의 균형을 맞춥니다.
프로덕션 사이징 가이드
메모리 추정
배포 전 KV 캐시 요구 사항을 계산합니다:
def estimate_kv_cache_memory(
num_layers: int,
hidden_dim: int,
num_kv_heads: int,
head_dim: int,
max_seq_len: int,
max_batch_size: int,
precision_bytes: int = 2, # FP16
) -> float:
"""KV 캐시 메모리를 GB 단위로 추정"""
per_token = num_layers * 2 * num_kv_heads * head_dim * precision_bytes
total = per_token * max_seq_len * max_batch_size
return total / (1024 ** 3)
# Llama 3.1-70B 예제
memory_gb = estimate_kv_cache_memory(
num_layers=80,
hidden_dim=8192,
num_kv_heads=8, # GQA
head_dim=128,
max_seq_len=8192,
max_batch_size=32,
)
print(f"KV 캐시 메모리: {memory_gb:.1f} GB")
용량 계획
경험 법칙: GPU 메모리의 40-60%를 KV 캐시용으로 예약하고, 나머지는 모델 가중치와 활성화에 사용합니다.
H100 80GB 예제: - 모델 가중치(70B FP16): ~140GB → 텐서 병렬화로 2x GPU - 캐시에 사용 가능한 GPU당 메모리: 가중치와 오버헤드 후 ~30-35GB - 최대 동시 시퀀스: 평균 컨텍스트 길이에 따라 다름
최적화 우선순위
- PagedAttention 활성화: vLLM에서 기본값, 주요 효율성 향상
- 접두사 캐싱 활성화: 워크로드에 공통 접두사가 있는 경우
- FP8 KV 캐시 구현: Hopper/Blackwell GPU 사용 시
- 캐시 인식 라우팅 추가: 분산 추론을 사용하는 클러스터 규모에서
- 오프로딩 고려: GPU 메모리가 부족할 때만
모니터링 및 관찰 가능성
프로덕션에서 KV 캐시 메트릭을 추적합니다:
주요 메트릭: - 캐시 활용률: 할당된 캐시 중 사용 중인 비율 - 캐시 적중률: 접두사 캐시 효과성 - 축출률: 캐시 오버플로우 빈도 - 메모리 단편화: 할당된 블록 내의 낭비 공간
vLLM 메트릭 엔드포인트:
# /metrics에서 Prometheus 메트릭 사용 가능
# kv_cache_usage_percent
# kv_cache_total_blocks
# kv_cache_used_blocks
# prefix_cache_hit_rate
알림 임계값: - 캐시 활용률 > 90%: 용량 확장 또는 배치 크기 축소 - 적중률 < 50%: 접두사 캐싱 구성 검토 - 축출률 높음: 메모리 할당 증가 또는 프롬프트 최적화
전 세계 배포에서 GPU 용량 계획 및 최적화를 위해 프로덕션 LLM 추론을 배포하는 조직은 Introl의 인프라 전문 지식을 활용할 수 있습니다.
메모리 효율성의 필수성
KV 캐시 최적화는 프로덕션 LLM 배포에서 가장 영향력 있는 개선 사항 중 하나입니다. PagedAttention만으로도 2-4배의 처리량 향상을 제공하며, 이는 추가 하드웨어 비용 없이 GPU 투자를 2배 또는 4배로 늘리는 것과 동등합니다.
최적화 환경은 계속 발전하고 있습니다. Microsoft의 FastGen은 적응형 압축을 통해 50%의 메모리 감소를 시연했습니다. 엔트로피 기반 캐싱은 레이어 전체에 지능적으로 예산을 할당합니다. 캐시 인식 라우팅은 이전에는 불가능했던 클러스터 규모의 효율성 향상을 가능하게 합니다.
대규모로 추론을 실행하는 조직에게 KV 캐시 최적화는 가장 먼저 평가해야 할 최적화 중 하나입니다. 이러한 기술은 최소한의 구성 변경만 필요로 합니다.