-
Ollama에서 vLLM으로 백엔드를 바꿨더니 throughput이 148% 올랐다 — 같은 모델, 다른 엔진IT 2026. 5. 6. 21:30
들어가며 — 같은 가중치, 같은 GPU, 다른 결과
같은 Qwen3.6 모델을 같은 DGX Spark에서 돌렸다. 한쪽은 Ollama Q4_K_M GGUF, 다른 쪽은 vLLM FP8. 측정 결과:
측정 Ollama Q4 vLLM FP8 변화 짧은 prompt TTFT 251 ms 101 ms −60% 긴 prompt(4K) TTFT 1186 ms 493 ms −58% 단일 디코드 60 tok/s 65 tok/s +8% 동시 4요청 throughput 27 tok/s 67 tok/s +148% "같은 모델인데 왜?" — 답을 깔끔하게 정리하기 위해 이 글을 쓴다. 차이는 두 엔진이 GPU 위에서 완전히 다른 일을 하고 있기 때문이다. 핵심은 세 가지: 가중치 형식, attention 메모리 관리, 동시 요청 처리 방식.
1. 두 엔진의 처리 흐름이 어떻게 다른가
Q4_K_M은 메모리에 4비트로 압축돼 있다. 곱셈을 하려면 매 행렬곱 직전에 FP16으로 풀어야 한다(dequantize). 그 풀어주는 단계가 무료가 아니고, 결과적으로 FP16 텐서코어를 쓴다.
vLLM이 다루는 FP8 체크포인트는 메모리에 이미 FP8 형식으로 저장돼 있고, Blackwell의 FP8 텐서코어가 곧장 받아 곱셈한다. 풀어주는 단계가 사라지고, 회로 자체가 FP16 회로의 두 배 처리량이다.
이전 세대(Hopper, Ampere)에서는 FP8 텐서코어가 부실해서 Q4 GGUF가 더 빠른 경우도 있었다. Blackwell에서 FP8이 1급 시민이 되면서 비로소 vLLM 경로의 진가가 드러난다.
2. PagedAttention — 동시 요청에서 격차가 폭발하는 이유
단일 요청(나 혼자 채팅)에서는 두 엔진의 차이가 +8% 정도다. 그런데 동시 4요청을 보내면 +148%. 왜 격차가 동시 요청에서 폭발하는가?
답은 vLLM의 PagedAttention이다. KV cache(자기회귀 디코딩 중 누적되는 attention key/value 텐서)를 운영체제의 페이징 방식으로 관리하는 기법이다.
핵심은 "낭비 페이지가 없으면 동시 슬롯이 늘어난다"이다. 단일 요청에서는 어차피 한 사람이 GPU를 다 쓰니 PagedAttention 효과가 작다. 동시 요청에서는 한 GPU에 들어가는 슬롯 수 자체가 늘어, throughput이 2~3배로 뛴다.
참고로 Qwen3.6은 PagedAttention과 궁합이 특히 좋다. 전체 40개 레이어 중 attention이 10개뿐이고, 나머지 30개는 linear-attention(Mamba 계열) 레이어다. PagedAttention 오버헤드는 attention 레이어에서만 발생하므로, attention 비율이 25%인 이 모델은 일반 트랜스포머보다 페이징 비용이 훨씬 작다 — 외부 분석 기준 약 75% 감소.
3. 측정값을 한눈에
단일 디코드는 +8%로 격차가 작다. 그러나 동시 요청에서 양상이 달라진다. Ollama는 NUM_PARALLEL=1 직렬이라 동시 4요청이든 16요청이든 시스템 total throughput은 단일과 거의 같은 ~60 tok/s에 머문다 — 늘어나는 건 사용자 한 명이 답을 받기까지의 latency뿐이다. 16명이 동시에 요청하면 16명이 줄을 서서 한 명씩 응답을 받는 셈이고, 마지막 사람은 16배 기다린다.
참고로 들어가며 표의 동시 4요청 "27 tok/s"는 측정 윈도우 안에서 첫 응답 시점 기준의 환산값에 가깝다. 직렬 처리의 시스템 total throughput은 단일과 동일하게 ~60 tok/s. 다이어그램은 그 본질을 시각화한 것.
반면 vLLM은 진짜 동시 처리라 GPU의 남는 연산 자원을 동시 요청에 분배해 시스템 throughput 자체를 끌어올린다 (4요청에서 67, 16요청에서 132). "엔진 차이"는 사용자가 한 명일 때가 아니라 여러 명이 동시에 들어올 때 압도적으로 드러난다.
4. 트레이드오프 — 빠르기에는 비용이 따른다
- 모델 크기: FP8 체크포인트가 35GB. Q4 GGUF(23GB)보다 12GB 더 크다. 디스크 여유가 부족하면 부담.
- 콜드 스타트: vLLM이 5~6분 걸린다 (Ollama는 ~30초). safetensors 42 shard 로드 + torch.compile + CUDA graph 캡처 + flashinfer autotune 등이 누적된 결과. 한 번 띄운 뒤엔 캐시 덕에 60초대로 떨어진다.
- GPU 종속성: FP8은 Blackwell 전용. 같은 가중치를 Ampere/Hopper로 옮기면 못 쓴다. Hopper에도 FP8이 있긴 하지만 처리량이 Blackwell의 절반 수준이라 이득이 작다.
- 운영 복잡도: vLLM은 Docker 컨테이너 + 옵션 수십 개. Ollama의 "한 줄 설치"와 비교하면 진입장벽이 있다.
정리
Ollama → vLLM 교체로 throughput +148%가 나온 이유는 한 가지가 아니다. 세 효과가 곱해진 결과다.
- FP8 네이티브: dequantize 비용 0 + FP8 텐서코어 처리량 2배.
- PagedAttention: KV cache 낭비 페이지 제거 → 동시 슬롯 폭증.
- 모델 궁합: Qwen3.6의 attention 25% 비율이 PagedAttention 오버헤드를 더 줄임.
한 줄로 줄이면, "Ollama는 한 사람용 데스크톱 도구, vLLM은 다중 사용자 서버 엔진"이다. 채팅 한 건만 돌리는 환경이라면 Ollama로도 충분하다. 그러나 같은 GPU 위에서 여러 작업이 돌고, 동시 요청을 견뎌야 한다면 — 그리고 GPU가 Blackwell이라면 — vLLM의 가치가 갑자기 압도적이 된다.
이 글은 생성형 AI의 도움을 받아 작성되었습니다. 원본 자료를 기반으로 AI가 초안을 생성하고, 작성자가 검토·편집하였습니다.
'IT' 카테고리의 다른 글
GPU 스케줄러를 Ollama warmup에서 vLLM 컨테이너로 옮긴 과정 — 시작·종료 시퀀스를 다시 짜다 (0) 2026.05.06 RAG 청크 맥락에서 thinking을 꺼야 하는 이유 — enable_thinking=False가 필요한 순간 (0) 2026.05.06 OpenAI-compat 표준화로 어댑터 100줄 들어내기 — passthrough가 가져온 코드 청결도 (0) 2026.05.06 vLLM reasoning_parser — <think> 블록을 정규식 말고 구조로 받는 법 (0) 2026.05.06 KV cache FP8로 동시 요청 76배 수용하기 — LLM 메모리의 숨은 주범 정리 (0) 2026.05.06 Gemma 4에서 Qwen 3.6으로 갈아탔다 — 두 모델을 모든 지표로 비교한 기록 (0) 2026.05.06 Fused 커널은 왜 3~4배 빠른가 — GPU 메모리 계층과 Marlin의 비밀 (0) 2026.05.05 Q4 양자화는 GPU 안에서 어떻게 동작하나 — Blackwell FP8 텐서코어와의 만남 (0) 2026.05.05 FP8이 왜 FP16보다 45% 빠를까 — Blackwell GPU의 '텐서코어 네이티브 처리' 이해하기 (0) 2026.05.05 TFLOPS가 뭔데? — FLOPS의 정의부터 요즘 GPU의 실제 수치까지 (0) 2026.05.05