Disaggregated Serving (분리 서빙)
Disaggregated Serving (분리 서빙 / Disaggregated Serving)
LLM 추론은 컨텍스트(프리필)와 생성(디코드) 두 단계로 나뉘는데, 이 둘은 컴퓨팅 특성이 완전히 달라요. 프리필 단계는 프롬프트 토큰의 KV 캐시를 계산하고, 생성 단계는 캐시된 값을 이용해 토큰을 하나씩 만들어 냅니다. 이 문서는 같은 GPU에서 두 단계를 함께 돌리는 방식과, 단계별로 다른 GPU에서 돌리는 분리 방식의 차이를 설명하고 TensorRT-LLM에서 분리 서빙을 구성하는 방법을 다뤄요.
동기 (Motivation)
LLM 추론 요청을 서빙하는 방법은 두 가지예요.
- 통합 LLM 서빙(이 테크 블로그에서 in-flight 배칭 또는 IFB라고도 함): 컨텍스트와 생성 단계를 같은 GPU에서 실행해요.
- 분리(Disaggregated) LLM 서빙: 컨텍스트와 생성 단계를 서로 다른 GPU에서 실행해요.
통합 서빙에서는 두 단계가 같은 컴퓨팅 자원을 두고 경쟁하며 서로 간섭할 수 있어요. 분리 서빙은 두 단계를 분리해 각각 별도 GPU 풀과 서로 다른 병렬화 전략을 쓰게 함으로써 이 문제를 해결합니다. 이렇게 분리하면 컨텍스트와 생성 단계 사이의 간섭이 사라지고, TTFT와 TPOT를 각각 독립적으로 최적화할 수 있어요. 분리 방식은 컨텍스트 GPU에서 생성 GPU로 KV 캐시 블록을 옮기는 오버헤드를 수반하지만, 혜택은 특히 입력 시퀀스가 길고 출력 길이가 적당한 워크로드에서 큽니다.
KV 캐시 교환 (KV Cache Exchange)
캐시 레이아웃 변환 (Cache Layout Transformation)
KV 캐시 전송에 필요한 최적화는 싱글 노드 멀티 GPU인지, 멀티 노드 멀티 GPU인지, GPU 모델이 다른지에 따라 달라져요. 이를 위해 TensorRT-LLM은 각 환경에서 선택할 수 있도록 여러 환경변수를 제공합니다.
전역 고유 요청 ID (Unique Global Request ID)
클라이언트가 자신의 양수 disagg_request_id를 제공하면 그 값이 그대로 사용되며 전역적으로 유일해야 해요. 설정하지 않으면 서버가 위에서처럼 snowflake ID를 발급합니다.
사용법 (Usage)
Dynamo
Dynamo는 다른 방법에는 없는 몇 가지 고급 기능을 도입하는데, 그중 하나가 디커플링된 전·후처리 워커로, 높은 동시성 조건에서 특히 유용해요. Dynamo를 이용한 분리 LLM 추론 워크플로는 공식 문서의 그림을 참고하면 됩니다.
trtllm-serve
backend는 KV 캐시를 전송하는 데 쓸 통신 라이브러리를 선택해요. RDMA / NVLink로 전송하는 NIXL로 설정하면 됩니다. 이 필드에는 기본값이 없어서, 남겨두지 않고 비워 두면 워커는 시작하지만 캐시 트랜시버를 띄우지 않고 이후 라우팅되는 분리 요청을 거부해요. max_tokens_in_buffer는 비워 두는 편이 좋아요. 이 값은 생성 워커가 동시에 수용하는 KV 전송 수를 제한하는데, 내장 기본값은 모델의 최대 시퀀스 길이에서 유도되므로 손으로 작게 쓴 값은 전송 경로만 조절할 뿐이거든요. kv_transfer_timeout_ms는 요청이 KV 캐시를 기다릴 수 있는 시간을 제한하고, 기본값은 60000이에요.
컨텍스트 서버와 생성 서버를 띄운 뒤에는, 클라이언트 요청을 받아 컨텍스트·생성 서버 사이를 조율하는 분리 서버를 띄울 수 있어요.
trtllm-serve disaggregated -c disagg_config.yaml
요청을 컨텍스트 서버로 라우팅할 때 분리 서버는 요청을 "context-only"로 표시해 생성 단계를 건너뛰게 하고, 반대로 생성 서버로 라우팅할 때는 "generation-only"로 표시해 컨텍스트 단계를 건너뛰게 합니다.
환경 변수 (Environment Variables)
TRT-LLM은 분리 서비스의 동작을 제어하기 위해 몇 가지 환경변수를 사용해요.
TRTLLM_DISABLE_KV_CACHE_TRANSFER_OVERLAP:1로 설정하면 생성 워커가 모델 추론과 KV 캐시 전송을 겹치지 않게 실행합니다. 기본값은0이에요.TRTLLM_NIXL_KVCACHE_BACKEND: NIXL 자체가 사용하는 전송 방식을 선택해요.NCCL_GRAPH_MIXING_SUPPORT: TensorRT-LLM은 이제 기본적으로 graph mixing 지원을 끈 채 공용 NCCL 커뮤니케이터를 초기화해, CUDA 그래프로 캡처된 NCCL 연산의 런칭 오버헤드를 줄여요. 이는 커뮤니케이터가 병렬 그래프 런칭이나 캡처되지 않은 NCCL 호출에 사용되지 않는다는 가정 하에 동작합니다.
트러블슈팅과 FAQ
디버깅 FAQ
Q. Disaggregated serving is not enabled, please check the configuration 오류는 어떻게 처리하나요?
A. cache_transceiver_config.backend는 기본값이 없어서, 비워 두면 해당 워커의 트랜시버가 비활성화돼요. 컨텍스트 워커와 생성 워커 양쪽의 --config 파일에 이 값을 설정해 주세요.
더 알아보기 (Learn more)
- 어텐션 MHA·MQA·GQA는 Multi-Head, Multi-Query, and Group-Query Attention 문서에 있어요.
- 임베딩(인코더 전용) 서빙은 Embeddings (Encoder-Only Models)을 참고해요.
- KV 캐시 시스템 전반은 KV Cache System에서 확인할 수 있어요.