Ana içeriğe atla

Veri Bilimi Okulu

vLLM: Bir GPU'dan Yüzlerce Kullanıcıyı Beslemek
vLLM: Bir GPU’dan Yüzlerce Kullanıcıyı Beslemek
vllm_rehberi_kapak_960x640

Ollama ile modelinizi ayağa kaldırdınız, harika çalışıyor. Sonra ekipten on kişi aynı anda bağlandı ve her şey tıkandı. Bu yazıda tam olarak bunun neden olduğunu, vLLM’in hangi numaralarla aynı ekran kartından 20 kat fazla iş çıkardığını ve alternatiflerinin ne zaman daha doğru tercih olduğunu birlikte öğreneceğiz.

Bu yazıya “LLM nedir biliyorum, hatta lokalde model çalıştırdım ama vLLM bana hep ‘ciddi insanların aracı’ gibi göründü” diyerek geldiyseniz doğru yerdesiniz. Sonuna vardığınızda şunları yapabileceksiniz: bir aracın neden 5 kullanıcıda tıkanıp ötekinin 200 kullanıcıyı taşıdığını mimari olarak açıklayabileceksiniz, PagedAttention ve continuous batching’in ne demek olduğunu bir arkadaşınıza anlatabileceksiniz, vLLM’i tek komutla ayağa kaldırıp hangi flag’in ne işe yaradığını bilerek ayar yapabileceksiniz ve — belki en önemlisi — vLLM’in gerekmediği durumları tanıyabileceksiniz.

1. Ollama’nın Yetersiz Olduğu Nokta

Olaya rakamlarla girelim, çünkü bunlar yazının geri kalanını anlamlı kılıyor. 2026’da yayımlanan hakemli bir çalışma; aynı H100 GPU üzerinde aynı modeli (Qwen3-4B) aynı parametrelerle Ollama ve vLLM ile servis edip dört farklı senaryoda ölçtü[5]. Sonuçlar şöyle:

Ölçüm (100 eşzamanlı kullanıcı)OllamavLLM
Throughput (istek/saniye)0.4515.20 (~22 kat)
Ortalama gecikme (latency)100+ saniye10 saniyenin altı
İlk token’a kadar geçen süre (TTFT)54–122 saniye3 saniyenin altı
Başarısız istek oranı%39.29%0
Kırılma noktası~10 kullanıcı200 kullanıcı ve ötesi

Çalışmanın toplamında vLLM 99.802 isteğin tamamını hatasız tamamlarken, Ollama senaryolara göre %13–30 arası hata verdi[5]. Kritik nokta şu: başarıyla tamamlanan isteklerde iki aracın cevap kalitesi birbirine denk çıktı. Yani mesele modelin zekâsı değil; mesele tamamen işin nasıl sıraya dizildiği.

Yanlış anlamayalım! Ollama kötü bir araç değil — bambaşka bir iş için tasarlanmış bir araç. Ollama varsayılan olarak model başına tek paralel istek işler (OLLAMA_NUM_PARALLEL ile elle artırılır) ve gerisini kuyruğa alır; kuyruk 512’yi geçince istekleri reddeder[16]. Bu, tek kişilik masaüstü kullanımı için son derece makul bir tasarım tercihidir. Ama “makul tasarım tercihi” ile “yüz kişiyi taşıyan sunucu” arasında bir mimari uçurum var. O uçurumu kapatan şeyin adı vLLM.

2. vLLM Nereden Çıktı?

vLLM, UC Berkeley’deki Sky Computing Lab’da doğdu ve 2023’te SOSP konferansında sunulan “Efficient Memory Management for Large Language Model Serving with PagedAttention” makalesiyle akademik olarak kayda geçti[21][22]. İlk duyuru yazısındaki iddia dönemin şartlarında çarpıcıydı: aynı donanımda Hugging Face Transformers’a göre 24 kata kadar, o zamanın en iyi servis aracı olan Hugging Face TGI’ya göre 3.5 kata kadar daha yüksek throughput[1].

