E-P-D 분리 서빙: 비전 인코더를 떼어내 TTFT를 최대 93% 줄이는 조건과 오히려 느려지는 조건 (feat. NVIDIA Dynamo)

Encode-Prefill-Decode(EPD) 분리 서빙 소개

Encode-Prefill-Decode 분리(EPD Disaggregation) 는 멀티모달 모델을 서빙할 때 비전 인코더 단계를 프리필(prefill)과 디코드(decode) 단계에서 떼어내 독립적인 워커로 실행하는 추론(inference) 최적화 기법입니다. Jesse Gu, Ryan McCormick, Akshatha Kamath가 2026년 9월 9일 NVIDIA 개발자 블로그에 공개한 글은 이 기법을 자사 추론 프레임워크 NVIDIA Dynamo에 적용해 어떤 조건에서 이득이 나고 어떤 조건에서 손해가 나는지를 격자 단위로 실측한 결과를 담고 있습니다.

텍스트만 다루는 LLM 서빙에서는 프리필과 디코드를 분리하는 방식이 이미 널리 쓰이고 있습니다. 프리필은 입력 전체를 한 번에 처리하는 연산 집약적(compute-bound) 단계이고, 디코드는 토큰을 하나씩 뽑아내는 메모리 대역폭 집약적(memory-bound) 단계라서 두 단계를 한 워커에 묶어 두면 서로의 발목을 잡습니다. 그래서 Mooncake처럼 KVCache를 중심에 두고 두 단계를 쪼개는 서빙 플랫폼이나 CPU 작업을 GPU에서 분리하는 접근이 계속 나왔습니다.

멀티모달 요청은 여기에 한 단계를 더 얹습니다. 이미지나 영상이 붙은 요청은 LLM 프리필이 시작되기 전에 미디어를 내려받아 디코딩하고 전처리한 뒤, 비전 트랜스포머(Vision Transformer, ViT) 를 통과시켜 임베딩(embedding)을 만들어야 합니다. 통합 서빙(aggregated serving)에서는 이 인코딩 작업과 LLM 프리필, 디코드가 모두 같은 GPU와 같은 스케줄러를 공유합니다. 미디어 처리가 전체 작업의 일부에 그칠 때는 이 단순한 설계가 잘 동작하지만, 요청에 이미지가 여러 장 붙거나 영상이 들어오면 균형이 무너집니다.

이 글에서 정리하는 실측의 핵심은 "인코더를 떼면 빨라진다" 는 단순한 결론이 아닙니다. NVIDIA는 이미지 개수, 출력 길이, 모델 크기, 정밀도, 트래픽 구성을 축으로 격자를 구성해 실측하고 TTFT(Time To First Token, 첫 토큰까지의 시간)는 모든 조건에서 개선되지만 종단 간(end-to-end) 지연은 조건에 따라 되레 나빠진다는 비대칭을 보여 줍니다. 그리고 그 손실이 어디에서 발생하는지도 격자에 그대로 남아 있습니다. 실험에 쓰인 모델은 Qwen3.5-122B-A10B의 NVFP4(Blackwell 세대의 4비트 부동소수점 형식) 양자화(quantization) 버전인 nvidia/Qwen3.5-122B-A10B-NVFP4이며, 전문가(expert) 256개 중 8개만 활성화되는 희소 MoE 구조에 27층 ViT가 붙은 멀티모달 에이전트 모델입니다.

TTFT의 대부분은 비전 트랜스포머가 아니다

먼저 멀티모달 요청의 TTFT가 실제로 어디에 쓰이는지를 봐야 합니다. NVIDIA는 TTFT를 미디어 디코딩과 멀티모달 전처리, ViT 순전파와 프로젝터(projector), LLM 프리필의 세 구간으로 쪼개 측정했습니다.

세 가지 요청 유형의 측정값은 다음과 같습니다.

요청 유형 미디어 디코딩 + 전처리 ViT + 프로젝터 LLM 프리필 TTFT 합계
단일 이미지 (480P JPEG) 65.4 ms 24.6 ms 127.8 ms 217.8 ms
다중 이미지 (480P JPEG 10장) 211.4 ms 27.3 ms 210.9 ms 449.6 ms
영상 (720p24, 10초, 30프레임 샘플링) 1205.7 ms 80.6 ms 356.8 ms 1643.2 ms

위 표에서 두 가지를 확인할 수 있습니다. 첫째, 이미지가 한 장에서 열 장으로 늘어날 때 미디어 전처리는 65.4 ms에서 211.4 ms로 3배 이상 늘어나지만 ViT 순전파는 24.6 ms에서 27.3 ms로 거의 그대로입니다. 이미지 한 장당 토큰 예산을 256개로 잘라 두었기 때문에 시각 토큰 수 자체는 늘어나도 ViT 배치가 효율적으로 소화한 결과입니다. 둘째, 영상 요청에서는 미디어 디코딩이 1205.7 ms로 TTFT의 73%를 차지하고 ViT는 80.6 ms, 즉 5%에 불과합니다.

"인코더 작업" 이라고 부르는 구간의 무게 중심은 비전 트랜스포머가 아니라 그 앞단의 미디어 다운로드와 디코딩, 전처리에 있습니다. Dynamo의 인코드 워커는 ViT만 실행하는 것이 아니라 이 전처리 구간까지 함께 담당하기 때문에 인코더 분리의 효과가 나오는 것입니다. 저자들은 결론부에서 이 그림을 다시 불러와 "TTFT의 43%가 ViT가 시작되기도 전에 소모되었다" 고 적으며, 인코더 분리만으로는 해결되지 않는 구간이 남아 있다고 밝힙니다. 그림에 표기된 값으로 다시 계산하면 그 비율은 요청 유형에 따라 단일 이미지 30%, 다중 이미지 47%, 영상 73%로 갈리므로 43%라는 단일 숫자보다 편차가 큽니다. 어느 쪽이든 결론은 같습니다. 이 남은 구간을 어떻게 다루는지는 뒤에서 따로 정리합니다.

:pytorch::kr:고해상도 입력에서 비전 인코더 비용이 어떻게 병목이 되는지는 다음 연구 정리도 함께 참고해주세요:

