Artikel

Lagere latentie en hogere doorvoer met Multi-Node DeepSeek-implementatie

Gloeiende walvis, refererend aan DeepSeek

In de meeste systemen zijn latentie en doorvoer vaak conflicterende doelen die afwegingen vereisen tijdens ontwerp en implementatie. Bijvoorbeeld, in dichte grote taalmodellen kan het vergroten van de batchgrootte de doorvoer verbeteren maar ook de latentie verhogen; het vergroten van tensorparallellisme binnen een enkele machine kan de latentie verminderen, maar vermindert het aantal replica's, wat leidt tot een lagere doorvoer.

Expertmodellen zoals Mixture of Experts (MoE) zoals DeepSeek-V3/R1 hebben onlangs uitstekende modelcapaciteiten en operationele efficiëntie gedemonstreerd. Zo heeft het DeepSeek-V3/R1-model in totaal 671B parameters, maar elke token gebruikt slechts 37B parameters tijdens inferentie. Deze modelarchitectuur biedt zowel uitdagingen als kansen voor inferentiesystemen.

Dit artikel toont aan dat, in tegenstelling tot conventionele systemen, MoE-modellen zoals DeepSeek-V3/R1 gelijktijdig een hogere doorvoer en lagere latentie kunnen bereiken bij het gebruik van meer GPU's in multi-node implementaties in de meeste scenario's.


Implementatie Architecturen

Vanwege het grote aantal kleine experts dat het model heeft, moeten implementaties worden verspreid over meerdere apparaten. We beschouwden zowel single-node implementaties op een enkele node met 8xH200 GPU's als multi-node implementaties op 8xH100 GPU's.

Beide implementatiearchitecturen maken gebruik van Dataparallellisme, georganiseerd door onze interne verzoekplanner. De implementatie van dataparallellisme omvat het starten van meerdere instantie van inferentie-engines, die elk onafhankelijk werken om verzoeken te bedienen en te onderhouden. De verzoekscheduler, die via GRPC met de engine communiceert, zorgt ervoor dat verzoeken zo gelijkmatig mogelijk worden verdeeld, terwijl ook hergebruik van KV wordt gefaciliteerd, door verzoeken met gedeeltelijk overeenkomende prefix naar de servers te sturen die de cache bevatten. Engine-instanties strekken zich niet uit over meerdere nodes. Ze kunnen optioneel tensorparallellisme gebruiken om aandacht over meerdere apparaten te verdelen. De instanties zijn onderling verbonden via NVLink in het geval van een enkele node of InfiniBand voor het geval van meerdere nodes, waarbij experts worden verzonden en verzameld.

De single-node implementatieconfiguratie levert superieure latentie op bij kleine batchgroottes; de prestaties gaan echter snel achteruit onder verhoogde werkomstandigheden.

Om de dienende engine te implementeren, starten we één pod per node die meerdere engine-instanties herbergt. PyTorch is verantwoordelijk voor het opzetten van de gedistribueerde communicatie en het onderhandelen over de NVSHMEM-initialisatie. Voor communicatie vertrouwen we op aangepaste CUDA-kernels die worden beschreven in een eerdere blog post. De implementatie van de twee implementaties is vrijwel identiek, waarbij het model de juiste kernels kiest op basis van de structuur die expertparallellisme implementeert.


Parallelisatietechnieken

Voordat we ingaan op onze prestatievergelijkingen, is het essentieel om de belangrijkste parallelisatiestrategieën te begrijpen die het mogelijk maken om enorme MoE-modellen zoals DeepSeek-V3/R1 te implementeren.

Tensorparallellisme

In LLM-inferentie wordt Tensorparallellisme (TP) doorgaans gebruikt om het geheugengebruik en de berekening per GPU te verminderen, waardoor de latentie wordt verminderd. Meestal kunnen we lineaire projecties in aandachts- en MLP-lagen opdelen langs rij- of kolomdimensies, en aandachtbewerkingen opdelen langs de aandachtskopdimensie.

Met TP heeft de Llama-3-architectuur geen gedupliceerde berekening voor lineaire projecties en aandachtbewerkingen over GPU's, wat een ideale splitsingsmethode is. In DeepSeek-V3/R1-modellen kan TP dit echter niet bereiken.

