병렬 처리와 확장
병렬 처리와 확장 (Parallelism and Scaling)
단일 모델 복제본을 분산 추론하는 전략을 고르는 방법과 단일 노드·멀티 노드 배포 구성을 다룹니다. GPU 메모리에 모델이 들어가는 방식에 따라 tensor parallelism과 pipeline parallelism을 조합해 확장합니다.
출처: 문서
본문
단일 모델 복제본의 분산 추론 전략
단일 모델 복제본에 대한 분산 추론 전략을 고르려면 다음 지침을 따르세요:
- 단일 GPU (분산 추론 불필요): 모델이 단일 GPU에 들어가면 분산 추론은 불필요할 것입니다. 그 GPU에서 추론을 실행하세요.
- Tensor parallel 추론을 쓰는 단일 노드 멀티 GPU: 모델이 단일 GPU에는 너무 크지만 멀티 GPU 단일 노드에는 들어가면 tensor parallelism을 사용하세요. 예를 들어 4 GPU 노드면
tensor_parallel_size=4로 설정합니다. - Tensor parallel + pipeline parallel 추론을 쓰는 멀티 노드 멀티 GPU: 모델이 단일 노드에는 너무 크면 tensor parallelism과 pipeline parallelism을 결합하세요.
tensor_parallel_size를 노드당 GPU 수로,pipeline_parallel_size를 노드 수로 설정합니다. 예를 들어 노드당 8 GPU짜리 2개 노드면tensor_parallel_size=8,pipeline_parallel_size=2로 설정합니다.
모델을 담을 GPU 메모리가 충분해질 때까지 GPU와 노드 수를 늘리세요. tensor_parallel_size는 노드당 GPU 수, pipeline_parallel_size는 노드 수로 설정합니다.
모델을 담을 충분한 리소스를 확보한 뒤 vllm을 실행하세요. 다음과 같은 로그 메시지를 찾으세요:
INFO 07-23 13:56:04 [kv_cache_utils.py:775] GPU KV cache size: 643,232 tokens
INFO 07-23 13:56:04 [kv_cache_utils.py:779] Maximum concurrency for 40,960 tokens per request: 15.70x
GPU KV cache size 줄은 GPU KV cache에 한 번에 저장할 수 있는 총 토큰 수를 보고합니다. Maximum concurrency 줄은 각 요청이 지정된 토큰 수(위 예시에서는 40,960)를 요구할 때 동시에 서빙할 수 있는 요청 수 추정치를 제공합니다. 요청당 토큰 수는 모델 구성의 최대 시퀀스 길이인 ModelConfig.max_model_len에서 가져옵니다. 이 숫자가 처리량 요구사항보다 낮다면 클러스터에 GPU나 노드를 더 추가하세요.
엣지 케이스: 불균등 GPU 분할
모델이 단일 노드에 들어가지만 GPU 수가 모델 크기를 균등히 나누지 못하면 pipeline parallelism을 활성화하세요. 이것은 레이어를 따라 모델을 분할해 불균등 분할을 지원합니다. 이 시나리오에서 tensor_parallel_size=1로, pipeline_parallel_size를 GPU 수로 설정합니다. 또한 노드의 GPU에 NVLINK 인터커넥트가 없으면(예: L40S) tensor parallelism 대신 pipeline parallelism을 활용해 더 높은 처리량과 더 낮은 통신 오버헤드를 얻으세요.
MoE (Mixture of Experts) 모델의 분산 서빙
전문가 레이어에 별도의 병렬화 전략을 사용해 전문가의 고유 병렬성을 활용하는 것이 유리한 경우가 많습니다. vLLM은 Data Parallel attention과 Expert 또는 Tensor Parallel MoE 레이어를 결합한 대규모 배포를 지원합니다. 자세한 내용은 Data Parallel Deployment를 참고하세요.
단일 노드 배포
vLLM은 분산 tensor-parallel 및 pipeline-parallel 추론·서빙을 지원합니다. 구현에는 Megatron-LM의 tensor parallel 알고리즘이 포함됩니다.
기본 분산 런타임은 멀티 노드 추론에 Ray, 단일 노드 추론에 네이티브 Python multiprocessing입니다. LLM 클래스의 distributed_executor_backend 또는 API 서버의 --distributed-executor-backend에서 기본값을 재정의할 수 있습니다. multiprocessing에는 mp, Ray에는 ray를 사용하세요.
멀티 GPU 추론을 위해 LLM 클래스에서 tensor_parallel_size를 원하는 GPU 수로 설정하세요. 예를 들어 4개 GPU에서 추론하려면:
from vllm import LLM
llm = LLM("facebook/opt-13b", tensor_parallel_size=4)
output = llm.generate("San Francisco is a")
멀티 GPU 서빙을 위해 서버 시작 시 --tensor-parallel-size를 포함하세요. 예를 들어 4개 GPU에서 API 서버를 실행하려면:
vllm serve facebook/opt-13b \
--tensor-parallel-size 4
pipeline parallelism을 활성화하려면 --pipeline-parallel-size를 추가하세요. 예를 들어 pipeline parallelism과 tensor parallelism으로 8개 GPU에서 API 서버를 실행하려면:
# Eight GPUs total
vllm serve gpt2 \
--tensor-parallel-size 4 \
--pipeline-parallel-size 2
멀티 노드 배포
단일 노드에 모델을 담을 GPU가 부족하면 vLLM을 여러 노드에 배포하세요. 모든 노드가 모델 경로와 Python 패키지를 포함해 동일한 실행 환경을 제공하는지 확인하세요. 컨테이너 이미지 사용이 권장됩니다. 환경을 일관되게 유지하고 호스트 이질성을 숨기는 편리한 방법이기 때문입니다.
Ray란 무엇인가?
Ray는 Python 프로그램 확장을 위한 분산 컴퓨팅 프레임워크입니다. 멀티 노드 vLLM 배포는 Ray를 런타임 엔진으로 사용할 수 있습니다.
vLLM은 Ray를 사용해 여러 노드에 걸친 작업의 분산 실행을 관리하고 실행 위치를 제어합니다.
Ray는 또한 vLLM을 엔진으로 활용할 수 있는 대규모 오프라인 배치 추론과 온라인 서빙용 하이레벨 API를 제공합니다. 이 API들은 vLLM 워크로드에 프로덕션급 내결함성·확장·분산 관측성을 추가합니다.
Ray는 선택적 의존성입니다. Ray 기반 실행을 사용하기 전에 명시적으로 설치하세요. 예를 들어:
pip install "ray[cgraph]"
자세한 내용은 Ray 문서를 참고하세요.
컨테이너로 Ray 클러스터 설정
헬퍼 스크립트 examples/ray_serving/run_cluster.sh는 여러 노드에 걸쳐 컨테이너를 시작하고 Ray를 초기화합니다. 기본적으로 이 스크립트는 관리 권한 없이 Docker를 실행하므로, 프로파일링/트레이싱 시 GPU 성능 카운터에 접근할 수 없습니다. 관리 권한을 활성화하려면 Docker 명령에 --cap-add=CAP_SYS_ADMIN 플래그를 추가하세요.
한 노드를 헤드 노드로 선택하고 실행:
bash run_cluster.sh \
vllm/vllm-openai \
<HEAD_NODE_IP> \
--head \
/path/to/the/huggingface/home/in/this/node \
-e VLLM_HOST_IP=<HEAD_NODE_IP>
각 워커 노드에서 실행:
bash run_cluster.sh \
vllm/vllm-openai \
<HEAD_NODE_IP> \
--worker \
/path/to/the/huggingface/home/in/this/node \
-e VLLM_HOST_IP=<WORKER_NODE_IP>
VLLM_HOST_IP는 각 워커마다 고유합니다. 이 명령을 실행하는 셸을 열어 둔 채 유지하세요. 셸을 닫으면 클러스터가 종료됩니다. 모든 노드가 IP 주소로 서로 통신할 수 있는지 확인하세요.
네트워크 보안
보안을 위해 VLLM_HOST_IP를 사설 네트워크 세그먼트의 주소로 설정하세요. 이 네트워크로 전송되는 트래픽은 암호화되지 않으며, 엔드포인트는 적이 네트워크에 접근하면 임의 코드를 실행할 수 있게 악용될 수 있는 형식으로 데이터를 교환합니다. 신뢰할 수 없는 주체가 네트워크에 닿지 못하게 하세요.
어느 노드에서든 컨테이너에 들어가 ray status와 ray list nodes를 실행해 Ray가 예상한 수의 노드와 GPU를 찾는지 확인하세요.
팁
대안으로 KubeRay로 Ray 클러스터를 설정할 수 있습니다. 자세한 내용은 KubeRay vLLM 문서를 참고하세요.
Ray 클러스터에서 vLLM 실행
팁
Ray가 컨테이너 안에서 실행된다면 이 가이드의 나머지 명령을 호스트가 아닌 컨테이너 안에서 실행하세요. 컨테이너 안에서 셸을 열려면 노드에 연결해 docker exec -it <container_name> /bin/bash를 사용하세요.
Ray 클러스터가 실행되면 단일 노드 설정처럼 vLLM을 사용하세요. Ray 클러스터의 모든 리소스가 vLLM에 보이므로, 단일 노드의 단일 vllm 명령으로 충분합니다.
일반적인 관행은 tensor parallel 크기를 각 노드의 GPU 수로, pipeline parallel 크기를 노드 수로 설정하는 것입니다. 예를 들어 2개 노드에 16 GPU(노드당 8 GPU)가 있다면 tensor parallel 크기 8, pipeline parallel 크기 2로 설정합니다:
vllm serve /path/to/the/model/in/the/container \
--tensor-parallel-size 8 \
--pipeline-parallel-size 2 \
--distributed-executor-backend ray
대안으로 tensor_parallel_size를 클러스터의 총 GPU 수로 설정할 수도 있습니다:
vllm serve /path/to/the/model/in/the/container \
--tensor-parallel-size 16 \
--distributed-executor-backend ray
MultiProcessing으로 vLLM 실행
Ray 외에도 멀티 노드 vLLM 배포는 multiprocessing을 런타임 엔진으로 사용할 수 있습니다. 다음은 2개 노드(노드당 8 GPU)에 tp_size=8·pp_size=2로 모델을 배포하는 예시입니다.
한 노드를 헤드 노드로 선택하고 실행:
vllm serve /path/to/the/model/in/the/container \
--tensor-parallel-size 8 --pipeline-parallel-size 2 \
--nnodes 2 --node-rank 0 \
--master-addr <HEAD_NODE_IP>
다른 워커 노드에서 실행:
vllm serve /path/to/the/model/in/the/container \
--tensor-parallel-size 8 --pipeline-parallel-size 2 \
--nnodes 2 --node-rank 1 \
--master-addr <HEAD_NODE_IP> --headless
tensor parallelism을 위한 네트워크 통신 최적화
효율적인 tensor parallelism은 빠른 inter-node 통신을 요구하며, 가급적 InfiniBand 같은 고속 네트워크 어댑터를 사용합니다. InfiniBand를 쓰도록 클러스터를 설정하려면 examples/ray_serving/run_cluster.sh 헬퍼 스크립트에 --privileged -e NCCL_IB_HCA=mlx5 같은 추가 인자를 붙이세요. 필요한 플래그에 대한 자세한 내용은 시스템 관리자에게 문의하세요.
GPUDirect RDMA 활성화
GPUDirect RDMA(Remote Direct Memory Access)는 네트워크 어댑터가 CPU와 시스템 메모리를 우회해 GPU 메모리에 직접 접근할 수 있게 하는 NVIDIA 기술입니다. 이 직접 접근은 지연과 CPU 오버헤드를 줄여, 노드 간 GPU 사이의 대용량 데이터 전송에 유리합니다.
vLLM에서 GPUDirect RDMA를 활성화하려면 다음 설정을 구성하세요:
IPC_LOCK보안 컨텍스트: 컨테이너 보안 컨텍스트에IPC_LOCK캐퍼빌리티를 추가해 메모리 페이지를 잠그고 디스크 스왑을 방지합니다./dev/shm공유 메모리: 프로세스 간 통신(IPC)용 공유 메모리를 제공하도록 파드 스펙에/dev/shm을 마운트합니다.
Docker를 사용한다면 컨테이너를 다음과 같이 설정:
docker run --gpus all \
--ipc=host \
--shm-size=16G \
-v /dev/shm:/dev/shm \
vllm/vllm-openai
Kubernetes를 사용한다면 파드 스펙을 다음과 같이 설정:
...
spec:
containers:
- name: vllm
image: vllm/vllm-openai
securityContext:
capabilities:
add: ["IPC_LOCK"]
volumeMounts:
- mountPath: /dev/shm
name: dshm
resources:
limits:
nvidia.com/gpu: 8
requests:
nvidia.com/gpu: 8
volumes:
- name: dshm
emptyDir:
medium: Memory
...
GPUDirect RDMA 동작 확인
InfiniBand 카드가 GPUDirect RDMA를 사용하는지 확인하려면 상세 NCCL 로그로 vLLM을 실행하세요: NCCL_DEBUG=TRACE vllm serve ....
그런 다음 NCCL 버전과 사용된 네트워크를 찾으세요.
- 로그에서
[send] via NET/IB/GDRDMA를 찾으면 NCCL이 GPUDirect RDMA로 InfiniBand를 사용하는 것이며, 효율적입니다. - 로그에서
[send] via NET/Socket을 찾으면 NCCL이 원시 TCP 소켓을 사용한 것이며, 노드 간 tensor parallelism에는 효율적이지 않습니다.
Hugging Face 모델 사전 다운로드
Hugging Face 모델을 사용한다면 vLLM을 시작하기 전에 모델을 다운로드하는 것이 권장됩니다. 모든 노드의 같은 경로에 모델을 다운로드하거나, 모든 노드가 접근 가능한 분산 파일 시스템에 모델을 저장하세요. 그런 다음 레포지토리 ID 대신 모델 경로를 전달하세요. 그렇지 않으면 run_cluster.sh에 -e HF_TOKEN=<TOKEN>을 붙여 Hugging Face 토큰을 제공하세요.
분산 배포 문제 해결
분산 디버깅에 대한 자세한 내용은 Troubleshooting distributed deployments를 참고하세요.
더 알아보기 (Learn more)
- 데이터 병렬 배포 — MoE 모델 대규모 배포
- 전문가 병렬 배포 — EP 배포
- 분산 배포 문제 해결 — 분산 디버깅