하나의 큐가 만드는 줄서기와 Dynamo가 역할을 쪼개는 방식

통합 서빙의 문제는 인코딩이 느린 것 자체가 아니라 인코딩과 LLM 작업이 하나의 스케줄링 도메인을 공유한다는 점입니다. 미디어가 무거운 요청은 자기 자신의 프리필을 지연시키는 데다, 동시에 진행 중인 다른 요청의 프리필과 디코드와도 GPU를 다투게 됩니다. 더 성가신 것은 텍스트 전용 요청입니다. 배치에 멀티모달 요청이 하나라도 섞이면 워커는 미디어 전처리와 ViT 순전파를 끝낸 다음에야 프리필을 시작하므로, 비전 인코딩이 전혀 필요 없는 텍스트 요청까지 그 뒤에서 기다립니다.

NVIDIA Dynamo는 이 문제를 워커 역할을 쪼개는 방식으로 다룹니다. 인코드 워커(E)는 미디어 디코딩과 전처리, ViT를 담당하고 LLM 가중치와 KV 캐시를 아예 갖지 않습니다. 원문은 이렇게 전용 인코더 워커를 두면 배칭과 메모리 효율, 전체 처리량이 함께 개선될 수 있다고 설명합니다. PD 워커는 그 임베딩을 받아 LLM을 실행합니다. 두 역할 사이의 임베딩 전송은 NVIDIA Inference Transfer Library(NIXL)가 담당하며, NVIDIA의 실험 환경에서는 UCX(Unified Communication X)의 RC/TCP 이더넷 경로로 최대 20 Gbps를 측정했다고 밝히고 있습니다.

위 흐름도에서 확인할 부분은 인코드 워커가 호출되는 시점입니다. 통합 서빙에서는 프런트엔드가 라우팅과 토크나이징만 한 뒤 하나의 통합 워커에 요청을 넘기고, 그 워커가 미디어 디코딩부터 디코드까지 전부 처리합니다. EPD 경로에서는 프리필 워커(P)가 먼저 임베딩 캐시를 조회하고, 캐시 미스일 때만 인코드 워커를 호출합니다. 인코드 워커가 만든 임베딩은 NIXL로 프리필 워커에 전달되고, 프리필 결과인 KV 블록은 다시 NIXL을 통해 디코드 워커(D)로 넘어갑니다. 다시 말해 EPD는 인코더를 떼어내는 것에서 멈추지 않고, 프리필과 디코드도 분리된 상태를 전제로 구성됩니다.

Dynamo와 NIXL 더 알아보기

NVIDIA Dynamo GitHub 저장소 - 데이터센터 규모 분산 추론 서빙 프레임워크

NVIDIA Inference Xfer Library (NIXL) - 워커 간 KV와 임베딩 전송 라이브러리

Dynamo 공식 문서

Dynamo 소개 게시물 - PyTorchKR 커뮤니티

인코더를 어디에 둘 것인가: 세 가지 배치 토폴로지

인코더를 떼어낸다고 해서 인코더가 놓일 자리가 자동으로 정해지는 것은 아닙니다. NVIDIA는 통합 서빙을 기준선으로 두고 두 가지 분리 배치를 비교했습니다.

통합 서빙(Aggregated): GPU 4장에 각각 통합 워커 하나가 올라가고, 그 워커의 스케줄러가 비전 인코딩과 LLM 프리필, 디코드를 같은 요청 수명 주기 안에서 관리합니다.


코로케이트 인코더(Colocated Encoder): 같은 등급의 GPU 4장을 쓰면서 각 GPU에 인코더 워커 하나 이상과 PD 워커 하나를 함께 올립니다. 워커들은 CUDA MPS(Multi-Process Service)를 통해 GPU 연산 자원을 공유하되 요청 큐와 배치는 따로 갖습니다. 비전 인코더는 LLM에 비하면 가벼우므로, 같은 등급 GPU 한 장을 인코더 전용으로 비워 두면 그 GPU의 상당 부분이 유휴 상태가 됩니다. 코로케이션은 GPU를 독점시키지 않으면서 워커만 분리하는 절충안입니다.


분리 인코더(Disaggregated Encoder): 인코더 작업에 더 잘 맞는 저비용 GPU 계층이 클러스터에 함께 있을 때 유리한 선택입니다. NVIDIA의 테스트 환경에서는 NVIDIA RTX 6000D 2장이 인코더 워커를, GB200 4장이 PD 워커를 담당했습니다. 가벼운 인코더 작업은 RTX GPU에 남기고 연산과 메모리를 많이 쓰는 LLM 작업에 GB200을 온전히 배정하는 구성입니다.

여기서 원문이 명시적으로 배제한 조합이 하나 있습니다. 동일 등급 GPU로 인코더를 물리적으로 분리하는 구성은 코로케이트 인코더보다 항상 성능이 낮았기 때문에 분석 대상에서 제외했다는 것입니다. 즉 인코더 분리를 물리적으로 할 가치가 생기는 조건은 "이종 하드웨어가 있을 때" 로 좁혀집니다.

항목 통합 서빙 코로케이트 인코더 분리 인코더
GPU 구성 동일 등급 4장 동일 등급 4장 RTX 6000D 2장 + GB200 4장
워커 배치 GPU당 통합 워커 1개 GPU당 인코더 2개 + PD 1개 인코더 계층과 PD 계층 분리
자원 공유 방식 단일 스케줄러 CUDA MPS로 연산 공유 물리적으로 분리
임베딩 전송 없음 (같은 워커 내부) 워커 간 전송 NIXL로 계층 간 전송
PD 워커 메모리 예산 0.85 0.78 0.78
유리한 환경 미디어가 가볍거나 출력이 매우 긴 경우 동종 클러스터 저비용 GPU 계층이 있는 이종 클러스터

표 마지막에서 두 번째 줄의 메모리 예산은 Dynamo 저장소의 재현용 스크립트에서 확인할 수 있는 값입니다. 통합 워커는 --gpu-memory-utilization 0.85를 쓰지만 EPD의 PD 워커는 0.78로 낮춰 잡습니다. 같은 GPU에 인코더 워커를 얹으려면 그만큼의 메모리를 양보해야 하고, 양보한 메모리는 곧 KV 캐시 용량입니다. 이 숫자 하나가 뒤에서 볼 종단 간 지연 역전의 원인을 상당 부분 설명합니다.

