본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 05. 27. 01:29

하나의 RTX 5080에서 SLM 군단 서빙하기: 단일 소비자용 GPU에서의 멀티 모델 운영

요약

단일 RTX 5080(16GB) 환경에서 여러 개의 소형 언어 모델(SLM)을 동시에 서빙하는 효율적인 방법을 제시합니다. Python이나 Rust 없이 쉘 스크립트와 기존 라우터를 활용하여 모델 배치 및 라우팅을 구현하는 기술적 가이드를 제공합니다.

핵심 포인트

  • 단일 16GB GPU에서 여러 SLM을 동시에 서빙 가능
  • 쉘 스크립트를 활용한 모델 배치 및 라우팅 구현
  • 0.5B 모델 기준 약 12,800 tok/s의 높은 처리량 달성
  • Prefix caching을 통한 프리필 워크로드 성능 향상

아래의 모든 수치는 단일 RTX 5080 (16 GB)에서 측정되었으며, 해당 리포지토리(repo)를 통해 재현 가능합니다. 각 결과는 측정된 정확한 설정을 명시합니다. 저는 서로 다른 설정 간의 수치를 비교하지 않으며, 우리가 깔끔하게 측정하지 못한 부분은 별도로 표시합니다.

요약 (TL;DR)

기존의 라우터(Shepherd Model Gateway)를 재사용하고 약 150줄의 쉘(shell) 스크립트를 사용하면, 단일 OpenAI 호환 엔드포인트 뒤에서 하나의 16 GB RTX 5080을 통해 여러 개의 소형 채팅 LLM을 서빙할 수 있습니다. 커스텀 라우터도, 추론 엔진(inference engine)도 필요 없으며, 서빙 스택에 Python이나 Rust가 전혀 포함되지 않습니다. 세 가지 통제된 실험 결과는 다음과 같습니다:

  • 0.5B 모델은 약 12,800 tok/s를 서빙합니다 (CUDA graphs 활성화, 동시성 48).
  • 모델에 GPU 메모리 전체가 아닌 1/3만 할당해도 처리량(throughput)에는 차이가 없었습니다 (12,766 vs 12,838 tok/s).
  • Prefix caching은 프리필(prefill) 비중이 높은 워크로드에서 처리량을 두 배로 높였으며, 특정 환경에서는 캐시 인식 라우팅(cache-aware routing)이 단순 라운드 로빈(round-robin) 방식보다 20% 낮은 성능을 보였습니다.

16 GB 카드에서 이것이 가능한 이유

소형 모델은 매우 작습니다. 양자화(quantized)된 약 1B 모델은 대략 0.5~2 GB 정도입니다. 따라서 여러 모델이 16 GB 안에 동시에 들어갈 수 있으며, 하나의 엔드포인트 뒤에서 이들을 동시에 서빙할 수 있습니다. 유일한 실제 과제는 하나의 카드에 이들을 어떻게 깔끔하게 배치(place)하고 라우팅(route)하느냐 하는 것입니다.

핵심 아이디어: 라우터는 라우팅을 할 뿐, 배치(place)를 하지 않는다

이미 성숙한 라우터들이 존재합니다 (NVIDIA Dynamo, vLLM의 라우터, Shepherd Model Gateway). 이들은 OpenAI 엔드포인트를 제공하고 워커(worker) 간의 캐시/로드 인식 라우팅을 수행하지만, 이들은 이미 존재하는 워커로 라우팅할 뿐입니다. 즉, 워커를 시작하거나 GPU 메모리를 분할하지 않습니다. 따라서 "하나의 GPU에서 여러 모델을 실행"하기 위해서는 오직 배치(placement) 단계만 필요합니다. 즉, 각 모델이 메모리 제한 내에서 공존할 수 있도록 N개의 모델 서버를 시작하고 이들을 등록하는 것입니다. 이는 쉘 스크립트로 구현 가능합니다:

클라이언트 → SMG (재사용된 바이너리) → 하나의 GPU 상에 있는 N개의 vLLM 워커
            ↑ 약 15줄의 bash 런처가 워커를 배치하고 등록함

(어디에도 사용된 유일한 Python은 아래 차트를 생성하는 오프라인 스크립트뿐입니다. 서빙 경로는 shell과 재사용된 바이너리로 구성됩니다.)

저는 세 개의 채팅 모델 (chat models) — Qwen2.5-0.5B-Instruct, Qwen2.5-1.5B-Instruct, SmolLM2-360M-Instruct — 을 하나의 게이트웨이 뒤에 공존(co-resident)하도록 실행했으며, 각 모델은 모델 이름으로 접근할 수 있습니다.

5080에서 실제로 겪은 세 가지 주의사항 (gotchas)

  1. flashinfer의 JIT는 PATH에 ninjanvcc가 필요합니다. 순수한 가상 환경 (venv) 경로에서 vLLM 워커 (worker)를 실행하면 커널 컴파일 과정에서 FileNotFoundError: 'ninja'와 함께 종료됩니다. 가상 환경을 활성화하고, 먼저 CUDA 툴킷 (toolkit)을 PATH에 추가하십시오.
  2. 동일한 위치에 있는 워커들을 동시에 시작하지 마세요. vLLM은 시작 시 --gpu-memory-utilization전체 메모리를 기준으로 측정합니다. 두 개를 동시에 실행하면 경합(race)이 발생하여, 하나는 "캐시 블록을 위한 사용 가능한 메모리가 없음 (No available memory for the cache blocks)" 오류를 겪게 됩니다. 워커들을 순차적으로 (sequentially) 시작하십시오 (다음 워커를 실행하기 전 각 워커의 상태 확인 (health-check)을 수행하십시오).
  3. 모델 3개 + CUDA 그래프 (CUDA graphs)는 16GB에 들어가지 않습니다. 그래프를 켠 상태에서는 세 번째 워커에서 OOM (Out of Memory)이 발생했습니다. 3개의 모델을 공존시키려면 그래프를 끄거나 (--enforce-eager), 모델 수를 줄여야 합니다.