DeepSeek-V3/R1-modellen gebruiken Multi-Latente Aandacht (MLA). Een MLA-laag gebruikt eerst een lineaire projectie kv_a_proj om de latente vector te berekenen en gebruikt vervolgens een andere lineaire projectie kv_b_proj om deze om te zetten in de ruimte van elke aandachtskop. Omdat alle aandachtskoppen dezelfde latente vector delen, kan TP de latente vector niet splitsen, dus moeten alle TP-rangen de parameters en berekening van kv_a_proj en kv_b_proj repliceren. Evenzo slaat MLA de latente vector op in de KV Cache, waarbij elke TP-rang een identieke kopie van de KV Cache opslaat.

Ondanks enige duplicatie in MLA, biedt tensorparallellisme nog steeds een gedeeltelijke vermindering van computationele eisen, waardoor het waardevol is voor scenario's die hoge uitvoersnelheden vereisen.

Expertparallellisme

DeepSeek-V3/R1-modellen vervangen MLP-lagen door MoE-lagen. Een MoE-laag heeft 256 gerouteerde experts en één gedeelde expert. Elke token wordt naar 8 verschillende gerouteerde experts gestuurd voor berekening en de resultaten worden gewogen gesommeerd. Elke token voert ook berekeningen uit in de gedeelde expert en het resultaat wordt toegevoegd aan het resultaat van de gerouteerde experts.

Expertparallellisme (EP) dient als de typische splitsingsbenadering voor MoE-lagen, waarbij elke GPU 256 / EP gerouteerde experts beheert terwijl een kopie wordt behouden van de gedeelde expert. In vergelijking met TP is het voordeel van EP dat het de berekening over meer GPU's kan verdelen, waardoor het gebruik van berekeningen en geheugen per GPU wordt verminderd.

Voordat expertberekeningen worden uitgevoerd, moeten alle GPU's een AllToAll-communicatie uitvoeren om tokens te verzenden naar de GPU's waar de bijbehorende experts zich bevinden; na expertberekeningen is een andere AllToAll-communicatie nodig om berekeningsresultaten van verschillende GPU's te verzamelen en een gewogen sommatie uit te voeren. We hebben een geoptimaliseerde versie van deze twee AllToAll-communicatie-kernels, Dispatch en Combine, geïmplementeerd met NVSHMEM. In een eerder blogbericht beschreven we de implementatie en onze kernels zijn open-source op GitHub beschikbaar gesteld.

Data Parallelism

Met EP kunnen we MoE-berekeningen over 128 of zelfs meer GPU's verdelen. MLA-berekeningen kunnen niet worden verdeeld met EP. Op dit punt kunnen we Data Parallelism (DP) introduceren. Elke DP Groep heeft een volledige kopie van de MLA-laag. Elke DP Groep accepteert verschillende invoer en voert onafhankelijk MLA-laagbepalingen uit.

De DP van de MLA-laag en TP kunnen worden gecombineerd, met één DP Groep opgesplitst in meerdere TP rangen. De EP van de MoE-laag kan worden gecombineerd met de DP/TP van de MLA-laag. EP = DP * TP. Bijvoorbeeld, op 16 machines, betekent EP128 DP32 TP4 dat gerouteerde experts worden verdeeld over 128 GPU's, waarbij elke 4 GPU's een DP Groep vormen, voor een totaal van 32 onafhankelijke DP Groepen.


Single-Node versus Multi-Node

De 671B parameters van DeepSeek overschrijden de geheugencapaciteit van een enkele 8-GPU H100-machine (80 GB * 8), maar een enkele 8-GPU H200-machine kan het gehele model volledig accommoderen (141 GB * 8). Met de EP8 DP8 TP1-configuratie gebruikt het model ongeveer 100 GB geheugen per GPU, waardoor er ongeveer 40 GB overblijft voor KV Cache en andere tussentijdse resultaten. Eén token neemt 70.272 bytes opslagruimte in de KV Cache in beslag. Aangezien we ervan uitgaan dat elke aanvraag 5.000 tokens heeft, kan elke GPU ongeveer 100 aanvragen ontvangen.

