Runpod의 vLLM 콜드스타트 최적화, Qwen3.8-27B에 적용해 봤습니다

Qwen3.8-27B에서 Network Volume에 저장한 vLLM 컴파일·커널 캐시가 새 Serverless 워커에서도 재사용되는지 확인한 실험입니다.

은긔
은긔

핵심 요약

1

torch.compile은 213.28초에서 8.51초로 줄었고 DeepGEMM 워밍업도 약 178초에서 약 2.7초로 짧아졌습니다.

2

콜드스타트 전체가 사라진 것은 아닙니다.

3

모델 파일과 함께 컴파일 캐시 경로와 graph capture 범위도 점검하는 편이 낫습니다.

Qwen3.8-27B를 Runpod Serverless에 올렸을 때, 새 워커마다 반복되는 vLLM 초기화 시간을 줄일 수 있을까요? 이 질문은 RTX 5090 한 장에서 Qwen3.8-27B를 구동한 실험 뒤에 생겼습니다.
그러던 중 Runpod가 공식 블로그에 공개한 vLLM 콜드스타트를 줄이는 방법을 봤습니다. 모델 가중치뿐 아니라 torch.compile과 GPU 커널 관련 캐시를 Network Volume에 남기고, CUDA graph capture 범위를 실제 동시성에 맞추는 방식입니다.
Runpod 글의 결과를 그대로 재현하려는 실험은 아니었습니다. 모델과 GPU 조건을 제 환경에 맞춰 Qwen/Qwen3.8-27B-FP8과 H100 NVL 한 장으로 바꿨고, FlashBoot도 끈 상태에서 캐시가 새 워커에서도 재사용되는지 확인했습니다.

RTX 5090에서 발견한 긴 vLLM 초기화

처음에는 Runpod Pod의 RTX 5090 한 장에서 PassingByPixels/Qwen3.8-27B-NVFP4를 실행했습니다. vllm/vllm-openai:v0.27.1 이미지로 모델을 정상 구동했고, 짧은 채팅 요청도 약 1초 만에 응답했습니다.
요청은 빨랐지만 준비 시간이 길었습니다. Pod 생성부터 API 준비까지 약 416.9초가 걸렸는데요. 모델 다운로드는 39.658초였지만 vLLM 엔진 초기화는 252.67초였고, 이 가운데 torch.compile이 152.39초를 차지했습니다.
같은 모델을 RTX 5090 Serverless로 옮겨 Network Volume 캐시도 시험했습니다. 첫 워커는 모델과 컴파일 캐시를 만드는 데 성공했지만, 캐시 재사용을 확인하려 보낸 두 번째 요청은 약 14분 동안 GPU를 배정받지 못해 취소했습니다. Network Volume은 특정 데이터센터에 연결되기 때문에, 해당 리전에 RTX 5090 여유 용량이 없으면 실험 자체가 시작되지 않습니다.
RTX 5090에서는 모델 구동과 캐시 생성까지 확인했지만, 새 Serverless 워커의 캐시 재사용 결과는 얻지 못했습니다. 그래서 모델 계열은 Qwen3.8-27B로 유지하고, Serverless 배치가 가능한 H100과 FP8 체크포인트로 실험을 이어갔습니다. NVFP4와 FP8의 성능을 비교하려는 변경은 아니었습니다.

Runpod가 제안한 vLLM 캐시 구성

Runpod 글은 Serverless 콜드스타트를 인프라 준비와 vLLM 초기화로 나눕니다. GPU 할당, 스토리지 연결, 이미지 준비가 끝난 뒤에도 모델 적재, torch.compile, CUDA graph capture, GPU 커널 워밍업이 이어진다는 설명입니다.
이 가운데 vLLM이 생성하는 산출물은 디스크에 남길 수 있습니다. 컨테이너 내부 경로에 두면 워커가 종료될 때 함께 사라집니다. Network Volume에 저장하면 다음 워커가 다시 읽을 수 있는데요. 공식 글은 이를 위해 네 가지를 설정합니다.
  • VLLM_CACHE_ROOT가 Network Volume 아래 경로를 가리키도록 설정해 vLLM 컴파일 산출물을 보존합니다.
  • SAFETENSORS_LOAD_STRATEGY=prefetch로 safetensors 파일을 page cache에 먼저 읽습니다.
  • MAX_NUM_SEQS와 CUDA graph capture 크기를 실제 동시성에 맞춥니다.
  • 모델 파일이 모두 준비된 환경에서는 HF_HUB_OFFLINE=1로 Hub 확인을 생략할 수 있습니다.