EPD의 이득을 결정하는 네 가지 요인

인코더를 떼어내는 것 자체가 공짜는 아닙니다. 원문이 명시하듯 인코드 분리가 TTFT를 줄이고 동일 SLO 굿풋을 늘리는 것은 격리한 인코드 작업이 워커 조정과 임베딩 전송 오버헤드를 상쇄할 만큼 클 때만 성립합니다. 이 손익분기가 뒤에 나오는 모든 음수 칸의 원인입니다.

NVIDIA는 EPD의 효과를 좌우하는 요인을 네 가지로 정리합니다. 요약하면 비전 인코딩이 요청 처리 시간에서 의미 있는 비중을 차지하거나 처리량을 제한할 때 EPD가 유용하고, 그 비중은 미디어 부하만으로 결정되지 않는다는 것입니다.

입력 미디어 부하(Input media load): 미디어 부하가 커지면 시각 토큰이 늘어나고 인코더 작업량도 함께 늘어납니다. EPD는 인코더만 따로 늘릴 수 있으므로 인코딩 병목을 막습니다. 이미지가 여러 장이거나 고해상도이거나 영상 입력처럼 시각 토큰이 많이 생기는 경우에 이득이 납니다.


출력 시퀀스 길이(Output Sequence Length, OSL): OSL이 길어지면 전체 지연의 무게가 디코드로 옮겨갑니다. TTFT 이득은 그대로 유지되지만 종단 간 이득은 줄어듭니다. 출력이 짧으면 종단 간 이득도 유지되고, 길어지면 잠식됩니다.


모델 크기와 정밀도(Model size / precision): ViT 연산량은 거의 고정인데 LLM 연산량은 활성 파라미터가 줄고 정밀도가 낮아질수록 감소합니다. 그래서 작은 모델, MoE 모델, 양자화된 LLM일수록 ViT 대 LLM 연산 비율이 높아지고 EPD의 이득이 커집니다. 반대로 큰 밀집(dense) 모델은 이득이 작습니다.


혼합 트래픽(Mixed traffic): 텍스트와 멀티모달이 섞인 프리필 배치에서는 텍스트 요청이 ViT를 기다리게 됩니다. EPD는 인코더 작업을 격리해 텍스트 요청이 기다리지 않게 합니다. 지연에 민감한 텍스트 요청이 무거운 멀티모달 트래픽과 섞여 있을 때 효과가 큽니다.

이 네 축은 서로 반대 방향으로 작동합니다. 미디어 부하는 EPD에 유리하게 작용하고 출력 길이는 불리하게 작용하므로, 실제 판단은 두 축이 만드는 격자 위에서 해야 합니다.

실측 1: 이미지 10장 요청에서 TTFT가 880 ms에서 374 ms로

첫 번째 실험은 이미지 부하가 상당히 무겁고 출력도 긴 조건입니다. 요청당 이미지 10장, 이미지당 토큰 예산 256개, OSL 1024로 두고 세 토폴로지를 비교했습니다. 굿풋(goodput) 기준 SLO(Service Level Objective, 서비스 수준 목표)는 토큰 간 지연(Inter-Token Latency, ITL) 100 ms 미만입니다.

수치를 읽기 전에 실험 환경 절의 조건 하나를 확인해 둘 필요가 있습니다. 원문은 모든 벤치마크를 Dynamo 프런트엔드의 병렬 미디어 디코딩을 켠 상태로 측정했다고 밝히고 있습니다. 아래 값들은 이미지 다운로드와 디코딩이 이미 프런트엔드로 옮겨간 뒤의 수치이므로, 뒤에서 정리하는 병렬 미디어 디코딩의 26% 개선분은 여기에 추가로 얹히는 몫이 아닙니다. 한편 공식 문서의 지원 매트릭스는 프런트엔드 디코딩의 지원 토폴로지를 통합 워커로만 표기하는데, release/1.5.0 벤치마크 스크립트는 인코드 워커와 PD 워커 양쪽에 --frontend-decoding을 붙입니다. 문서와 벤치마크 하네스 사이에 이 차이가 있으니 자기 Dynamo 버전에서 직접 확인하는 편이 안전합니다.

지표 통합 서빙 코로케이트 인코더 분리 인코더
평균 TTFT 880 ms 374 ms (58% 감소) 442 ms (50% 감소)
평균 종단 간 지연 5.81초 5.27초 4.98초
동일 SLO 굿풋 1.0배 1.45배 1.70배

TTFT는 코로케이트 인코더에서 58%, 분리 인코더에서 50% 줄었습니다. 반면 종단 간 개선은 크지 않습니다. OSL 1024는 모델이 토큰 1024개를 생성한다는 뜻이고, 그 디코드 시간은 인코더 분리로 줄어들지 않기 때문입니다.

더 큰 신호는 굿풋입니다. 여기서 굿풋은 단순 처리량이 아니라 SLO를 만족한 상태로 처리한 트래픽 양을 뜻합니다. 이종 계층 구성은 같은 지연 SLO에서 70% 더 많은 트래픽을 처리했는데, 이는 GB200 예산을 건드리지 않고 인코더 용량만 추가했기 때문입니다. 지연 시간 숫자만 보면 4.98초와 5.81초의 차이가 소소해 보이지만, 운영 관점에서는 같은 GB200 4장으로 1.7배의 트래픽을 받는 쪽이 훨씬 중요한 차이입니다.

실측 2: 이미지 개수가 늘 때와 출력이 길어질 때

두 번째 실험은 두 축을 각각 바꿔 가며 측정합니다. 먼저 OSL을 512로 고정하고 이미지를 5장에서 50장까지, 이미지당 토큰 예산은 128개와 256개로 바꿔 가며 측정했습니다.

