LLM WikiAccess-protected knowledge portal

WIKI

vLLM Decode Context Parallelism: 텐서 병렬성의 한계를 넘어 KV 캐시를 시퀀스 차원으로 샤딩하는 방법

요약 LLM 서빙에서 긴 컨텍스트를 다루는 방식이 바뀌고 있다. 지금까지 텐서 병렬성 TP 은 모델 가중치와 KV 캐시를 여러 GPU에 분산하는 표준 수단이었지만, GQA Grouped Query Attention 와 MLA Multi Head Latent Attention 가 주류 아키텍처가 되면서 TP만으로는 해결할 수 없는 메모리 병목이 드러났다. Decode Context Parallelism DCP 은 2026년 8월

경로human/study/content/ai-frontier/118-vllm-decode-context-parallelism-kv-cache-sequence-shard.md
카테고리Study
태그#ai-review #cache #context #parallelism #sequence #shard #study

요약

LLM 서빙에서 긴 컨텍스트를 다루는 방식이 바뀌고 있다. 지금까지 텐서 병렬성(TP)은 모델 가중치와 KV 캐시를 여러 GPU에 분산하는 표준 수단이었지만, GQA(Grouped Query Attention)와 MLA(Multi-Head Latent Attention)가 주류 아키텍처가 되면서 TP만으로는 해결할 수 없는 메모리 병목이 드러났다.

Decode Context Parallelism(DCP) 은 2026년 8월 7일 vLLM 블로그에 공개된 기법으로, KV 캐시를 어텐션 헤드 수(H) 대신 시퀀스 길이(T) 차원으로 샤딩한다. 각 GPU는 전체 요청의 KV 데이터 중 1/N만 저장하고, 디코드 스텝에서 AllGather Q → 로컬 어텐션 → AllGather+ReduceScatter 리듬으로 분산 계산을 수행한다.

결과는 명확하다. 8×B200 노드에서 Kimi K2.6(MLA 모델)으로 측정했을 때, TP 단독 기준선이 동시성 64에서 메모리 상한에 막혀 ~1,863 tok/s/GPU 에 머무는 반면, DCP 적용 후 동시성 512, KV 사용률 82%에서 6,091 tok/s/GPU — 약 3.3배 향상을 달성한다.


배경: 텐서 병렬성의 KV 캐시 한계

TP가 KV 캐시를 분산하는 방식

Tensor Parallelism은 어텐션 레이어에서 Q/K/V 헤드를 GPU 수(tp_size)로 나눠 배분한다. 헤드 수가 H이고 tp_size가 8이라면, 각 GPU는 H/8개의 KV 헤드를 담당한다.

전통적인 MHA(Multi-Head Attention)에서는 이 방식이 잘 작동했다. GPT-3 기준 96개 헤드를 8 GPU에 나누면 GPU당 12개 헤드를 책임지고, KV 캐시도 1/8로 줄어든다.

GQA와 MLA에서 무슨 일이 생기는가

문제는 최신 아키텍처가 KV 헤드를 극단적으로 줄이면서 시작된다.

[TP=8, GQA KV heads=8]
GPU 0: KV[head 0]   (각 GPU가 서로 다른 헤드 담당 → 정상)

[TP=16, GQA KV heads=8]
GPU 0~1: KV[head 0] 복제  (16 > 8 이므로 복제 발생 → 메모리 낭비)

[TP=8, MLA KV heads=1]
GPU 0~7: KV[latent] 복제  (8 > 1 이므로 전부 복제 → 심각한 낭비)

MLA 모델에서 TP=8을 쓰면 같은 KV 데이터가 8개 GPU에 모두 올라가 있다. 이 낭비된 메모리만큼 배치 사이즈를 늘릴 수 없고, 동시 처리 요청 수의 상한이 낮아진다.


DCP 아키텍처: 시퀀스 차원 샤딩

핵심 아이디어

DCP는 KV 캐시를 시퀀스 길이(T) 차원으로 나눈다. dcp_size=N이면 토큰 i의 KV 항목은 dcp_rank = i % N인 GPU에 저장된다. 인터리브 방식이다.