We wilden de prestatieverschillen begrijpen tussen single-node en multi-node implementaties onder verschillende configuraties. We gebruikten een H200-machine voor single-node-implementatie en maximaal 16 H100-machines voor multi-node-implementaties. Voor elke implementeeromgeving gebruikten we combinaties van TP 1, 2, 4, 8 en batchgroottes per GPU van 1, 2, 4, 8, 16, 32, 64, 128. We gingen ervan uit dat elke aanvraag een KV Cache-lengte van 5.000 tokens had. We gingen er ook vanuit dat de voorspelling van Multi-Token Prediction (MTP) 1 extra token (d.w.z. de querylengte van elke aanvraag is 2) voorspelt en we conservatief uitgingen van een acceptatiegraad van 60%. De afbeelding hieronder toont de verwerkingssnelheid en uitvoersnelheid voor verschillende configuraties.

De horizontale as vertegenwoordigt de uitvoersnelheid per aanvraag in tokens/s. De verticale as gebruikt een logaritmische schaal om de verwerkingssnelheid per machine in tokens/s weer te geven. We hebben de Pareto-grens voor elke EP-configuratie gemarkeerd met verschillend gekleurde lijnen.

In scenario's met extreem hoge uitvoersnelheidseisen kan het gebruik van single-node EP8 DP1 TP8 met een batchgrootte van 1 een uitvoersnelheid van meer dan 100 tokens/s bereiken, maar de verwerkingssnelheid is extreem laag, gelijk aan de uitvoersnelheid. In dit scenario heeft de hele batch slechts 2 tokens, die kunnen worden verzonden naar maximaal 2*8=16 experts, wat leidt tot een activering van maximaal 57B parameters.

In het uitvoersnelheidsbereik van 80-40 tokens/s, zodra de verwerkingssnelheid toeneemt, neemt de uitvoersnelheid aanzienlijk af. In tegenstelling daarmee heeft EP128 ongeveer 5x hogere verwerkingssnelheid dan single-node-implementatie bij dezelfde uitvoersnelheid.

We kunnen dit fenomeen verklaren door te onderzoeken hoe single-node-implementaties zich gedragen: het vergroten van de batchgrootte correleert direct met een toename van geactiveerde experts. Wanneer de batchgrootte 1 is, is het gemiddelde aantal geactiveerde experts per GPU 2 * 8 / 8 = 2. Wanneer de batch groot genoeg is, worden alle experts geactiveerd, wat betekent dat elke GPU 256 / 8 = 32 experts activeert. Het activeren van meer experts betekent dat de GPU meer parameters moet lezen vanuit het geheugen, wat de geheugengebruikdruk aanzienlijk vergroot. Aangezien de decodeerfase van grote taalmodellen al beperkt wordt door geheugengebruik in plaats van door rekenprestaties, vermindert het vergroten van de batchgrootte in single-node-implementatie de uitvoersnelheid aanzienlijk.

Vergelijking van de vier multi-node-implementatieconfiguraties (EP16, EP32, EP64 en EP128) toont aan dat hogere EP-waarden de Pareto-grens verleggen in de richting van gelijktijdige verbeteringen in verwerkingssnelheid en uitvoersnelheid.

Door een hoger EP-nummer te gebruiken, wordt elke GPU toegewezen aan minder experts. Bijvoorbeeld, EP128 betekent dat elke GPU verantwoordelijk is voor 256 / 128 = 2 experts, dus de druk op de geheugengebruik wordt aanzienlijk verminderd. Met andere woorden, door een groter EP-nummer te gebruiken, winnen we effectief meer geheugengebruik. Wanneer de batchgrootte per GPU kleiner is dan 64, heeft het vergroten van de batchgrootte geen significant effect op de snelheid van expertberekeningen omdat het vergroten van het aantal inputten de geheugengebruikdruk niet significant verhoogt. Daarom observeren we dat bij het gebruik van EP128, het verhogen van de batchgrootte de uitvoersnelheid niet zo significant beïnvloedt.

Interessant genoeg, bij grotere batchgroottes (64 aanvragen per GPU), observeerden we een nieuw fenomeen: de verwerkingssnelheid bij single-node-implementaties is iets hoger dan bij multi-node-implementaties. Voor een deel komt dit doordat intra-node NVLink een hogere bandbreedte heeft dan inter-node InfiniBand. Een andere oorzaak is te wijten aan beperkingen van onze implementatie. We zullen dit fenomeen later in meer detail analyseren.

Vanwege beperkingen in de geheugencapaciteit kan de EP8 DP8 TP1-configuratie geen batchgrootte van 128 per GPU bereiken, dus multi-node-implementatie blijft een betere keuze in scenario's die hogere verwerkingssnelheid nastreven.