Aradan geçen sürede vLLM bir araştırma projesinden ekosistemin fiili omurgasına dönüştü. Bugün NVIDIA’nın yanında AMD, Intel CPU/GPU, TPU ve Gaudi üzerinde çalışıyor; AWQ, GPTQ, GGUF, FP8, INT4/INT8 gibi bir düzineden fazla quantization formatını destekliyor; LoRA adaptörleri, structured output, tool calling ve çok modlu (multimodal) girdi işleyebiliyor[3]. Geliştirme temposu da buna göre: Ağustos 2026’da çıkan v0.27.0 sürümü tek başına 242 committer’dan gelen 561 commit içeriyordu[18]. Bu dönüşümün en net kanıtı da rakip cepheden geldi. Hugging Face, bir zamanların en güçlü servis aracı olan kendi TGI’ını bakım moduna aldı; deponun ilk satırındaki uyarıda artık yalnızca küçük hata düzeltmelerini kabul ettiklerini, ileriye dönük olarak “vLLM ve SGLang’i, lokal tarafta da llama.cpp ve MLX’i kullanmanızı önerdiklerini ve bu projelere katkı verdiklerini” yazıyorlar[9].

Burada bir şirketin pazar kaybettiği filan yok — hepsi açık kaynak; TGI da Apache 2.0, vLLM de. Açık kaynak dünyasında normal olan şey tam da bu: aynı problemi çözen beş ayrı proje bir süre yarışır, biri kritik kütleye ulaşınca geri kalanların ekipleri kendi kodlarını sürdürmek yerine emeklerini o ortak omurgaya taşır. Hugging Face’in yaptığı bir teslim olma değil, kaynak tahsisi kararı: TGI’ı ayakta tutmaya harcayacağı mühendis saatini vLLM’e katkı olarak vermek. Bizim için önemi şu — vLLM’i öneren taraf, onun en yakın rakibini yazmış olan ekip.

Bir cümlelik tanım: vLLM, bir GPU’daki belleği ve zamanı aynı anda gelen çok sayıda istek arasında olabildiğince az israfla paylaştıran bir inference (çıkarım) motorudur. Tek kullanıcının cevabını hızlandırmaz; aynı donanımdan kaç kullanıcının beslenebileceğini kökten değiştirir.

3. Perde Arkası I — PagedAttention: İşletim Sisteminden Çalınan Fikir

Şimdi asıl meseleye girelim. Bir LLM cevap üretirken, sohbetin o ana kadarki her token’ı için hesapladığı ara değerleri (key ve value tensörleri) bellekte tutar; bu depoya KV cache denir. Amaç her yeni token’da tüm geçmişi baştan hesaplamamaktır. Sorun şu ki bu depo devasadır: Llama-3-70B’de FP16 hassasiyetle her bir token, tüm katmanlar boyunca yaklaşık 160 KB yer kaplar[4].

Klasik yaklaşımda sistem, her istek için “bu istek en fazla 2048 token üretebilir” varsayıp bitişik (contiguous) bir bellek bloğunu baştan rezerve ederdi — 70B model için istek başına ~327 MB[4]. Peki kullanıcı 40 token’lık kısa bir cevap alıp gittiyse? Rezerve edilen alanın neredeyse tamamı boşa gitti. vLLM ekibinin ölçümüne göre bu yaklaşımda belleğin %60–80’i fragmentasyon ve aşırı rezervasyon yüzünden çöpe gidiyordu[1].

PagedAttention’ın fikri şu: işletim sistemleri bu problemi 1960’larda çözdü, adı virtual memory (sanal bellek) ve paging (sayfalama). Nasıl ki bir process belleğe sanal adreslerle erişip arka planda dağınık fiziksel frame’lere yönlendiriliyorsa, vLLM de KV cache’i sabit boyutlu bloklara (nominal varsayılan 16 token; güncel sürümlerde attention backend’i daha büyük bir değer seçebiliyor) böler ve her isteğe bir block table (blok tablosu) verir. İstek büyüdükçe boş blok havuzundan (free_block_queue) blok alır; bittiğinde bırakır. Bloklar bellekte bitişik olmak zorunda değildir[2][4].

Sonuç? İsraf yalnızca her dizinin son bloğunda, ortalama yarım blok kadar olur. Toplam bellek israfı %60-80 bandından %4’ün altına iner[1]. Aynı ekran kartına aynı anda çok daha fazla canlı istek sığar; basitleştirilmiş senaryolarda eşzamanlı istek kapasitesinde ~2.5 katlık artış ölçülüyor[9].

Şekil 1 — PagedAttention, KV cache’i (Şekil 1 caption’ı) işletim sistemindeki paging gibi bloklara böler. İsraf yalnızca son blokta kalır; boşalan bloklar anında başka isteğe gider [1][2][4].

