[vLLM] RunPod L40S에서 콜드 스타트 최적화해보기

RunPod L40S에서 Qwen3-8B의 vLLM 캐시 최적화를 적용해보고 새 컨테이너 기동 시간을 166초에서 120초로 줄인 결과를 정리했습니다.

vLLM으로 모델을 서빙해보면 서버가 준비되기까지 생각보다 오래 걸립니다. 온프레미스 기반으로 플랫폼 과정을 확인하면서 L40S 환경으로 몇 가지 vLLM 설정을 적용해봤습니다.

Qwen3-8B를 배포한 뒤 같은 Pod에서 vLLM을 다시 실행하자 기동 시간이 크게 줄었습니다. 캐시를 명시적으로 저장하면 새 컨테이너에서도 효과가 있는지 이어서 살펴봤습니다.

테스트 환경

기동 시간은 vllm serve 실행부터 /health 요청이 성공할 때까지 측정했습니다. 모델은 미리 /workspace에 받아둔 상태로 비교했습니다.

적용한 설정

RunPod의 vLLM 콜드 스타트 최적화 글을 참고해 네 가지 설정을 골라 적용했습니다.

  1. vLLM 컴파일 캐시: /workspace에 저장
  2. Safetensors 가중치: prefetch 방식으로 로드
  3. CUDA 그래프 캡처 크기: 동시 요청 수 16 이하
  4. Hugging Face: 이미 저장된 모델만 쓰도록 오프라인 모드 적용
export PATH=/workspace/.venvs/vllm/bin:$PATH
export HF_HOME=/workspace/.cache/huggingface
export HF_HUB_OFFLINE=1
export VLLM_CACHE_ROOT=/workspace/vllm-opt/vllm-cache

vllm serve 'Qwen/Qwen3-8B' \
  --dtype bfloat16 \
  --max-model-len 8192 \
  --max-num-seqs 16 \
  --safetensors-load-strategy prefetch \
  --compilation-config '{"cudagraph_capture_sizes":[1,2,4,8,16]}' \
  --port 8000

측정 결과

조건 기동 시간
새 컨테이너, 기존 설정 166초
실행 중인 Pod에서 vLLM 프로세스만 재기동 32초
Pod 중단 후 새 컨테이너에서 최적화 기동 120초

새 컨테이너 기준으로 166초에서 120초로 약 28% 줄었습니다. 실행 중인 Pod에서 vLLM 프로세스만 다시 띄웠을 때는 모델과 로컬 캐시를 모두 재사용해 32초가 걸렸습니다.

32초는 Pod를 중단했다가 다시 시작한 결과가 아닙니다. Pod를 중단하면 /workspace의 모델과 vLLM 컴파일 캐시는 유지되지만, 컨테이너 로컬의 GPU 커널 준비 상태는 사라졌습니다.

컴파일 캐시 효과

적용한 설정 가운데 vLLM 컴파일 캐시의 효과가 가장 컸습니다.

Safetensors prefetch와 CUDA 그래프 범위 축소는 이번 환경에서 큰 차이를 만들지 못했습니다. Hugging Face 오프라인 모드도 정상 적용됐지만 절감 시간을 따로 구분하기는 어려웠습니다.

Pod를 다시 시작했을 때 남은 시간의 대부분은 GPU 커널 JIT 준비에 사용됐습니다. vLLM 컴파일 캐시는 0.46초 만에 불러왔지만, 이후 커널 준비에 약 79초가 걸렸습니다.

다음 실험

다음에는 새 컨테이너마다 다시 발생하는 GPU 커널 JIT 준비 시간을 줄일 수 있는지 측정해보고자 합니다.
동시에 왜 최적화되는지 원리 자체를 정리하여 추가 포스팅 예정입니다.

참고 자료