Overlapping van Berekeningen en Communicatie

Zoals kort geïntroduceerd bovenin Expertparallellisme, zijn GPU's inactief tijdens MoE-laagcommunicatie. Om verspilling te verminderen en latentie te verlagen, moeten we gegevensonafhankelijke berekeningstaken vinden om deze inactieve tijd te vullen.

Het bovenste deel van de bovenstaande afbeelding toont de berekeningsstroom van één laag. MoE-berekeningen zijn afhankelijk van Dispatch, en de volgende laagberekening is afhankelijk van het resultaat van Combine.

We plaatsen de gedeelde expert op elke GPU. Op deze manier vereist de gedeelde expertberekening geen AllToAll-communicatie. Daarom kunnen we direct na Dispatch Send gedeelde expertberekeningen uitvoeren, waarna we wachten tot Dispatch Recv is voltooid. We noemen dit overlapping-schema 'Dispatch Overlap'.

Dispatch Overlap biedt eenvoudige implementatie en brede toepasbaarheid. Deze techniek verbergt de tijd van gedeelde expertberekeningen over alle EP-groottes en batchgroottes.

Om de overlapping van berekeningen en communicatie verder te vergroten, gebruikten we de micro-batching die in het DeepSeek-technisch rapport wordt genoemd om gegevensafhankelijkheid te doorbreken. Zoals weergegeven in het onderste deel van de afbeelding, hebben we de berekening van één Transformer-laag opgedeeld in 5 fasen:

  • Fase 1: InputNorm, QKVProj, AppendKV, BMM

  • Fase 2: BMM, Attn, OProj, PostNorm, Gate

  • Fase 3: Dispatch Send, Gedeelde Expert

  • Fase 4: Dispatch Recv, MoE, Combine Send

  • Fase 5: Combine Recv

In de eerste 3 Dense Transformer-lagen gebruiken we de hele batch. In de volgende 58 MoE Transformer-lagen verdelen we de batch gelijkmatig over twee micro-batches. De twee micro-batches worden afwisselend uitgevoerd, met een verschuiving van 3 fasen. Aangezien er geen gegevensafhankelijkheid bestaat tussen deze twee micro-batches, kunnen we na Dispatch Send en na Combine Send overschakelen naar de berekening van een andere micro-batch.


Verdeling van Latentie

Vervolgens vergelijken we de effecten van overlapping door middel van een experiment, evenals de prestatieverschillen tussen single-node-implementatie EP8 en multi-node-implementatie EP128. Voor de duidelijkheid gingen we uit van H100 GPU's voor het volgende experiment. We gebruikten TP1, een batchgrootte van 128 per GPU, een Querylengte van 2 per resultaat en een KV Cache-lengte van 5000.

De bovenstaande afbeelding toont de totale tijd besteed aan één MoE Transformer-laag en de latentieproportie van verschillende soorten kernels. Behalve Dispatch, Combine en GroupGEMM zou de uitvoeringstijd van andere kernels gelijk moeten zijn in de EP8, EP128 NoOverlap en EP128 DispatchOverlap series omdat de batchgrootte hetzelfde is.

Overlapping

Laten we eerst de effecten van de drie overlapmethoden vergelijken. NoOverlap kostte in totaal 2667 µs, DispatchOverlap kostte 2651 µs, waarmee 16 µs werd bespaard, of slechts 0,6%. MicroBatch toonde een zeer significante verbetering, kostte 1896 µs, een snelheidsverbetering van 29%. Zowel Dispatch- als Combine-tijd werden aanzienlijk verminderd. Dispatch nam af van 593 µs tot 367 µs, en Combine van 1012 µs tot 237 µs.

Het is belangrijk op te merken dat het splitsen van een batch van grootte 128 in twee batches van grootte 64 de totale uitvoeringstijd verhoogt voor de compute-kernels. Daarom, alhoewel de tijd besteed aan communicatie met 1001 µs verminderde, werd de totale tijd slechts met 771 µs verminderd. We zullen de reden gebruiken met behulp van het Roofline-model in de volgende sectie uitleggen.

Om deze reden verbetert microbatching niet altijd de prestaties.

De bovenstaande afbeelding toont de prestatieverbetering van Microbatch vergeleken met DispatchOverlap voor batchgroottes 4-128. Wanneer de batchgrootte minder is dan 32, verlaagt Microbatch de prestaties met 5%-40%. Wanneer de batchgrootte groter dan of gelijk aan 32 is, kan Microbatch de prestaties met 10%-35% verbeteren.

