SSD Nodes Learn Hosting plans →
Anleitungen Matt ConnorVon Matt Connor · Aktualisiert 2026-10-26

Warum Ihr LLM bei 5 Benutzern stockt

Ein Benutzer ist schnell, fünf warten? Ollama verarbeitet standardmäßig nur 1 Anfrage parallel. Erfahren Sie, wie Batching, KV-Cache, Prefill und Warteschlangen die Kapazität begrenzen.

Warum wird ein selbst gehostetes LLM langsamer, wenn mehr Benutzer hinzukommen?

Wenn ein selbst gehostetes LLM bei 5 gleichzeitigen Benutzern ins Stocken gerät, liegt das meist daran, dass der Server so eingestellt ist, dass er jeweils nur eine Antwort generiert und die anderen vier in einer Warteschlange stehen. Die Dokumentation von Ollama formuliert den Standardwert eindeutig: OLLAMA_NUM_PARALLEL ist „die maximale Anzahl paralleler Anfragen, die jedes Modell gleichzeitig verarbeitet, standardmäßig 1“. Es ist nichts defekt, und die Serving-Software kann mehrere Anfragen gleichzeitig bearbeiten. Vier von fünf Personen warten auf ihre Bearbeitung, weil dies eine Einstellung vorgibt.

Die Lösung ist nur selten ein leistungsfähigerer Server. Erforderlich ist eine Serving-Engine, die viele Anfragen im selben Forward Pass durch das Modell verarbeitet, sowie ausreichend freier Speicher, um währenddessen die Konversationen aller Benutzer vorzuhalten. Beide Komponenten sind wichtig. Die zweite legt tatsächlich die Obergrenze fest.

Die beiden Phasen jeder Anfrage

Prefill liest den gesamten Prompt auf einmal und baut dafür den Attention-Cache auf. Jeder Prompt-Token durchläuft das Modell gemeinsam mit den anderen Tokens. Deshalb ist Prefill eine große Matrixmultiplikation und wird durch den Rechendurchsatz begrenzt. Decode erzeugt die Antwort anschließend jeweils für einen Token. Für jeden Token müssen die vollständigen Gewichte des Modells erneut aus dem Speicher gelesen werden, während die für diesen einzelnen Token ausgeführten Berechnungen gering sind. Decode wird durch die Speicherbandbreite begrenzt.

Diese Asymmetrie ist der eigentliche Grund, warum Batching funktioniert. Beim Decodieren für einen Benutzer werden beispielsweise pro Token 5 GB an Gewichten gelesen, während die meisten Recheneinheiten ungenutzt bleiben. Kommt eine zweite Anfrage hinzu, liest die Engine dieselben 5 GB einmal und berechnet anschließend daraus zwei Tokens. Der zweite Benutzer verursacht dadurch kaum zusätzliche Laufzeit. Wenn Anfragen strikt nacheinander verarbeitet werden, geht dieser Vorteil verloren.

Zwei Kennzahlen bestimmen, wie ein Benutzer die Leistung wahrnimmt. TTFT (time to first token) ist die Wartezeit in der Warteschlange plus Prefill. ITL (inter-token latency) ist der Abstand zwischen den gestreamten Tokens und wird durch Decode bestimmt. Ein langsamer Server ist meist bei einer dieser Kennzahlen langsam, und die erforderlichen Anpassungen sind nicht identisch. Sie sollten daher zunächst feststellen, gegen welche dieser beiden Größen Sie ankämpfen, bevor Sie Einstellungen ändern. Prefill und Decode getrennt messen zeigt Ihnen, welche davon betroffen ist.

Statisches Batching lässt alle auf die langsamste Antwort warten

Statisches Batching ist die naive Variante. Sie erhalten es, wenn Sie Anfragen selbst im Anwendungscode gruppieren. Die Engine sammelt N Anfragen, verarbeitet sie gemeinsam und hält jeden Slot belegt, bis die längste Generierung in der Gruppe abgeschlossen ist.