İşin güzel tarafı burada bitmiyor. Bloklar paylaşılabilir de. Aynı sistem prompt’uyla gelen yüzlerce istek varsa ya da tek bir prompt’tan paralel olarak birkaç farklı cevap üretiliyorsa, vLLM aynı blokları copy-on-write mantığıyla ortak kullanır. Orijinal ölçümlerde bu paylaşım, karmaşık sampling senaryolarında bellek kullanımını %55’e varan oranda düşürüp throughput’u 2.2 kata kadar artırıyor[1].

4. Perde Arkası II — Continuous Batching: Sırayı Bekletmeyen Kasiyer

İkinci büyük numara için önce bir GPU gerçeğini hatırlayalım: GPU’lar aynı işi çok sayıda veri üzerinde toplu yapmakta harikadır. Bir token üretmek için modelin tüm ağırlıklarını bellekten okumak gerekir; bu okuma masrafını tek bir kullanıcı için ödemek de otuz kullanıcı için ödemek de neredeyse aynıdır. Yani batch (toplu işleme) yapmak sudan ucuz.

Klasik static batching (statik batch’leme) bunu şöyle yapar: N tane isteği toplar, hepsini birlikte çalıştırır, hepsi bitene kadar yeni istek almaz. Sorun ortada: 30 istek 50 token’da bitip 2 istek 500 token’a kadar sürerse, batch’in geri kalanı boş boş dönerken GPU kullanımı %20–40 bandına düşer[4]. Süpermarkette tüm kasaların, en yavaş müşteri işini bitirene kadar kapalı beklemesi gibi.

Continuous batching (sürekli batch’leme) bu kuralı yıkar: batch’i bir “grup” olmaktan çıkarıp akışkan bir havuza çevirir. Her forward pass’ten (ileri geçiş) sonra scheduler devreye girer, biten istekleri havuzdan çıkarır ve boşalan yere bekleyen isteği anında alır. Hiçbir istek bir diğerinin bitmesini beklemez[4][2]

Şekil 2 — Static batching’de her istek, batch’in en yavaşını bekler. Continuous batching’de scheduler her adımda boşalan slotu yeni istekle doldurur; GPU hiç boş dönmez [4][7].

Rakamlar: karışık uzunluklu iş yüklerinde continuous batching, static batching’e göre 2–4 kat throughput getiriyor[4]. H100 SXM5 üzerinde Llama 3.3 70B FP8 ile 128 eşzamanlı istekte 1.900 token/s’den 2.380 token/s’ye çıkış ölçülmüş; eşzamanlılık düşükken fark daha da dramatik (4 istekte 290 → 480 token/s)[7]. A100 80GB üzerinde Llama 2 13B ile yapılan bir başka ölçümde ise batch’siz 120 token/s olan hız, continuous batching ile 890’a, PagedAttention eklendiğinde 1.240’a, parametreler optimize edilince 1.580 token/s’ye çıkıyor[17].

Prefill ve decode: iki farklı iş, tek scheduler

Bir ayrıntıya daha girelim, çünkü sonraki bölümleri anlamlı kılıyor. Model bir isteği iki fazda işler. Prefill fazında prompt’un tüm token’ları tek seferde işlenir — bu compute-bound (hesap sınırlı) bir iştir, GPU’nun çarpma gücünü zorlar. Decode fazında ise her adımda tek bir token üretilir — bu memory-bandwidth-bound (bellek bant genişliği sınırlı) bir iştir[2]. vLLM’in V1 scheduler’ı bu iki farklı işi aynı adımda bir arada çalıştırabilir; eski V0’ın ikisini sırayla işleyen yaklaşımına göre ciddi bir kazanç[2].

5. Perde Arkası III — İki Numara Daha: Chunked Prefill ve Prefix Caching

Chunked prefill: uzun prompt’un sırayı kilitlemesini engellemek

Şöyle bir sahne düşünün: siz “merhaba” yazdınız, tam o sırada başka bir kullanıcı 32.000 token’lık bir doküman yapıştırdı. O devasa prefill H100’de 70B model için 200–400 ms boyunca tüm hattı bloke eder ve sizin “merhaba”nız bekler[7]. Buna head-of-line blocking (sıra başı tıkanması) denir.

Chunked prefill, uzun prompt’u parçalara bölüp birden fazla adıma yayar; aralara başka isteklerin işi girer[2]. Ölçülen etki çarpıcı: 32K girdilerde 50 eşzamanlı istekle p95 TTFT 2.800 ms’den 890 ms’ye iniyor — %68 iyileşme. Buna karşılık p50 (medyan) neredeyse hiç değişmiyor[7]. Yani chunked prefill medyan hızı artırmaz; kuyruktaki en talihsiz kullanıcıyı kurtarır. Adalet ile ham medyan hız arasındaki klasik takas.

