Documents
Home>Documents>AI>Inference

vLLM의 Preemption 전략 해부: KV 캐시 Swap과 Recompute는 어떤 상황에서 갈리는가

9 min readSep 5, 2026Sep 5, 2026

LLM 서빙에서 KV 캐시 eviction 정책 — 어떤 캐시를 버릴 것인지 — 은 많이 다뤄진다. 덜 다뤄지는 건 그 다음 단계다. 버린 뒤, 해당 요청이 재개될 때 어떻게 복구할 것인가.

스케줄러가 현재 실행 중인 요청을 중단(preempt)할 때, KV 블록을 어디로 보내느냐에 따라 경로가 갈린다. CPU DRAM으로 오프로드하고 나중에 읽어오는 방식이 Swap이다. 아예 버리고 요청이 재개될 때 처음부터 다시 Prefill하는 방식이 Recompute다. vLLM V1은 기본값을 Recompute로 설정한다. 이미 계산해둔 걸 버린다는 게 낭비처럼 보이지만, 실제 비용 구조를 보면 이 선택은 합리적이다.

메모리 압박 상황에서 스케줄러가 직면하는 것

KV 캐시 공간이 부족해질 때 스케줄러에는 세 가지 경로가 있다.

첫 번째는 대기(waiting)다. 새 요청 수락을 멈추고 현재 배치가 자연스럽게 줄어들길 기다린다. GPU throughput을 희생하는 대신 구현이 단순하고 기존 KV 캐시에 손을 대지 않는다. 두 번째가 Swap — 선점된 시퀀스의 KV 블록을 CPU DRAM으로 내리고, 다시 스케줄될 때 읽어온다. 세 번째가 Recompute — 블록을 그냥 버리고 재개 시 해당 시퀀스를 처음부터 Prefill한다.

Swap과 Recompute를 고를 때 직관은 Swap 쪽으로 기울어진다. "계산을 다시 하는 건 낭비"라는 감각. 하지만 이 감각은 CPU↔GPU 전송 비용을 과소평가한다.

Swap의 실제 비용

Swap 비용은 전적으로 전송 시간이다. 얼마를 전송하느냐는 KV 캐시 크기로 결정된다.

KV_bytes = 2 × num_layers × num_kv_heads × head_dim × seq_len × dtype_bytes

앞의 2는 K와 V 두 행렬을 각각 저장하기 때문이다. Llama-3 8B를 예로 들면 num_layers = 32, num_kv_heads = 8(GQA), head_dim = 128, BF16 = 2 bytes로 토큰당 2 × 32 × 8 × 128 × 2 = 131,072 bytes = 128 KB다.

시퀀스 길이 기준으로 환산하면:

시퀀스 길이KV 캐시 크기PCIe 4.0 이론 전송 (~30 GB/s)PCIe 3.0 이론 전송 (~15 GB/s)
512 토큰64 MB2 ms4 ms
1K 토큰128 MB4 ms9 ms
2K 토큰256 MB9 ms17 ms
4K 토큰512 MB17 ms34 ms
8K 토큰1 GB34 ms68 ms

여기에 두 가지를 덧붙여야 한다. 하나는 실제 PCIe 전송에 커널 런칭 고정 오버헤드가 붙는다는 점이다. 데이터가 작을수록 이 오버헤드의 비율이 커져 표의 숫자보다 훨씬 느려진다. vLLM PagedAttention 논문에서 블록 크기가 작을수록 Swap 효율이 급격히 떨어지는 이유가 이것이다 — 작은 블록을 수백 번 전송할 때 PCIe 대역폭보다 전송당 고정 오버헤드가 병목이 된다. 다른 하나는 Preemption 시 쓰기(GPU→CPU)와 재개 시 읽기(CPU→GPU)가 각각 발생한다는 점이다. 4K 토큰 시퀀스 하나의 왕복 전송 시간은 PCIe 4.0 기준으로 34ms가 된다.

Recompute가 경쟁력을 갖는 이유

Recompute는 짧은 Prefill이다. 선점된 시퀀스를 새 프롬프트처럼 취급하고 처음부터 어텐션·MLP 연산을 다시 돌린다.

이 연산이 얼마나 빠른지는 시퀀스 길이에 따라 크게 달라진다. Roofline 관점에서 보면, Prefill 커널의 산술 강도(FLOPs/byte)는 시퀀스가 짧을수록 낮다. A100 SXM의 Ridge point는 BF16 기준 대략 156 FLOPs/byte인데, 짧은 시퀀스의 Prefill은 이 값을 밑돌아 HBM 대역폭에 묶인다. 연산 유닛이 메모리 전송을 기다리는 구간이라는 뜻이고, 이론 FLOPs에서 예측하는 것보다 실제 시간이 훨씬 짧다.

배치 처리도 핵심 변수다. 고처리량 서빙 환경에서 Recompute 대상 시퀀스는 다음 Prefill 배치에 합류해 신규 요청들과 함께 처리된다. 해당 시퀀스를 추가했을 때 증가하는 한계 비용은, 그 시퀀스를 단독으로 처리하는 비용보다 훨씬 작다. Swap 재개 시 CPU→GPU 전송은 그 반대다 — 해당 시퀀스만을 위해 PCIe를 단독으로 소비하는 직렬 비용이다.