Ein Benutzer, der eine Zusammenfassung mit 1,200 Tokens anfordert, hält vier einzeilige Antworten im Batch fest, weil der Batch keinen Slot freigibt, bevor sein langsamstes Element abgeschlossen ist.

Daraus ergeben sich zwei Nachteile. Abgeschlossene Sequenzen belegen weiterhin Slots, obwohl sie keine nützliche Rechenarbeit mehr ausführen. Dadurch sinkt der effektive Durchsatz, wenn die Ausgabelängen variieren. Bei Chat-Anfragen unterscheiden sich die Ausgabelängen häufig stark. Eine Anfrage, die einen Schritt nach der Bildung des Batch eintrifft, wartet, bis der gesamte Batch abgearbeitet ist, bevor ihr Prefill überhaupt beginnt. Dadurch wird ihr TTFT durch den Essay eines anderen Benutzers bestimmt.

Continuous Batching nimmt in jedem Token-Schritt Anfragen auf und entfernt sie

Continuous Batching plant auf der Ebene eines einzelnen Decoding-Schritts. Nach jedem Schritt entfernt der Scheduler Sequenzen, die gerade ihr Stop-Token ausgegeben haben, und nimmt wartende Anfragen in die freien Slots auf. Eine Antwort, die in Schritt 40 endet, gibt ihren Slot in Schritt 40 frei, nicht erst am Ende eines Batches.

Das ist kein exotisches Verfahren. llama-server dokumentiert -cb, --cont-batching als „whether to enable continuous batching (a.k.a dynamic batching) (default: enabled)“, führt „Parallel decoding with multi-user support“ als Feature auf und startet seit einer im November 2025 zusammengeführten Änderung standardmäßig mit 4 Slots (-np steht standardmäßig auf -1, also automatisch). vLLM basiert auf diesem Konzept. Auch Ollama verarbeitet parallele Anfragen. Die Standardeinstellung begrenzt die Anzahl lediglich auf eins. Deshalb schließen viele daraus, dass ihre Hardware keine Parallelität unterstützt, obwohl ihre Konfiguration dies verhindert.

Veröffentlichte Ergebnisse zu Continuous Batching werden meist auf Datacenter-Karten gemessen, die sowohl freie Rechenkapazität als auch mehrere zehn Gigabyte für den Cache haben. Die Form dieser Ergebnisse lässt sich auf Ihr System übertragen. Ihre Größenordnung jedoch nicht. Warum das so ist, erklärt der folgende Abschnitt zum Speicherbedarf.

Prefill konkurriert mit Decode um dieselben Rechenressourcen

Wenn eine neue Anfrage eingeht, während vier Antworten gestreamt werden, muss ihr Prompt zuerst vorverarbeitet werden. Prefill ist rechenintensiv. Gibt der Scheduler diesem Prefill einen eigenen Schritt, erhalten die vier Nutzer währenddessen kein Token. Bei einem langen Prompt ist das in jedem geöffneten Fenster als sichtbare Pause bemerkbar. Das ist das Stottern, das gemeint ist, wenn der Server jedes Mal kurz stockt, sobald jemand anderes auf „Senden“ klickt.

Chunked Prefill teilt einen langen Prompt in Abschnitte auf und verarbeitet jeden Abschnitt im selben Schritt wie die laufenden Decodes. Der Tuning-Leitfaden von vLLM beschreibt den Zielkonflikt direkt: Kleinere Chunk-Budgets „achieve better ITL because there are fewer prefills slowing down decodes“, während höhere Werte „achieve better time to first token (TTFT) as you can process more prefill tokens in a batch“. Sie entscheiden, wessen Nutzungserlebnis geschützt werden soll: das der Person, die auf den Beginn einer Antwort wartet, oder das der Personen, die den Text beim Streamen beobachten.