두 그래프의 형태가 결론을 그대로 보여 줍니다. 통합 서빙의 TTFT는 이미지 5장 조건에서 약 0.35초로 시작해 50장 조건에서 10초를 넘기며 급격히 치솟습니다. 종단 간 지연도 약 2.9초에서 15초까지 올라갑니다. 반면 두 EPD 토폴로지는 시각 토큰 부하가 늘어나도 거의 평평합니다. 인코더 워커를 따로 두면 인코딩 대기열이 LLM 스케줄러를 밀어내지 않으므로, 미디어 부하 증가가 지연 곡선의 기울기로 나타나지 않는 것입니다.

이어서 이미지를 5장으로 고정하고 OSL을 128에서 2048까지 늘렸습니다. 이번에는 방향이 뒤집힙니다.

OSL 코로케이트 인코더 분리 인코더
128 +11.8% +20.3%
256 +4.9% +14.2%
512 -1.2% +10.2%
1024 -1.2% +9.8%
2048 -2.5% +5.2%

분리 인코더는 20.3%에서 5.2%로 이득이 줄어들지만 끝까지 양수를 유지합니다. 코로케이트 인코더는 11.8%에서 시작해 OSL 512에서 이미 마이너스로 넘어가고 2048에서 2.5% 손실로 끝납니다. 원문 본문은 이 변화를 "11.8% 이득에서 2.5% 손실로 이동한다" 고만 서술하지만, 그래프의 값을 보면 손익분기점은 OSL 512와 256 사이에 있습니다.

원인은 코로케이션의 구조 자체입니다. 인코더 워커가 PD 워커와 같은 GPU를 공유하므로, OSL이 커져 디코드 압력이 높아질수록 GPU 경합이 인코더 분리의 이득을 상쇄하고 결국 넘어섭니다. 앞에서 확인한 PD 워커의 메모리 예산 축소(0.85에서 0.78로)도 여기에 더해집니다. KV 캐시 여유가 줄면 긴 출력에서 동시에 유지할 수 있는 시퀀스 수가 줄고, 그만큼 디코드 효율이 떨어집니다.

전체 격자 실측: TTFT는 전 구간 이득, 종단 간은 조건부

이미지 부하와 OSL을 격자로 교차시킨 결과는 다음과 같습니다. 먼저 TTFT 개선율입니다.

두 토폴로지 모두 격자의 모든 칸에서 양수입니다. 코로케이트 인코더는 이미지 5장에 토큰 128개인 가장 가벼운 조건에서 +25.1%에서 +28.3%, 이미지 50장에 토큰 128개인 가장 무거운 조건에서 +92.4%에서 +93.4%를 기록했습니다. 분리 인코더는 +36.8%에서 +91.4% 범위입니다.

세로축인 OSL을 따라가도 값이 거의 변하지 않습니다. TTFT는 정의상 첫 토큰까지의 시간이므로 출력 길이에 영향을 받지 않기 때문입니다. 흥미로운 점은 두 토폴로지의 순서가 부하에 따라 뒤집힌다는 것입니다. 가벼운 조건(5장 x 128토큰)에서는 분리 인코더가 +39.1%로 코로케이트의 +28.2%를 앞서지만, 가장 무거운 조건(50장 x 128토큰)에서는 코로케이트가 +92.4%로 분리 인코더의 +90.6%를 살짝 앞섭니다. 인코더 전용 GPU를 두는 것이 가벼운 부하에서는 확실한 이득이고, 부하가 극단으로 가면 임베딩 전송 비용이 그 이득을 조금씩 깎는 셈입니다.

종단 간 지연 격자는 그림이 다릅니다.

분리 인코더는 최소 +5.2%(5장 x 128토큰, OSL 2048)에서 최대 +86.6%(50장 x 128토큰, OSL 128)까지 격자 전체에서 양수를 유지합니다. 코로케이트 인코더는 최대 +87.3%까지 올라가지만, 이미지 5장에 토큰 128개인 가장 왼쪽 열에서 OSL 512, 1024, 2048의 세 칸이 모두 음수입니다. 각각 -1.2%, -1.2%, -2.5%입니다.

원문의 그림 설명은 이 중 OSL 2048 칸 하나만 언급하고 있습니다. 실제로는 미디어가 가벼워지는 순간부터 코로케이션의 손실 구간이 열 단위로 나타나며, 손실 폭 자체는 작지만 "가벼운 미디어와 긴 출력" 이라는 조합이 EPD의 금기 구역이라는 사실은 칸 하나가 아니라 열 하나로 읽어야 합니다. 원문이 도입부에서 제시한 "최대 5배 빠른 TTFT, 7배 빠른 종단 간 응답 시간" 이라는 요약도 격자의 최댓값에 비하면 보수적인 표현입니다. 개선율 87.3%는 약 7.9배, 93.4%는 약 15배에 해당합니다.

모델 크기와 정밀도: 같은 구성에서 이득의 부호가 바뀐다

같은 서빙 구성이라도 어떤 모델을 올리느냐에 따라 EPD의 부호가 바뀝니다. NVIDIA는 밀집 모델 세 가지로 모델 크기 절제 실험(ablation)을 수행했습니다.

모델 ViT 파라미터 비중 코로케이트 EPD 굿풋 (통합 서빙 대비)
Qwen3.5-4B 7.2% 2.62배
Qwen3.5-9B 4.7% 1.50배
Qwen3.5-27B 1.7% 0.65배

27B 구성에서는 EPD를 켠 쪽의 굿풋이 통합 서빙의 0.65배, 즉 35% 낮은 수준으로 떨어졌습니다. 모델이 커질수록 LLM이 서빙 작업의 더 많은 부분을 차지하고 비전 인코더의 크기는 거의 그대로이므로, 떼어내서 최적화할 인코더 작업 자체가 상대적으로 사라집니다.

Hugging Face에 공개된 세 모델의 config.json을 열어 보면 이 추세의 근거가 더 분명해집니다. 9B와 27B는 완전히 같은 비전 인코더(27층, 은닉 차원 1152)를 쓰고 4B만 더 작은 인코더(24층, 은닉 차원 1024)를 씁니다. 9B에서 27B로 갈 때 ViT 비중이 4.7%에서 1.7%로 떨어진 것은 인코더가 작아져서가 아니라 언어 모델만 커졌기 때문입니다. 세 모델 모두 전문가 설정이 없는 밀집 구조이고 BF16입니다.