Prefix caching: aynı sistem prompt’unu bin kere hesaplamamak

Gerçek uygulamalarda istekler birbirine çok benzer başlar: aynı sistem prompt’u, aynı araç (tool) tanımları, RAG’de aynı doküman parçaları, çok turlu sohbette aynı geçmiş. vLLM her 16 token’lık bloğun hash’ini tutar; yeni bir istek geldiğinde hash zinciri tuttuğu yere kadar olan kısmı hiç hesaplamadan hazır KV bloklarından alır[2][14].

Üç pratik not. Birincisi, bu özellik V1 motorunda varsayılan olarak açıktır; çoğu ekip farkında olmadan zaten kullanıyor[14]. İkincisi, eşleşme “benzer metin” değil, blok sınırına kadar token token birebir eşleşmedir — prompt’unuzun başına kullanıcı adı ya da zaman damgası koyarsanız cache’i tamamen öldürürsünüz. Üçüncüsü, gerçek isabet oranınızı tahmin etmeyin, ölçün: vllm:prefix_cache_queries ve vllm:prefix_cache_hits metrikleri tam olarak bunun için var[14]. Çok kiracılı (multi-tenant) bir sistemde ise cache_salt parametresiyle kiracılar arası cache paylaşımını mutlaka kapatın.

Şekil 3 — Bölüm 5’in iki numarası. Üstte chunked prefill, uzun bir prompt’u parçalayıp araya kısa istekleri sokar. Altta prefix caching, tekrar eden başlangıcı hiç hesaplamadan cache’ten verir — ama prompt’un başına değişken bir şey koyarsanız zincir ilk bloktan kırılır.

Bu arada bir rakibin farkını da burada görelim: SGLang’ın RadixAttention‘ı aynı problemi radix ağacı ile çözer; vLLM düz bir hash tablosu kullanıp eviction (tahliye) politikasıyla ağaç davranışını yaklaşık olarak taklit eder[14]. Ortak prefix’in çok yoğun olduğu agent döngülerinde SGLang’ın veri yapısı hâlâ bir adım önde[30].

6. Elimizi Kirletelim: vLLM’i Ayağa Kaldırmak

Teori bu kadar; şimdi çalıştıralım. vLLM’in iki kullanım modu var ve ikisini de bilmekte fayda var.

Mod 1: Offline batch inference (sunucu yok, sadece Python)

Elinizde 10.000 doküman var ve hepsini özetlemek istiyorsunuz. Sunucuya gerek yok:

pip install vllm

# ozet.py
from vllm import LLM, SamplingParams

prompts = ["Şu metni özetle: ...", "Bunu da özetle: ...", ...]
params  = SamplingParams(temperature=0.3, top_p=0.9, max_tokens=512)

llm = LLM(model="Qwen/Qwen3-8B", gpu_memory_utilization=0.90)
for out in llm.generate(prompts, params):
    print(out.outputs[0].text)

Bu mod, vLLM’in en az bilinen ama en çok kazandıran kullanımıdır: listeyi verirsiniz, motor continuous batching’i kendi içinde uygular ve GPU’yu ağzına kadar doldurur. Aynı işi tek tek API çağrısıyla yapmaya kıyasla fark katlarla ölçülür.

Mod 2: OpenAI uyumlu sunucu

vllm serve Qwen/Qwen3-8B \
  --host 0.0.0.0 --port 8000 \
  --max-model-len 16384 \
  --gpu-memory-utilization 0.90 \
  --max-num-seqs 256

Sunucu ayağa kalktığında elinizde /v1/chat/completions uçlu, OpenAI SDK’sının olduğu gibi konuşabildiği bir servis olur. Yani kodunuzda değişecek tek şey base URL:

curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model":"Qwen/Qwen3-8B",
       "messages":[{"role":"user","content":"Merhaba, ayakta mısın?"}],
       "max_tokens":50}'

Docker ile: prod’a giden yol

docker run --gpus all --ipc=host -p 8000:8000 \
  -e HUGGING_FACE_HUB_TOKEN=... \
  vllm/vllm-openai:latest \
  --model meta-llama/Llama-3.3-70B-Instruct \
  --dtype fp8 \
  --tensor-parallel-size 2 \
  --max-model-len 16384 \
  --gpu-memory-utilization 0.92 \
  --max-num-seqs 512 \
  --max-num-batched-tokens 65536 \
  --enable-chunked-prefill \
  --kv-cache-dtype fp8