Die Prompt-Länge bestimmt, wie stark sich dies auswirkt. Ein Prompt mit 6,000 Token und einer Antwort mit 200 Token verursacht 6,000 Token Prefill-Arbeit gegenüber 200 Decode-Schritten. Retrieval-augmented Chat und lange System-Prompts führen beide in diesen Bereich. Prefill ist dann kein vernachlässigbarer Anteil mehr, sondern der Vorgang, auf den die Nutzer warten. Prefix-Caching hilft, wenn sich der lange Teil wiederholt: vLLM stellt --enable-prefix-caching bereit. Damit wird der Cache für ein gemeinsames Prompt-Präfix wiederverwendet, anstatt es für jede Anfrage neu zu berechnen.

Der KV-Cache läuft zuerst voll

Jedes Token in jeder aktiven Konversation hinterlegt in jeder Schicht des Modells einen Key-Vektor und einen Value-Vektor. Das ist der KV-Cache (Key/Value-Cache). Er verhindert, dass beim Dekodieren für jedes neue Token der gesamte Prompt erneut berechnet werden muss. Die Anzahl der Cache-Werte pro Token ist durch die Modellstruktur festgelegt: 2 (ein Key und ein Value) mal die Anzahl der Schichten, mal die Anzahl der Key/Value-Heads, mal die Head-Dimension. Lesen Sie diese Werte aus dem config.json des Modells aus. Multiplizieren Sie sie mit der Byte-Anzahl pro Wert, um die Größe zu berechnen. Dieser letzte Faktor ist eine Laufzeiteinstellung und kein Bestandteil des Modells: llama-server speichert den Cache standardmäßig in f16 (2 Byte) und unterstützt über -ctk und -ctv auch kleinere Datentypen wie q8_0.

Rechnen Sie es einmal durch, dann ist die Obergrenze keine unbekannte Größe mehr. Ein typisches 8B-Modell mit 36 Schichten, 8 Key/Value-Heads und einer Head-Dimension von 128 benötigt bei einem 16-Bit-Cache pro Token 2 36 8 128 2 Byte. Das sind 147,456 Byte, also ungefähr 144 KiB. Eine Konversation mit 8,192 Token benötigt daher etwa 1.2 GB Cache. Fünf solche Konversationen benötigen zusätzlich zu den Gewichten ungefähr 6 GB. Das ist die entscheidende Größe dafür, wie viele Benutzer gleichzeitig unterstützt werden.

Parallele Anfragen vervielfachen den Kontext. Die Werkzeuge dokumentieren das ausdrücklich. In der FAQ von Ollama heißt es: "Parallel request processing for a given model results in increasing the context size by the number of parallel requests. For example, a 2K context with 4 parallel requests will result in an 8K context and additional memory allocation." Der benötigte Arbeitsspeicher skaliert mit OLLAMA_NUM_PARALLEL multipliziert mit OLLAMA_CONTEXT_LENGTH. In llama-server führt die standardmäßige automatische Slot-Anzahl jeden Slot in einem gemeinsamen KV-Puffer aus. Der gesamte -c-Kontext bildet dadurch einen einzigen Pool, aus dem die Slots Speicher beziehen. Wenn Sie -np selbst setzen, ist der gemeinsame Puffer deaktiviert, sofern Sie nicht zusätzlich --kv-unified übergeben. Der mit -c angeforderte Kontext wird dann auf die -np Slots verteilt. Wenn Sie nur die Slot-Anzahl erhöhen, verringert sich dadurch der Kontext, den jede Anfrage halten kann. Lesen Sie den Kontext pro Slot aus dem Start-Log aus, statt ihn anzunehmen.

vLLM reserviert den Speicher dagegen vorab. --gpu-memory-utilization (standardmäßig 0.92) ist "the fraction of GPU memory to be used for the model executor". Wenn Sie --kv-cache-memory-bytes nicht setzen, leitet vLLM die Größe des KV-Caches aus diesem Anteil ab. Der Teil des Budgets, der nach Abzug der Gewichte und des vom Engine-Profiling ermittelten Arbeitsspeichers übrig bleibt, wird zum paged KV-Pool. Wenn dieser Pool nicht mehr ausreicht, verdrängt der Scheduler eine Anfrage, statt mit einem Fehler abzubrechen:

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.

