Twee dozen van het DGX Spark-klasse, één model: een kopie op elk verslaat het splitsen

Ops

Zeven weken lang draaide ons lokale taalmodel gesplitst over twee NVIDIA GB10-machines met tensor parallelisme. Op 22 oktober vervingen we dat door een volledige kopie van het model op elke machine met een least-connection proxy ervoor. De doorvoer ging van ongeveer 180 naar 210 tokens per seconde, en elke machine kan nu herstarten zonder het model weg te halen.

Waarom we het hadden gesplitst

Elke machine heeft 128 GB geheugen dat de CPU en de GPU delen. In september paste het model op één machine, maar de cache nauwelijks: de vLLM-build die we gebruikten kon de KV-cache van dit model niet in FP8 houden, dus de cache was in BF16, en één machine had ruimte voor 499.110 tokens daarvan. Dat is minder dan twee aanvragen bij de volledige context van het model van 262.144 tokens. Gesplitst over beide machines met tensor parallelisme over hun directe netwerkverbinding, groeide de cache tot meer dan drie miljoen tokens. We hadden het model gesplitst voor ruimte, niet voor snelheid.

Wat is er veranderd

Een nieuwere 4-bit build van hetzelfde model (NVFP4, gemaakt met quantisatie-bewuste distillatie) neemt ongeveer 71 GiB geheugen in beslag, en een community vLLM-build voor GB10 (eugr/spark-vllm-b12x) draait de cache in FP8. Nu houdt één machine het hele model en een cache van 0,76 tot 1,08 miljoen tokens, ruimte voor 2,9 tot 4,1 aanvragen bij volledige context, afhankelijk van hoeveel geheugen de machine eraan geeft. Beide kopieën gebruiken de eigen speculatieve decoding van het model (MTP, vier draft-tokens). Voordat we overschakelden, draaiden we onze tool-calling test op de nieuwe build: deze scoorde 86, de build die het verving 75.

Wat we hebben gemeten

Gesplitst over twee machinesEen kopie op elke machine
KV-cachemeer dan 3 miljoen tokens0,76 en 1,08 miljoen tokens
Aanvragen bij volledige contextongeveer 122,9 en 4,1
Doorvoer onder onze belastingongeveer 180 tokens/s210 tokens/s (111 + 99)
Opstartenongeveer 20 minuten5 tot 13 minuten per kopie
Eén machine herstarthet model is uitde andere kopie bedient

Eén kopie op zichzelf, naar het aantal gelijktijdige verzoeken: met korte prompts gaf 1 verzoek 36 tokens per seconde, 4 gaven 82, 8 gaven 109 en 16 gaven 150. Met de langere prompts van onze e-mailagent gaven 4 verzoeken 81, 8 gaven 113 en 16 slechts 87: voorbij acht van zulke verzoeken werd het trager.

Gedurende een middag nam de ene kopie maximaal 12 gelijktijdige verzoeken en de andere 8. De eerste produceerde 91 tot 93 tokens per seconde en voltooide 26 tot 27 verzoeken per minuut; de tweede 81 tot 83 tokens per seconde en 22 verzoeken per minuut. Beide nemen nu 12.

Wat we opgegeven hebben

Ruimte. Het gesplitste model had één cache van meer dan drie miljoen tokens; de kopieën hebben twee kleinere, en een verzoek kan alleen de cache gebruiken van de kopie die het bedient. Onze agents sturen veel korte en middelgrote verzoeken, en voor hen was doorvoer belangrijker. Als je een paar zeer lange contexten tegelijk bedient, kan splitsen nog steeds de betere keuze zijn. We hebben de gesplitste opstelling bewaard, en terugschakelen is één script.

Wat er misging tijdens de overstap

  1. Elf minuten zonder model, daarna 30 seconden van 502-fouten. Het gesplitste model moest stoppen voordat een kopie op dezelfde machines kon laden, dus onze agents wachtten ongeveer elf minuten. Toen de eerste kopie omhoog kwam, bleef de proxy nog ongeveer 30 seconden "502 no live upstreams" beantwoorden: hij had de backends als mislukt gemarkeerd terwijl ze uit waren (max_fails=3, fail_timeout=30s) en probeerde ze niet opnieuw totdat die tijd verstreken was.
  2. Een client die de proxy oversloeg. Een van onze batchjobs had het adres van de eerste machine in zijn configuratie, dus ging de hele belasting naar één kopie terwijl de andere capaciteit overhad. Elke client gaat nu via de proxy; de eigen adressen van de machines zijn alleen voor health checks.
  3. Metrics die sprongen. Onze doorvoermonitor las de /metrics van vLLM via de proxy. Met twee backends kwamen opeenvolgende lezingen van verschillende kopieën, de tellers sprongen heen en weer, en de monitor meldde het model als uitgeput. Hij leest nu elke kopie direct en telt ze op.
  4. Een oude watchdog die de nieuwe kopie zou hebben gestopt. De gesplitste opstelling had een watchdog die zijn service opnieuw startte wanneer het model niet meer antwoordde. De nieuwe service verklaart Conflicts= met de oude, zodat die herstart de nieuwe kopie zou hebben gestopt. Deze moest worden uitgeschakeld met systemctl disable --now, niet alleen gestopt, omdat onze ops-laag units opnieuw start die ingeschakeld zijn maar niet draaien.
  5. Geheugen op de machine die ander werk doet. Eén machine draait ook onze databases en site-builds. Met vLLM's gpu-memory-utilization op 0,78 bleef er slechts 5 GiB over voor de rest, dus hebben we dat verlaagd naar 0,74 en alleen die kopie opnieuw gestart terwijl de andere de last droeg. Op deze machines komt de geheugentoewijzing aan vLLM uit hetzelfde geheugen als alles anders.

Als je twee van deze machines hebt

Factory Floor bevat de proxy- en startconfiguraties voor één of twee machines, de health check en de tool-use test die we uitvoeren voordat we van model wisselen, met de watchdogs en geheugenbewakers voor de rest van de machine.

Bijgewerkt: