상태: 초안 (2026-10-13), 일부 실측. 논문·공식 문서·NVIDIA 블로그는 2026-10-13 에 직접 열어 확인했고, 문서는 Dynamo v1.5.1(2026-10-07) 기준입니다. NVIDIA 가 낸 성능 수치는 「업체 발표」로 표시했습니다. 실측은 같은 사이트의 「토스 ML/AI Infra 준비」 14편(8GB급 GPU, vLLM)과 24편(Dynamo 1.6.0 개발 빌드, 8GB급·24GB급 GPU, 0.6B 모델)에서 다시 인용했습니다. NVLink·RDMA 로 연결된 환경의 분리 서빙 이득은 미실측입니다. 작성 규칙: 실측 데이터가 기본이고, 못 잰 것은 「미실측」, 확인하지 못한 것은 「미확인」으로 표시합니다.
NVIDIA Dynamo: 프리필과 디코드를 나누기
목차
- 1. 프리필과 디코드는 같은 GPU 에서 서로를 방해한다
- 2. 분리 서빙: 나누고, KV 를 옮긴다
- 3. NVIDIA Dynamo 의 구성
- 4. 왜 처리량이 오르나
- 5. 직접 재 본 Dynamo
- 6. Dynamo 와 LMCache 의 관계
- 7. 언제 이득이 없나
- 8. 시리즈 정리
- 참고
1. 프리필과 디코드는 같은 GPU 에서 서로를 방해한다
1편에서 프리필은 계산에, 디코드는 메모리 대역폭에 묶인다고 했습니다. 둘이 한 GPU 를 나눠 쓰면 문제가 생깁니다. 연속 배칭은 새 요청의 프리필을 디코드 걸음 사이에 넣는데, 프리필이 긴 걸음은 오래 걸리고 그동안 배치 안의 다른 요청은 다음 토큰을 받지 못합니다.
우리 실측. 8GB급 GPU 에서 vLLM 기본 설정(한 걸음 입력 상한 2,048토큰)으로 디코드 중인 요청 옆에 3,500토큰짜리 입력을 끼우자, 그 구간의 최대 토큰 간격이 227ms 였습니다(3회 227·226·226ms). 평소 간격은 약 15ms 입니다. 2편의 청크 프리필로 이 값을 69ms 까지 줄일 수 있었지만, 그 대가로 긴 입력의 첫 토큰이 조금 늦어졌습니다. 청크는 간섭을 나눠 낼 뿐 없애지 못합니다.
분리 서빙을 처음 체계적으로 다룬 두 논문은 이 문제를 이렇게 짚습니다.
- DistServe(Zhong 외, OSDI 2024): 한 GPU 에 두면 (1) 두 단계가 서로 느리게 만들고, 프롬프트가 길수록 더하며, (2) 두 단계가 같은 자원과 같은 병렬화 설정을 써야 해서 TTFT 와 토큰 간격 목표 가운데 까다로운 쪽에 맞춰 GPU 를 과하게 잡게 된다고 봅니다. 청크 프리필은 TTFT 와 토큰 간격을 맞바꿀 뿐이라고 평가합니다.
- Splitwise(Patel 외, ISCA 2024): 실제 클라우드 기록을 분석해, 프롬프트 단계는 계산 위주이고 토큰 단계는 메모리 대역폭·용량 위주라는 것을 보였습니다. BLOOM-176B 에서 1,500토큰 프롬프트 처리 시간이 출력 토큰 6개를 만드는 시간과 같았고, 토큰 단계는 GPU 전력을 700W 에서 350W 로 낮춰도 지연이 거의 늘지 않았습니다. 성격이 이렇게 다르면 다른 하드웨어나 다른 설정을 쓰는 편이 낫다는 결론입니다.
2. 분리 서빙: 나누고, KV 를 옮긴다
방법은 단순합니다. 프리필 전용 GPU 와 디코드 전용 GPU 를 따로 둡니다. 프리필 GPU 가 프롬프트의 KV 를 만들면 그 KV 를 디코드 GPU 로 보내고, 디코드 GPU 는 받은 KV 에 이어 토큰을 만듭니다.
- 디코드 GPU 에는 긴 프리필이 끼어들지 않으므로 토큰 간격이 고릅니다. 간격 목표를 지키면서 디코드 배치를 더 크게 잡을 수 있습니다.
- 두 단계에 다른 병렬화와 다른 GPU 수를 줄 수 있습니다. 프리필은 계산을 나누는 쪽으로, 디코드는 큰 배치를 담는 쪽으로 맞춥니다.
- 대가는 KV 전송입니다. 1편의 식대로 KV 는 크고, 그것을 첫 토큰 전에 옮겨야 합니다.
DistServe 의 결과. A100 80GB(노드 안 NVLink, 노드 사이 25Gbps), OPT-13B·66B·175B 에서 지연 목표를 90% 이상 지키는 최대 요청률(goodput)을 쟀습니다.
| 작업 | 모델 | vLLM 대비 요청률 | vLLM 대비 지연 목표 |
|---|---|---|---|
| 챗봇(ShareGPT) | OPT-13B·66B·175B | 2.0~4.6배 | 1.8~3.2배 엄격 |
| 코드 완성(HumanEval) | OPT-66B | 5.7배 | 1.4배 엄격 |
| 요약(LongBench) | OPT-66B | 4.3배 | 12.6배 엄격 |
다른 기준선(DeepSpeed-MII)과 비교하면 최대 7.4배였고, 초록의 「요청률 최대 7.4배 또는 지연 목표 12.6배 엄격」이 이 두 표를 합친 값입니다. 동기 예시도 직관적입니다. 13B 모델을 A100 한 장에 두면 약 1.6 요청/초였는데, 프리필만 하면 5.6, 디코드만 하면 10 요청/초를 냈고, 프리필 2장 + 디코드 1장으로 나누면 GPU 당 3.3 요청/초로 2.1배가 되었습니다.
KV 전송은 어땠을까요. 논문은 OPT-66B 의 512토큰 요청 하나가 KV 약 1.13GB 라서 초당 10요청이면 11.3GB/s 가 필요하다고 계산합니다. 그래서 프리필과 디코드를 같은 노드 안(NVLink) 에 배치하도록 설계했고, 그 결과 OPT-175B 에서 전송이 전체 지연의 0.1% 미만이었습니다.
Splitwise 의 결과. KV 를 층마다 비동기로 보내 다음 층 계산과 겹쳤습니다(InfiniBand). 겹치지 못한 전송은 A100 약 8ms, H100 약 5ms 로 프롬프트 계산 시간의 7% 미만이었고 전체 지연에 0.8% 를 더했습니다. 전력이 같은 조건에서 A100 으로만 나눈 구성이 기준(A100)보다 처리량 2.15배였습니다(본문 그림 18a). 초록의 대표 수치(「비용 20% 절감하며 1.4배」, 「같은 비용·전력에서 2.35배」)는 본문 실험과 같은 짝으로 찾지 못해 여기서는 본문 값만 적습니다.
3. NVIDIA Dynamo 의 구성
Dynamo 는 vLLM·SGLang·TensorRT-LLM 같은 엔진 위에서 여러 GPU·여러 노드를 묶는 서빙 프레임워크입니다. 엔진을 대신하지 않고, 엔진 여러 개를 어떻게 나누고 어디로 보낼지를 맡습니다. 문서(v1.5.1)에서 확인한 구성은 다음과 같습니다.
- 프런트엔드: OpenAI 호환 API, 토큰화.
- KV 인지 라우터: 요청을 어느 워커에 보낼지 정합니다. 워커마다 비용을 계산하고 가장 싼 곳을 고릅니다. v1.5.1 의 비용은 「그 워커에서 새로 계산해야 할 프리필 블록(이미 가진 블록은 빼 줌) × 가중치 + 디코드 블록 부하 + 실행 중 요청 수 × 가중치」입니다. 이미 같은 앞부분의 KV 를 가진 워커는 프리필 몫이 줄어 싸게 나옵니다. 다만 너무 한 곳에 몰리지 않도록 부하도 함께 봅니다. 앞부분 겹침에 주는 가산을 키우면 TTFT 가 줄고, 줄이면 부하가 고르게 퍼져 토큰 간격이 줄어든다고 문서는 설명합니다.
- 워커가 무엇을 가졌는지 아는 방법: 워커가 블록을 저장·삭제할 때마다 이벤트를 보내 라우터가 색인을 만드는 방식이 기본이고, 이벤트 없이 「최근에 보낸 요청」을 기억해 어림하는 근사 모드(기본 TTL 120초)도 있습니다.
- 분리 서빙: 프리필 워커를 고르는 라우터가 따로 있고, 프리필 워커가 KV 를 만든 뒤 디코드 워커가 NIXL 로 그 KV 를 직접 가져갑니다.
- NIXL: GPU 메모리·CPU 메모리·파일·객체 저장소 사이의 전송을 한 인터페이스로 감싼 라이브러리입니다. 실제 전송은 플러그인이 맡습니다(UCX 가 기본, GPUDirect Storage, POSIX, Mooncake, libfabric, 객체 저장소 등). NVLink, InfiniBand·RoCE 같은 RDMA, PCIe, TCP 를 상황에 맞게 씁니다.
- 플래너: 부하를 보고 프리필·디코드 워커 수를 바꿉니다. 처리량 목표(대기열 깊이·KV 사용률, 기본), 지연 목표(TTFT·토큰 간격 SLA) 등 모드가 있고, 들어올 요청 수·입출력 길이·캐시 적중률을 예측해 정하는 방식과 엔진의 걸음별 지표에 회귀를 거는 방식이 있습니다. 쿠버네티스에서는 오퍼레이터가 그 수를 맞춥니다.
- KV 블록 관리자(KVBM): GPU(G1) → 고정 호스트 메모리(G2) → 로컬 디스크(G3) → 객체 저장소(G4)로 KV 를 내리는 계층이었습니다. v1.5.0 릴리스 노트에서 deprecated 로 바뀌었고 v1.7.0 에서 빠질 예정입니다. 호스트·디스크 계층은 엔진 자체 오프로딩(또는 LMCache 같은 연결)으로 옮기라고 안내합니다.
4. 왜 처리량이 오르나
| 원천 | 무엇이 바뀌나 | 근거 |
|---|---|---|
| 간섭 제거 | 디코드 GPU 에 긴 프리필이 끼지 않아, 토큰 간격 목표를 지키며 디코드 배치를 키운다 | 실측(간섭 227ms), DistServe·Splitwise |
| 단계별 맞춤 | 프리필·디코드에 다른 병렬화·GPU 수·하드웨어를 준다. 플래너가 비율을 부하에 맞춘다 | DistServe(2.1배 예시), Splitwise |
| 캐시 적중 | 같은 앞부분을 가진 워커로 보내 프리필 자체를 건너뛴다 | 실측(5절), 업체 발표 |
| 작업 집합 나누기 | 앞부분이 워커별로 갈라져, 각 워커의 GPU 캐시에 자기 몫이 다 들어간다 | 실측(5절) |
NVIDIA 의 발표 수치는 이렇습니다. 모두 업체 발표이고, 직접 재현하지 않았습니다.
- 소개 블로그(2025-03-18): GB200 NVL72 에서 DeepSeek-R1 671B(FP4, 입력 32K·출력 8K)를 분리 서빙으로 돌려 처리량 최대 30배, Hopper 에서 Llama 70B(FP8, 입력 3K·출력 50)로 2배 이상. 그림 각주에 「예상 성능, 바뀔 수 있음」이라고 적혀 있습니다.
- 문서 v0.9.0 의 설계 문서: 분리 서빙은 Llama 70B 계열(FP8, H100, 입력 3K·출력 150)에서 단일 노드 GPU 당 처리량 +30%, 2노드에서 2배 이상. KV 인지 라우팅은 H100 2노드에 실제 요청 10만 건(평균 입력 4K·출력 800)을 보내 무작위 라우팅보다 TTFT 3배, 평균 지연 2배 감소. KVBM 의 CPU 오프로드는 Qwen3-8B(H100, 다회전 대화, 평균 입력 20K)에서 GPU 프리픽스 캐시만 쓸 때보다 TTFT 2.2~12배 개선.
5. 직접 재 본 Dynamo
다른 시리즈에서 Dynamo(1.6.0 개발 빌드, vLLM 0.30.0, NIXL 1.3.2)를 Qwen3-0.6B(토큰당 KV 114,688바이트)로 재 보았습니다.
KV 인지 라우팅. 워커 둘을 띄우고, 약 1,500단어짜리 앞부분 12종을 6번씩 섞어 보냈습니다(재요청 60번). 재요청이 같은 앞부분의 KV 를 가진 워커로 가면 첫 토큰이 약 15ms, 아니면 약 80ms 였습니다.
| 라우팅 | 60번 중 적중(3회) | 첫 토큰 평균 |
|---|---|---|
| 라운드 로빈 | 35, 40, 43 | 34~42ms |
| 무작위 | 44, 31, 45 | 32~46ms |
| KV 인지, 근사 모드 | 60, 53, 60 | 15~26ms |
| KV 인지, 이벤트 모드인데 이벤트 없음 | 39, 44, 41 | 32~38ms |
| KV 인지, 이벤트 모드 | 60, 60, 60 | 15ms |
- 라우터를 켜면 적중이 거의 100% 였습니다.
- 조용한 실패에 주의해야 합니다. 이벤트 모드를 켰는데 워커가 이벤트를 안 보내면 라우터의 색인이 비어 적중이 무작위 수준으로 떨어졌고, 오류 없이 로그 경고 한 줄만 남았습니다. 라우팅을 켠 뒤에는 「같은 앞부분을 다시 보내면 첫 토큰이 줄어드는가」를 직접 재야 합니다.
- 라운드 로빈이 무작위보다 나은 것도 아니었습니다. 한 워커의 KV 자리(14,816토큰)에 앞부분 12종(약 18,000토큰)이 다 들어가지 않는데, KV 인지 라우팅은 앞부분을 워커별로 6종씩 나눠 각자 다 담았습니다. 라우팅의 이득에는 「같은 곳으로 보낸다」에 「각 워커의 작업 집합이 작아진다」가 더해집니다.
- 프런트엔드를 거치는 비용은 한가할 때 약 13ms 였고, 동시 8·32 에서는 구별되지 않았습니다.
분리 서빙. 결과는 반대였습니다. 모두 단독 서빙보다 느렸습니다.
| 구성(동시 1) | 1,500단어 | 3,000단어 |
|---|---|---|
| 8GB급 GPU 단독 | 78ms | 172ms |
| 같은 GPU 한 장을 프리필·디코드 프로세스로 나눔 | 406ms | 812ms |
| 서로 다른 서버 둘로 나눔(1GbE 급 링크) | 1,721~1,752ms | 3,407~3,533ms |
- 한 장을 나누면 계산 자원은 늘지 않고 KV 전송만 더해집니다. 분리가 풀려는 문제를 풀 GPU 가 없는 구성입니다.
- 서버 둘로 나누면 늘어난 시간이 KV 바이트 ÷ 링크 처리량과 맞았습니다. 3,000단어 요청 하나의 전송이 351.75MB, 3,374ms, 104MB/s 였고, 프리필 83ms 에 전송 약 3.4초를 더한 값이 측정과 같았습니다. 어느 GPU 가 프리필을 맡든 거의 같았습니다. 시간이 계산이 아니라 링크에 묶였기 때문입니다.
이것은 「분리 서빙이 느리다」가 아니라 **「느린 링크로 나누면 느리다」**입니다. 논문들이 NVLink 나 InfiniBand 를 전제로 하는 까닭이 이 표에 있습니다.
6. Dynamo 와 LMCache 의 관계
둘은 경쟁 관계가 아니라 층이 다릅니다. LMCache 는 엔진 하나 옆에서 KV 를 저장·불러오는 캐시 계층이고, Dynamo 는 엔진 여러 개를 묶어 나누고 보내는 프레임워크입니다. 문서에서 확인한 통합 지점은 다음과 같습니다.
- 집계 구성(한 워커가 프리필·디코드를 다): Dynamo 의 vLLM 워커가
LMCacheMPConnector(역할kv_both)로 노드의lmcache server에 KV 를 내리고 불러옵니다. 워커와 LMCache 서버가 CUDA IPC 로 붙으므로 쿠버네티스에서는hostIPC: true가 필요합니다. v1.5.1 의 쿠버네티스 안내는 이 집계 구성만 다루고, 검증된 버전 조합을 따로 적으며 서버와 워커의 LMCache 버전이 다르면 통신 규약이 맞지 않는다고 경고합니다. - 분리 구성: v1.3.0 문서는 프리필 쪽에서 LMCache 커넥터와 NIXL 커넥터를 함께 감싸 쓰는 예를 듭니다. 프리필→디코드 전송은 NIXL 이 맡고, LMCache 는 요청 사이 재사용을 맡는 분업입니다. LMCache 문서의 분리 구성도 같은 모양입니다(3편 7절). v1.5.1 에서 LMCache 를 분리 서빙과 함께 쓰는 공식 절차는 찾지 못했습니다(미확인).
- KVBM 과의 관계: Dynamo 의 오프로딩 개요 문서는 LMCache, SGLang 의 HiCache, FlexKV 를 대안으로 소개하고 겹쳐 쓰지 말라고 합니다. KVBM 은 v1.5.0 부터 deprecated 입니다.
- 라우터가 보는 범위: v1.5.1 의 라우터 지원표는 vLLM 자체 오프로딩·SGLang HiCache·TensorRT-LLM 의 호스트·디스크 적중을 점수에 반영한다고 적고(호스트 적중 0.75, 디스크 0.25), LMCache 행은 없습니다. 그래서 LMCache 에 내려 둔 KV 를 라우터가 점수에 넣는지는 문서로 확인하지 못했습니다(미확인).
7. 언제 이득이 없나
분리 서빙의 손익은 3편과 같은 모양의 식으로 어림할 수 있습니다. 첫 토큰에 더해지는 시간 ≈ 토큰당 KV × 입력 토큰 ÷ 링크 처리량(층별 전송으로 일부는 계산과 겹쳐 숨길 수 있음). 입력 4,096토큰의 KV 를 옮기는 시간을 계산하면 다음과 같습니다(전송 시간만, 계산).
링크 속도는 1GbE 급이 우리 실측 실효 104MB/s, 100Gb/s 가 이론 12.5GB/s, NVLink 급이 DistServe 논문에 적힌 A100 사이 600GB/s 입니다.
| 모델 | KV 크기 | 1GbE 급 | 100Gb/s | NVLink 급 |
|---|---|---|---|---|
| Qwen3-0.6B | 470MB | 4.5초 | 38ms | 0.8ms |
| Llama 3.1 8B | 537MB | 5.2초 | 43ms | 0.9ms |
| Llama 3.1 70B | 1.34GB | 12.9초 | 107ms | 2.2ms |
이 값이 아낄 수 있는 것(간섭으로 늦어지던 디코드, 과하게 잡던 GPU)보다 크면 손해입니다. 그래서 분리가 이득이 없거나 손해인 경우는 다음과 같습니다.
- 링크가 느리다. 위 표의 첫 열이 그 경우이고, 실측에서 20배 넘게 느렸습니다.
- 프롬프트가 짧다. 프리필이 짧으면 디코드에 끼어드는 시간도 짧아 없앨 간섭이 적습니다. 반면 전송과 라우팅의 고정 비용은 남습니다.
- 부하가 낮다. 동시에 디코드하는 요청이 적으면 간섭받을 대상이 없습니다. 분리는 GPU 를 둘로 나누므로 한가할 때는 놀리는 GPU 만 늘어납니다.
- GPU 가 한 장이다. 나눠도 계산 자원이 늘지 않습니다(실측 4.7~7.2배 느림).
- 작은 모델. 프리필이 이미 싸서(0.6B 의 프리필 83ms) KV 전송이 상대적으로 커집니다.
Dynamo 문서도 보편적인 문턱은 없다고 적습니다. 모델·GPU·입력 길이 분포에 따라 경계가 달라지므로, 초기 판(v0.1.0)은 「프리픽스 적중을 뺀 프리필 길이가 문턱을 넘고 원격 프리필 대기열이 짧을 때만」 원격 프리필을 썼고, v1.5.1 에서는 라우터 비용에 따라 조건부로 나누는 기능이 실험 단계로 들어가 있습니다. 분리할지는 내 링크로 KV 전송 처리량을 먼저 재고, 그 값으로 위 식을 계산한 뒤에 정하는 것이 안전합니다.
KV 인지 라우팅은 사정이 다릅니다. KV 를 옮기지 않고 요청을 KV 쪽으로 옮기므로 링크 비용이 없습니다. 같은 앞부분이 다시 오는 부하라면 비교적 손해 볼 일이 적습니다. 다만 한 워커에 몰리지 않게 부하 가중치를 맞추고, 이벤트가 실제로 들어오는지 확인해야 합니다.
8. 시리즈 정리
| 편 | 무엇을 아끼나 | 언제 효과가 크나 | 언제 없나 |
|---|---|---|---|
| 1. KV 캐시 | 지난 토큰의 K·V 재계산 | 항상(출력이 같음) | — 대신 메모리를 먹는다 |
| 2. PagedAttention·연속 배칭·프리픽스 캐시 | 메모리 낭비, 빈 자리, 같은 앞부분 계산 | 동시 요청이 많을 때, 공통 프롬프트 | 작업 집합이 GPU 보다 클 때 캐시가 지워짐 |
| 3. LMCache | GPU 밖에 둔 KV 로 프리필 대체 | 긴 문맥, 재사용 많음, 빠른 저장 경로 | 짧은 입력, 낮은 적중, 느린 링크, 작은 용량 |
| 4. Dynamo | 간섭 제거, 단계별 맞춤, KV 쪽으로 라우팅 | 높은 부하, 긴 프롬프트, 빠른 GPU 사이 링크 | 느린 링크, 한 장, 낮은 부하, 작은 모델 |
네 편을 관통하는 질문은 하나였습니다. 「이 KV 를 다시 계산하는 것과 어딘가에서 가져오는 것 가운데 무엇이 싼가.」 답은 모델의 토큰당 KV 크기, GPU 의 계산 속도, KV 가 지나는 길의 속도, 그리고 같은 앞부분이 얼마나 자주 다시 오는지로 정해집니다. 넷 다 재 볼 수 있는 값입니다.
티티 한마디. 서브 연습하는 사람과 랠리 연습하는 사람을 한 테이블에 두면 서로 공을 기다리느라 둘 다 손해예요. 테이블을 나누면 좋아지죠. 그런데 공 바구니를 옆 건물에서 날라 와야 한다면? 그때는 그냥 같이 치는 게 나아요. 나누기 전에 바구니가 얼마나 빨리 오는지부터 재 보세요.
참고
- Zhong 외, DistServe: Disaggregating Prefill and Decoding for Goodput-optimized LLM Serving (OSDI 2024): https://arxiv.org/abs/2401.09670 (v3, 1·2.3·3.3·6절, 표 1, 그림 8·9·10)
- Patel 외, Splitwise: Efficient Generative LLM Inference Using Phase Splitting (ISCA 2024): https://arxiv.org/abs/2311.18677 (v2, 3·4.C·6절, 그림 18), Microsoft Research 페이지: https://www.microsoft.com/en-us/research/publication/splitwise-efficient-generative-llm-inference-using-phase-splitting/
- NVIDIA Dynamo 저장소·릴리스: https://github.com/ai-dynamo/dynamo (v1.5.1, 2026-10-07), 문서: https://docs.nvidia.com/dynamo/ (아키텍처, 라우터 개념·설정, 분리 서빙, 플래너, KVBM 설정, KV 오프로딩·LMCache MP 배포, 라우터 오프로딩 지원표, 2026-10-13 열람), 초기 판 분리 서빙 문서: https://github.com/ai-dynamo/dynamo/blob/v0.1.0/docs/disagg_serving.md
- NIXL: https://github.com/ai-dynamo/nixl (README,
docs/nixl.md) - NVIDIA 소개 블로그(업체 발표): https://developer.nvidia.com/blog/introducing-nvidia-dynamo-a-low-latency-distributed-inference-framework-for-scaling-reasoning-ai-models/ (2025-03-18), 설계 문서 v0.9.0(업체 발표): https://docs.nvidia.com/dynamo/v-0-9-0/design-docs/overall-architecture
- LMCache 의 Dynamo 연동 문서: https://docs.lmcache.ai/production/dynamo_coordination.html
- 실측 인용: 같은 사이트 「토스 ML/AI Infra 준비」 14편(청크와 간섭), 24편(Dynamo 실측)