EP8 versus EP128

Keer terug naar de vorige figuur en vergelijk EP8 en EP128 Microbatch. EP8 duurde in totaal 1802 μs, iets minder dan de 1896 μs van EP128. Naast de verhoogde kerneltijd die Microbatch met zich meebrengt, liggen de hoofdverschillen in GroupGEMM gebruikt voor MoE-berekening en de twee communicatiekernen, Dispatch en Combine.

EP8's GroupGEMM duurde 555 μs, terwijl EP128's GroupGEMM slechts 270 μs duurde, wat tot halvering heeft gereduceerd. Dit is het kernvoordeel van multi-node-implementatie.

Helaas verhoogde de tijd besteed aan communicatie met 213 µs, wat de voordelen van GroupGEMM grotendeels tenietdeed. In afzonderlijke prestatietests van onze communicatiekernels ontdekten we dat zij slechts de helft van de Infiniband-bandbreedte konden bereiken. We zullen onze communicatiekernels blijven optimaliseren.

Een andere kernel die aanzienlijk achterblijft, is GEMM. Microbatch verhoogde de GEMM-tijd met 95 μs. We gaan dieper ingaan op GEMM in de Roofline-secties beneden. We geloven dat de huidige GEMM-implementatie nog niet de optimale prestaties heeft bereikt.

Roofline

Het Roofline-model is een goed hulpmiddel voor het analyseren van kernelprestaties. Zijn horizontale as is Rekenkundige Intensiteit, de verhouding van FLOP tot geheugen I/O-bytes. De waarde op de horizontale as kan direct vanuit de semantiek van de kernel worden berekend. De verticale as vertegenwoordigt behaalde prestaties, berekend door FLOP te delen door benchmarkinglatentie.

De theoretische bovengrens van kernelprestaties is direct bepaald door de specificaties van de GPU. De FP8-piekprestaties van de H100 zijn 1979 TFLOP/s, weergegeven als een horizontale lijn in het Roofline-model. De geheugengebruik van de H100 is 3,35 TB/s, vertegenwoordigd als de helling van een lijn die door de oorsprong gaat. De twee lijnen geven de prestatielimieten voor door berekening beperkte en door geheugen beperkte kernels, respectievelijk.

Hieronder bespreken we de prestaties van de GroupGEMM en GEMM kernels.

GroupGEMM

De GroupGEMM-kernel in MoE voert de volgende berekening uit: Er zijn g groepen in totaal, de i-de groep heeft m_i tokens en voert een matrixvermenigvuldiging uit van [m_i, k] x [k, n] -> [m_i, n]. In prestatietests gaan we ervan uit dat het aantal tokens in elke groep hetzelfde is, aangeduid als m_i = m. Dan is het FLOP-aantal voor GroupGEMM 2 * g * m * k * n en de geheugen I/O-bytes is g * (m * k + n * k + m * n).

In het DeepSeek-V3/R1-model zijn er 256 experts en wordt elke token naar 8 experts voor berekeningen gestuurd. Als we uitgaan van een batchgrootte van 128, een querylengte van 2, die EP128 DP128-configuratie gebruikt, is het gemiddelde aantal tokens ontvangen door elke expert (d.w.z. m) 128 * 2 * 8 * 128 / 256 = 1024. Op dezelfde manier kunnen we m berekenen voor andere configuraties en batchgroottes.

We gebruikten de DeepGEMM GroupGEMM-implementatie voor prestatietests. Testpunten bedekten combinaties van EP8, EP16, EP32, EP64, EP128 configuraties met TP1 en batchgroottes 1-128.

De figuur hierboven toont het Roofline-model voor GroupGEMM onder verschillende EP-configuraties. Verschillende EP's corresponderen met verschillende aantallen groepen. De figuur illustreert bijna overlappende prestatiecurves, wat aangeeft dat GroupGEMM-prestaties hoofdzakelijk worden bepaald door het totale aantal tokens (vertegenwoordigd als g * m).

De sterren markeren de datapunten die overeenkomen met een batchgrootte van 128 per GPU voor elke EP-configuratie. Als we deze gemarkeerde datapunten vergelijken, zien we dat naarmate EP toeneemt (en gelijktijdig DP toenemen), het aantal tokens per expert m ook toeneemt. Bij EP8, m=128, terwijl bij EP128, m=2048.

