LLM WikiAccess-protected knowledge portal
← 스터디 홈
118편 · 약 15분

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월 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배 향상을 달성한다.

  • vLLM 블로그 포스트: 2026-08-07
  • CLI 사용: vllm serve <model> --tensor-parallel-size N --dcp <dcp_size>
  • 지원 모델: GQA(LLaMA 등), MLA(DeepSeek-V2/V3, Kimi K2.6 등)

배경: 텐서 병렬성의 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 헤드를 극단적으로 줄이면서 시작된다.

  • GQA(Grouped Query Attention): LLaMA 3 70B는 Q 헤드가 64개지만 KV 헤드는 8개다. TP=8이면 GPU당 KV 헤드가 1개다. TP=16을 적용하면 헤드가 8개밖에 없으니 KV 헤드 < GPU 수 조건이 발생해 KV 캐시를 각 GPU에 복제해야만 한다.
  • MLA(Multi-Head Latent Attention): DeepSeek, Kimi K2.6이 사용하는 방식이다. 전체 KV를 단일 지연 벡터(latent vector)로 압축한다. 실질적으로 KV 헤드가 1개다. TP가 몇 개든 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 캐시를 줄이는 것이 처리량 향상으로 직결된다.


실제 워크로드 벤치마크

실험 환경

  • 하드웨어: 8×NVIDIA B200 (NVLink 연결)
  • 모델: Kimi K2.6 (MLA 아키텍처)
  • 설정: TP=8 기준선 vs TP=8 + DCP=2

처리량 결과

설정최대 동시성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가 효과적인 경우:

  • 컨텍스트가 32K 토큰 이상인 요청이 주를 이룰 때
  • MLA 모델(DeepSeek-V2/V3/R1, Kimi K2.x)을 서빙할 때
  • GPU 수가 GQA 모델의 KV 헤드 수를 초과할 때
  • KV 메모리가 병목(KV 사용률이 90%+)이어서 배치 사이즈를 늘리지 못할 때

DCP를 피해야 하는 경우:

  • 컨텍스트가 8K 이하인 단문 요청이 대부분일 때 (AllGather 오버헤드가 이득보다 클 수 있음)
  • GPU가 NVLink로 연결되지 않아 AllGather 대역폭이 낮을 때

설정 예시

# 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는 독립적이지만 다른 최적화와 병행 가능하다.

  • 투기적 디코딩(Speculative Decoding): DCP와 독립적으로 결합 가능. EAGLE-3 같은 드래프터가 KV 샤딩 위에서 동작한다.
  • Prefill-Decode 분리(PD Disaggregation): vLLM 0.25에서 안정화된 PD 분리와 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

  • vLLM Blog — "Efficient Decode Context Parallelism with vLLM for Long Context Workloads" (2026-08-07): https://vllm.ai/blog/2026-08-07-decode-context-parallelism
  • vLLM GitHub RFC — Decode Context Parallel for GQA: https://github.com/vllm-project/vllm/issues/24685
  • vLLM GitHub PR — Support Decode Context Parallel (DCP) for MLA: https://github.com/vllm-project/vllm/pull/23734
  • vLLM Documentation — Context Parallel Deployment: https://docs.vllm.ai/en/latest/serving/context_parallel_deployment/
  • Kimi K2.6 vLLM Recipe: https://recipes.vllm.ai/moonshotai/Kimi-K2.6
  • Helix Parallelism RFC (combining TP + CP): https://github.com/vllm-project/vllm/issues/34018