In der V1-Engine von vLLM ist der standardmäßige Preemption-Modus RECOMPUTE. Eine verdrängte Anfrage verwirft daher ihren Cache und führt beim erneuten Einplanen den Prefill erneut aus. Diese Arbeit fällt zweimal an. Die Dokumentation warnt: "preemption and recomputation can adversely affect end-to-end latency". Diese Logzeile erklärt am besten, warum ein einzelner Benutzer deutlich länger warten musste, obwohl der Durchschnittswert unauffällig war. Setzen Sie disable_log_stats=False, um die kumulierte Anzahl zu protokollieren, oder lesen Sie den Preemption-Zähler aus den Prometheus-Metriken aus, die vLLM bereitstellt.

Änderungen bei 2, 5 und 20 gleichzeitig aktiven Benutzern

Zwei Benutzer. Auf einer GPU mit ausreichendem Cache ist die zusätzliche Last nahezu nicht wahrnehmbar, weil der zweite Decodierungsstream den ersten mit sehr geringem Mehraufwand begleitet. Auf einer CPU-only-VPS mit 4 bis 8 GB RAM ist sie dagegen nicht kostenlos: Beide Streams teilen sich dieselben wenigen vCPUs und dieselbe RAM-Bandbreite. Daher sieht jeder Benutzer ungefähr halb so viele Tokens pro Sekunde, und der Cache-Bedarf verdoppelt sich bei einem deutlich kleineren verfügbaren Budget.

Fünf Benutzer. Ab hier reichen die Standardwerte nicht mehr aus. Zunächst entsteht ein Warteschlangenproblem. Bei OLLAMA_NUM_PARALLEL auf 1 warten vier Personen auf diejenige, die die lange Antwort angefordert hat. Sobald sie an der Reihe sind, sehen sie jeweils die normale Geschwindigkeit. Erhöhen Sie die Anzahl der parallelen Verarbeitungen, verändert sich das Problem: Fünf Slots mit jeweils 8K Kontext benötigen einen Cache für 40K Tokens. Passt dieser nicht in den VRAM, lagert die Engine Layer in den System-RAM aus. Passt er auch dort nicht hinein, verwendet das System Swap, und die Anzahl der Tokens pro Sekunde bricht ein.

Zwanzig Benutzer. Zwanzig Menschen in einer Chat-Oberfläche bedeuten normalerweise nicht zwanzig gleichzeitig aktive Anfragen. Das ist der wichtigste Punkt, den Sie vor dem Kauf der Hardware verstehen sollten. Eine Person liest eine Antwort und wartet zwischen den Eingaben 20 bis 60 Sekunden. Der größte Teil ihrer Sitzung ist daher inaktiv. Zwanzig Agenten oder zwanzig Aufgaben zur Dokumentzusammenfassung erzeugen dagegen zwanzig echte Streams ohne Leerlauf. Dafür ist eine andere Maschine erforderlich. Ein Entwickler, der einen Coding-Agent auf seinen eigenen Ollama-Server angesetzt hat, liegt näher am zweiten Fall als am ersten. Der Agent sendet so lange weitere Anfragen, wie die Aufgabe läuft, und lässt die Lesepausen eines Menschen vollständig aus.

Sind Ihre Benutzer gleichzeitig aktiv oder nur angemeldet?