En sık yapılan hata: --ipc=host flag’ini unutmak. vLLM arka planda PyTorch’un paylaşımlı bellek (shared memory) mekanizmasını kullanır — özellikle tensor parallel çalışırken. Container’ın varsayılan küçük shm alanı yetmezse sistem yük altında anlaşılmaz hatalarla çöker. --ipc=host yerine yeterince büyük bir --shm-size vermek de aynı işi görür[8].

Ve prod’da gözünüzü ayırmayacağınız üç metrik (/metrics ucundan Prometheus formatında gelir)[8]:

curl http://localhost:8000/metrics | grep vllm:

vllm:num_requests_waiting          # kuyruk derinliği — sürekli artıyorsa kapasiteniz yetmiyor
vllm:kv_cache_usage_perc           # KV cache doluluğu — %100'e dayanınca preemption başlar
vllm:time_to_first_token_seconds   # kullanıcının hissettiği gecikme

7. Ayar Odası: Hangi Vida Ne İşe Yarar?

vLLM’in onlarca flag’i (komut satırı seçeneği) var ama pratikte hayatınızı belirleyen bir avuç tanesi. Tabloyu ezberlemeyin, mantığını anlayın:

FlagNe yaparPratik öneri
--gpu-memory-utilizationGPU belleğinin ne kadarını vLLM’e ayırdığınız (güncel varsayılan 0.92)Bare-metal’de 0.95’e kadar çıkın; kartı başka iş paylaşıyorsa 0.85’te kalın[7]
--max-model-lenİzin verilen maksimum context uzunluğuGerçekten ihtiyacınız olan değeri yazın. Gereksiz büyütmek KV cache’i şişirir ve eşzamanlı kullanıcı sayınızı düşürür
--max-num-seqsAynı anda batch’te tutulacak maksimum istek sayısıYüksek eşzamanlılıklı API’lerde 512–2048; düşük gecikme istiyorsanız düşük tutun[7]
--max-num-batched-tokensBir adımda işlenecek toplam token bütçesiThroughput odaklıysa 16K–64K; düşük gecikme odaklıysa 8K civarı[7][17]
--kv-cache-dtype fp8KV cache’i 8 bitte tutarBellek ihtiyacını yarıya indirir; context bütçenizi bir hamlede ikiye katlar[8]
--tensor-parallel-sizeModeli kaç GPU’ya bölecekModel tek karta sığmıyorsa şart. Kart sayınıza eşitleyin[29]
--enable-chunked-prefillUzun prompt’ları parçalara bölerGirdi uzunlukları çok değişkense açın; hepsi kısa ve benzerse gereksiz[7]
--quantization / --dtype fp8Ağırlıkları düşük hassasiyette tutar70B FP16 ≈ 140 GB (2× H100), FP8 ≈ 70 GB (tek H100). Sığdırma matematiğinin can simidi[8]

Bir de “OOM (out of memory) hatası aldım, ne yapayım” refleksi olsun: sırasıyla --max-model-len‘i düşürün, --max-num-seqs‘i kısın, --kv-cache-dtype fp8 açın, quantize edilmiş bir model ağırlığına geçin, hâlâ olmuyorsa --tensor-parallel-size ile ikinci karta yayın[19].

Bunun karşılığı sadece hız değil, doğrudan para: bir vaka çalışmasında varsayılan ayarlardan optimize ayarlara geçiş, aynı throughput’u %40 yerine %85 GPU kullanımıyla sağlayarak aylık maliyeti 5.789 dolardan 2.894 dolara indiriyor[7].

8. Kıyas Zamanı I: Ollama, llama.cpp, LM Studio ve Docker Model Runner

Şimdi kafa karışıklığının en yoğun olduğu yere gelelim. Sık sorulan “Ollama mı vLLM mi?” sorusunun dürüst cevabı: bu ikisi aynı ligde değil. Ollama, llama.cpp ve LM Studio tek kullanıcıyı mutlu etmek için tasarlandı; vLLM bir GPU filosundan maksimum iş çıkarmak için. Kıyaslamak, bisiklet ile şehirlerarası otobüs kıyaslamak gibi — ikisi de doğru, mesele nereye gittiğiniz.