다만 원문이 그림 각주로 붙여 둔 단서도 함께 읽어야 합니다. ViT 파라미터 비중은 전체 파라미터 대비 ViT 파라미터의 비율일 뿐이고, 세 모델은 모두 BF16으로 ViT와 LLM 어느 쪽도 양자화하지 않았습니다. 각주는 "파라미터 비중이 성능을 직접 예측하지는 않는다. 런타임과 스케줄링도 함께 작용하기 때문에 방향성 신호로만 유용하다" 고 명시합니다. 더 직접적인 요인은 ViT 순전파와 LLM 프리필, 디코드 사이의 런타임 균형이며, 파라미터 비중은 그 대리 지표(proxy)입니다.

정밀도 축은 방향이 반대입니다. 동일한 Qwen3.5-122B-A10B를 두고 비전 인코더와 LLM을 모두 BF16으로 돌렸을 때와, 활성 언어 모델(LM) 가중치만 NVFP4로 양자화했을 때를 비교했습니다.

NVFP4의 구조는 부호 1비트와 지수 2비트, 가수 1비트(E2M1)에 16개 값 블록마다 FP8 스케일 하나를 공유하는 형태입니다. 32개 값 블록에 2의 거듭제곱 스케일을 공유하는 MXFP4와 갈리는 지점이고, NVIDIA는 이 두 단계 마이크로 블록 스케일링 덕에 큰 모델에서 정확도 손실 위험이 낮다고 설명합니다.

BF16에서 1.78배였던 코로케이트 EPD의 굿풋 이득이 NVFP4에서 2.64배로 올라갔습니다. 두 구성 모두 비전 인코더는 BF16을 유지했고 활성 LM 가중치만 양자화했습니다. NVFP4가 LLM 프리필과 디코드를 가속하는 사이 ViT 순전파는 BF16에 머무르므로, 요청 시간에서 인코더 작업이 차지하는 몫이 커집니다. EPD가 인코더를 독립적으로 스케줄링할 여지도 그만큼 넓어집니다.

이 결과는 실무에서 반대 방향으로도 읽을 수 있습니다. LLM 쪽을 열심히 최적화할수록 인코더가 상대적 병목으로 부상하므로, 모델 경량화 도구로 배포용 체크포인트를 만든 서비스라면 EPD를 검토할 이유가 오히려 커집니다. 반대로 양자화하지 않은 중형 밀집 모델을 쓰고 있다면 EPD 도입이 손해일 가능성이 높습니다.

모델과 정밀도 더 알아보기

Qwen3.5-122B-A10B - Apache 2.0 라이선스, 전문가 256개 중 8개 활성화, 27층 ViT

nvidia/Qwen3.5-122B-A10B-NVFP4 - 실험에 사용된 NVFP4 양자화 체크포인트

Introducing NVFP4 for Efficient and Accurate Low-Precision Inference - NVIDIA 기술 블로그

Mixture of Experts 용어 설명 - NVIDIA 용어집

텍스트와 이미지가 섞인 트래픽에서의 줄서기 해소

프로덕션 트래픽은 텍스트 전용 요청과 멀티모달 요청이 섞여 들어오고, 두 유형이 함께 프리필 배치에 묶일 수 있습니다. 통합 서빙에서는 배치에 멀티모달 요청이 포함되면 워커가 미디어 전처리와 ViT 순전파를 마친 뒤 프리필을 시작하므로, 그 작업이 필요 없는 텍스트 요청의 TTFT까지 늘어납니다. 이것이 행 선두 차단(head-of-line blocking) 입니다.

EPD는 비전 인코딩을 별도 인코더 워커로 옮겨 이 의존성을 끊습니다. 프런트엔드는 두 유형 모두 프리필 워커로 보내지만, 임베딩이 없는 멀티모달 요청만 인코더 풀을 호출합니다. 텍스트 전용 요청은 인코더를 기다리지 않고 곧바로 프리필로 넘어갑니다.

텍스트와 이미지를 50대 50으로 섞은 지속 트래픽, OSL 128 조건에서 측정한 결과입니다.

요청 유형 통합 서빙 코로케이트 인코더 감소율
텍스트 요청 92.3 ms 53.3 ms 42.2%
이미지 요청 289.9 ms 200.6 ms 30.8%

이미지 요청은 여전히 인코더 지연을 감당해야 하지만 텍스트 요청은 비전 인코딩 완료를 기다리지 않고 LLM 프리필을 시작할 수 있습니다. 그래서 상대적 개선 폭이 텍스트 쪽에서 더 크게 나타납니다. 텍스트 요청이 지연에 민감한 대화형 서비스와 이미지 분석 요청이 같은 엔드포인트를 공유하는 구성이라면, 이 42.2%가 앞서 본 격자 수치보다 더 직접적인 도입 근거가 될 수 있습니다.

인코더 분리로 해결되지 않는 구간

앞에서 확인했듯 멀티모달 요청 TTFT의 상당 부분은 ViT가 시작되기도 전에, 미디어 다운로드와 디코딩과 전처리에서 소모됩니다. EPD는 그 구간을 최적화하지 않으므로 NVIDIA는 Dynamo의 다른 레버 세 가지를 함께 제시합니다.

병렬 미디어 디코딩(Parallel Media Decoding) 은 이미지 다운로드와 base64 디코딩, 이미지 압축 해제를 백엔드 워커에서 Dynamo의 Rust 프런트엔드로 옮깁니다. 프런트엔드는 CPU 워커 풀에서 이미지를 동시에 디코딩한 뒤 디코딩된 픽셀 버퍼를 NIXL로 백엔드에 전달합니다. 이미지당 토큰 256개로 30장을 보내는 인코더 전용 벤치마크(GB200 1장, 인코드 워커 2개)에서 동일 처리량 기준 평균 인코더 요청 지연이 281.3 ms에서 207.0 ms로 26%, P99가 752.1 ms에서 581.7 ms로 23% 줄었습니다. 백엔드 워커 명령에 --frontend-decoding을 추가해 켜며, dynamo.frontend 쪽에는 붙이지 않습니다. JPEG 입력에는 기본적으로 libjpeg-turbo를 씁니다.