Ermitteln Sie zunächst die gleichzeitig laufenden Anfragen, bevor Sie die Größe festlegen. Die Berechnung ist einfach: gleichzeitig laufende Anfragen entsprechen der Anzahl der Benutzer multipliziert mit der Generierungsdauer pro Durchlauf und geteilt durch die Zeit zwischen den Durchläufen.

  1. Messen Sie zuerst Ihre eigene Geschwindigkeit für einen einzelnen Datenstrom, sowohl beim Prefill als auch beim Decode. Übernehmen Sie keinen Wert von einer fremden Karte: messen Sie die Token pro Sekunde auf Ihrem eigenen System und verwenden Sie den ermittelten Wert.
  2. Schätzen Sie den Auslastungszyklus. Zwanzig Chat-Benutzer mit 12 Sekunden Generierungsdauer pro Durchlauf und einem Durchlauf alle 90 Sekunden ergeben 20 * 12 / 90, also etwa 2.7 gleichzeitig laufende Anfragen.
  3. Legen Sie die Anzahl der Slots etwas höher fest und prüfen Sie sie anschließend anhand des Speichers: Die Anzahl der Slots multipliziert mit dem Kontext pro Anfrage muss in die tatsächlich verfügbaren Cache-Tokens passen.
  4. Halten Sie die Warteschlange kurz, damit ein Überlauf schnell und sichtbar fehlschlägt.

Die verfügbaren Cache-Tokens entsprechen dem freien Speicher nach dem Laden der Gewichte, geteilt durch den Token-Speicherbedarf aus dem vorherigen Abschnitt. Eine 24-GB-Karte mit einem 8B-Modell in 16-bit verwendet etwa 16 GB für die Gewichte. Bei der standardmäßigen Auslastung stehen dadurch höchstens ungefähr 6 GB nutzbarer Cache zur Verfügung. Sobald Arbeitsspeicher reserviert wurde, ist es etwas weniger. Das entspricht etwa fünf 8K-Konversationen. Um mehr Konversationen unterzubringen, verkürzen Sie den Kontext pro Anfrage oder speichern Sie den Cache in 8-bit (llama-server benötigt --cache-type-k q8_0). Beides erhöht die gleichzeitige Verarbeitung, erfordert aber einen Verzicht an anderer Stelle. Diese Abwägung sollten Sie ehrlich prüfen, bevor Sie Geld in Hardware investieren: wann sich ein GPU VPS gegenüber API-Tokens amortisiert.

Wenn Ollamas Standardwerte nicht mehr ausreichen

Erhöhen Sie die Anzahl der parallelen Anfragen über die Service-Unit, weil ein Export in der Shell einen von systemd verwalteten Daemon nicht erreicht.

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 ps

systemctl show sollte die drei Variablen ausgeben, die Sie gerade gesetzt haben. Falls das nicht geschieht, wurde das Drop-in nicht gespeichert, und alle weiteren Schritte bleiben wirkungslos. ollama ps listet anschließend das geladene Modell mit einer Größe auf, die über die reinen Gewichte hinausgeht, weil vier Slots mit jeweils 8,192 Tokens zusätzlich 32,768 Tokens Cache reservieren. Eine PROCESSOR-Spalte, die einen Teil des Modells auf der CPU ausweist, obwohl Sie mit einem vollständigen Laden auf der GPU gerechnet haben, bedeutet, dass Sie mehr Cache angefordert haben, als auf der Karte noch verfügbar war. Verringern Sie eine der beiden Zahlen. Die Verringerung des Kontexts ist normalerweise die sicherere Option. Ein zu kleines Fenster schneidet lange Prompts jedoch stillschweigend ab, statt einen Fehler auszugeben. Daher sollten Sie num_ctx gezielt dimensionieren, statt den Wert so lange zu reduzieren, bis das Modell passt.

Der Standardwert für die Warteschlange verdient eine genauere Betrachtung. Ollama reiht bis zu OLLAMA_MAX_QUEUE Anfragen ein, und „der Standardwert ist 512“. Darüber hinaus antwortet es „mit einem 503-Fehler, der angibt, dass der Server überlastet ist“. Eine Warteschlange mit 512 Einträgen ist auf einem System, das vier Anfragen gleichzeitig verarbeitet, ein Versprechen, das Sie nicht einhalten können, weil der Client an Position 300 lange vor seinem Aufruf einen Timeout erreicht. Eine kurze Warteschlange gibt einen Fehler zurück, den Ihre Anwendung erneut versuchen oder melden kann. Das ist besser als ein Ladeindikator, der nie verschwindet.

