Ollama concurrency instellen met NUM_PARALLEL en MAX_QUEUE
Begrijp hoe OLLAMA_NUM_PARALLEL en OLLAMA_MAX_QUEUE uw wachtrij beheren. Voorkom HTTP 503-fouten en ontdek waarom elk extra parallel slot direct extra VRAM-geheugen vereist.
Wat gebeurt er met het tweede Ollama-verzoek terwijl het eerste wordt gegenereerd
De gelijktijdigheid van Ollama wordt bepaald door drie omgevingsvariabelen; standaard verwerkt één geladen model één verzoek tegelijk. Het tweede verzoek wordt niet geweigerd en ontvangt geen gedeeltelijk antwoord. Het verzoek wacht in een wachtrij totdat er een slot vrijkomt en wordt daarna op normale snelheid uitgevoerd.
Een inkomend verzoek heeft drie mogelijke uitkomsten. Het start direct in een vrij slot. Het wacht in de wachtrij. Of de wachtrij is al vol en de server weigert het verzoek met een HTTP 503-foutmelding. Welke uitkomst u krijgt, wordt bepaald door OLLAMA_NUM_PARALLEL, OLLAMA_MAX_QUEUE en OLLAMA_MAX_LOADED_MODELS.
De standaardinstelling is veilig, en dit is ook de reden waarom een tweede gebruiker meldt dat de server "vastloopt" terwijl er niets kapot is. Het toevoegen van slots is een wijziging van twee regels. Het lastige punt is het geheugen. Elk parallel slot heeft een eigen key/value cache (KV cache) nodig; dit is het geheugenblok dat een model bijhoudt voor de tokens die het al heeft verwerkt. Voegt u slots toe zonder extra VRAM (videogeheugen op de GPU) toe te voegen, dan verandert u een traag antwoord in een mislukte laadactie.
Wat OLLAMA_NUM_PARALLEL, OLLAMA_MAX_QUEUE en OLLAMA_MAX_LOADED_MODELS elk aansturen
Dit zijn de standaardwaarden in huidige Ollama-releases per augustus 2026. Controleer uw eigen instellingen in plaats van op deze getallen te vertrouwen, door de logregel hieronder te gebruiken.
OLLAMA_NUM_PARALLELbepaalt hoeveel verzoeken één geladen model tegelijkertijd afhandelt. De standaardwaarde is 1, waardoor verzoeken na elkaar worden verwerkt.OLLAMA_MAX_LOADED_MODELSbepaalt hoeveel verschillende modellen tegelijkertijd in het geheugen blijven. De standaardwaarde is 0, wat betekent dat Ollama zelf kiest: drie modellen per GPU, en drie op een machine zonder GPU.OLLAMA_MAX_QUEUEbepaalt hoeveel verzoeken er in de wachtrij mogen staan. De standaardwaarde is 512. Een verzoek dat binnenkomt wanneer de wachtrij vol is, wordt direct afgewezen.
Het worst-case geheugengebruik is het product van de eerste twee instellingen. Twee geladen modellen met elk vier slots betekent acht slot-toewijzingen van KV-cache die tegelijkertijd in het geheugen staan, en Ollama zal proberen dit te faciliteren. Op een systeem met één GPU is het meestal beter om één model geladen te houden en dit van slots te voorzien, omdat de berekening dan eenvoudig blijft.
Waarom elke parallelle slot VRAM kost
Wanneer Ollama een model laadt, start het een afzonderlijk runner-proces. Twee van de argumenten die worden meegegeven zijn hier van belang: -c is de totale context waarvoor de runner een KV-cache reserveert, en -np is het aantal parallelle sequenties. Ollama stelt -c in op de contextlengte per verzoek vermenigvuldigd met het aantal slots. De runner verdeelt dit totaal vervolgens gelijkmatig over de slots, zodat elk verzoek de gevraagde contextlengte behoudt.
Dit is de enige beperking, en het is de reden waarom parallellisme niet gratis is. Van één naar vier slots gaan vereist vier keer zoveel KV-cache bij dezelfde contextlengte per verzoek. Er wordt niets gedeeld tussen slots, en het aandeel van een inactieve slot wordt niet uitgeleend aan een actieve slot, omdat de verdeling vaststaat bij het starten van de runner.
U kunt de werkelijke getallen aflezen in plaats van de getallen die u dacht in te stellen:
journalctl -u ollama --no-pager -n 500 | grep "starting llama-server"Die regel bevat de volledige opdrachtregel van de runner, inclusief -c en -np. Als -np op 1 staat nadat u de variabele heeft ingesteld, bereikt de instelling de server niet; de volgende sectie behandelt de oorzaak hiervan.
Als de modelgewichten plus de KV-cache niet in het VRAM passen, verplaatst Ollama enkele lagen naar het systeem-RAM en worden die lagen op de CPU uitgevoerd. CPU-lagen zijn aanzienlijk trager dan GPU-lagen, waardoor elk verzoek trager wordt, inclusief het enkele verzoek waarmee u begon. Het verhogen van het parallellisme kan daarom de doorvoer verlagen in plaats van verhogen.
ollama psDe kolom PROCESSOR geeft 100% GPU aan wanneer het geheel in het geheugen past. Een verdeling zoals 35%/65% CPU/GPU betekent dat een deel van het model op de CPU draait. De kolom SIZE bevat de KV-cache, dus deze groeit wanneer u het aantal slots verhoogt en het model opnieuw laadt. Verhoog OLLAMA_NUM_PARALLEL, start opnieuw op, verstuur één verzoek en voer ollama ps opnieuw uit: dit is de geheugenkost van uw wijziging, gemeten in plaats van geschat.
Contextlengte en het aantal slots vermenigvuldigen elkaar, dus ze moeten in samenhang worden gekozen. Een grote context met vier slots staat gelijk aan vier grote contexten. Als u ook het num_ctx contextvenster voor uw model aanpast, wijzig dan één van de twee tegelijk, anders weet u niet welke instelling de kaart heeft gevuld.
Hoe u deze variabelen instelt zodat ze een herstart overleven
Op Linux draait Ollama als een systemd-service. Het uitvoeren van export OLLAMA_NUM_PARALLEL=4 in uw shell verandert niets, omdat systemd de service start met een eigen omgeving en uw shell nooit ziet. Gebruik een drop-in bestand.
sudo systemctl edit ollama.serviceVoeg dit toe in de editor die wordt geopend:
[Service]
Environment="OLLAMA_NUM_PARALLEL=4"
Environment="OLLAMA_MAX_LOADED_MODELS=1"
Environment="OLLAMA_MAX_QUEUE=32"Herlaad en herstart vervolgens:
sudo systemctl daemon-reload
sudo systemctl restart ollama
systemctl show ollama --property=Environmentsystemctl show toont wat systemd aan het proces zal meegeven. Als uw variabele daar ontbreekt, is de drop-in niet opgeslagen of is daemon-reload overgeslagen. Controleer dit ook vanaf de kant van de server zelf:
journalctl -u ollama --no-pager | grep "server config" | tail -1Ollama logt de volledige omgeving bij het opstarten op een regel met de melding server config. Die map is de waarheid. Dit is de snelste manier om vast te stellen of een variabele effect heeft gehad.
Een model dat al geladen is, behoudt het aantal slots waarmee het is gestart, omdat de waarde bij het opstarten in het runner-proces wordt vastgelegd. De bovenstaande herstart ontlaadt alles, waardoor het volgende verzoek het model opnieuw laadt met de nieuwe instelling en de laadtijd eenmalig in rekening brengt. Hoe lang een model daarna in het geheugen blijft, is een aparte instelling, die wordt behandeld in een Ollama-model geladen houden tussen verzoeken.
Hoe served, queued en refused eruitzien voor de client
Verstuur meerdere verzoeken tegelijk en meet de tijd. Dit voert acht streaming-verzoeken parallel uit en toont de status en de tijdsduur voor elk verzoek:
for i in $(seq 1 8); do
curl -s -o /dev/null \
-w "req$i http=%{http_code} ttfb=%{time_starttransfer}s total=%{time_total}s\n" \
http://127.0.0.1:11434/api/generate \
-d '{"model":"llama3.2:3b","prompt":"Explain what a KV cache is.","stream":true}' &
done
waitttfb is de tijd tot de eerste byte van de stream. Dit komt dicht in de buurt van de time to first token (TTFT), omdat het eerste gestreamde fragment het eerste token bevat.
Served in parallel. Elk verzoek rapporteert een vergelijkbare ttfb, en total stijgt voor alle verzoeken tegelijk. De GPU wordt gedeeld tussen de actieve slots, waardoor elk antwoord trager is dan wanneer het alleen zou draaien, terwijl er per minuut meer verzoeken worden afgerond. Dit is het regime dat u inkoopt wanneer u OLLAMA_NUM_PARALLEL verhoogt.
Queued. De eerste verzoeken antwoorden snel en de latere verzoeken tonen een grote ttfb, gevolgd door een normale generatie. De wachttijd is de wachtrij, niet het model. Een gebruiker die naar een chatvenster kijkt, ziet een lange lege pauze en daarna tekst op volledige snelheid. Die vorm, traag bij de start en daarna snel, is het kenmerk van een wachtrij in plaats van een overbelaste GPU.
Refused. De client ontvangt vrijwel direct http=503, en de body bevat:
{"error":"server busy, please try again. maximum pending requests exceeded"}Dat bericht betekent dat de wachtrij vol was op het moment dat het verzoek arriveerde. Het zegt niets over VRAM en niets over het model.
Eén eerlijke beperking: Ollama publiceert geen wachtrijdiepte. ollama ps en het /api/ps-eindpunt rapporteren de modellen die geladen zijn, niet de verzoeken die in de wachtrij staan. U meet de wachtrij dus vanaf de clientzijde door de tijd tot de eerste byte te observeren, of u telt de 503-antwoorden bij de component die voor de service is geplaatst.
Waarom een kleinere MAX_QUEUE vaak de betere instelling is
Een wachtrij van 512 klinkt ruim, maar op een enkele slot is dit vrijwel nutteloos. Verzoek 300 wacht achter 299 voltooide generaties. Dat duurt in het gunstigste geval minuten. Elke HTTP-client geeft het al lang daarvoor op, waardoor de aanroeper een client-side timeout ziet. Dit vertelt de gebruiker niets over de oorzaak en geeft uw monitoring geen gegevens om een waarschuwing op te baseren.
Stel de wachtrij in op ongeveer het aantal dat uw server kan verwerken binnen de timeout van uw client; de overloop wordt dan direct een 503-fout. Een 503 is nuttig: een reverse proxy kan het verzoek opnieuw proberen, een client kan wachten (back-off), een dashboard kan de fout tellen en een beheerder kan deze aflezen. Bepaal dit getal op basis van uw eigen metingen. Als een generatie ongeveer tien seconden duurt en uw client zestig seconden wacht, kunnen er ongeveer zes verzoeken per slot binnen dat tijdsbestek worden afgehandeld. Een wachtrij die veel dieper is dan dat, levert alleen maar timeouts op.
Wanneer plaatst u een wachtrij voor Ollama
De ingebouwde wachtrij werkt volgens het principe first-in, first-out (FIFO) en heeft geen inzicht in de identiteit van de aanroeper. Voor één applicatie die met één server communiceert, is dit voldoende; het toevoegen van extra infrastructuur introduceert in dat geval alleen maar extra storingspunten. Kies voor een tussenlaag wanneer een van de volgende situaties van toepassing is:
- U heeft prioriteit nodig. Een interactieve chat mag niet wachten achter een batch-taak voor samenvattingen. De wachtrij van Ollama kent geen prioriteit, dus batch-taken moeten extern worden vastgehouden en gedoseerd worden aangeboden.
- U heeft behoefte aan eerlijke verdeling. Eén client kan de wachtrij volledig vullen, waardoor alle andere gebruikers een 503-foutmelding ontvangen.
- U wilt dat taken een herstart overleven. De wachtrij bevindt zich in het werkgeheugen van de server. Bij een herstart van Ollama gaan alle wachtende verzoeken verloren.
- U heeft behoefte aan echte retries met backoff, die ergens worden vastgelegd zodat u ze achteraf kunt inzien.
De lichte variant is een reverse proxy. In nginx beperkt limit_conn het aantal gelijktijdige verbindingen en begrenst limit_req de aankomstsnelheid per client, waardoor overloop bij de proxy wordt geweigerd en de wachtrij van Ollama nooit bereikt. De zware variant is een taakwachtrij met een database voor een worker die Ollama aanroept; dit is de gewenste oplossing zodra verzoeken een procesherstart moeten overleven. Het dimensioneren hiervan voor daadwerkelijk verkeer is een vak apart: het plannen van een zelfgehoste LLM voor gelijktijdige gebruikers doorloopt de berekeningen, en het draaien van Ollama op een VPS behandelt de basisinstallatie waar deze variabelen van uitgaan.
Wanneer het eerlijke antwoord een andere server is
Er is een limiet die u niet kunt omzeilen door instellingen aan te passen. Ollama splitst de KV-cache in gelijke, vaste slots wanneer het model wordt geladen. Het geheugen van een inactief slot kan niet worden gebruikt door een actief slot, en het aantal slots kan niet worden gewijzigd zonder het model te ontladen. Dat ontwerp is zeer geschikt voor één persoon, een klein team of een coding agent.
Servers die zijn gebouwd voor veel gelijktijdige gebruikers werken anders. Zij wijzen KV-cache toe in kleine pagina's op aanvraag en voegen binnenkomende verzoeken toe aan een batch die al wordt uitgevoerd. Geheugengebruik volgt hierdoor de werkelijke vraag in plaats van een vaste verdeling. Als uw doel een groot aantal gelijktijdige gebruikers op één GPU is, is dat architecturale verschil belangrijker dan welke waarde van OLLAMA_NUM_PARALLEL dan ook. De vergelijking tussen Ollama en vLLM is de plek om die beslissing te nemen. Schakel echter niet over uit principe: een andere server betekent meer beheer, en als uw verkeer uit enkele personen bestaat, is het ingebouwde gedrag het juiste antwoord.
Meet uw eigen doorvoer en tijd tot het eerste token
Gepubliceerde cijfers over tokens per seconde zijn afkomstig van de GPU, het model, de kwantisatie, de contextlengte en de prompt van iemand anders. Niets daarvan komt overeen met uw situatie, dus beschouw elk gelezen getal als een ruwe indicatie en meet de machine die voor u staat.
Ollama geeft timinggegevens terug in het laatste JSON-object van elk antwoord. eval_count is het aantal gegenereerde tokens en eval_duration is de tijd die aan het genereren is besteed, in nanoseconden.
sudo apt install -y jq
curl -s http://127.0.0.1:11434/api/generate \
-d '{"model":"llama3.2:3b","prompt":"Explain what a KV cache is.","stream":false}' \
| jq '{prompt_eval_count, eval_count, eval_duration, tokens_per_second: (.eval_count / (.eval_duration / 1000000000))}'Voer dit uit met één slot en daarna opnieuw met de gelijktijdigheid die u daadwerkelijk verwacht. Vergelijk de twee getallen die bepalen of gebruikers tevreden zijn: de tijd tot het eerste token en het aantal tokens per seconde per verzoek. De doorvoer per verzoek daalt altijd naarmate er meer slots worden toegevoegd. De vraag is of deze verder daalt dan uw gebruikers accepteren. Tokens per seconde meten op een lokale LLM behandelt de methode in meer detail, inclusief hoe u de prompt constant houdt tussen runs.
Een publiek eindpunt met een ruime wachtrij is een doelwit voor denial-of-service-aanvallen
Het instellen van OLLAMA_HOST=0.0.0.0:11434 plaatst de API op elke interface, en Ollama beschikt niet over ingebouwde authenticatie. Een open eindpunt met de standaardwachtrij accepteert 512 wachtende verzoeken van iedereen die het weet te vinden. Het vullen van die wachtrij kost een aanvaller vrijwel niets: lange prompts, geen inlogprocedure, geen rate limiting, geen kosten. Uw eigen gebruikers krijgen vervolgens 503-foutmeldingen of lange wachttijden, terwijl de machine continu belast is.
Houd de listener op loopback en benader deze via een SSH-tunnel of een privénetwerk, of plaats authenticatie en rate limiting vóór de service. Het beveiligen van een Ollama API-eindpunt behandelt beide opties. Pas de wachtrij pas aan nadat dit is geregeld, aangezien een wachtrijlengte een capaciteitsinstelling is en geen enkele vorm van beveiliging biedt.
FAQ
Waarom wacht mijn tweede Ollama-verzoek tot het eerste is voltooid?
Omdat OLLAMA_NUM_PARALLEL standaard op 1 staat, verwerkt een geladen model één verzoek tegelijk en wachten de overige verzoeken in de rij. Het wachtende verzoek houdt de HTTP-verbinding open en verstuurt geen bytes totdat er een slot vrijkomt; voor de client lijkt dit op een traag model. Het verschil is te zien aan het timingpatroon: een lange pauze gevolgd door tekst op volledige snelheid duidt op een wachtrij, terwijl een langzame stroom vanaf het eerste token duidt op een traag model. Verhoog het aantal slots via een systemd drop-in en herstart de service.
Wat betekent "server busy, please try again. maximum pending requests exceeded"?
Dit is de foutmelding voor een overvolle wachtrij van Ollama, die wordt geretourneerd met HTTP-status 503. Het aantal wachtende verzoeken heeft OLLAMA_MAX_QUEUE bereikt (standaard 512), waardoor het nieuwste verzoek werd geweigerd in plaats van toegevoegd. Dit is geen geheugenfout en geen modelfout. Het vergroten van de wachtrij zorgt er alleen voor dat aanroepers langer wachten voordat ze dezelfde weigering krijgen. De echte oplossingen zijn: meer slots toevoegen als u voldoende VRAM heeft, de inkomende belasting verlagen, of een wachtrij voor de service plaatsen die verzoeken kan herhalen en prioriteren.
Wordt Ollama sneller door OLLAMA_NUM_PARALLEL te verhogen?
Nee. Het staat toe dat meer verzoeken tegelijkertijd draaien, waarbij elk verzoek trager is dan wanneer het alleen zou draaien, omdat ze de GPU delen. Het vermenigvuldigt ook de KV-cache, aangezien Ollama de runner start met een totale context die gelijk is aan uw contextlengte vermenigvuldigd met het aantal slots. Als het resultaat niet meer in het VRAM past, verplaatst Ollama lagen naar de CPU en wordt elk verzoek trager, zelfs als er geen andere verzoeken actief zijn. Controleer ollama ps na de wijziging en bevestig dat de kolom PROCESSOR nog steeds 100% GPU aangeeft.
Moet ik Ollama herstarten na het wijzigen van deze variabelen?
Ja. De server leest deze bij het opstarten en een draaiend model behoudt het aantal slots dat bij de start in het runner-proces is vastgelegd. Bewerk de drop-in met sudo systemctl edit ollama.service, voer daarna sudo systemctl daemon-reload en sudo systemctl restart ollama uit. Bevestig dit met systemctl show ollama --property=Environment en controleer de regel server config in journalctl -u ollama, waarin de omgeving staat die de server daadwerkelijk heeft geladen.
Hoeveel parallelle slots moet ik instellen?
Begin bij 1 en verhoog dit stap voor stap. Herstart na elke stap Ollama, stuur één verzoek om het model te laden en voer ollama ps uit. Stop bij de laatste waarde waarbij PROCESSOR nog steeds 100% GPU aangeeft en de kolom SIZE voldoende ruimte overlaat voor de langste context die u aanbiedt. Meet vervolgens de tijd tot het eerste token en het aantal tokens per seconde bij die instelling onder uw werkelijke gelijktijdigheid, en verlaag het aantal met één stap als de snelheid per verzoek onder het niveau zakt dat uw gebruikers tolereren.