Ollama / LM Studiollama.cppDocker Model RunnervLLM
HedefTek kullanıcı, masaüstüGömülü / taşınabilir çalışma zamanıGeliştirici iş akışı, tek APIÇok kullanıcılı servis, prod
Model formatıGGUFGGUFGGUF + safetensors (OCI paketi)Safetensors (GGUF de destekli)
DonanımCPU, Mac, her türlü GPUHer yerde — CPU dahilNVIDIA / AMD / Apple SiliconAğırlıklı NVIDIA; AMD, TPU, CPU, Gaudi
EşzamanlılıkVarsayılan 1; elle artırılır[16]Sınırlı, elle ayarlanırArka uca göre değişirYüzlerce
Başlangıç süresiSaniyelerSaniyelerSaniyeler~60 saniye[6]
Kurulum yüküTek komutDerleme / flag bilgisiDocker varsa yokCiddi; GPU sürücüsü, bellek planı

Peki Docker Model Runner tam olarak nedir?

Bu, listedeki en yeni ve en çok yanlış anlaşılan isim. Docker Model Runner (DMR) bir inference motoru değil; motorların üzerine geçen bir yönetim ve dağıtım katmanı. Modelleri OCI artifact’ı olarak — yani container image’ları gibi — Docker Hub, herhangi bir OCI registry’si ya da Hugging Face üzerinden çeker, tek bir OpenAI uyumlu API sunar ve arkada üç farklı motoru koşturabilir: yerel geliştirme için llama.cpp, görsel üretim için Diffusers ve yüksek throughput için vLLM[10][23].

# vLLM arka ucunu kur (Linux + NVIDIA)
docker model install-runner --backend vllm --gpu cuda

# modeli çek ve çalıştır — API yine OpenAI uyumlu
docker model run ai/smollm2-vllm "Beni duyuyor musun?"

Buradaki asıl fikir şu: aynı iş akışı içinde llama.cpp ile lokalde prototip yapıp, tek satır değiştirerek vLLM ile prod’a ölçeklemek[11]. Modeli container gibi versiyonlayıp registry’de tutabilmek de kurumsal tarafta ciddi bir kolaylık. Sınırlar da net: vLLM arka ucu Linux ve WSL2 üzerinde NVIDIA GPU ister, model kayıt/başlatma sırasında llama.cpp’den yavaştır ve API’nin kimlik doğrulaması yoktur — servise erişebilen herkes model çalıştırabilir[10][11].

Mac tarafında güzel bir gelişme de var: Docker ve vLLM ekibinin birlikte geliştirdiği vllm-metal arka ucu, MLX ile PyTorch’u tek bir yolda birleştirip Apple Silicon’ın unified memory’sini sıfır kopyayla kullanıyor. Docker Desktop 4.62+ ile docker model install-runner --backend vllm deyip MLX formatındaki modelleri çalıştırabiliyorsunuz[12][13]. Beklentiyi doğru ayarlayalım ama: aynı ölçümlerde llama.cpp hâlâ ~1.2–1.3 kat daha hızlı; vllm-metal’in avantajı uzun çıktılarda daha iyi ölçeklenmesi[12].

9. Kıyas Zamanı II: vLLM’in Gerçek Rakipleri

vLLM’in asıl rakipleri Ollama değil, aynı problemi çözen diğer prod servis motorları. Sahne bugün üç isimden ibaret: SGLangTensorRT-LLM ve azalan bir üçüncü, TGI.

Mart 2026’da H100 SXM5 üzerinde Llama 3.3 70B Instruct FP8 ile, 200 benzersiz prompt kullanılarak yapılan bir ölçüm şöyle[6][9]:

EşzamanlılıkvLLMSGLangTensorRT-LLM
1 istek120 tok/s125 tok/s130 tok/s
50 istek1.850 tok/s1.920 tok/s2.100 tok/s
100 istek2.400 tok/s2.460 tok/s2.780 tok/s
TTFT p50 (10 istek)120 ms112 ms105 ms
Soğuk başlangıç~62 sn~58 sn~28 dakika (derleme)

Tabloyu okurken iki şeye dikkat edelim. Birincisi, aradaki farklar sandığınızdan küçük — üçü de aynı büyüklük mertebesinde. İkincisi ve daha önemlisi: bu test benzersiz prompt’larla yapıldı, yani prefix caching’in hiç devreye girmediği en kötü senaryoydu. Gerçek trafiğinizde aynı sistem prompt’u tekrar ediyorsa sıralama pekâlâ değişebilir[9].