Testen Sie die Einstellung unter realen Bedingungen. Senden Sie aus zwei Terminals gleichzeitig jeweils eine Anfrage und beobachten Sie beide. Wenn die zweite Anfrage erst dann eine Ausgabe erzeugt, wenn die erste abgeschlossen ist, wurde die Einstellung für parallele Anfragen nicht übernommen.

Wann sich eine echte Serving-Engine amortisiert

vLLM rechtfertigt den zusätzlichen Einrichtungsaufwand, wenn Sie eine GPU mit freien Kapazitäten haben und tatsächlich mehr als ungefähr vier Anfragen gleichzeitig verarbeitet werden. Der Scheduler arbeitet tokenweise, der Cache ist seitenweise organisiert, sodass freie Fragmente wiederverwendet werden, und freier VRAM wird in Parallelität umgewandelt, statt ungenutzt zu bleiben. Seit October 2026 besteht die dokumentierte GPU-Installation und der Start aus drei Befehlen. vllm download-kernels ruft vorkompilierte Kernel ab, die vLLM sonst beim Start herunterladen und kompilieren würde:

uv pip install vllm --torch-backend=auto
vllm download-kernels
vllm serve Qwen/Qwen2.5-1.5B-Instruct
curl 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."}]
    }'

Eine Antwort mit einem choices-Array bedeutet, dass der Server läuft und das Modell geladen ist. Unter Last sind die beiden wichtigen Parameter --max-num-seqs, die „maximale Anzahl der Sequenzen, die in einer einzelnen Iteration verarbeitet werden“, und --max-num-batched-tokens, die „maximale Anzahl der Tokens, die in einer einzelnen Iteration verarbeitet werden“. Der erste Parameter begrenzt die Parallelität. Der zweite legt das zuvor beschriebene Budget für Chunked Prefill fest.

Bei weniger als ungefähr vier gleichzeitig verarbeiteten Anfragen verursacht vLLM zusätzliche Komplexität und bringt wenig Nutzen. Eine GPU ist nicht mehr erforderlich: Seit October 2026 dokumentiert der CPU-Installationsleitfaden „grundlegende Modellinferenz und Serving“ auf x86- und Arm-CPUs. Vorgefertigte x86-Wheels gibt es seit Version 0.17.0 sowie ein CPU-Docker-Image. Das Speicherverhalten bleibt jedoch gleich. Auf der CPU verwendet vLLM denselben Auslastungsanteil von 0.92 für den Arbeitsspeicher des Systems und weist dem KV-Cache den Speicher zu, der nach dem Laden der Gewichte übrig bleibt. Standardmäßig beansprucht vLLM daher beim Start den größten Teil des Arbeitsspeichers, sofern Sie den Cache nicht mit --kv-cache-memory-bytes begrenzen. Auf einem VPS mit 4 bis 8 GB ist das der falsche Kompromiss. Dort ist ein kleineres Modell mit kürzerem Kontext und einer von Ihnen kontrollierten Warteschlange die bessere Lösung. wie sich Ollama und vLLM als Serving-Engines unterscheiden behandelt diese Auswahl vollständig. Qwen 3 8B auf einem VPS ausführen zeigt, welche Anforderungen ein mittelgroßes Modell stellt, bevor Sie auch nur einen weiteren Benutzer hinzufügen.

Der Zielkonflikt, den die gängige Überlieferung verschweigt

Continuous Batching erhöht den Gesamtdurchsatz und verbessert in der Regel auch die mediane Latenz, weil eine eingereihte Anfrage früher startet. Die Tail-Latenz entwickelt sich jedoch in die entgegengesetzte Richtung. Dieser Aspekt wird nur selten erwähnt.