요청 A: 컨텍스트 길이 4096 토큰, dcp_size=4
  GPU 0: token[0], token[4], token[8], ...  (1/4 of KV)
  GPU 1: token[1], token[5], token[9], ...  (1/4 of KV)
  GPU 2: token[2], token[6], token[10], ... (1/4 of KV)
  GPU 3: token[3], token[7], token[11], ... (1/4 of KV)

각 GPU는 1/N만큼의 KV만 저장하므로, 같은 GPU 메모리로 N배 더 많은 요청을 동시에 처리할 수 있다.

TP vs DCP: KV 캐시 샤딩 전략 비교 텐서 병렬성 (TP) — 헤드 차원 샤딩 ▶ MHA (96 heads), TP=8 → 정상 12 H 12 H 12 H ... × 8 GPUs ✓ 각 GPU가 다른 헤드 담당, KV 복제 없음 ▶ GQA (KV heads=8), TP=16 → 문제! H=0 복제 H=0 복제 H=1 ... 16 GPUs ✗ 8 heads < 16 GPUs → 같은 KV가 2배 복제 ▶ MLA (KV heads=1), TP=8 → 심각! latent 복제 latent 복제 latent 복제 × 8 GPUs ✗ 단 1개 KV가 8 GPU 전부에 복제 → 메모리 8× 낭비 TP 전략 메모리 효율 (MLA 기준) 유효 KV 12.5% — 나머지 87.5%는 복제 낭비 이 낭비된 공간 때문에 배치 사이즈 상한이 낮아진다 → TP=8로는 동시성 64 요청이 메모리 한도 도달 Decode Context Parallelism (DCP) — 시퀀스 차원 샤딩 ▶ KV 캐시를 토큰 인덱스로 분산 (dcp_size=4) 요청 A (컨텍스트 4096 토큰) t[0,4,8…] GPU 0 t[1,5,9…] GPU 1 t[2,6,10…] GPU 2 t[3,7,11…] GPU 3 ✓ 각 GPU는 전체 KV의 25%만 보유 (복제 없음) ▶ 해방된 메모리로 더 많은 요청 처리 요청 A 요청 B 요청 C 요청 D 요청 E 요청 F 요청 G 요청 H 동시 8 요청 (TP 단독 대비 4× 더 많은 배치) 메모리 사용률 82% — TP는 이 지점에서 OOM DCP 메모리 효율 (MLA 기준, dcp_size=4) 유효 KV 82% 활용 ▶ 디코드 스텝 통신 흐름 1. AllGather Q — 단일 새 토큰 Q벡터 수집 (작음) 2. 로컬 어텐션 — GPU가 자신의 KV 슬라이스만 계산 3. AllGather + ReduceScatter — 어텐션 출력 합산 (MLA: load-time Q 복제로 AllGather Q 생략 가능) DCP 전환
TP와 DCP의 KV 캐시 샤딩 방식 비교

디코드 계산 흐름

디코드 스텝에서 DCP 그룹의 GPU들이 협력해 어텐션을 계산하는 방식은 다음과 같다.

단계별 통신 패턴

  1. AllGather Q: 새로 생성한 토큰 하나의 Query 벡터를 DCP 그룹 내 모든 GPU에 공유한다. 디코드에서 새 토큰은 항상 하나이므로 이 통신 비용은 작다. (MLA 모델에서는 모델 로드 시 Q 프로젝션을 각 GPU에 복제해 두면 이 AllGather를 건너뛸 수 있다.)
  1. 로컬 어텐션 계산: 각 GPU는 자신이 보유한 KV 슬라이스에 대해서만 어텐션을 계산한다. 로컬 KV만 읽으므로 메모리 대역폭 부하가 1/N으로 줄어든다.
  1. AllGather + ReduceScatter: 각 GPU에서 나온 부분 어텐션 출력을 모아 최종 결과를 얻는다. Flash Attention 구현에서는 LSE(Log-Sum-Exp) 값을 함께 전달해 수치 안정성을 유지한다.