환경 변수만 복사해서는 효과를 확인하기 어렵습니다. VLLM_CACHE_ROOT가 실제 Network Volume을 가리키는지, 두 번째 부팅 로그에 AOT cache를 직접 불러왔다는 기록이 남는지 확인해야 합니다.

Qwen3.8-27B FP8과 H100 NVL 실험 환경

캐시 재사용 실험은 다음 조건에서 진행했습니다.
항목설정
모델`Qwen/Qwen3.8-27B-FP8`
모델 revision`017b9c7af6b5689d5dd426a76e0bc077eb5ca20a`
체크포인트28.75GiB, safetensors 66개
GPUNVIDIA H100 NVL 94GB 1장
리전`US-KS-2`
worker 이미지Runpod 공식 `worker-vllm:v2.25.2`
vLLM0.27.1
CUDA13.0
Network VolumeStandard 80GB, `/runpod-volume`
FlashBoot꺼짐
최대 모델 길이32,768 tokens
`MAX_NUM_SEQS`4
FlashBoot를 끈 이유는 snapshot restore와 Network Volume에 남긴 캐시의 효과를 섞지 않기 위해서입니다. 워커가 0대인 것을 확인한 뒤 새 워커를 시작했고, 빈 캐시 부팅과 캐시가 생성된 뒤의 부팅 로그를 나눠 기록했습니다.
캐시 경로는 한곳에 몰아두지 않고 각 라이브러리가 실제로 읽는 경로를 Network Volume 아래로 지정했습니다.
HF_HOME=/runpod-volume/huggingface
VLLM_CACHE_ROOT=/runpod-volume/vllm_cache
TRITON_CACHE_DIR=/runpod-volume/triton
TORCHINDUCTOR_CACHE_DIR=/runpod-volume/torchinductor
CUDA_CACHE_PATH=/runpod-volume/cuda_cache
FLASHINFER_WORKSPACE_BASE=/runpod-volume/flashinfer

SAFETENSORS_LOAD_STRATEGY=prefetch
SAFETENSORS_PREFETCH_NUM_THREADS=8
COMPILATION_CONFIG='{"cudagraph_capture_sizes":[1,2,4]}'
MAX_NUM_SEQS=4
VLLM_USE_DEEP_GEMM=true
이번 테스트에서는 MAX_NUM_SEQS=4로 상한을 두고 graph capture 크기를 [1,2,4]로 맞췄습니다. 실제 동시성 성능은 측정하지 않았습니다. 이 값을 낮추면 부팅 때 준비할 작업은 줄지만, vLLM이 한 번에 처리할 수 있는 sequence 수에도 영향을 줍니다.

빈 캐시에서 반복된 컴파일과 워밍업

첫 부팅은 Network Volume이 비어 있는 상태에서 시작했습니다. 모델 가중치를 받고 AOT, Triton, CUDA, FlashInfer 관련 산출물을 생성하는 캐시 준비 회차였습니다.
vLLM wrapper 시작부터 health check 통과까지 792.362초가 걸렸습니다. 내부 로그에서 vLLM 엔진 초기화는 476.10초였고, torch.compile은 213.28초였습니다. DeepGEMM은 1,496개 항목을 워밍업하는 데 약 178초를 사용했습니다.
이 회차가 끝나자 Network Volume에는 모델 파일과 함께 AOT artifact 21개, submodule 65개가 남았습니다. 빈 캐시 첫 요청은 플랫폼의 후속 워커에서 처리됐기 때문에 작업 API의 delayTime을 단일 부팅 기준값으로 사용하지 않았습니다. 캐시 효과는 컨테이너 내부 단계별 로그로 비교했습니다.

기존 컴파일 캐시를 다시 읽은 새 워커

캐시 생성 후 워커를 0대로 내리고, 워커 목록이 비어 있는 것을 확인했습니다. 그다음 별도 worker ID의 워커를 시작해 동일한 모델 revision과 설정을 사용했습니다.
초기화 구간빈 캐시캐시 재사용변화
wrapper 시작 → vLLM healthy792.362초272.145초65.65% 감소
모델 로딩112.619초93.673초16.82% 감소
`torch.compile`213.28초8.51초96.01% 감소
초기 profiling·warmup29.73초16.08초45.91% 감소
DeepGEMM 워밍업약 178초약 2.7초약 98.48% 감소
vLLM 엔진 초기화476.10초52.59초88.95% 감소
두 번째 워커 로그에는 Directly load AOT compilation이 기록됐습니다. torch.compile이 213.28초에서 8.51초로 줄고, DeepGEMM 워밍업도 약 178초에서 약 2.7초로 줄었으므로 캐시는 볼륨에 남은 데 그치지 않고 새 워커에서 실제로 사용됐다고 볼 수 있습니다.
캐시 재사용 회차의 작업 delayTime은 281.947초, executionTime은 7.058초였고 응답은 OK였습니다. 다만 독립된 캐시 재사용 부팅은 한 번만 측정했습니다. 이 수치를 H100 환경의 일반적인 콜드스타트 시간으로 일반화하면 안 됩니다. 캐시가 초기화 단계에 미친 영향을 확인한 사례로 보는 편이 정확합니다.