vLLM 논문(Kwon et al., 2023) Figure 19의 마이크로벤치마크가 이를 뒷받침한다. 실험 결과에서 Recompute 오버헤드는 Swap 대비 최대 20% 느린 수준에서 상한이 잡혔다. 블록 크기가 작을수록 Recompute가 크게 유리하고, 블록 크기가 클수록 두 방식이 수렴하지만 역전되지는 않는다. 즉, Recompute는 최악의 경우에도 Swap보다 20%만 느리고, 대부분의 경우 더 빠르다.

Swap이 이길 수 있는 조건

두 가지 상황에서 Swap이 의미 있는 우위를 갖는다.

PCIe 대역폭이 충분히 넓고 블록 크기가 커서 전송 오버헤드가 작을 때다. PCIe 4.0 환경에서 8K 토큰 이상의 긴 시퀀스를 처리하는 문서 요약이나 코드 생성 서빙이라면, 34ms 단방향 전송도 대규모 Prefill 재계산보다 빠를 수 있다. 특히 Attention FLOPs가 시퀀스 길이의 제곱으로 증가하는 구간에서 긴 시퀀스의 Recompute 비용은 빠르게 커진다.

같은 요청이 여러 번 선점될 때도 Swap이 유리해진다. Recompute는 재개할 때마다 전체 Prefill을 다시 돌린다. Swap은 처음 CPU로 이동한 KV를 계속 보존한다. 한 요청이 세 번 선점되면 Recompute는 같은 시퀀스를 세 번 계산하지만, Swap은 쓰기 한 번 + 읽기 한 번으로 끝난다. 부하가 집중되는 구간에서 장시간 대기하는 요청이 많은 환경이라면 이 차이가 누적된다.

서빙 환경권장 전략
챗봇 · 짧은 컨텍스트 (≤ 2K), 고처리량 배치Recompute
문서 요약 · 긴 컨텍스트 (8K+), 단일 요청 반복 선점Swap 고려
PCIe 3.0 환경Recompute (전송 효율 낮아 Swap 우위 없음)
vLLM V1 일반 배포Recompute (기본값 유지)

vLLM의 구현과 기본값 선택

vLLM은 --preemption-mode 인자로 두 모드를 전환한다. V0에서는 Swap이 더 적극적으로 활용됐지만, V1 아키텍처로 전환하면서 Recompute가 기본값이 됐다.

V1에서 Recompute를 선택한 배경은 아키텍처 변화와 맞닿아 있다. V1은 Worker와 Scheduler가 별도 프로세스로 분리된 구조다. Swap을 사용하면 IPC(프로세스 간 통신)를 통해 블록 이동을 조율해야 한다. 여기서 발생하는 오버헤드가 Swap의 이론적 우위를 상쇄하는 방향으로 작용한다. Recompute는 해당 시퀀스를 다시 Prefill 큐에 넣으면 된다 — 프로세스 간 조율 없이 구현이 단순하게 유지된다.

Swap 모드를 쓰려면 --swap-space를 함께 지정해야 한다. 이 공간은 실제 CPU 핀 메모리(pinned memory)로 할당되므로, 크게 잡으면 CPU 메모리 사용량이 눈에 띄게 늘어난다.

vllm serve meta-llama/Llama-3-8B-Instruct \
  --preemption-mode swap \
  --swap-space 8    # GB 단위, 기본값 4GB

SGLang은 접근이 다르다. Preemption 자체의 발생 빈도를 최소화하는 방향으로 배치 크기를 조절하고, 발생 시에는 Recompute를 사용한다. 두 프레임워크 모두 Recompute를 기본 복구 전략으로 수렴한 셈이고, 이 선택의 근거는 공통적으로 PCIe 전송 오버헤드와 배치 아래서의 비용 분산에 있다.

운영에서 보는 법

vLLM이 Prometheus로 노출하는 vllm:num_preemptions_total이 이 문제의 첫 번째 신호다. 전체 요청 대비 Preemption 비율이 수 % 이내라면 기본 설정에서 실질적 손실이 없다. 10%를 넘기 시작하면 배치 설정을 손봐야 한다.

개입 순서:

  1. --max-num-seqs 감소 — 동시 처리 시퀀스 수를 줄여 Preemption 발생 자체를 억제한다.
  2. --gpu-memory-utilization 상향 (기본 0.9 → 0.95) — KV 캐시에 할당되는 공간이 늘어 Preemption 발생이 줄어든다. OOM 여유를 확인하고 올린다.
  3. 양자화(AWQ / GPTQ) — 가중치를 4비트로 줄여 KV 캐시 할당 가능 공간을 확보한다.
  4. GPU 증설 · Tensor Parallelism — 모델을 분산해 각 GPU의 KV 캐시 공간을 늘린다.

Preemption 빈도가 20%를 넘는 상황에서 --preemption-mode swap으로 전환하는 건 대부분 올바른 처방이 아니다. Preemption 빈도 자체는 줄지 않고, 환경에 따라 복구 비용이 오히려 늘어난다. 먼저 KV 캐시 공간을 늘리거나 동시 요청 수를 줄이는 쪽이 실질적인 개선으로 이어진다.

Tags
LLMvLLMKV 캐시Inference서빙GPU메모리아키텍처