vLLM vs LMDeploy vs Ollama, 동시성이 올라갈 때 무슨 일이 일어나는가
on this page
vLLM vs LMDeploy vs Ollama, 동시성이 올라갈 때 무슨 일이 일어나는가
Slug:
vllm-lmdeploy-ollama-concurrency-benchmarkDifficulty: 중급
Duration: 약 20분 (재현 시 벤치마크 실행 시간 별도)
GPU: RTX 5090 (32GB) · 모델: Qwen3-8B
왜 이 벤치마크를 했는가
LLM 서빙 엔진을 고를 때 가장 많이 하는 질문은 "뭐가 제일 빠른가요?"입니다. 하지만 실제로 중요한 질문은 하나 더 있습니다. "몇 명이 동시에 쓸 건데요?"
vLLM, LMDeploy, Ollama는 셋 다 OpenAI 호환 API를 제공하지만 내부 처리 방식이 다릅니다. 이번 글에서는 같은 GPU(RTX 5090), 같은 모델(Qwen3-8B), 같은 벤치마크 도구로 세 엔진을 동시성(concurrency) 8 / 32 / 64 세 구간에서 측정했습니다. "일반적으로 빠르다"가 아니라 "어느 트래픽 구간에서 뭐가 유리한가"를 데이터로 확인하는 게 목표였습니다.
벤치마크 환경 구성
하드웨어
- gcube 워크로드 컨테이너, GPU: NVIDIA GeForce RTX 5090 (32GB, CUDA 12.0)
- 모델: Qwen3-8B (vLLM/LMDeploy는
Qwen/Qwen3-8B, Ollama는qwen3:8b태그, 동일 가중치)
엔진 버전
| 엔진 | 버전 | 비고 |
|---|---|---|
| vLLM | 0.26.0 | Python venv(/opt/venv-vllm)에 격리 설치 |
| LMDeploy | 0.14.0 (TurboMind 백엔드) | 별도 venv에 설치 |
| Ollama | 0.32.5 | 시스템 전역 설치, ollama serve로 상시 기동 |
설치 커맨드 (핵심만)
# 시스템 패키지
apt-get install -y build-essential curl pciutils
# Ollama
curl -fsSL https://ollama.com/install.sh | sh
ollama serve & # 백그라운드 기동
ollama pull qwen3:8b
# vLLM (서빙 + 벤치마크 클라이언트 겸용)
python -m venv /opt/venv-vllm
/opt/venv-vllm/bin/pip install vllm==0.26.0
# LMDeploy
python -m venv /opt/venv-lmdeploy
/opt/venv-lmdeploy/bin/pip install lmdeploy==0.14.0
측정 도구를 하나로 통일한 이유
세 엔진 모두 자체 벤치마크 스크립트를 갖고 있지만, 스크립트가 다르면 측정 방식의 미묘한 차이(웜업 처리, 토큰 카운팅 방식 등) 때문에 숫자를 그대로 비교하기 어렵습니다. 그래서 vLLM에 내장된 vllm bench serve를 공통 로드 제너레이터로 사용해, 세 엔진의 OpenAI 호환 /v1/chat/completions 엔드포인트를 동일한 방식으로 두드렸습니다.
측정 방법론
모든 테스트는 다음 조건을 고정했습니다.
| 항목 | 값 |
|---|---|
| 데이터셋 | random (합성 프롬프트) |
| 입력 길이 | 128 tokens |
| 출력 길이 | 128 tokens |
| 동시성(max-concurrency) | 8 / 32 / 64 |
vllm bench serve \
--backend openai-chat \
--endpoint /v1/chat/completions \
--base-url http://127.0.0.1:{PORT} \
--model {MODEL_NAME} \
--dataset-name random \
--random-input-len 128 --random-output-len 128 \
--max-concurrency {8|32|64} \
--num-prompts {N}
💡 실무 팁: Ollama는 API에 노출하는 모델명이
qwen3:8b같은 태그 형식이라 HuggingFace 저장소 ID로 토크나이저를 로드하는 벤치마크 도구와 충돌합니다.--model qwen3:8b(API 요청용)과--tokenizer Qwen/Qwen3-8B(토크나이징용)를 분리 지정하면 해결됩니다.
결과: 처리량(req/s) 비교
| 동시성 | vLLM | LMDeploy | Ollama |
|---|---|---|---|
| 8 | 3.64 req/s | 5.10 req/s | 0.14 req/s |
| 32 | 17.47 req/s | 12.93 req/s | 0.31 req/s |
| 64 | 31.93 req/s | 23.05 req/s | 0.30 req/s |
세 가지가 눈에 띕니다.
- 동시성 8에서는 LMDeploy가 앞선다. 낮은 동시성 구간에서는 TurboMind 백엔드의 오버헤드가 더 적습니다.
- 동시성이 오르면 vLLM이 역전한다. vLLM의 연속 배칭(continuous batching)이 요청이 몰릴수록 더 큰 이득을 만들어, 32부터는 vLLM이 확실히 앞서고 64에서 격차가 더 벌어집니다.
- Ollama는 동시성을 올려도 거의 그대로다. 8→32→64로 올려도 0.14 → 0.31 → 0.30 req/s로 사실상 평평합니다. 오히려 64에서는 32보다 살짝 떨어집니다.
세 번째 포인트가 핵심입니다. Ollama는 로컬 사용 편의성에 맞춰 기본값이 OLLAMA_NUM_PARALLEL=1로, 요청을 사실상 한 번에 하나씩 순차 처리합니다. 벤치마크 도구가 동시성 64로 요청을 밀어 넣어도, 서버가 실제로 병렬 처리하는 양은 거의 늘지 않는 겁니다.
결과: 첫 토큰 응답 속도(TTFT) 비교
처리량만큼, 혹은 그 이상으로 체감에 영향을 주는 지표가 TTFT(Time To First Token, 요청 후 첫 토큰이 나오기까지 걸리는 시간)입니다. 동시성 8 기준으로 세 엔진을 나란히 놓으면 차이가 더 극명합니다.
| 엔진 | Mean TTFT |
|---|---|
| LMDeploy | 104 ms |
| vLLM | 782 ms |
| Ollama | 30,055 ms (약 30초) |
Ollama의 평균 TTFT는 약 30초, P99는 75초까지 올라갑니다. 8명이 동시에 요청을 보내면 뒤쪽 사용자는 응답을 받기까지 1분 가까이 기다릴 수 있다는 뜻입니다. 이건 처리량 수치보다 사용자 체감에 훨씬 직접적으로 와닿는 차이입니다.
언제 무엇을 쓸까
세 엔진의 성격이 다른 만큼, 결론도 "무엇이 최고냐"가 아니라 "어떤 상황에 맞느냐"입니다.
- Ollama — 로컬 개발, 개인 실험, 동시 사용자가 1~2명인 저트래픽 환경. 설치와 모델 전환이 가장 간편하다는 장점이 이 구간에서는 그대로 강점이 됩니다.
- LMDeploy — 동시 사용자가 적고(수십 명 이하) 응답 지연에 민감한 서비스. 낮은 동시성에서의 TTFT 우위가 그대로 체감 품질로 이어집니다.
- vLLM — 동시 사용자가 많은 프로덕션 서빙. 연속 배칭 덕분에 동시성이 오를수록 처리량 우위가 커집니다.
gcube에서는 컨테이너 단위로 GPU를 즉시 띄우고 내릴 수 있어서, 이런 비교를 워크로드 배포 후 몇 분 안에 직접 재현해볼 수 있습니다. 자신의 서비스가 어느 동시성 구간에 있는지 먼저 가늠해보고, 그 구간에 맞는 엔진을 고르는 걸 추천합니다.
이 글의 모든 수치는 gcube RTX 5090 컨테이너에서 직접 측정한 결과입니다.