Naarmate m stijgt, neemt de Rekenkundige Intensiteit ook toe. In de meeste configuraties wordt GroupGEMM beperkt door geheugengebruik, dus het verhogen van m verbetert de prestaties.

GEMM

De GEMM-kernel komt overeen met lineaire projecties in het model, zoals Q/K/V/O Projectie. Voor een matrixvermenigvuldiging van [m, k] x [k, n] -> [m, n], is het FLOP-aantal 2 * m * k * n en de geheugen I/O-bytes is m * k + n * k + m * n. We kunnen ook de latentie voor batchgroottes 1-128 testen.

De figuur hierboven toont het Roofline-model voor GEMM onder verschillende EP-configuraties. We kunnen zien dat GEMM-prestaties worden beperkt door geheugengebruik. Naarmate de batchgrootte toeneemt, neemt de Rekenkundige Intensiteit toe, wat de prestaties verbetert.

Microbatch

Bij gebruik van microbatching delen we de batch gelijkmatig in twee delen. Uit de twee figuren hierboven kunnen we zien dat wanneer m m/2 wordt, de efficiëntie van matrixvermenigvuldiging afneemt. Daarom duurt het uitvoeren van twee matrixvermenigvuldigingen van grootte m/2 langer dan het uitvoeren van één matrixvermenigvuldiging van grootte m.

Multi-Token Prediction

Door het artikel heen zijn we uitgegaan van het gebruik van Multi-Token Prediction (MTP) voor speculatieve decodering. MTP verandert de querylengte per aanvraag van 1 naar 2. Voor matrixvermenigvuldiging is dit equivalent aan het veranderen van m naar m * 2, waardoor de efficiëntie van matrixvermenigvuldiging toeneemt. Aan de andere kant, als we het Roofline-model voor MLA tekenen, zouden we vinden dat het verhogen van de querylengte de efficiëntie van de MLA-kernels aanzienlijk verbetert.

Daarom speelt het gebruik van MTP een belangrijke rol in de model efficiëntie.

Implementatie & Optimalisaties

In deze sectie zullen we enkele implementatie- en optimalisatiedetails voor ons DeepSeek-V3/R1-model introduceren.

Kwantisatie

DeepSeek-V3/R1 werd natief getraind op FP8 met behulp van een per-blok kwantisatieschema, waarbij gewichten statisch worden gekwantiseerd en activaties worden gekwantiseerd tijdens verwerking. In plaats van een schalingsfactor per kanaal of per matrix statisch te berekenen, worden schalingsfactoren berekend over vectoren van 128 elementen voor activaties en tegels van 128x128 elementen voor matrices, waardoor nauwkeurigheidsverlies door kwantisatie wordt beperkt.

Bij Perplexity vertrouwen we op een mix van CUDA en Triton-kernels om inferentie te ondersteunen, waarbij CUDA wordt gebruikt voor de meest prestatiegevoelige en zelden gewijzigde kernels (zoals attentie en GEMM), en Triton een breed scala aan activatie-, normalisatie- en hulproutines implementeert. Triton stelde ons in staat de kernels snel aan te passen aan het blokkantisatieschema.

Voor lineaire en MoE-lagen mengen we de Deep GEMM-kernels met onze eigen Triton GEMM-kernels, want we hebben opgemerkt dat voor bepaalde matrixafmetingen en lage batchgroottes Split-K lagere latentie oplevert. Als de ongekwantiseerde laag een vermenigvuldiging (M, K) x (K, N) uitvoert, moet het (M x ceil_div(K, 128)) x (ceil_div(K, 128), ceil_div(N, 128)) schalingsfactoren hebben voor blok kwantisatie. Voor blokkwantisatie worden de schalingsfactoren voor activatie berekend tijdens verwerking, in plaats van vooraf te worden gekalibreerd. Aangezien activering schalingsfactoren alleen worden geaggregeerd langs de K en niet langs de M dimensie, vereisen kernsels alleen kleine aanpassingen om het schema te ondersteunen.