SGLang, RadixAttention’ı sayesinde ortak prefix’in yoğun olduğu işlerde — sohbet, RAG, few-shot, agent döngüleri — vLLM’e göre daha iyi TTFT verir[6][30]TensorRT-LLM ham hızın zirvesidir ama bedeli ağırdır: yalnızca NVIDIA, dar model desteği ve modeli önceden derleme zorunluluğu. Haftada bir model değiştiren bir ekip için 28 dakikalık derleme süresi tek başına caydırıcıdır[6][20]TGI ise artık bakım modunda; Hugging Face yeni işler için kullanıcıları vLLM, SGLang, llama.cpp ve MLX’e yönlendiriyor[9].

Pratikte karar şuna geliyor: çoğu ekip için gerçek seçim vLLM ile SGLang arasındadır[6]. vLLM’i öne çıkaran şey ham hız değil, en geniş model desteği, derleme gerektirmeyen esneklik ve en olgun operasyon ekosistemi. Yeni bir model çıktığında ilk gün destekleyen genelde vLLM olur.

Benchmark okuma kılavuzu: Sürüm kayması gerçek bir sorundur. TensorRT-LLM v1.2 derlemeli, v1.3 PyTorch tabanlıdır; ikisini karşılaştırmak motor kabiliyetini değil sürüm etkisini ölçer[9]. Kendi bake-off’unuzu yaparken üç ayrı trafik şekli deneyin — benzersiz prompt’lar, tekrar eden prefix’ler ve gerçek prod karışımınız — ve başarısız istekleri de raporlayın, sadece başarılıların ortalamasını değil.

10. vLLM’i Ne Zaman Seçmemeli?

Bir aracı gerçekten anlamak, sınırlarını bilmekle olur. vLLM’den uzak durmanız gereken durumlar:

Tek kullanıcıysanız. vLLM’in tüm sihri paylaşımda. Kendi başınıza sohbet ediyorsanız Ollama ya da LM Studio hem daha hızlı kurulur hem daha hızlı başlar. ~60 saniyelik soğuk başlangıcı her seferinde ödemenin anlamı yok[6][27][28].

Mac’teyseniz (çoğunlukla). vllm-metal umut verici ama topluluk tarafından sürdürülüyor, arm64 Python 3.12 ve Xcode Command Line Tools istiyor ve kaynaktan derleniyor[13]. Apple Silicon’da hâlâ pratik cevap MLX ya da llama.cpp.

VRAM’iniz darsa. vLLM belleği baştan rezerve edip yönetir; llama.cpp’nin “katmanların bir kısmını CPU’ya taşı” esnekliği yoktur. GGUF ile 8 GB’lık bir kartta 30B model koşturma numaraları vLLM’in dünyasına ait değil.

Model desteği doğrulanmadıysa. “Mimariyi destekliyor” ile “prod’a hazır” aynı şey değil. Ciddi model kartları artık hangi motor sürümüyle hangi komutla çalıştırılacağını açıkça yazıyor; oradan başlayın, sürümleri sabitleyin, sonra kendi GPU’nuzda yük, tool çağrısı ve throughput testi yapın[9].

11. Ufuk: Tek Sunucudan Dağıtık Servise

Son olarak nereye gittiğimize bakalım, çünkü bu yön vLLM’in gelecekteki rolünü belirliyor. İki büyük kavram öne çıkıyor.

KV offloading: vLLM 0.11.0 ile gelen KV offloading connector, GPU belleği dolduğunda KV değerlerini atıp sonra yeniden hesaplamak yerine CPU RAM’ine asenkron olarak taşıyor. Llama-3.1-8B ile H100’de tek istekte TTFT’de 2–22 kat, 10.000 istekli testte throughput’ta 9 kata varan iyileşme raporlanıyor; 0.12.0’daki bellek yerleşimi optimizasyonuyla bunun üstüne 4 kat TTFT ve 5 kat throughput daha ekleniyor[15]. Son sürümlerde bu, katmanlı ikincil depolamayı da kapsayacak şekilde genişledi[18].

Disaggregated serving (ayrıştırılmış servis): Hatırlayın, prefill compute-bound, decode memory-bound bir işti. Neden ikisini aynı GPU’da yapalım? Yeni mimari bu iki fazı ayrı GPU havuzlarına dağıtıp KV cache’i aralarında transfer ediyor. Kubernetes üzerinde llm-d, NVIDIA Dynamo ve KServe gibi projeler tam olarak bu deseni operasyonel hale getiriyor[24][25][26]. Bu katmanların çoğunda motor olarak yine vLLM koşuyor — yani vLLM giderek “tek sunucu aracı” olmaktan çıkıp dağıtık bir servis katmanının çekirdeğine dönüşüyor.

