Prefix Caching

김동준·2025년 10월 20일

Prefix Caching은 반복되는 프롬프트의 앞부분(prefix)을 캐싱하여 재사용하는 최적화 기법입니다.

핵심 아이디어

동일하거나 유사한 프롬프트가 반복될 때, 매번 처음부터 다시 계산하지 않고 공통 부분의 KV 캐시를 재사용합니다.

실제 사용 사례

1. 시스템 프롬프트가 있는 챗봇

요청 1:
[시스템 프롬프트 1000토큰] + "Python으로 정렬 알고리즘 작성해줘"
→ 전체 계산

요청 2:
[시스템 프롬프트 1000토큰] + "JavaScript로 API 호출 예제 보여줘"
→ 시스템 프롬프트는 캐시 재사용! (1000토큰 prefill 생략)

2. RAG (Retrieval-Augmented Generation)

[긴 문서/컨텍스트 5000토큰] + "질문 1"
[긴 문서/컨텍스트 5000토큰] + "질문 2"
[긴 문서/컨텍스트 5000토큰] + "질문 3"
→ 문서는 한 번만 처리, 질문만 매번 추가

3. Few-shot 프롬프팅

[예제 1, 예제 2, 예제 3... 2000토큰] + "새로운 입력 1"
[예제 1, 예제 2, 예제 3... 2000토큰] + "새로운 입력 2"
→ 예제들은 캐시 재사용

작동 방식

1. 기본 메커니즘

첫 번째 요청:
입력: [A][B][C][D]
처리: Prefill 전체 → KV 캐시 생성 및 저장
캐시 키: hash([A][B][C])

두 번째 요청:
입력: [A][B][C][E]
처리: 
  - [A][B][C]: 캐시 HIT! → 재사용
  - [E]: 새로 계산
  - 전체 prefill 시간의 75% 절약!

2. 캐시 매칭

완전 일치 방식 (Exact Match):

  • 토큰 시퀀스가 정확히 일치해야 함
  • 가장 간단하고 확실

해시 기반:

# 의사 코드
def get_cache_key(tokens):
    return hash(tuple(tokens))

# 캐시 조회
cache_key = get_cache_key(prefix_tokens)
if cache_key in kv_cache_store:
    return kv_cache_store[cache_key]

3. 계층적 캐싱

레벨 1: [시스템 프롬프트]
레벨 2: [시스템 프롬프트] + [문서 컨텍스트]
레벨 3: [시스템 프롬프트] + [문서 컨텍스트] + [대화 기록]

각 레벨을 독립적으로 캐싱하여 유연성 향상

성능 개선

시간 절약:

시스템 프롬프트: 1000토큰 (prefill 시간: 100ms)
사용자 입력: 50토큰 (prefill 시간: 5ms)

캐싱 없이: 105ms
캐싱 있을 때: 5ms
→ 95% 시간 절약!

비용 절감:

  • 일부 API 서비스(예: Anthropic Claude)는 캐시된 토큰에 대해 90% 할인 제공
  • 반복적인 워크로드에서 큰 비용 절감

구현 고려사항

1. 캐시 저장소

In-memory: 빠르지만 재시작 시 손실
Redis/Memcached: 영구 저장, 여러 서버 간 공유
로컬 디스크: 대용량, 느림

2. 캐시 만료 정책 (Eviction)

  • LRU (Least Recently Used): 가장 오래 사용 안 된 것 제거
  • TTL (Time To Live): 시간 기반 만료
  • 크기 기반: 메모리 한계 도달 시 제거

3. 캐시 키 설계

# 세밀한 캐시 키
cache_key = {
    'model_id': 'gpt-4',
    'tokens': tuple(tokens),
    'temperature': 0.7,  # 생성 파라미터도 포함할지?
}

PagedAttention과의 결합

PagedAttention + Prefix Caching = 최강 조합!

물리 블록 풀:
[1][2][3][4][5][6][7][8]...

요청 A (시스템 프롬프트 + 질문1):
논리: [prefix][query1]
물리: [1][2] + [5]

요청 B (동일 시스템 프롬프트 + 질문2):
논리: [prefix][query2]
물리: [1][2] + [7]  ← prefix 블록 [1][2] 공유!

실제 시스템 예시

1. Anthropic Claude

  • Prompt Caching 기능 제공
  • 캐시된 토큰: 정상 가격의 10%
  • 5분간 유효

2. vLLM

  • Automatic Prefix Caching (APC) 지원
  • PagedAttention과 통합

3. TGI (Text Generation Inference)

  • Prefix caching 기본 지원

최적화 팁

1. 프롬프트 구조화

❌ 나쁜 예:
"질문: {질문} 시스템: {시스템_프롬프트}"

✅ 좋은 예:
"{시스템_프롬프트} 질문: {질문}"
→ prefix가 앞에 있어야 캐싱 효과적!

2. 배치 처리

동일한 prefix를 가진 요청들을 묶어서 처리
→ 캐시 히트율 극대화

3. 캐시 워밍 (Warming)

자주 사용되는 prefix를 미리 캐싱
→ 첫 요청부터 빠른 응답

성능 지표

실제 벤치마크 (시스템 프롬프트 1000토큰 기준):

지표개선도
Prefill 시간90% 감소
전체 지연시간30-50% 감소
처리량2-3배 향상
비용 (API)80-90% 절감

한계점

1. 메모리 오버헤드

  • 캐시 저장 공간 필요
  • 너무 많은 prefix 캐싱 시 메모리 부족

2. 캐시 미스 패널티

  • 조회 오버헤드
  • 복잡한 매칭 로직

3. 가변성 문제

프롬프트에 타임스탬프나 무작위 요소가 있으면:
"현재 시각은 {timestamp}입니다..."
→ 매번 다르므로 캐싱 불가

Prefix Caching은 특히 반복적인 패턴이 있는 워크로드(챗봇, RAG, 에이전트 등)에서 매우 효과적인 최적화 기법입니다!

profile
Story Engineer

0개의 댓글