De SiLU-activeringsfunctie die door DeepSeek-V3/R1 is gebruikt, vereiste substantiële wijzigingen om CUDA-graphics, blokkwantisatie en dynamisch gerouteerde tokenaantallen te ondersteunen. Blokkwantisatie kan problematisch zijn omdat het horizontale reducties introduceert, maar de kernel splitste activaties al langs hun verborgen dimensie in blokken van 1024 elementen. Binnen één blok werd de tensor die gekwantiseerd moest worden verder gesplitst in blokken van 128 om de grootste absolute waarde te berekenen, waarbij Triton efficiënte kruiswaardemax-reducties genereerde, waardoor slechts minimale overhead werd toegevoegd.

Om MoE-routing onder CUDA-graphics te ondersteunen, moeten de kernsels op de hoogte zijn van de routeringsinformatie die het aantal tokens per expert aangeeft, in plaats van werk te plannen op basis van de grootte van de buffers die zijn toegewezen om de bovengrens van het aantal tokens te houden. We kunnen het probleem niet opsplitsen op basis van invoertensorafmetingen, dus we lanceren een vast aantal persistente kernsels die de routeringsinformatie lezen om te bepalen hoeveel tokens zijn ingevuld en splitsen dynamisch het werk van het verwerken van de activaties onder hen.

We hebben al enkele van onze kernels upstream vrijgegeven naar het FlashInfer-project en in de toekomst zullen we meer van onze code open soresen.

MLA-Laag

We gebruiken FlashInfer voor MLA-berekeningen. FlashInfer ondersteunt flexibele paginatabelinstellingen en extreem hoge prestaties.

We fuseerden q_a_proj en kv_a_proj tot een enkele qkv_a_proj. De latentie nam af van 15,4 µs + 14,8 µs = 30,2 µs tot 16,7 µs.

We splitsten kv_b_proj op in twee matrices, k_b_proj en v_b_proj. We schreven een FP8 Block Quantized BMM-kernel voor berekeningen met betrekking tot deze twee matrices.

Cuda Grafiek

Cuda Grafiek kan de kernlanceringsomvang aanzienlijk verlagen, wat cruciaal is voor prestaties. We maken een Cuda Grafiek voor elke batchgrootte.

Alvorens onze AllToAll Kernel te ontwikkelen, gebruikten we torch.all_to_all_single() voor AllToAll-communicatie. Deze operatie vereist dat alle GPU's dezelfde batchgrootte gebruiken. Echter, verschillende DP Groepen kunnen verschillende batchgroottes gebruiken.

Om ervoor te zorgen dat all_to_all_single() compatibel is met verschillende DP Groepen met verschillende batchgroottes, gebruikten we eerst een allreduce() operatie voor elke modeluitvoering om de maximale batchgrootte onder alle DP Groepen te verkrijgen. Daarna lieten we alle DP Groepen deze batchgrootte gebruiken om te draaien.

Hoewel deze benadering ervoor zorgt dat we Cuda Grafiek kunnen gebruiken, heeft het drie nadelen. Ten eerste, het vereist een extra allreduce()-operatie. Ten tweede, DP Groepen met kleinere batchgroottes worden gedwongen te vullen. Ten derde, het maakt onze implementatiecode complex.

Na het implementeren van onze eigen AllToAll Kernel, hoeven we niet langer alle GPU's dezelfde batchgrootte te laten gebruiken. Daarom hoeven we geen extra allreduce()-operatie uit te voeren of batchgroottes te vullen.

MoE Router

De MoE-router is geïmplementeerd in Triton, gebaseerd op een gewijzigde sorteerbewerking die is afgeleid van de standaardbibliotheek, die ook de indexen bijhoudt van de gesorteerde elementen. De implementatie wordt gedeeld door alle MoE-modellen, aangezien Mixtral-routering een speciaal geval is van de DeepSeek-roetes waar de Top-K-groep hetzelfde is als de groep van alle experts. De schaarse kernels gebruiken de Top-K indexen en scores direct, terwijl dichte dispatch/combine-schemas afhankelijk van all-to-all routeringsinformatie per-expert moeten worden geaggregeerd in plaats van op een per-tokenbasis.

Toekomstige werken

In toekomstig werk zijn we van plan om de prestaties van het DeepSeek-model verder te optimaliseren.

De belangrijkste volgende optimalisatie is Prefill-uitsplitsing. De Prefill-fase en decodeerfase van het DeepSeek-V3/R1-model hebben zeer verschillende berekeningskenmerken. Beide kunnen verschillende optimalisatiestrategieën en implementatieregels gebruiken.