Kapanış: Karar Sizde

Toparlayalım. vLLM’in bütün hikâyesi üç cümleye sığıyor. PagedAttention belleği kurtarır — KV cache’i işletim sistemi sayfaları gibi yönetip israfı %60-80’den %4’ün altına indirir. Continuous batching zamanı kurtarır — kimse kimseyi beklemez, GPU boş dönmez. Ve bu ikisi yalnızca paylaşımda anlam kazanır — tek kullanıcıysanız vLLM size bir şey kazandırmaz, sadece kurulum zahmeti verir.

Karar ağacınız bu kadar basit: kendinize çalıştırıyorsanız Ollama ya da LM Studio; taşınabilirlik ve tam kontrol istiyorsanız llama.cpp; aynı iş akışında hem prototip hem prod istiyorsanız Docker Model Runner; başkalarına servis ediyorsanız vLLM; prefix’i çok ağır agent yükleriniz varsa yanına SGLang’ı da tartın; tek modeli yıllarca sabit koşturacaksanız TensorRT-LLM’i değerlendirin.

Ve en önemlisi: bu yazıdaki hiçbir sayıyı olduğu gibi kabul etmeyin. Kendi modelinizle, kendi prompt dağılımınızla, kendi kartınızda ölçün. İyi haber şu ki artık neyi ölçeceğinizi ve çıkan sayının neden o çıktığını biliyorsunuz. Kolay gelsin — GPU’nuz dolu, kuyruğunuz boş olsun!


Kaynaklar

  1. vLLM Blog — vLLM: Easy, Fast, and Cheap LLM Serving with PagedAttention
  2. vLLM Blog — Inside vLLM: Anatomy of a High-Throughput LLM Inference System
  3. vLLM — Official Documentation
  4. Runpod — vLLM Explained: PagedAttention and Continuous Batching
  5. Applied Sciences (MDPI) — Benchmarking Ollama and vLLM for Concurrent LLM Serving: A Multi-Scenario Evaluation
  6. Spheron — vLLM vs TensorRT-LLM vs SGLang: Which Is Fastest? (H100 Benchmarks, 2026)
  7. Spheron — LLM Serving Optimization: Continuous Batching, PagedAttention and Chunked Prefill on H100
  8. Spheron — vLLM Production Deployment 2026: Multi-GPU Tensor Parallel + FP8 Docker Setup
  9. LeetLLM — vLLM vs SGLang vs TensorRT-LLM vs Ollama: Choosing an Inference Engine in 2026
  10. Docker Docs — Docker Model Runner
  11. vLLM Blog — Docker Model Runner Integrates vLLM for High-Throughput Inferencing
  12. Docker Blog — Docker Model Runner Adds vLLM Support on macOS
  13. vllm-metal — Community Hardware Plugin for vLLM on Apple Silicon (GitHub)
  14. packet.ai — vLLM Prefix Caching Explained
  15. vLLM Blog — Inside vLLM’s New KV Offloading Connector
  16. Ollama — Official FAQ (Concurrency & Environment Variables)
  17. EaseCloud — vLLM Throughput Guide: PagedAttention and Batching Tips (2026)
  18. vLLM — Releases (GitHub)
  19. vLLM Docs — Optimization and Tuning
  20. Runpod — vLLM vs TensorRT-LLM vs SGLang: Which Inference Engine to Deploy
  21. UC Berkeley Sky Computing Lab — vLLM Project Page
  22. Efficient Memory Management for Large Language Model Serving with PagedAttention (arXiv 2309.06180)
  23. Docker Docs — Model Runner Inference Engines
  24. Spheron — llm-d on Kubernetes: Disaggregated LLM Inference Deployment Guide
  25. NVIDIA Technical Blog — Deploying Disaggregated LLM Inference Workloads on Kubernetes
  26. vLLM Docs — Disaggregated Prefilling
  27. Rost Glukhov — Ollama vs vLLM vs LM Studio: Best Way to Run LLMs Locally in 2026
  28. Codersera — vLLM vs Ollama vs LM Studio: The 2026 Production Self-Host Benchmark
  29. vLLM Docs — Parallelism and Scaling
  30. Spheron — vLLM vs SGLang 2026: RadixAttention vs PagedAttention Benchmarks
  31. Kapak Görseli: Photo by Klara Kulikova on Unsplash

Bir yanıt yazın