왜 디코드에 집중하는가

길고 짧은 출력이 섞이는 에이전틱 워크로드에서 실측한 분포는 흥미롭다. 입력 컨텍스트는 이봉분포(bimodal)를 보인다: 요청의 약 53%는 64K 토큰 이상(최대 1M까지)이고, 나머지 47%는 64K 미만이다. 반면 출력 토큰은 중앙값 400개 수준으로 매우 짧다.

이 패턴에서 병목은 명확하다. 긴 컨텍스트를 KV 캐시로 유지한 채 짧은 출력만 생성하는 상황이 반복된다. 계산 집약도가 낮고 메모리 대역폭 집약도가 높은 전형적인 메모리 바운드 워크로드다. KV 캐시를 줄이는 것이 처리량 향상으로 직결된다.


실제 워크로드 벤치마크

실험 환경

처리량 결과

설정최대 동시성tok/s/GPUKV 사용률상한 이유
TP=8 (기준선)~64~1,863~100% → OOM메모리 부족
TP=8 + DCP=25126,09182%처리 포화

동시성 64에서 기준선은 KV 메모리가 가득 차 OOM 상황에 가깝다. DCP를 적용하면 같은 메모리로 약 8배 더 많은 동시 요청을 수용하고, GPU당 처리량은 3.3배 증가한다.

MLA와 GQA에서의 효과 차이

DCP는 MLA 모델에서 특히 극적인 효과를 낸다. MLA는 KV 헤드가 사실상 1개이므로 TP 단독으로는 KV 복제를 피할 방법이 없다. DCP는 이 제약을 우회하는 유일한 방법이다.

GQA 모델에서도 TP가 KV 헤드 수를 초과하는 상황, 또는 컨텍스트가 매우 길어 KV 사용률이 포화되는 상황에서 유효하다.


운영 가이드

언제 DCP를 쓸 것인가

DCP가 효과적인 경우:

DCP를 피해야 하는 경우:

설정 예시

# TP=8 + DCP=2: 총 16 GPU (TP 8개 × DCP 2그룹)
vllm serve moonshotai/Kimi-K2.6 \
  --tensor-parallel-size 8 \
  --dcp 2

# DCP 그룹 내 KV 캐시 인터리브 크기 조정 (기본값=1 토큰)
# 더 큰 청크로 인터리빙하면 CPU 정렬 오버헤드 감소 대신 언밸런스 위험
export VLLM_DCP_KV_INTERLEAVE_SIZE=16

메모리 오버헤드

DCP는 KV를 샤딩하지만 AllGather 시 임시 버퍼가 필요하다. 실용적인 규칙으로, DCP 그룹 크기를 2~4로 유지하면 통신 오버헤드가 GPU 메모리 절약 대비 작다. 8 이상으로 늘리면 AllGather 비용이 증가해 실효 처리량이 오히려 낮아질 수 있다.

연관 기법

DCP는 독립적이지만 다른 최적화와 병행 가능하다.


요점 정리

GQA와 MLA가 대세가 된 2026년, TP 단독으로 KV 캐시를 효율적으로 분산하는 것은 구조적으로 불가능해졌다. KV 헤드가 1~8개에 불과한 아키텍처에서 TP=8~16을 쓰면 같은 데이터가 GPU 수만큼 복제될 뿐이다.

DCP는 이 문제를 근본적으로 다르게 접근한다: 헤드 수와 무관하게 시퀀스 차원으로 나누면 복제가 없다. 단일 B200 노드에서 3.3배 처리량 향상은 인프라 비용 대비 명확한 이점이다.

실용적인 권장사항은 단순하다: MLA 모델을 멀티-GPU로 서빙하거나, 에이전틱 장문 컨텍스트 요청이 많다면 --dcp 2 또는 --dcp 4를 기본 설정에 추가하라. 통신 비용은 NVLink 환경에서 무시할 수준이고, KV 메모리 절약 효과는 즉각적이다.


References