Jede zusätzliche Sequenz in einem Schritt verursacht etwas mehr Arbeit. Deshalb steigt die ITL für alle, sobald sich der Batch füllt. Das Prefill einer neu eingegangenen Anfrage beansprucht einen Teil eines Schritts, der den bereits streamenden Benutzern sonst zur Verfügung gestanden hätte. Unter Cache-Druck führt der Scheduler eine Präemption durch. Dadurch wird eine teilweise generierte Anfrage an den Anfang ihres Prefills zurückgesetzt.

Eine Chat-Oberfläche macht die Tail-Latenzen sichtbar, nicht die Durchschnittswerte. Ein Stream, der mitten im Satz zwei Sekunden pausiert, wirkt fehlerhaft, selbst wenn die Gesamtzeit bis zum Abschluss gut ist. Messen Sie p95 TTFT und p95 ITL unter der erwarteten Last. Betrachten Sie die mittlere Tokenrate pro Sekunde als Kapazitätswert und nicht als Beschreibung der tatsächlichen Nutzungserfahrung.

Daraus ergibt sich die praktische Einstellung. Begrenzen Sie die Parallelität etwas unterhalb dessen, was der Speicher zulässt, damit die Engine nie eine Präemption durchführen muss. Eine kurze, vorhersehbare Warteschlange ist besser als ein tiefer Batch, der thrashing verursacht. Ein Benutzer, der vier Sekunden wartet und danach einen gleichmäßigen Stream erhält, ist zufriedener als ein Benutzer, dessen Stream sofort startet und anschließend zweimal stockt.

Was bei langsamer Verarbeitung zu prüfen ist

Jeder einzelne Benutzer ist unauffällig, aber die Wartezeit ist lang. Das ist eine Warteschlange, kein Geschwindigkeitsproblem. Prüfen Sie zuerst die Einstellung für die Parallelverarbeitung. Das Modell verarbeitet die Anfragen korrekt, jedoch eine nach der anderen.

HTTP 503 von Ollama. Die Warteschlange ist voll. Entweder ist der Server tatsächlich ausgelastet, oder OLLAMA_MAX_QUEUE ist absichtlich niedrig gesetzt, um die Last zu reduzieren. Genau das soll diese Einstellung bewirken.

Die Tokens pro Sekunde brechen unter Last auf einem CPU-Server ein. Führen Sie währenddessen vmstat 1 aus. Werte ungleich 0 in den Spalten si und so bedeuten, dass der Rechner den Swap verwendet. Die Gewichte werden dann für jedes Token vom Datenträger gelesen. Keine Konfigurationsänderung kann das ausgleichen. Verwenden Sie ein kleineres Modell oder reduzieren Sie die Anzahl der Slots.

Einer von zehn Benutzern wartet deutlich länger als die übrigen. Suchen Sie im vLLM-Log nach preempted. Preemption und die anschließende Neuberechnung sind in der Regel die Ursache. Das bedeutet, dass der Cache für die zulässige Kontextlänge zu klein ist.

TTFT ist schlecht, obwohl der Server im Leerlauf ist. Das betrifft das Prefill, nicht die Parallelverarbeitung. Lange Prompts benötigen bereits vor dem ersten Token erhebliche Zeit. Prüfen Sie daher zunächst die Promptgröße und das Prefix-Caching, bevor Sie die Hardware untersuchen. Tritt die lange Wartezeit nur beim ersten Benutzer nach einer längeren Ruhephase auf und sind alle nachfolgenden Anfragen unauffällig, handelt es sich nicht um Prefill. In diesem Fall hat Ollama das Modell entladen und liest die Gewichte erneut vom Datenträger. Das lässt sich ausschließen, indem Sie das Modell zwischen Anfragen im Speicher halten.

FAQ

Warum wird mein selbst gehostetes LLM langsamer, wenn eine zweite Person es verwendet?

