KV 오프로딩 사용 가이드

KV 오프로딩 사용 가이드 (KV Offloading Usage Guide)

KV 캐시(KV cache)는 LLM 추론에서 큰 메모리를 차지해요. KV 오프로딩(KV Offloading) 은 완료된 KV 블록을 더 느리지만 더 큰 저장소(CPU 호스트 메모리 + 선택적으로 2차 저장소)로 오프로딩해 접두사 캐시(prefix cache)를 확장하는 기법이에요. 이 가이드는 그 동작을 담당하는 OffloadingConnector의 구성을 다룹니다.

출처: vLLM 공식 문서 — kv_offloading_usage

개요 (Overview)

오프로딩 티어에 적중(hit)한 블록은 필요할 때 GPU로 다시 승격(promote) 됩니다. GPU와 CPU 사이의 전송은 DMA(cudaMemcpyAsync) 를 사용하며, 모델 연산과 비동기로 함께 실행되기 때문에 CPU/GPU 코어 오버헤드가 최소화돼요.

📌 참고: OffloadingConnector는 현재 CUDA, ROCm, XPU만 지원합니다.

사용 가능한 스펙(spec)은 두 가지이며, kv_connector_extra_config 안의 spec_name 키로 선택해요.

  • CPUOffloadingSpec (기본값) — 단일 CPU 티어. 완료된 GPU 블록이 고정(pinned) 호스트 메모리에 복사됩니다.
  • TieringOffloadingSpec (다중 티어) — CPU 1차 티어 + 하나 이상의 2차 티어(secondary tier).

전체 구조를 다이어그램으로 보면 대략 이렇습니다.

flowchart LR
    GPU <--> CPU["CPU primary tier"]
    CPU <--> S0["Secondary tier 0"]
    CPU <--> S1["Secondary tier 1"]
    CPU <--> SN["..."]

GPU → CPU(1차 티어) → 2차 티어들로 이어지는 계층 구조예요.

단일 티어 설정 (CPU 전용: Single-Tier Setup)

CPU만 쓰는 가장 단순한 구성입니다.

vllm serve <model> \
  --kv-transfer-config '{
    "kv_connector": "OffloadingConnector",
    "kv_role": "kv_both",
    ...

다중 티어 설정 (Multi-Tier Setup)

spec_name"TieringOffloadingSpec"으로 설정하고 secondary_tiers 목록을 제공하면 돼요. 각 항목은 필수 type 키와 티어별 필드를 가진 딕셔너리예요. 목록의 순서가 중요해서, 티어 0이 티어 1보다 먼저 조회됩니다.

vllm serve <model> \
  --kv-transfer-config '{
    "kv_connector": "OffloadingConnector",
    "kv_role": "kv_both",
    "kv_connector_extra_config": {
      ...
    }
  }'

kv_connector_extra_config 레퍼런스

주요 설정 키를 정리하면 이렇습니다.

Key 필수 기본값 범위 설명
spec_name 아니오 CPUOffloadingSpec both 다중 티어로 쓰려면 TieringOffloadingSpec으로 설정
block_size 아니오 GPU 블록 크기 both 오프로딩 블록 크기(토큰 단위). GPU 블록 크기의 배수여야 하며 blocks_per_chunk와 상호 배타적
blocks_per_chunk 아니오 1 both 오프로딩 청크 크기(GPU 블록 단위). 0보다 커야 함
eviction_policy 아니오 lru both 1차 티어 정책: lru 또는 arc
store_threshold 아니오 0 single-tier 블록이 오프로딩되기 전 최소 조회 수. TieringOffloadingSpec에서는 2 이상 값이 거부됨
max_tracker_size 아니오 64000 single-tier 조회 추적기의 최대 항목 수
secondary_tiers 아니오 [] multi-tier 2차 티어 설정 목록
offload_prompt_only 아니오 true both true면 프롬프트(프리필) 블록만 오프로딩하고 디코드 블록은 건너뜀
spec_module_path 아니오 both 내장 레지스트리에 없는 커스텀 OffloadingSpec의 Python import 경로

2차 티어 (Secondary Tiers)

2차 티어는 type 키로 구분됩니다.

파일시스템 (FS)

  • type필수, 반드시 fs.
  • localityLOCAL/REMOTE. 명시적으로 설정된 경우에만 티어의 KV 이벤트에 포함.

디스크 레이아웃: root_dir 아래에 vLLM이 <model>_<digest> 하위 디렉토리를 만들어요. <model>/_로 바꾼 모델 이름(예: meta-llama/Llama-3-8B), <digest>는 실행 구성(모델, 블록 크기 등)에서 파생된 짧은 SHA256 접두사예요.

프로세스 간 공유: 같은 root_dir(예: 공유 PVC)로 여러 vLLM 인스턴스 간 KV 캐시를 공유하려면, 모든 인스턴스에 PYTHONHASHSEED 환경 변수를 같은 고정값(예: "0")으로 설정해야 해요.

오브젝트 스토어 (OBJ)

  • type필수, 반드시 obj.
  • enable_kv_events — 성공적으로 저장된 블록에 대해 BlockStored KV 이벤트를 게시할지 여부.
  • localityLOCAL/REMOTE.

오브젝트 키는 파일시스템 티어와 같은 실행 구성 다이제스트 방식을 따르며, 선택적 prefix 아래에 저장돼요.

P2P (P/D 포함)

UCX 전용 에이전트로, 설정된 num_threads를 사용해요. 이 방식을 쓰면 P2P 티어가 같은 프로세스에서 실행되는 메인 NixlConnector와 다른 전송(예: MOONCAKE, GDS_MT, LIBFABRIC)을 사용할 수 있습니다.

기본값은 루프백 인터페이스에만 바인딩하므로 다른 호스트의 피어는 접근할 수 없어요. 크로스 호스트 P2P 배포라면 노드의 라우팅 가능한 IP로 명시적으로 설정해야 합니다.

튜닝 팁 (Tuning Tips)

  • 단일 티어(CPU 전용): cpu_bytes_to_use를 GPU KV 캐시 전체보다 크게 설정하세요. 오프로딩이 즉시 일어나므로, 더 작은 CPU 티어는 GPU가 이미 가진 것을 그대로 반영할 뿐 적중률을 높이지 못해요.
  • block_size / blocks_per_chunk: 오프로딩 청크가 클수록 블록별 부기(bookkeeping) 오버헤드는 줄지만, 조회의 세분성(granularity)은 커집니다.
  • FS 스레드 수: n_read_threadsn_write_threads를 저장소가 버틸 수 있는 병렬도에 맞춰 튜닝하세요.

요청별 선택적 오프로드 (Per-Request Selective Offload)

개별 요청은 kv_transfer_paramsmax_offload_tokens로 오프로딩할 수 있는 토큰 수를 제한할 수 있어요. 요청의 첫 max_offload_tokens 토큰만 오프로딩되고, 그 이후 블록은 저장 경로에서 건너뜁니다.

Key 타입 설명
max_offload_tokens non-negative int 이 요청에서 오프로딩할 토큰 수의 상한. 0이면 요청의 오프로딩을 완전히 비활성화. 키를 생략하거나 None이면 제한 없음. 정수가 아니거나 음수, bool 값은 경고와 함께 거부되고 무제한으로 처리

이 기능은 알려진 접두사(예: 시스템 프롬프트나 공유 컨텍스트)는 캐시할 가치가 있지만, 이후 요청별 토큰은 그렇지 않을 때 유용해요.

{
  "model": "<model>",
  "prompt": "...",
  "kv_transfer_params": {
    "max_offload_tokens": 1024
  }
}

더 알아보기 (Learn more)