여기에는 짚어 둘 제약이 있습니다. 공식 문서의 지원 매트릭스는 이 기능이 현재 이미지 입력만 지원하고 영상과 오디오는 지원하지 않는다고 명시합니다. 영상은 여전히 워커에서 디코딩됩니다. 앞의 TTFT 분해에서 영상 요청의 미디어 디코딩이 1205.7 ms로 가장 컸다는 점을 떠올리면, 개선 여지가 가장 큰 구간이 아직 이 레버의 사정권 밖에 있는 셈입니다.

임베딩 캐시(Embedding Cache) 는 계산된 임베딩을 CPU 측 LRU(Least Recently Used) 캐시에 저장해 같은 미디어를 다시 인코딩하지 않게 합니다. 공식 문서에 따르면 vLLM과 TensorRT-LLM의 분리 흐름에서는 프리필 워커가 캐시를 소유하고 히트 시 인코드 워커를 아예 건너뛰며, SGLang의 E/PD 구성에서는 인코드 워커가 캐시를 소유해 재인코딩을 생략합니다. --multimodal-embedding-cache-capacity-gb로 용량을 지정하고, vLLM은 0.17.0 이상이 필요합니다. 상품 카탈로그 질의나 같은 이미지를 두고 오가는 다중 턴 대화, 공유 도표를 반복 참조하는 문서 처리 파이프라인처럼 반복 미디어가 있는 워크로드에서만 의미가 있고, 모든 미디어가 유일하다면 효과가 없습니다.

멀티모달 KV 라우팅(Multimodal KV Routing) 은 Dynamo의 KV 인식 라우터가 텍스트와 함께 미디어 콘텐츠도 해싱하도록 만들어, 같은 미디어를 공유하는 요청이 해당 KV 블록을 이미 갖고 있는 워커로 향하게 합니다. 이것이 없으면 라우터 입장에서 모든 이미지가 동일한 플레이스홀더 토큰으로 보입니다. 공식 문서는 두 가지 경로를 안내합니다. 기본 Rust 프런트엔드는 이미지 식별자와 라우팅 토큰 레이아웃만 계산하고 멀티모달 프로세서는 선택된 워커가 실행하므로 프런트엔드 부담이 작지만, 모델이 Dynamo의 Rust 프로세서 레지스트리에 등록되어 있어야 합니다. --dyn-chat-processor vllm을 쓰면 프런트엔드가 vLLM의 전체 멀티모달 프로세서를 실행해 더 넓은 모델을 지원하는 대신 전처리와 전송 부담이 프런트엔드로 옮겨갑니다.

운영에서 걸리기 쉬운 조건이 하나 더 있습니다. 같은 문서에 따르면 HTTP 이미지의 식별자는 기본적으로 질의 문자열을 포함한 URL 바이트를 그대로 해싱합니다. 완전히 같은 URL을 재사용하면 같은 식별자가 나오지만, 같은 이미지를 가리키는 서로 다른 URL은 다른 식별자가 됩니다. CDN이 URL마다 서명이나 만료 파라미터를 붙이는 구성이라면 캐시가 사실상 매번 미스가 됩니다. 이때 --frontend-decoding을 켜면 프런트엔드가 디코딩된 이미지 콘텐츠를 해싱해 URL과 무관하게 식별자가 안정됩니다. 데이터 URL도 같은 규칙을 따릅니다. 앞서 본 병렬 미디어 디코딩 플래그가 지연 최적화뿐 아니라 캐시 적중률에도 관여하는 부분입니다. 지원 모델 계열 표에는 Qwen2-VL과 Qwen2.5-VL, Qwen3-VL, LLaVA 1.5, LLaVA-NeXT, Llama 4, Kimi K2.5와 K2.6, Qwen3.5, Qwen3.6이 올라 있고 나머지는 텍스트 접두 문맥만으로 라우팅됩니다.

Dynamo 멀티모달 기능 더 알아보기

Parallel Media Decoding - 이미지 디코딩을 Rust 프런트엔드로 이동

Embedding Cache - 비전 인코더 출력의 CPU 측 LRU 캐시

Multimodal KV Routing - 미디어 콘텐츠를 해싱하는 KV 인식 라우팅

직접 재현해보기

NVIDIA는 실험 재현용 스크립트를 Dynamo 저장소의 benchmarks/multimodal/sweep/experiments/epd 경로에 공개했습니다. 저장소의 README는 vLLM 0.26.0(vllm/vllm-openai:v0.26.0-ubuntu2404 런타임 이미지)과 SGLang 0.5.16(lmsysorg/sglang:v0.5.16-cu130-runtime)에서 테스트했다고 밝히고 있습니다. 즉 이 벤치마크는 Dynamo가 오케스트레이션을 담당하고 실제 추론 엔진은 vLLM 또는 SGLang이 맡는 구성입니다.

먼저 데이터셋을 내려받습니다. 기본값은 이미지 50장이며 --count N으로 줄일 수 있습니다.

cd benchmarks/multimodal/sweep/experiments/epd
python download_dataset.py \
  --output-dir /to/your/path

단일 워크로드를 실행하는 명령입니다.

# sglang or vllm
python run_experiment.py \
  --backend sglang \
  --topology aggregate epd \
  --image-count 5 \
  --osl 128 \
  --model nvidia/Qwen3.5-122B-A10B-NVFP4 \
  --image-dir /to/your/path/images \
  --output-dir /to/your/path/results

격자 전체를 훑는 스윕(sweep)은 이미지 개수와 토큰 예산, OSL을 목록으로 넘깁니다.

# sglang or vllm
python run_experiment.py \
  --backend sglang \
  --topology aggregate epd \
  --image-count 5,10,30 \
  --image-token-budget 128 256 \
  --osl 128,512,2048 \
  --model nvidia/Qwen3.5-122B-A10B-NVFP4 \
  --image-dir /to/your/path/images \
  --output-dir /to/your/path/results