Meistens wird es überhaupt nicht langsamer. Die Anfrage wird in eine Warteschlange gestellt. Ollama wird mit OLLAMA_NUM_PARALLEL auf 1 ausgeliefert, daher wartet die zweite Anfrage, bis die erste ihr letztes Token erzeugt hat. Unterscheiden Sie die beiden Fälle, indem Sie den Token-Stream eines Benutzers messen, während ein anderer wartet: Wenn die Tokens pro Sekunde nach dem Start normal sind, liegt eine Warteschlange vor, und eine Erhöhung der Anzahl paralleler Anfragen behebt das Problem. Wenn beide Streams mit halber Geschwindigkeit laufen, teilen sie tatsächlich die Speicherbandbreite. Das ist eine Hardwaregrenze.

Wie viele gleichzeitige Benutzer kann eine kleine GPU bedienen?

Zählen Sie den Speicher, nicht die Benutzer. Zuerst kommen die Gewichte, danach der KV-Cache. Dieser benötigt pro Token und pro aktiver Konversation 2 mal Layer mal Key/Value-Heads mal Head-Dimension mal Bytes. Ein typisches 8B-Modell mit 36 Layern, 8 Key/Value-Heads und einer Head-Dimension von 128 benötigt im 16-Bit-Format etwa 144 KiB pro Token. Eine Konversation mit 8,192 Tokens benötigt daher ungefähr 1.2 GB. Auf einer 24-GB-Karte, die dieses Modell im 16-Bit-Format hält, bleiben höchstens etwa 6 GB für den Cache übrig. Das reicht für ungefähr fünf Konversationen mit vollständig ausgeschöpftem Kontext oder für mehr Konversationen bei kürzerem Kontext.

Macht Continuous Batching die Antwort für jeden Benutzer langsamer?

Die mediane Latenz verbessert sich normalerweise, weil Anfragen nicht mehr warten müssen, bis ein kompletter Batch fertig ist. Die Tail-Latenz verschlechtert sich. Jede zusätzliche Sequenz erzeugt bei jedem Decoding-Schritt weiteren Aufwand. Das Prefill einer neu eintreffenden Anfrage beansprucht einen Teil eines Schritts, der sonst den Benutzern mit laufendem Stream zur Verfügung stünde. Eine unterbrochene Anfrage muss außerdem zweimal ein Prefill durchführen. Messen Sie die p95-Latenz zwischen Tokens, nicht den Durchschnitt. In einem Chatfenster sind Pausen deutlich sichtbar, während der Durchschnitt sie verschleiert.

Sollte ich OLLAMA_NUM_PARALLEL erhöhen oder zu vLLM wechseln?

Erhöhen Sie zuerst die Anzahl paralleler Anfragen. Das kostet nichts, erfordert nur eine Drop-in-Datei und behebt den häufigen Fall, dass vier Personen hinter einer langen Antwort warten. Der Speicher ist die Begrenzung: Parallele Anfragen vervielfachen den Kontext, den Sie vorhalten müssen. Achten Sie daher darauf, ob Layer auf die CPU ausgelagert werden. Wechseln Sie zu vLLM, wenn Ihre GPU noch VRAM frei hat und tatsächlich mehr als ungefähr vier Anfragen gleichzeitig verarbeitet werden. Ab diesem Punkt bringen der paged Cache und die Token-basierte Planung mehr Nutzen, als sie Kosten verursachen.

Beheben zusätzliche CPU-Kerne einen langsamen LLM-Server?

Nicht den Teil, den Benutzer am stärksten wahrnehmen. Beim Decoding wird das gesamte Modell für jedes Token aus dem Speicher gelesen. Daher ist die Geschwindigkeit durch die RAM-Bandbreite begrenzt. Zusätzliche Kerne helfen nicht mehr, sobald die Bandbreite ausgelastet ist. Das Prefill skaliert mit der Anzahl der Kerne. Mehr Kerne verkürzen daher bei langen Prompts die Zeit bis zum ersten Token. Auf einer VPS mit 4 bis 8 GB ist meistens die Speicherkapazität der begrenzende Faktor. Die wirksame Lösung ist dann ein kleineres Modell oder ein kürzerer Kontext und nicht mehr vCPUs.

War dieser Artikel hilfreich?