Voor de MLA-laag, gebruiken we Matrix Absorption tijdens de decodeerfase om het FLOP-aantal van MLA-berekeningen te verminderen. In de Prefill-fase zou het eerst projecteren van de latente vector in K/V-ruimte en vervolgens berekeningen in Multi-Head Attentie (MHA) vorm betere prestaties opleveren.

Als Prefill en decodeer op dezelfde GPU draaien, gebruiken we meestal opgedeelde aanvulling om de query in meerdere stukken te delen voor aanvulling, om de impact van Prefill op Decode uitvoersnelheid te verminderen. Omdat de KV Cache de latente vector opslaat, wordt het moeilijk om MLA om te zetten in MHA-vorm.

Voor de MoE-laag gebruiken we tijdens de decodeerfase zo groot mogelijk EP en DP om het aantal invoertokens per expert te vergroten, waardoor GroupGEMM-prestaties verbeteren. In de Prefill-fase is het aantal tokens al groot genoeg, en is GroupGEMM al rekengrens. Daarom kunnen we voor aanvulling kleinere EP en DP gebruiken.

Als Prefill en Decode op dezelfde GPU draaien, zolang als een DP Groep aanvulling uitvoert, zal de latentie van MoE-laag op alle GPU's toenemen, wat decode-uitvoersnelheid aanzienlijk beïnvloeden.

Naast Prefill-uitsplitsing zijn we ook van plan om de volgende aspecten te optimaliseren:

  • AllToAll Prestaties: Onze AllToAll-kernel bereikt momenteel slechts 1/3 van de Infiniband-bandbreedte. We blijven deze kernel optimaliseren.

  • EAGLE-stijl speculatieve decodering: In de bovenstaande gegevens gingen we ervan uit dat speculatieve decodering werd gebruikt om 1 token te voorspellen. EAGLE kan een boomstructuur gebruiken om meerdere tokens te voorspellen, waardoor de acceptatielengte toeneemt, wat de uitvoersnelheid aanzienlijk kan verhogen.

  • GEMM Kernel: In het eerder getoonde Roofline-model kunnen we zien dat de efficiëntie van de GEMM-kernel nog steeds ver van de theoretische limiet verwijderd is. We blijven deze kernel optimaliseren.

  • GB200 NVL72: In NVIDIA's nieuwste GB200 NVL72-oplossing zijn 72 Blackwell GPU's verbonden via een snelle NVLink. Voor MoE-architectuurmodellen is dit een zeer grote kans en uitdaging.

Conclusie

Multi-node-implementatie van DeepSeek MoE-modellen bereikt wat typisch onmogelijk is met dichte LLM's: gelijktijdig zowel de doorvoer als de latentie verbeteren. Door experts over meer GPU's te verdelen, verminderen we de druk op geheugengebruik per apparaat, waardoor snellere verwerking en hogere systeemdoorvoer mogelijk is. Onze experimenten tonen aan dat EP128-configuraties tot 5x hogere verwerkingssnelheid bereiken bij equivalente uitvoersnelheden in vergelijking met single-node-implementaties.

Technieken voor overlappende berekeningen en communicatie, zoals micro-batching, verminderen de multi-node-communicatieoverhead aanzienlijk, waarbij onze implementatie tot 40% snelheidsverbetering vertoont. Onze aangepaste AllToAll communicatiekernen en geoptimaliseerde kernelimplementaties hebben de efficiënte implementatie van het model met 671B parameters mogelijk gemaakt.

Naarmate MoE-architecturen populairder worden voor hun capaciteiten, bieden deze implementatiestrategieën waardevolle inzichten voor het efficiënt schalen van dergelijke modellen.

Referenties

Geïnteresseerd in het vormgeven van de toekomst van ons API Platform? We zijn aan het werven.

Word lid van onze ontwikkelaarsgemeenschap om op de hoogte te blijven van nieuwe releases, functies en updates.

Geïnteresseerd in het vormgeven van de toekomst van ons API Platform? We zijn aan het werven.

Word lid van onze ontwikkelaarsgemeenschap om op de hoogte te blijven van nieuwe releases, functies en updates.

Geïnteresseerd in het vormgeven van de toekomst van ons API Platform? We zijn aan het werven.

Word lid van onze ontwikkelaarsgemeenschap om op de hoogte te blijven van nieuwe releases, functies en updates.