Zwei Boxen der DGX-Spark-Klasse, ein Modell: eine Kopie auf jeder schlägt das Aufteilen
Ops
Sieben Wochen lang lief unser lokales Sprachmodell aufgeteilt über zwei NVIDIA GB10-Maschinen mit Tensor-Parallelismus. Am 22. Oktober haben wir das durch eine vollständige Kopie des Modells auf jeder Maschine und einen Least-Connection-Proxy davor ersetzt. Der Durchsatz stieg von etwa 180 auf 210 Tokens pro Sekunde, und jede Maschine kann jetzt neu gestartet werden, ohne dass das Modell verschwindet.
Warum wir es aufgeteilt hatten
Jede Maschine hat 128 GB Speicher, die sich CPU und GPU teilen. Im September passte das Modell auf eine Maschine, aber sein Cache kaum: Der vLLM-Build, den wir verwendeten, konnte den KV-Cache dieses Modells nicht in FP8 halten, daher war der Cache in BF16, und eine Maschine hatte Platz für 499.110 Tokens davon. Das sind weniger als zwei Anfragen beim vollen Kontext des Modells von 262.144 Tokens. Aufgeteilt über beide Maschinen mit Tensor-Parallelismus über ihre direkte Netzwerkverbindung wuchs der Cache auf mehr als drei Millionen Tokens. Wir hatten das Modell für Platz aufgeteilt, nicht für Geschwindigkeit.
Was sich geändert hat
Ein neuerer 4-Bit-Build desselben Modells (NVFP4, erstellt mit quantisierungsbewusster Distillation) benötigt etwa 71 GiB Speicher, und ein Community-vLLM-Build für GB10 (eugr/spark-vllm-b12x) führt seinen Cache in FP8. Jetzt hält eine Maschine das gesamte Modell und einen Cache von 0,76 bis 1,08 Millionen Tokens, Platz für 2,9 bis 4,1 Anfragen bei vollem Kontext, abhängig davon, wie viel Speicher die Maschine bereitstellt. Beide Kopien nutzen das eigene spekulative Decoding des Modells (MTP, vier Draft-Tokens). Vor dem Wechsel haben wir unseren Tool-Calling-Test auf dem neuen Build ausgeführt: Er erzielte 86 Punkte, der ersetzte Build 75.
Was wir gemessen haben
| Aufgeteilt über zwei Maschinen | Eine Kopie auf jeder Maschine | |
|---|---|---|
| KV-Cache | mehr als 3 Millionen Tokens | 0,76 und 1,08 Millionen Tokens |
| Anfragen bei vollem Kontext | etwa 12 | 2,9 und 4,1 |
| Durchsatz unter unserer Last | etwa 180 Tokens/s | 210 Tokens/s (111 + 99) |
| Start | etwa 20 Minuten | 5 bis 13 Minuten pro Kopie |
| Eine Maschine startet neu | das Modell ist down | die andere Kopie bedient |
Ein einzelnes Exemplar für sich, gemessen an der Anzahl der gleichzeitig bedienten Anfragen: Bei kurzen Prompts ergab 1 Anfrage 36 Tokens pro Sekunde, 4 ergaben 82, 8 ergaben 109 und 16 ergaben 150. Bei den längeren Prompts unseres E-Mail-Agents ergaben 4 Anfragen 81, 8 ergaben 113 und 16 nur 87: Ab acht solchen Anfragen wurde es mit weiteren Anfragen langsamer.
An einem Nachmittag nahm ein Exemplar maximal 12 Anfragen gleichzeitig an, das andere 8. Das erste lieferte 91 bis 93 Tokens pro Sekunde und erledigte 26 bis 27 Anfragen pro Minute; das zweite 81 bis 83 Tokens pro Sekunde und 22 Anfragen pro Minute. Beide nehmen jetzt 12 an.
Was wir aufgegeben haben
Speicherplatz. Das aufgeteilte Modell hatte einen Cache mit mehr als drei Millionen Tokens; die Exemplare haben zwei kleinere, und eine Anfrage kann nur den Cache des Exemplars nutzen, das sie bedient. Unsere Agents senden viele kurze und mittellange Anfragen, und für sie war der Durchsatz wichtiger. Wenn Sie wenige sehr lange Kontexte gleichzeitig bedienen, ist die Aufteilung möglicherweise immer noch die bessere Wahl. Wir haben die aufgeteilte Konfiguration behalten, und das Zurückschalten ist ein einziges Skript.
Was beim Wechsel schiefging
- Elf Minuten ohne Modell, dann 30 Sekunden lang 502er-Fehler. Das Split-Modell musste stoppen, bevor eine Kopie auf denselben Maschinen geladen werden konnte, sodass unsere Agenten etwa elf Minuten warteten. Als die erste Kopie hochkam, antwortete der Proxy noch etwa 30 Sekunden lang mit „502 no live upstreams“: Er hatte die Backends als ausgefallen markiert, während sie unten waren (
max_fails=3,fail_timeout=30s), und versuchte sie erst nach Ablauf dieser Zeit erneut. - Ein Client, der den Proxy übersprang. Einer unserer Batch-Jobs hatte die Adresse der ersten Maschine in seiner Konfiguration, sodass seine gesamte Last an ein Exemplar ging, während das andere Kapazität übrig hatte. Jeder Client geht jetzt über den Proxy; die Adressen der Maschinen selbst sind nur für Health Checks.
- Metriken, die sprunghaft anstiegen. Unser Durchsatz-Monitor las die
/metricsvon vLLM über den Proxy. Bei zwei Backends stammten aufeinanderfolgende Lesevorgänge von unterschiedlichen Kopien, die Zähler sprangen hin und her, und der Monitor meldete das Modell als ausgehungert. Er liest nun jede Kopie direkt und addiert die Werte. - Ein alter Watchdog, der die neue Kopie gestoppt hätte. Die Split-Konfiguration hatte einen Watchdog, der seinen Dienst neu startete, wenn das Modell nicht mehr antwortete. Der neue Dienst deklariert
Conflicts=mit dem alten, sodass dieser Neustart die neue Kopie gestoppt hätte. Er musste mitsystemctl disable --nowdeaktiviert werden, nicht nur gestoppt, da unsere Ops-Ebene Units neu startet, die aktiviert, aber nicht laufen. - Speicher auf der Maschine, die andere Aufgaben erledigt. Eine Maschine führt auch unsere Datenbanken und Website-Builds aus. Bei einer
gpu-memory-utilizationvon 0,78 für vLLM blieben nur noch 5 GiB für alles andere, also senkten wir den Wert auf 0,74 und starteten nur diese Kopie neu, während die andere die Last trug. Auf diesen Maschinen stammt der Anteil, den Sie vLLM zuweisen, aus demselben Speicher wie alles andere.
Wenn Sie zwei dieser Maschinen haben
- Wenn das Modell und der benötigte Cache auf eine Maschine passen, starten Sie je eine Instanz hinter einem Least-Connection-Proxy. Teilen Sie das Modell nur auf, wenn eine Maschine den benötigten Cache nicht fassen kann.
- Richten Sie alle Clients auf den Proxy aus, einschließlich Batch-Jobs und alter Konfigurationen.
- Lesen Sie die Metriken direkt von jeder Instanz aus.
- Weisen Sie jeder Maschine ihren eigenen Speicheranteil zu, je nachdem, was sonst noch darauf läuft.
- Legen Sie fest, wie viele Anfragen eine Instanz gleichzeitig bedient, basierend auf Ihrem eigenen Traffic: Bei unserer Mischung schlugen 12 die 8.
- Rechnen Sie damit, dass der Wechsel das Modell so lange aus dem Betrieb nimmt, wie eine Instanz zum Starten braucht, und planen Sie dies ein.
Factory Floor liefert den Proxy und die Startkonfigurationen für eine oder zwei Maschinen, den Health Check und den Tool-Use-Test, den wir vor dem Modellwechsel durchführen, sowie die Watchdogs und Speicher-Sicherheitsregeln für den Rest der Maschine.