적용하면서 확인한 세 가지 조건

첫째, 모델 이름만 같다고 캐시를 공유할 수 있는 것은 아닙니다. 컴파일 캐시는 모델 revision, GPU 아키텍처, vLLM 버전, serving flag 조합에 영향을 받습니다. 설정을 바꾸면 캐시 생성 부팅부터 다시 진행하는 편이 안전합니다.
둘째, 첫 부팅과 캐시 재사용 부팅을 분리해야 합니다. 첫 실행은 최적화 결과가 아니라 다음 워커를 위한 준비 단계입니다. 워커를 완전히 내린 뒤 다른 worker ID의 워커에서 torch.compile과 커널 워밍업 시간이 줄었는지 확인해야 합니다.
셋째, Serverless 작업의 delayTime만 보고 특정 설정의 효과를 판단하기는 어렵습니다. GPU 할당 대기와 이미지 준비 같은 플랫폼 구간도 포함되기 때문입니다. endpoint health에 표시되는 throttled 상태와 vLLM 내부 로그를 함께 남겨야 어떤 단계가 실제로 달라졌는지 설명할 수 있습니다.

새 워커로 이어진 Qwen3.8-27B 컴파일 캐시

이번 실험의 출발점은 RTX 5090에서 Qwen3.8-27B를 구동하는 것이었습니다. Pod에서는 모델이 정상 작동했지만 Serverless의 반복 실험은 GPU 배치 조건 때문에 이어가지 못했습니다. 그래서 H100 NVL과 FP8으로 조건을 바꿔, 같은 Qwen3.8-27B 계열에서 Network Volume에 남긴 캐시를 새 워커가 다시 쓰는지 확인했습니다.
새 워커 로그에서 캐시 재사용을 확인했습니다. Network Volume에 모델 가중치와 vLLM의 컴파일·커널 산출물을 함께 보존하자 AOT cache를 직접 불러왔습니다. torch.compile은 213.28초에서 8.51초로 줄었고 DeepGEMM 워밍업도 약 178초에서 약 2.7초로 짧아졌습니다.
콜드스타트 전체가 사라진 것은 아닙니다. 새 워커에서도 컴파일과 커널 워밍업은 실행됐지만, 기존 캐시를 읽으면서 소요 시간이 크게 줄었다는 점은 확인했습니다. Qwen3.8-27B를 Runpod Serverless에 올린다면 모델 파일만 저장하지 말고, 실제 로그를 보면서 컴파일 캐시 경로와 graph capture 범위까지 함께 점검하는 편이 낫습니다.

자주 묻는 질문

Network Volume만 연결하면 캐시가 자동으로 적용되나요?

아닙니다. Network Volume 연결만으로 캐시 경로가 자동 전환되지는 않습니다. 최소한 VLLM_CACHE_ROOT를 Network Volume 아래 경로로 지정해야 하며, 이번 실험에서는 TorchInductor·Triton·CUDA·FlashInfer 경로도 각각 Network Volume 아래로 지정했습니다. 두 번째 부팅 로그에서 AOT cache가 직접 로드됐는지와 컴파일 시간이 줄었는지도 확인해야 합니다.

RTX 5090 NVFP4와 H100 FP8 성능을 비교한 실험인가요?

아닙니다. RTX 5090에서는 Qwen3.8-27B NVFP4의 구동과 캐시 생성을 확인했고, H100에서는 FP8 체크포인트로 Serverless 캐시 재사용을 확인했습니다. GPU와 양자화 방식이 달라 추론 성능 비교 자료로 사용할 수 없습니다.

첫 부팅도 바로 빨라지나요?

빈 캐시 첫 부팅은 모델 파일과 컴파일 산출물을 준비해야 하므로 오래 걸릴 수 있습니다. 이 방식의 효과는 캐시가 만들어진 뒤 워커가 종료되고, 새 워커가 같은 캐시를 다시 읽을 때 확인해야 합니다.

🔗 References

Runpod에서 LLM 서빙 환경을 구성하고 있다면 현재 워크로드를 함께 살펴봅니다.

Runpod 도입·GPU 운영 상담하기