여기서 확인해 둘 점은 공개된 재현 스크립트의 범위입니다. README는 "통합 서빙과 코로케이트 EPD 토폴로지를 비교한다" 고 적고 있고, --topology 인자도 aggregateepd 두 값만 받습니다. run_experiment.pyTOPOLOGY_ALIASES에는 aggregate, agg, epd 세 키뿐이고 BACKEND_LAUNCHERS에도 vLLM과 SGLang 각각의 통합, EPD 런처 네 개만 등록되어 있습니다. 본문에서 여러 차례 등장한 이종 하드웨어 구성(RTX 6000D 인코더 계층 + GB200 PD 계층)은 이 스크립트로 그대로 재현되지 않습니다. 격자에서 유일하게 손실 칸이 없었던 토폴로지가 재현 범위 밖이라는 점은 결과를 인용할 때 함께 밝혀야 할 조건입니다.

부하 생성기는 NVIDIA의 AIPerf이고, 스크립트가 EXPECTED_AIPERF_VERSION = "0.10.0"으로 버전을 검증하므로 다른 버전에서는 결과 검증 단계가 실패합니다. 원문이 밝히지 않은 기본값도 스크립트에 남아 있습니다. --isl 기본값이 9000, --qps 기본값이 0.5이므로 README 예시대로 두 인자를 생략하면 시각 토큰과 별개로 텍스트 입력 9000토큰, 초당 0.5요청 조건에서 측정됩니다. 본문의 수치를 자기 트래픽에 옮길 때 함께 봐야 할 조건입니다.

실행 스크립트를 들여다보면 워커 역할이 CLI 플래그로 어떻게 나뉘는지도 보입니다. SGLang 경로에서는 인코드 워커가 --disaggregation-mode encode로, PD 워커가 --dedicated-mm-encoder --disaggregation-mode pd로 뜹니다. vLLM 경로에서는 PD 워커에 --route-to-encoder --enable-mm-embeds --disaggregation-mode pd가 붙습니다. 코로케이션은 nvidia-cuda-mps-control -d로 MPS 데몬을 띄우고 워커들에게 CUDA_MPS_PIPE_DIRECTORY를 공유시키는 방식으로 구현되어 있습니다. 벤치마크 조건을 깔끔하게 만들기 위해 접두 문맥 캐싱(prefix caching)은 양쪽 모두 끄고(--no-enable-prefix-caching, --disable-radix-cache) MoE 백엔드로는 FlashInfer CuteDSL 경로를 씁니다.

vLLM과 SGLang의 EPD 지원 현황

원문은 마무리에서 "vLLM과 SGLang이 각자의 EPD 스택을 더 발전시킬 로드맵을 갖고 있다" 고 적으며 두 저장소의 이슈를 링크합니다. 두 이슈를 실제로 열어 보면 상태와 진행 정도가 서로 많이 다릅니다.

vLLM 쪽 EPD (EC connector) Tracker는 열려 있는 우산(umbrella) 트래커이고 이 글을 쓰는 시점에도 갱신되고 있습니다. Model Runner V2의 EC 커넥터 지원과 인코더 전용 인스턴스에서 멀티모달 임베딩 수집을 건너뛰는 변경은 병합되었고, 공유 메모리 커넥터(ECSharedMemoryConnector)와 EC 커넥터 메트릭 수집, 동적 EPD 프록시 지원은 아직 열린 항목입니다.

트래커에서 눈에 띄는 것은 인코더 캐시(Encoder Cache, EC)를 옮기는 전송 백엔드가 여러 갈래로 나뉘어 있다는 점입니다. CPU 오프로딩 커넥터와 NIXL 기반 P2P 커넥터는 병합되었고, Mooncake의 TransferEngine을 쓰는 ECMooncakeConnector도 병합되어 있습니다. LMCache와 ZMQ 커넥터는 열린 상태입니다. 즉 vLLM에서 EPD는 하나의 구현이 아니라 커넥터 인터페이스이고, 어느 전송을 고르느냐가 배포 형태를 좌우합니다. XPU에서의 EC 커넥터 KV 오프로딩 지원도 이미 병합되어 있습니다.

영상 쪽 진행 상황은 앞에서 짚은 공백과 정확히 겹칩니다. 영상 임베딩 입력 지원은 병합되었지만 인코더 전용 인스턴스에서 GPU NVDEC로 영상 미디어 입출력을 처리하는 항목은 아직 초안(draft) 으로 남아 있습니다. 영상 디코딩이 TTFT에서 가장 큰 덩어리인데 그 구간의 가속이 가장 늦게 오고 있는 셈입니다.