발견 1: 메모리 분할은 중요하지 않았다 (제어된 환경)

다른 모든 조건(동시성 48, CUDA 그래프 활성화)을 동일하게 유지한 채, 하나의 0.5B 모델에 GPU 전체를 할당했을 때와 단 30%만 할당했을 때를 비교했습니다:

Memory split has no effect

12,766 vs 12,838 tok/s — 동일합니다. 이 동시성 수준에서는 KV 캐시 (KV cache)가 병목 (bottleneck)이 아니었으므로, 이웃 모델들을 위한 공간을 만들기 위해 캐시를 줄여도 성능 손실이 없었습니다. 이는 모델 공존 (co-location)에 있어 좋은 소식입니다. 작은 모델의 처리량 (throughput)을 해치지 않으면서 그래픽 카드의 대부분을 다른 모델에 할당할 수 있습니다.

발견 2: 프리픽스 캐싱 (prefix caching)이 처리량을 두 배로 높였다 (프리필 (prefill)이 지배적일 때)

vLLM의 자동 프리픽스 캐싱 (automatic prefix caching)은 기본적으로 활성화되어 있지만, 무작위 프롬프트 (random-prompt) 벤치마크에서는 (공유된 프리픽스가 없으므로) 이 기능이 숨겨집니다. 동일한 모델, 동일한 설정 (그래프 비활성화)에서 워크로드의 공유 프리픽스 비율만 변경하여 테스트했습니다:

Prefix cache A/B

2048-토큰의 공유 프리픽스 (shared prefix)와 32-토큰의 출력 (prefill-heavy) 조건에서, 처리량 (throughput)은 **두 배(1,153 → 2,316 tok/s)**로 증가했으며 p99 TTFT (Time To First Token)는 64% 감소했습니다. 짧은 프리픽스와 긴 출력 조건에서는 약 15%의 완만한 개선을 보였습니다. 따라서 공유 시스템 프롬프트 (system prompt) 또는 RAG 컨텍스트 (context)를 사용하는 것은 매우 가치가 크며, 무작위 프롬프트 (random prompts)는 아무런 이득을 얻지 못합니다.

발견 3: "스마트"한 라우팅이 항상 스마트한 것은 아니다

캐시 인식 라우팅 (Cache-aware routing)은 하나의 모델에 대해 *여러 개의 복제본 (multiple replicas)*이 있을 때만 의미가 있습니다 (동일한 프리픽스를 가진 요청을 동일한 복제본에 고정하는 방식). 설정을 일정하게 유지하고, 제한된 복제본당 캐시 용량에 대해 프리픽스 워킹 셋 (prefix working set)을 변화시키며 테스트했습니다:

Routing regimes

Prefix working setcache_awareround_robinresult
small (fits everywhere)62.460.6 req/stie
...

워킹 셋이 복제본의 캐시 용량을 초과할 때, 캐시 인식 고정 (cache-aware pinning)은 부하 분산 (load balance)을 희생하며 20%의 성능 손실을 입습니다. 이러한 소형 모델들의 경우, 단순한 라운드 로빈 (round-robin) 또는 power-of-two 방식이 더 나은 기본 설정이었습니다.

명확하게 측정하지 못한 부분

한계점에 대해 솔직하게 말씀드리자면 다음과 같습니다:

  • 경합 (contention) 상황에서의 멀티 모델 총합 처리량. 저희의 통제된 3개 모델 실행 중 워커 (worker)에서 OOM (Out Of Memory)이 발생했습니다 (그래프 활성화, 16 GB 환경). 따라서 명확한 경합 수치는 확보하지 못했으며, 추측하기보다는 생략하였습니다.
  • 단일 GPU. 여기서의 모든 결과는 RTX 5080 기준입니다. 다른 하드웨어에 대해서는 어떠한 주장도 하지 않습니다.
  • 프리픽스 캐시 (prefix-cache) 및 라우팅 실행 시 CUDA 그래프 (CUDA graphs)를 비활성화 (off) 했으므로, 해당 절대적 tok/s 수치는 '발견 1'의 결과와 직접 비교할 수 없습니다. 오직 상대적인 효과 (2배, -20%)만이 결과값입니다.

재현하기

scripts/launch_workers.sh   # GPU 탐색, 크기 설정 + N개의 제한된 워커 시작 (순차적)
scripts/run_gateway.sh      # 전면에 smg 실행
bench/sweep.sh              # QPS + goodput 스윕 (sweep)
...

맺음말

이 실험의 핵심은 처리량(throughput) 기록을 세우는 것이 아닙니다. **재사용(reuse)과 쉘 스크립트(shell script)**만으로도 소비자용 GPU에서 작동하는 멀티 모델 서빙 스택을 구축할 수 있다는 점, 그리고 통제된 측정이 직관을 뛰어넘는다는 점입니다. 메모리 분할(memory split)은 중요하지 않았고, 프리픽스 캐싱(prefix caching)은 공유된 프리픽스(shared prefixes)가 있을 때만 2배의 이득을 주었으며, 캐시 인식 라우팅(cache-aware routing)은 잘못된 영역(regime)에서는 오히려 성능이 저하되었습니다. 여러분의 워크로드(workload)를 직접 측정해 보십시오.

리포지토리(Repo), 스크립트 및 원본 벤치마크 JSON: https://github.com/dk67604/monogpu.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0