Self-hosted LLM Neden 5 Kullanıcıda Yavaşlar?
Ollama varsayılan ayarlarında num_parallel değeri 1 olduğu için eşzamanlı istekler kuyrukta bekler. KV cache yönetimi ve batching ile sunucu kapasitesini artırın.
Self-hosted bir LLM, kullanıcı sayısı arttığında neden yavaşlar?
Self-hosted bir LLM, 5 eşzamanlı kullanıcıda takılır çünkü sunucu aynı anda yalnızca tek bir yanıt üretmektedir ve diğer dört kullanıcı kuyrukta beklemektedir. Ollama belgeleri, varsayılan ayar konusunda oldukça nettir: OLLAMA_NUM_PARALLEL, "her modelin aynı anda işleyeceği maksimum paralel istek sayısıdır ve varsayılan değer 1'dir." Herhangi bir arıza yoktur. Beş kullanıcınızdan dördü sıra beklemektedir.
Çözüm nadiren daha güçlü bir donanıma geçmektir. Çözüm, birçok isteği aynı ileri geçiş (forward pass) işleminde model üzerinden geçiren bir servis motoru kullanmak ve bu işlem sırasında tüm konuşmaları bellekte tutacak kadar boş alan bırakmaktır. Her iki kısım da önemlidir; ancak ikinci kısım, sisteminizin kapasitesini belirleyen asıl unsurdur.
Her isteğin geçtiği iki aşama
Prefill, istemin tamamını bir kerede okur ve bunun için dikkat (attention) önbelleğini oluşturur. Her istem belirteci (token) modelden birlikte geçer; bu nedenle prefill tek bir büyük matris çarpımıdır ve aritmetik işleme kapasitesiyle sınırlıdır. Decode aşaması ise yanıtı her seferinde bir belirteç olacak şekilde yazar. Her belirteç, modelin tüm ağırlıklarının bellekten tekrar okunmasını gerektirirken, o tek belirteç üzerinde yapılan aritmetik işlem oldukça küçüktür. Decode, bellek bant genişliği ile sınırlıdır.
Bu asimetri, toplu işlemenin (batching) çalışma nedenidir. Tek bir kullanıcı için decode işlemi, belirteç başına yaklaşık 5 GB ağırlık okur ve aritmetik birimlerin çoğunu boşta bırakır. İkinci bir istek eklendiğinde, motor aynı 5 GB'ı bir kez okur ve ardından bu veriden iki belirteç hesaplar. İkinci kullanıcı neredeyse hiç ek süre maliyeti oluşturmaz. İstekleri kesinlikle arka arkaya sunmak, bu avantajı ortadan kaldırır.
Kullanıcının deneyimini iki sayı tanımlar. TTFT (ilk belirtece kadar geçen süre), kuyruk bekleme süresi ile prefill süresinin toplamıdır. ITL (belirteçler arası gecikme), akış halindeki belirteçler arasındaki boşluktur ve decode aşaması tarafından belirlenir. Yavaş bir sunucu genellikle bunlardan birinde yavaş kalır ve çözüm yolları birbirinden farklıdır. Herhangi bir ayarı değiştirmeden önce hangi sorunla uğraştığınızı belirlemek önemlidir; prefill ve decode sürelerini ayrı ayrı ölçmek bunu anlamanızı sağlar.
Statik toplu işleme, herkesin en yavaş yanıtı beklemesine neden olur
Statik toplu işleme (static batching), yöntemin en ilkel halidir ve istekleri uygulama kodunda kendiniz grupladığınızda ortaya çıkan sonuçtur. Motor, N adet isteği toplar, bunları birlikte çalıştırır ve gruptaki en uzun üretim süreci tamamlanana kadar her bir yuvayı (slot) meşgul tutar.
1.200 token'lık bir özet isteyen bir kullanıcı, dört adet tek satırlık yanıtı toplu işlem içinde kilitli tutar; çünkü toplu işlem, en yavaş üyesi bitene kadar hiçbir yuvayı serbest bırakmaz.
Bu durum iki maliyeti beraberinde getirir. Tamamlanan diziler, hiçbir yararlı hesaplama yapmadıkları halde yuvaları işgal etmeye devam eder; bu nedenle çıktı uzunlukları değiştikçe etkin iş hacmi düşer ve sohbet çıktılarının uzunlukları büyük değişkenlik gösterir. Toplu işlem oluşturulduktan hemen sonra gelen bir istek, ön dolum (prefill) aşamasına başlamadan önce tüm toplu işlemin bitmesini bekler; bu da isteğin TTFT (ilk token'a kadar geçen süre) değerinin başka birinin yazdığı uzun bir metin tarafından belirlenmesi anlamına gelir.
Sürekli toplu işleme (continuous batching) her belirteçte istekleri kabul eder ve sonlandırır
Sürekli toplu işleme, zamanlama işlemini tek bir kod çözme adımı seviyesinde gerçekleştirir. Her adımdan sonra zamanlayıcı, durdurma belirtecini (stop token) henüz yayınlamış olan dizileri çıkarır ve ardından boşalan yuvalara bekleyen istekleri dahil eder. 40. adımda sona eren bir yanıt, yuvasını toplu işin sonunda değil, 40. adımda serbest bırakır.
Bu egzotik bir yöntem değildir. llama-server, -cb, --cont-batching parametresini "sürekli toplu işlemenin (diğer adıyla dinamik toplu işleme) etkinleştirilip etkinleştirilmeyeceği (varsayılan: etkin)" şeklinde tanımlar ve vLLM tamamen bu fikir üzerine inşa edilmiştir. Ollama da paralel istekleri sunabilir. Varsayılan ayar bu sayıyı bir ile sınırlandırır; pek çok kişinin donanımının eşzamanlılığı destekleyemeyeceği sonucuna varmasının nedeni, donanımları değil, yapılandırmalarının buna izin vermemesidir.
Yayınlanan sürekli toplu işleme sonuçları genellikle hem yedek işlem gücüne hem de önbellek için onlarca gigabayt alana sahip veri merkezi kartları üzerinde ölçülür. Bu sonuçların biçimi sizin sisteminize de uyarlanabilir. Ancak sonuçların ölçeği aynı olmayacaktır; bunun nedeni aşağıdaki bellek bölümünde açıklanmıştır.
Prefill, kod çözme (decode) işlemiyle aynı işlem gücü için rekabet eder
Dört yanıt akış halindeyken yeni bir istek geldiğinde, bu isteğin isteminin (prompt) öncelikle ön doldurma (prefill) işleminden geçmesi gerekir ve prefill işlemi yoğun işlem gücü gerektirir. Zamanlayıcı bu prefill işlemine kendi başına bir adım ayırırsa, bu süre zarfında akış halindeki dört kullanıcı hiçbir token alamaz. Uzun bir istemde bu durum, açık olan her pencerede gözle görülür bir duraksamaya neden olur. İnsanların "bir başkası gönder tuşuna bastığında sunucu tekliyor" dediklerinde kastettikleri kekemelik budur.
Parçalı prefill (chunked prefill), uzun bir istemi parçalara böler ve her parçayı çalışan kod çözme işlemleriyle aynı adıma karıştırır. vLLM'in ayarlama kılavuzu bu dengeyi doğrudan belirtir: daha küçük parça bütçeleri, "kod çözme işlemlerini yavaşlatan daha az prefill olduğu için daha iyi ITL (ilk token sonrası gecikme) sağlar", daha yüksek değerler ise "bir yığında daha fazla prefill token'ı işlenebildiği için daha iyi ilk token süresi (TTFT) sağlar". Burada kimin deneyimini koruyacağınızı seçersiniz: yanıtın başlamasını bekleyen kişi mi, yoksa metnin akışını izleyen kişiler mi?
İstem uzunluğu, bu durumun ne kadar etkili olacağını belirler. 200 token'lık bir yanıt içeren 6.000 token'lık bir istem, 200 kod çözme adımına karşı 6.000 token'lık bir prefill iş yükü demektir. Geri getirme destekli sohbet (RAG) ve uzun sistem istemleri sizi bu rejime sokar; bu nedenle prefill, ihmal edilebilir bir hata payı olmaktan çıkıp kullanıcıların beklediği ana işleme dönüşür. Uzun kısım tekrarlandığında önek önbellekleme (prefix caching) yardımcı olur: vLLM, paylaşılan bir istem öneki için önbelleği yeniden hesaplamak yerine tekrar kullanan --enable-prefix-caching özelliğini sunar.
İlk tükenen bellek KV önbelleğidir
Aktif bir görüşmedeki her token, modelin her katmanında bir anahtar (key) vektörü ve bir değer (value) vektörü bırakır. Buna KV önbelleği (key/value cache) denir; decode işleminin her yeni token için tüm istemi (prompt) yeniden hesaplamasını engelleyen yapı budur. Token başına düşen boyut, modelin yapısı tarafından belirlenir: 2 (bir anahtar, bir değer), katman sayısı, anahtar/değer başlığı sayısı, başlık boyutu ve değer başına bayt sayısı ile çarpılır. Bu sayıları modelin config.json dosyasından okuyabilirsiniz.
Hesaplamayı bir kez yaptığınızda üst sınır bir gizem olmaktan çıkar. 36 katmanlı, 8 anahtar/değer başlıklı ve 128 başlık boyutlu tipik bir 8B model, önbelleği 16-bit olarak tuttuğunda token başına 2 36 8 128 2 baytlık bir maliyet oluşturur. Bu da 147.456 bayt, yani yaklaşık 144 KiB eder. Dolayısıyla 8.192 tokenlık bir görüşme yaklaşık 1,2 GB önbellek gerektirir. Beş görüşme, ağırlıkların üzerine yaklaşık 6 GB ek yük getirir; kaç kullanıcının sığabileceği sorusunun gerçek cevabı budur.
Eşzamanlılık bağlamı (context) çoğaltır ve araçlar bunu açıkça belirtir. Ollama'nın FAQ bölümü: "Belirli bir model için paralel istek işleme, bağlam boyutunun paralel istek sayısıyla çarpılmasına neden olur. Örneğin, 4 paralel istek ile 2K bağlam, 8K bağlam ve ek bellek tahsisine yol açar." Gerekli RAM, OLLAMA_NUM_PARALLEL ile OLLAMA_CONTEXT_LENGTH çarpılarak ölçeklenir. llama-server içinde, -c ile talep ettiğiniz bağlam -np yuvaları arasında paylaştırılır; bu nedenle yuva sayısını artırmak, her isteğin tutabileceği kapasiteyi tek başına düşürür. Varsayımda bulunmak yerine yuva başına düşen bağlamı başlangıç günlüğünden okuyun.
vLLM ise önceden tahsis (preallocate) yapar. --gpu-memory-utilization (varsayılan 0.92), "model yürütücüsü için kullanılacak GPU belleğinin oranıdır". Ağırlıklardan geriye kalan her şey sayfalanmış KV havuzu olur ve bu havuz yetersiz kaldığında zamanlayıcı, isteği başarısız kılmak yerine onu sistemden çıkarır (evict):
WARNING 05-09 00:49:33 scheduler.py:1057] Sequence group 0 is preempted by PreemptionMode.RECOMPUTE mode because there is not enough KV cache space.vLLM'in V1 motorunda varsayılan öncelik alma (preemption) modu RECOMPUTE'tur; bu nedenle sistemden çıkarılan bir istek önbelleğini atar ve tekrar kabul edildiğinde ön doldurma (prefill) işlemini yeniden yapar. Bu iş iki kez yapılmış olur. Belgeler, "öncelik alma ve yeniden hesaplamanın uçtan uca gecikmeyi olumsuz etkileyebileceği" konusunda uyarır. Bu günlük satırı, ortalama değerleriniz sağlıklı görünürken neden şanssız bir kullanıcının diğerlerinden çok daha uzun süre beklediğinin en iyi açıklamasıdır. Kümülatif sayıyı günlüğe kaydetmek için disable_log_stats=False ayarını yapın veya vLLM tarafından sunulan Prometheus metriklerinden öncelik alma sayacını okuyun.
2, 5 ve 20 eşzamanlı kullanıcıda neler değişir
İki kullanıcı. Önbellek alanı yeterli olan bir GPU üzerinde neredeyse fark edilmez, çünkü ikinci kod çözme akışı ilkiyle birlikte çok az ek süreyle ilerler. 4 ila 8 GB RAM'e sahip, yalnızca CPU kullanan bir VPS'te ise bu işlem ücretsiz değildir: her iki akış da aynı sınırlı vCPU ve RAM bant genişliğini paylaşır. Bu nedenle her kullanıcı saniyedeki token miktarının yaklaşık yarısını görür ve önbellek talebi, çok daha kısıtlı bir bütçeye karşı iki katına çıkar.
Beş kullanıcı. Varsayılan ayarların artık yeterli olmadığı ve sorunun bir kuyruk yönetimi problemine dönüştüğü nokta burasıdır. OLLAMA_NUM_PARALLEL değeri 1 olduğunda, dört kişi uzun yanıtı talep eden kişinin bitmesini bekler ve sıra kendilerine geldiğinde her biri normal hızı görür. Paralel işlem sayısını artırdığınızda sorunun doğası değişir: her biri 8K bağlam (context) içeren beş yuva, bulunması gereken 40K token'lık bir önbellek demektir. Eğer bu miktar VRAM'e sığmazsa, motor katmanları sistem RAM'ine aktarır; eğer RAM'e de sığmazsa sunucu takas (swap) alanına düşer ve saniyedeki token hızı çöker.
Yirmi kullanıcı. Bir sohbet arayüzündeki yirmi insan, genellikle yirmi eşzamanlı istek anlamına gelmez; donanım satın almadan önce anlaşılması gereken en önemli nokta budur. Bir kişi yanıtı okur ve hamleler arasında 20 ila 60 saniye düşünür, bu nedenle oturumlarının çoğu boşta geçer. Yirmi yapay zeka ajanı veya yirmi belge özetleme işi ise, hiç boş zamanı olmayan yirmi gerçek akış demektir. Bu, farklı bir makine gerektirir. Kendi Ollama sunucusuna bir kodlama ajanı yönlendiren bir geliştirici, ilk durumdan ziyade ikinci duruma daha yakındır; çünkü ajan, görev çalıştığı sürece istek göndermeye devam eder ve bir insanın yaptığı okuma duraklamalarına izin vermez.
Kullanıcılarınız eş zamanlı mı, yoksa sadece oturum açmış durumda mı?
Herhangi bir boyutlandırma yapmadan önce işlemdeki istek sayısını hesaplayın. Aritmetik basittir: işlemdeki istek sayısı, kullanıcı sayısı çarpı tur başına üretim için harcanan saniye, bölü turlar arasındaki saniyedir.
- Önce kendi tek akışlı hızınızı ölçün; hem ön doldurma (prefill) hem de kod çözme (decode) işlemlerini dahil edin. Başkasının kartına ait bir değeri ödünç almayın: kendi makinenizde saniye başına token ölçümü yapın ve elde ettiğiniz sonucu kullanın.
- Görev döngüsünü tahmin edin. Yirmi sohbet kullanıcısı, tur başına 12 saniyelik üretim ve her 90 saniyede bir tur, 20 * 12 / 90 hesabıyla yaklaşık 2.7 işlemdeki istek anlamına gelir.
- Slot sayısını bunun biraz üzerine ayarlayın, ardından bellek ile karşılaştırın: slot sayısı çarpı istek başına bağlam (context), sahip olduğunuz önbellek token'larına sığmalıdır.
- Kuyruğu kısa tutun; böylece taşma durumları hızlı ve görünür şekilde başarısız olur.
Kullanılabilir önbellek token'ları, ağırlıklar çıkarıldıktan sonra kalan boş belleğin, yukarıdaki bölümde belirtilen token başına maliyete bölünmesiyle bulunur. 16-bit formatında 8B model çalıştıran 24 GB'lık bir kart, ağırlıklar için yaklaşık 16 GB harcar ve varsayılan kullanım oranında yaklaşık 6 GB kullanılabilir önbelleğe sahiptir; bu da yaklaşık beş adet 8K'lık görüşmeye denk gelir. Daha fazlasını sığdırmak için istek başına bağlamı kısaltın veya önbelleği 8-bit olarak saklayın (llama-server, --cache-type-k q8_0 kullanır). Her iki yöntem de bir şeylerden feragat ederek eş zamanlılık sağlar; bu takasın dürüst bir değerlendirmesini yapmak, donanıma yatırım yapmadan önce okumaya değerdir: GPU VPS'in API token'larına karşı maliyetini kurtardığı nokta.
Ollama varsayılanlarının yetersiz kaldığı durumlar
Paralel istek sayısını servis birimi üzerinden artırın; çünkü shell ortamında yapılan bir export işlemi, systemd tarafından yönetilen bir daemon sürecine ulaşmayacaktır.
sudo systemctl edit ollama.service[Service]
Environment="OLLAMA_NUM_PARALLEL=4"
Environment="OLLAMA_CONTEXT_LENGTH=8192"
Environment="OLLAMA_MAX_QUEUE=64"sudo systemctl daemon-reload
sudo systemctl restart ollama
systemctl show ollama --property=Environment
ollama pssystemctl show komutu, az önce ayarladığınız üç değişkeni yazdırmalıdır. Eğer yazdırmıyorsa, drop-in dosyası kaydedilmemiştir ve yapacağınız diğer işlemlerin bir etkisi olmayacaktır. ollama ps komutu ise yüklü modeli, yalnızca ağırlıkların boyutundan daha büyük bir değerle listeler; çünkü 8,192 token kapasiteli dört yuva, yanlarında 32,768 tokenlik bir önbellek alanı rezerve eder. PROCESSOR sütununda modelin bir kısmının GPU yerine CPU üzerinde göründüğünü fark ederseniz, bu durum ekran kartının kapasitesinden daha fazla önbellek talep ettiğiniz anlamına gelir. İki değerden birini düşürün. Bağlam (context) boyutunu kısmak genellikle daha güvenli bir yoldur; ancak çok küçük bir pencere, hata vermek yerine uzun istemleri sessizce kırpacağı için num_ctx değerini bilinçli bir şekilde boyutlandırmak, modeli sığana kadar rastgele düşürmekten daha sağlıklıdır.
Kuyruk varsayılanı ayrıca değerlendirilmelidir. Ollama, OLLAMA_MAX_QUEUE değerine kadar istek kuyruğa alır ve "varsayılan değer 512'dir". Bu sayının ötesinde, "sunucunun aşırı yüklendiğini belirten bir 503 hatası" ile yanıt döner. Aynı anda dört istek işleyebilen bir sunucuda 512 derinliğinde bir kuyruk, tutamayacağınız bir sözdür; çünkü 300. sıradaki istemci, sıra kendisine gelmeden çok önce zaman aşımına uğrayacaktır. Kısa bir kuyruk, uygulamanızın yeniden deneyebileceği veya raporlayabileceği bir hata döndürür; bu, asla sonuçlanmayan bir yükleme simgesinden daha iyidir.
Gerçek bir test gerçekleştirin. İki farklı terminalden aynı anda iki istek gönderin ve her ikisini de izleyin. Eğer ikinci istek, ilki bitene kadar hiçbir çıktı üretmiyorsa, paralel ayarı devreye girmemiş demektir.
Gerçek bir sunum motoru ne zaman kendini amorti eder
vLLM, GPU üzerinde boş alanınız olduğunda ve aynı anda işlenen dört isteğin üzerinde gerçek bir trafik yükü bulunduğunda kurulum maliyetini karşılar. Zamanlayıcısı token bazlı çalışır, önbelleği sayfalandırılmıştır; böylece boş parçalar yeniden kullanılır ve boşta kalan VRAM, atıl bırakılmak yerine eşzamanlılığa dönüştürülür. Ağustos 2026 itibarıyla belgelenen kurulum ve başlatma işlemleri iki komuttan ibarettir:
uv pip install vllm --torch-backend=auto
vllm serve Qwen/Qwen2.5-1.5B-Instructcurl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-1.5B-Instruct",
"messages": [{"role": "user", "content": "Say hello."}]
}'choices dizisini içeren bir yanıt, sunucunun ayakta olduğunu ve modelin yüklendiğini gösterir. Yük altındayken dikkat edilmesi gereken iki temel ayar; "tek bir iterasyonda işlenecek maksimum dizi sayısı" olan --max-num-seqs ve "tek bir iterasyonda işlenecek maksimum token sayısı" olan --max-num-batched-tokens değerleridir. İlki eşzamanlılığı sınırlar. İkincisi ise daha önce açıklanan parçalı ön doldurma (chunked prefill) bütçesidir.
Aynı anda işlenen dört isteğin altında veya desteklenen bir GPU'nun bulunmadığı sistemlerde vLLM, karmaşıklığı artırır ancak çok az verim sağlar. CUDA sınıfı bir kart bekler ve başlangıçta belleğin büyük kısmını rezerve eder; bu durum 4 ila 8 GB RAM'e sahip bir VPS üzerinde yanlış bir tercihtir. Bu tür durumlarda çözüm, daha kısa bağlama sahip daha küçük bir model ve sizin kontrol ettiğiniz bir kuyruk yapısıdır. Ollama ve vLLM'in sunum motoru olarak farkları bu seçimi tüm detaylarıyla ele alır; bir VPS üzerinde Qwen 3 8B çalıştırmak ise orta ölçekli bir modelin, tek bir ek kullanıcı bile eklemeden önce ne kadar kaynak talep ettiğini gösterir.
Folklorun gizlediği ödünleşim
Continuous batching toplam iş hacmini artırır ve genellikle ortanca gecikmeyi de iyileştirir; çünkü kuyruktaki bir istek daha erken başlar. Kuyruk gecikmesi (tail latency) ise ters yönde hareket eder ve bu durum nadiren dile getirilir.
Bir adımdaki her ek dizi biraz daha fazla iş yükü ekler, bu nedenle batch doldukça herkes için ITL yükselir. Yeni gelen bir isteğin prefill işlemi, streaming kullanıcılarının aksi takdirde sahip olacağı bir adım diliminden pay alır. Önbellek baskısı altında zamanlayıcı (scheduler) önceliklendirme yapar (preempt), bu da yarı oluşturulmuş bir isteği prefill aşamasının başına geri gönderir.
Bir sohbet arayüzü ortalamaları değil, kuyrukları gösterir. Cümlenin ortasında iki saniye duraksayan bir akış, toplam tamamlanma süresi iyi olsa bile bozuk olarak algılanır. Beklediğiniz yük altında p95 TTFT ve p95 ITL değerlerini ölçün; saniye başına ortalama token değerini kullanıcı deneyiminin bir tanımı olarak değil, bir kapasite sayısı olarak ele alın.
Pratik ayar buradan çıkar. Eşzamanlılığı (concurrency) belleğin izin verdiğinden biraz daha düşük tutun; böylece motorun hiçbir zaman önceliklendirme yapması gerekmez. Kısa ve öngörülebilir bir kuyruk, sürekli kesintiye uğrayan (thrashing) derin bir batch yapısından daha iyidir. Çünkü dört saniye bekleyip ardından akıcı bir şekilde veri alan bir kullanıcı, anında başlayıp iki kez duraksayan bir kullanıcıdan daha memnundur.
Yavaşlık durumunda kontrol edilmesi gerekenler
Her kullanıcı normal, ancak bekleme süresi uzun. Bu bir hız sorunu değil, kuyruk sorunudur. Öncelikle parallel ayarını kontrol edin. Model, her seferinde tek bir istek olacak şekilde doğru hizmet veriyor.
Ollama üzerinden HTTP 503 hatası. Kuyruk doludur. Sunucu kapasitesi gerçekten dolmuş olabilir veya OLLAMA_MAX_QUEUE değeri, yükü azaltmak amacıyla kasıtlı olarak düşük tutulmuştur; bu, sistemin yapması beklenen davranıştır.
CPU tabanlı bir sunucuda yük altında saniye başına üretilen token sayısı düşüyor. Bu durum yaşanırken vmstat 1 komutunu çalıştırın. si ve so sütunlarında sıfırdan farklı değerler görülmesi, makinenin swap yaptığını ve ağırlıkların her token için diskten okunduğunu gösterir. Hiçbir yapılandırma değişikliği bunu düzeltemez. Model boyutunu veya slot sayısını azaltın.
On kullanıcıdan biri diğerlerinden çok daha uzun süre bekliyor. vLLM günlüklerinde preempted ifadesini aratın. Bunun yaygın nedeni preemption ve buna bağlı yeniden hesaplama işlemidir; bu, önbelleğin izin verilen bağlam uzunluğu için aşırı yüklendiği anlamına gelir.
Sunucu boşta olsa bile TTFT (ilk token süresi) kötü. Bu durum eşzamanlılık ile değil, prefill (ön doldurma) ile ilgilidir. Uzun istemler (prompt), ilk token görünmeden önce gerçek zaman harcar; bu nedenle donanıma bakmadan önce istem boyutunu ve prefix caching ayarlarını inceleyin. Eğer uzun bekleme süresi yalnızca sessiz bir dönemin ardından gelen ilk kullanıcıyı etkiliyor ve sonrakiler için sorun olmuyorsa, bu prefill değil, Ollama'nın modeli bellekten atıp ağırlıkları tekrar diskten okumasıdır. Bu durumu, modeli istekler arasında bellekte tutarak elemekte fayda vardır.
FAQ
İkinci bir kullanıcı bağlandığında self-hosted LLM neden yavaşlıyor?
Çoğu durumda yavaşlama olmaz, sadece kuyruğa girilir. Ollama, OLLAMA_NUM_PARALLEL değerini varsayılan olarak 1 ile sunar; bu nedenle ikinci istek, ilkinin son token'ı üretmesini bekler. İki durumu ayırt etmek için bir kullanıcının akışını, diğeri beklerken zamanlayın: Eğer akış başladığında token/saniye değeri normalse, bir kuyruk sorununuz vardır ve paralel sayısını artırmak bunu çözer. Eğer her iki akış da yarı hızda çalışıyorsa, bellek bant genişliğini paylaşıyorsunuz demektir; bu bir donanım sınırıdır.
Küçük bir GPU aynı anda kaç kullanıcıya hizmet verebilir?
Kullanıcı sayısını değil, belleği hesaplayın. Önce ağırlıklar, ardından her aktif konuşma için token başına; 2 çarpı katman sayısı çarpı anahtar/değer başlıkları çarpı başlık boyutu çarpı bayt şeklinde hesaplanan KV önbelleği gelir. 36 katmanlı, 8 anahtar/değer başlıklı ve 128 başlık boyutlu tipik bir 8B model, 16-bit modunda token başına yaklaşık 144 KiB yer kaplar; dolayısıyla 8,192 token'lık bir konuşma yaklaşık 1.2 GB gerektirir. Bu modeli 16-bit modunda tutan 24 GB'lık bir kartta önbellek için yaklaşık 6 GB boş yer kalır; bu da tam bağlamda yaklaşık beş konuşma veya bağlamı kısaltırsanız daha fazlası demektir.
Sürekli toplu işleme (continuous batching) her kullanıcının yanıtını yavaşlatır mı?
Medyan gecikme genellikle iyileşir çünkü istekler tüm grubun bitmesini beklemek zorunda kalmaz. Kuyruk gecikmesi (tail latency) ise kötüleşir. Eklenen her dizi, her kod çözme adımına iş yükü ekler; yeni gelen bir isteğin ön doldurma (prefill) işlemi, akış halindeki kullanıcılardan bir adımın bir kısmını çalar ve kesintiye uğrayan bir istek iki kez ön doldurma yapmak zorunda kalır. Ortalamaları değil, p95 token arası gecikmeyi ölçün; çünkü sohbet penceresinde duraksamalar, ortalamaların gizlediği bir şekilde belirginleşir.
OLLAMA_NUM_PARALLEL değerini mi artırmalıyım yoksa vLLM'e mi geçmeliyim?
Önce paralel sayısını artırın. Bu işlem ücretsizdir, tek bir yapılandırma dosyası gerektirir ve dört kişinin uzun bir yanıtın arkasında kuyrukta beklediği yaygın durumu çözer. Sınır bellektir: paralel istekler tutmanız gereken bağlamı çoğaltır, bu yüzden katmanların CPU'ya taşmadığından emin olun. VRAM'iniz boşta olduğunda ve aynı anda dört isteğin üzerinde gerçek bir trafik olduğunda vLLM'e geçin; çünkü paged cache ve token bazlı zamanlamanın maliyetinden daha fazla verim sağladığı nokta burasıdır.
Daha fazla CPU çekirdeği yavaş bir LLM sunucusunu düzeltir mi?
Kullanıcıların en çok fark ettiği kısım için hayır. Kod çözme (decode) işlemi, her token için tüm modeli bellekten okur; bu nedenle RAM bant genişliği ile sınırlıdır ve bant genişliği doygunluğa ulaştığında ek çekirdekler yardımcı olmaz. Ön doldurma (prefill) işlemi çekirdek sayısıyla ölçeklenir, bu nedenle daha fazla çekirdek, uzun istemlerde ilk token'a ulaşma süresini kısaltır. 4 ila 8 GB RAM'e sahip bir VPS'te kısıtlayıcı faktör genellikle bellek kapasitesidir; bu durumda etkili çözüm daha fazla vCPU değil, daha küçük bir model veya daha kısa bir bağlam kullanmaktır.