SGLang 쪽은 원문 링크만 보고 판단하면 상태를 거꾸로 읽게 됩니다. 링크된 RFC 이슈inactive 라벨이 붙은 채 2026년 9월 7일에 닫혔지만, 닫힌 이유는 제안이 거절된 것이 아니라 활동이 멈춰 스테일 처리된 것이고 RFC가 열거한 PR 대부분은 그 전에 이미 업스트림에 들어갔습니다. RFC의 PR 표를 하나씩 확인하면 MiMo-V2.5 EPD 지원(#24931), GPU 이미지 전처리와 병렬 영상 디코딩(#25588), 인코더의 크로스 요청 배칭(#25964), 인코더 데이터 병렬 모드(#26576), 멀티모달 URL 다운로드의 HTTP 세션 재사용(#28056), VLM 임베드 경로의 CUDA 동기 제거(#26082), 멀티모달 토큰 수 계측(#27122), EPD 인코더 서버의 Prometheus 메트릭(#27564)이 2026년 5월부터 7월 사이에 병합되었습니다. 이미지 로더 분리(#29712), 인코더 공유 메모리 캐시(#28435), 프리필 파이프라이닝(#26708)은 아직 열려 있습니다.

SGLang의 EPD 분리 자체는 더 앞선 2025년 12월 PR #12263으로 병합되었고, RFC는 제안자 팀이 v0.5.5 기반 자체 포크에서 MiMo-V2.5 프로덕션 서빙으로 검증한 최적화를 메인라인에 다시 올리는 작업이었습니다. RFC가 함께 보고한 자체 측정값은 이 글의 주제와 같은 방향을 가리킵니다. 1K 토큰 이미지로 돌린 독립 인코더 벤치마크에서 소화 가능한 QPS가 15에서 30으로 두 배가 되는 동안 평균 지연은 78.39 ms에서 80.28 ms로 사실상 그대로였고, P90은 100.76 ms에서 82.94 ms로 오히려 줄었습니다. RFC는 이 이득의 출처로 크로스 요청 배칭, 병렬 이미지 다운로드, 다운로드와 순전파의 파이프라이닝, GPU 측 전처리를 꼽습니다. 넷 중 셋이 ViT 연산이 아니라 그 앞단입니다.

RFC가 열거한 병목 목록에는 EPD를 직접 운영할 때 밟기 쉬운 함정도 들어 있습니다. EPD 모드에서 디코드 노드가 이미지와 영상과 오디오를 다시 내려받고 프로세서를 다시 실행하고 있었다는 항목입니다. 제안 팀은 프리필이 끝난 뒤 경량 메타데이터만 부트스트랩 서버로 디코드에 넘겨 다운로드와 전처리 경로를 통째로 건너뛰도록 고쳤습니다. 큰 이미지에서 CPU 리사이즈와 정규화, 패치화가 종단 간 지연을 지배하는 문제와 높은 QPS에서 이미지를 순차로 내려받고 PIL 디코딩이 GIL에 묶이는 문제는 커뮤니티가 #15456에서 독립적으로 같은 접근을 구현했다고 RFC가 함께 밝히고 있습니다.

두 프레임워크를 나란히 놓으면 Dynamo와의 차이도 드러납니다. Dynamo의 병렬 미디어 디코딩은 앞서 확인한 대로 이미지 전용인데, SGLang은 병렬 영상 디코딩을 이미 병합했습니다. 정리하면 EPD는 특정 프레임워크의 고유 기능이 아니라 주요 추론 엔진들이 공통으로 향하고 있는 방향이고, 진행 속도와 완성도는 엔진마다, 그리고 모달리티마다 다릅니다.

정리: 언제 쓰고 언제 쓰지 않을 것인가

이 실측이 남기는 판단 기준을 정리하면 다음과 같습니다.

조건 권장 토폴로지 근거
이미지 여러 장 또는 영상, 출력 짧거나 중간 코로케이트 또는 분리 인코더 격자 전체에서 TTFT 25% 이상, 종단 간 최대 87% 개선
이미지 적고 출력 아주 긴 요청 위주 통합 서빙 코로케이트가 OSL 512부터 종단 간 손실
동종 GPU 클러스터 코로케이트 인코더 가벼운 ViT에 같은 등급 GPU를 통째로 비워 두지 않음
저비용 GPU 계층이 있는 이종 클러스터 분리 인코더 격자 전체 양수, 동일 SLO 굿풋 1.70배
양자화된 MoE 모델 코로케이트 인코더 NVFP4에서 굿풋 2.64배
양자화 없는 중형 밀집 모델 통합 서빙 27B BF16에서 굿풋 0.65배
텍스트와 멀티모달 혼합 트래픽 코로케이트 인코더 텍스트 TTFT 42.2% 감소

한 줄로 줄이면 인코더 분리는 성능 스위치가 아니라 워크로드 형태에 대한 베팅입니다. 요청 처리 시간에서 비전 인코딩이 차지하는 비중이 클 때만 값을 하고, 그 비중은 미디어 부하와 출력 길이, 모델 크기, 정밀도가 함께 결정합니다. 그리고 실측에서 확인했듯 이 요인들은 서로 반대 방향으로 작동합니다.

실무적으로 유용한 지점은 판단 순서입니다. 토폴로지를 먼저 고르는 것이 아니라, 먼저 자기 트래픽의 TTFT를 미디어 전처리와 ViT, LLM 프리필로 쪼개 보는 것입니다. 이 글의 첫 표에서 ViT가 TTFT의 5%에서 11% 사이였던 것처럼, 실제 병목이 인코더가 아닌 다른 곳에 있다면 EPD가 아니라 병렬 미디어 디코딩이나 임베딩 캐시가 먼저 검토할 도구입니다. 엣지 환경의 MoE 서빙이나 배치 크기에 맞춘 추측 디코딩 조절처럼, 최근의 추론 최적화 연구가 공통적으로 "어떤 조건에서 이 기법이 유효한가" 를 앞세우는 것도 같은 이유입니다.

라이선스

NVIDIA Dynamo와 NIXL은 모두 Apache License 2.0으로 배포되고 있어, 연구 목적은 물론 상업적 용도로도 자유롭게 사용 및 수정이 가능합니다. 두 저장소 모두 DeepSeek에서 파생된 일부 파일(Dynamo의 테스트 데이터, NIXL의 예제 코드)에 대해서만 MIT License를 별도로 표기하고 있습니다. 실험에 사용된 Qwen3.5-122B-A10B 모델 역시 Apache 2.0으로 공개되어 있습니다.

:scroll: When to Use Encode-Prefill-Decode Disaggregation to Accelerate Multimodal Model Serving 소개 블로그

:github: NVIDIA Dynamo GitHub 저장소

:github: NVIDIA Inference Transfer Library (NIXL) GitHub 저장소

:books: NVIDIA Dynamo 공식 문서

더 읽어보기




이 글은 GPT 모델로 정리한 초안을 바탕으로 한 것으로, 원문의 내용 또는 의도와 다르게 정리된 내용이 있을 수 있습니다. 관심있는 내용이시라면 원문도 함께 참고해주세요! 읽으시면서 어색하거나 잘못된 내용을 발견하시면 댓글로 알려주시기를 부탁드립니다. :hugs:

이 글은 :pytorch:파이토치 한국 사용자 모임:south_korea:이 직접 정리한 글입니다. 새 글을 놓치지 않으시려면 텔레그램(Telegram)이나 Slack/Discord/Teams/Dooray/GoogleChat 등으로 알림을 받으시고, 회원으로 가입하시면 주요 글들을 이메일:love_letter:로도 보내드립니다! :smiley:

:wrapped_gift: 아래:down_right_arrow:쪽에 좋아요:+1:를 눌러주시면 새로운 소식들을 정리하고 공유하는데 힘이 됩니다~ :star_struck: