Lavere latens og højere throughput med multi-node DeepSeek-implementering
Multi-GPU-implementering øger MoE-modelns ydeevne på både hastigheds- og skalafrynter samtidigt
I de fleste systemer er latens og throughput ofte modstridende mål, der kræver afvejninger under design og implementering. For eksempel kan en øget batchstørrelse i tætte store sprogmodeller forbedre throughput, men det øger også latensen; en øget tensorparallelisme inden for en enkelt maskine kan mindske latensen, men mindsker antallet af replikaer, hvilket fører til lavere throughput.
Mixture of Experts (MoE)-modeller som DeepSeek-V3/R1 har for nylig demonstreret fremragende modelkapacitet og operationel effektivitet. For eksempel har DeepSeek-V3/R1-modellen 671B parametre i alt, men hver token bruger kun 37B parametre under inferens. Denne modelarkitektur præsenterer både udfordringer og muligheder for inferenssystemer.
Denne artikel viser, at i modsætning til konventionelle systemer kan MoE-modeller som DeepSeek-V3/R1 samtidig opnå højere throughput og lavere latens, når de udnytter flere GPU'er i multi-node-implementeringer i de fleste scenarier.
Implementeringsarkitekturer
På grund af det store antal små eksperter, modellen har, skal implementeringer spredes over flere enheder. Vi overvejede både single-node-implementeringer på en enkelt node med 8xH200 GPU'er og multi-node-implementeringer på 8xH100 GPU'er.
Begge implementeringsarkitekturer udnytter Data Parallelism, orkesteret gennem vores interne forespørgselskoordinator. Implementeringen af data parallelisme involverer igangsættelse af flere instanser af inferensmotoren, der hver opererer uafhængigt for at betjene og opretholde forespørgsler. Forespørgselskoordinatoren, som interagerer med motoren via GRPC, er ansvarlig for at sprede forespørgsler så jævnt som muligt, samtidig med at den muliggør genbrug af KV ved at sende forespørgsler med delvist matchede præfider til de servere, der indeholder cachen. Motorinstanser spænder ikke over flere noder. De kan valgfrit bruge tensorparallelisme til at sharde opmærksomhed på tværs af flere enheder. Instanserne er forbundet via NVLink i tilfældet med en enkelt node eller InfiniBand i multi-node-tilfældet, og udsender og indsamler eksperter.
Single-node-implementeringskonfigurationen leverer overlegen latens med små batchstørrelser; dog forringes ydeevnen hurtigt under øgede belastningsforhold.
For at implementere serveringsmotoren lancerer vi én pod pr. node, der huser flere motorinstanser. PyTorch er ansvarlig for at opsætte den distribuerede kommunikation og forhandle NVSHMEM-initialiseringen. Til kommunikation er vi afhængige af tilpassede CUDA-kerner beskrevet i et tidligere blogindlæg. Implementeringen af de to implementeringer er praktisk talt identisk, hvor modellen vælger de korrekte kerner at bruge baseret på det stof, der implementerer ekspertparallelisme.
Paralleliseringsteknikker
Før vi dykker ned i vores ydeevnesammenligninger, er det vigtigt at forstå de centrale paralleliseringsstrategier, der gør det muligt at implementere massive MoE-modeller som DeepSeek-V3/R1.
Tensor Parallelism
I LLM-inferens bruges Tensor Parallelism (TP) typisk til at reducere hukommelsesforbrug og beregning pr. GPU og derved reducere latensen. Normalt kan vi sharde Linear-projektioner i opmærksomheds- og MLP-lag langs række- eller kolonnedimensioner og sharde opmærksomhedsoperationer langs opmærksomhedshovedets dimension.
Med TP har Llama-3-arkitekturen ingen duplikeret beregning for Linear-projektions- og opmærksomhedsoperationer på tværs af GPU'er, hvilket er en ideel shardingsmetode. I DeepSeek-V3/R1-modeller kan TP dog ikke opnå dette.
DeepSeek-V3/R1-modeller bruger Multi-Latent Attention (MLA). Et MLA-lag bruger først en Linear-projektion kv_a_proj til at beregne den latente vektor, og bruger derefter en anden Linear-projektion kv_b_proj til at transformere den til rummet for hvert opmærksomhedshoved. Da alle opmærksomhedshoveder deler den samme latente vektor, kan TP ikke sharde den latente vektor, så alle TP-ranglister skal replikere parametrene og beregningen af kv_a_proj og kv_b_proj. Tilsvarende, da MLA gemmer den latente vektor i KV-cachen, gemmer hver TP-rangliste en identisk kopi af KV-cachen.
På trods af en vis duplikering i MLA giver Tensor Parallelism stadig delvis reduktion i beregningskrav, hvilket gør det værdifuldt til scenarier, der kræver høje udgangshastigheder.
Expert Parallelism
DeepSeek-V3/R1-modeller erstatter MLP-lag med MoE-lag. Et MoE-lag har 256 routerede eksperter og én delt ekspert. Hver token sendes til 8 forskellige routerede eksperter til beregning, og resultaterne vægtes og summeres. Hver token beregner også i den delte ekspert, og resultatet lægges til resultatet fra de routerede eksperter.
Expert Parallelism (EP) fungerer som den typiske shardingsmetode for MoE-lag, hvor hver GPU håndterer 256 / EP routerede eksperter, samtidig med at den opretholder en kopi af den delte ekspert. Sammenlignet med TP er fordelen ved EP, at den kan distribuere beregning på tværs af flere GPU'er, hvilket reducerer beregnings- og hukommelsesforbruget pr. GPU.
Før ekspertberegning udføres, skal alle GPU'er udføre en AllToAll-kommunikation for at udsende tokens til de GPU'er, hvor de tilsvarende eksperter er placeret; efter ekspertberegning er der brug for en anden AllToAll-kommunikation for at indsamle beregningsresultater fra forskellige GPU'er og udføre vægtet summation. Vi implementerede en optimeret version af disse to AllToAll-kommunikationskerner, Dispatch og Combine, ved hjælp af NVSHMEM. I vores tidligere blogindlæg beskrev vi implementeringen, og vores kerner er blevet open-sourced på GitHub.
Data Parallelism
Med EP kan vi distribuere MoE-beregning på tværs af 128 eller endda flere GPU'er. MLA-beregning kan dog ikke opdeles med EP. På dette tidspunkt kan vi introducere Data Parallelism (DP). Hver DP-gruppe har en fuldstændig kopi af MLA-laget. Hver DP-gruppe accepterer forskellige input og udfører MLA-lagberegning uafhængigt.
MLA-lagets DP og TP kan kombineres, idet én DP-gruppe opdeles i flere TP-ranglister. MoE-lagets EP kan kombineres med MLA-lagets DP/TP. EP = DP * TP. For eksempel på 16 maskiner betyder EP128 DP32 TP4 at distribuere routerede eksperter på tværs af 128 GPU'er, hvor hver 4. GPU danner en DP-gruppe, i alt 32 uafhængige DP-grupper.
Single-Node vs Multi-Node
DeepSeeks 671B parametre overstiger hukommelseskapaciteten for en enkelt 8-GPU H100-maskine (80 GB * 8), men en enkelt 8-GPU H200-maskine kan fuldt ud rumme hele modellen (141 GB * 8). Ved hjælp af EP8 DP8 TP1-konfigurationen bruger modellen ca. 100 GB hukommelse pr. GPU, hvilket efterlader ca. 40 GB til KV-cache og andre mellemliggende resultater. Én token optager 70.272 bytes KV-cache. Forudsat at hver forespørgsel har 5.000 tokens, kan hver GPU rumme ca. 100 forespørgsler.
Vi ønskede at forstå ydeevneforskellene mellem single-node- og multi-node-implementeringer under forskellige konfigurationer. Vi brugte én H200-maskine til single-node-implementering og op til 16 H100-maskiner til multi-node-implementeringer. For hvert implementeringsmiljø brugte vi kombinationer af TP 1, 2, 4, 8 og batchstørrelser pr. GPU på 1, 2, 4, 8, 16, 32, 64, 128. Vi antog, at hver forespørgsel havde en KV-cache-længde på 5.000 tokens. Vi antog også, at Multi-Token Prediction (MTP) forudsiger 1 yderligere token (dvs. hver forespørgsels forespørgselslængde er 2), og antog konservativt en acceptrate på 60%. Figuren nedenfor viser throughput og udgangshastighed for forskellige konfigurationer.
Den vandrette akse repræsenterer udgangshastighed pr. forespørgsel i tokens/s. Den lodrette akse bruger en logaritmisk skala til at vise throughput pr. maskine i tokens/s. Vi markerede Pareto-grænsen for hver EP-konfiguration med linjer i forskellige farver.
I scenarier med ekstremt høje krav til udgangshastighed kan brug af single-node EP8 DP1 TP8 med en batchstørrelse på 1 opnå en udgangshastighed på over 100 tokens/s, men throughput er ekstremt lav, svarende til udgangshastigheden. I dette scenarie har hele batchen kun 2 tokens, som kan sendes til højst 2*8=16 eksperter, hvilket aktiverer i alt højst 57B parametre.
I udgangshastighedsområdet 80-40 tokens/s faldt udgangshastigheden markant, i takt med at throughput steg. I modsætning hertil har EP128 ca. 5x højere throughput end single-node-implementering ved samme udgangshastighed.
Dette fænomen kan forklares ved at undersøge, hvordan single-node-implementeringer opfører sig: øget batchstørrelse korrelerer direkte med en stigning i aktiverede eksperter. Når batchstørrelsen er 1, er det gennemsnitlige antal aktiverede eksperter pr. GPU 2 * 8 / 8 = 2. Når batchen er stor nok, aktiveres alle eksperter, hvilket betyder, at hver GPU aktiverer 256 / 8 = 32 eksperter. Aktivering af flere eksperter betyder, at GPU'en skal læse flere parametre fra hukommelsen, hvilket øger presset på hukommelsesbåndbredden markant. Da afkodningsfasen for store sprogmodeller allerede er begrænset af hukommelsesbåndbredde snarere end beregningsydelse, reducerer øget batchstørrelse i single-node-implementering udgangshastigheden markant.
Sammenligning af de fire multi-node-implementeringskonfigurationer (EP16, EP32, EP64 og EP128) viser, at højere EP-værdier skubber Pareto-grænsen mod samtidige forbedringer i throughput og udgangshastighed.
Brug af et højere EP-tal betyder, at hver GPU tildeles færre eksperter. For eksempel betyder EP128, at hver GPU er ansvarlig for 256 / 128 = 2 eksperter, så presset på hukommelsesbåndbredden reduceres markant. Med andre ord, ved at bruge et større EP-tal opnår vi effektivt mere hukommelsesbåndbredde. Når batchstørrelsen pr. GPU er mindre end 64, påvirker øget batchstørrelse ikke ekspertberegningshastigheden markant, fordi øget antal input ikke øger presset på hukommelsesbåndbredden markant. Derfor observerer vi, at når man bruger EP128, påvirker øget batchstørrelse ikke udgangshastigheden så markant.
Interessant nok observerede vi ved større batchstørrelser (64 forespørgsler pr. GPU) et nyt fænomen: single-node-implementeringens throughput er lidt højere end multi-node-implementeringens. En del af årsagen er, at NVLink inden for en node har højere båndbredde end InfiniBand mellem noder. En anden del skyldes begrænsninger i vores implementering. Vi vil analysere dette fænomen nærmere senere.
På grund af begrænsninger i hukommelseskapaciteten kan EP8 DP8 TP1-konfigurationen ikke nå en batchstørrelse på 128 pr. GPU, så multi-node-implementering er stadig et bedre valg i scenarier, der forfølger højere throughput.
Overlappende beregning og kommunikation
Som kort introduceret ovenfor vedrørende Expert Parallelism er GPU'er inaktive under MoE-lagkommunikation. For at reducere spild og sænke latensen er vi nødt til at finde datauafhængige beregningsopgaver til at udfylde denne inaktive tid.
Den øverste del af ovenstående figur viser beregningsforløbet for ét lag. MoE-beregning afhænger af Dispatch, og det næste lags beregning afhænger af resultatet af Combine.
Vi placerer den delte ekspert på hver GPU. På denne måde kræver den delte eksperts beregning ikke AllToAll-kommunikation. Derfor kan vi udføre den delte eksperts beregning umiddelbart efter Dispatch Send, og derefter vente på, at Dispatch Recv fuldføres. Vi kalder dette overlappende skema "Dispatch Overlap".
Dispatch Overlap tilbyder ligetil implementering og bred anvendelighed. Denne teknik skjuler den delte eksperts beregningstid på tværs af alle EP-størrelser og batchstørrelser.
For yderligere at øge beregnings- og kommunikationsoverlap brugte vi mikrobatcing nævnt i DeepSeek-tekniske rapport til at bryde dataafhængighed. Som vist i den nederste del af figuren opdelte vi beregningen af ét Transformer-lag i 5 faser:
Fase 1: InputNorm, QKVProj, AppendKV, BMM
Fase 2: BMM, Attn, OProj, PostNorm, Gate
Fase 3: Dispatch Send, delt ekspert
Fase 4: Dispatch Recv, MoE, Combine Send
Fase 5: Combine Recv
I de første 3 Dense Transformer-lag bruger vi hele batchen. I de følgende 58 MoE Transformer-lag opdeler vi jævnt batchen i to mikrobatches. De to mikrobatches udføres skiftevis, forskudt med 3 faser. Da der ikke er nogen dataafhængighed mellem disse to mikrobatches, kan vi skifte til en anden mikrobatchs beregning efter Dispatch Send og efter Combine Send.
Latensfordeling
Dernæst sammenligner vi effekterne af overlapping gennem et eksperiment samt sammenligner ydeevneforskellene mellem single-node-implementering EP8 og multi-node-implementering EP128. For nemheds skyld brugte vi H100 GPU'er til det følgende eksperiment. Vi brugte TP1, en batchstørrelse på 128 pr. GPU, en forespørgselslængde på 2 pr. forespørgsel og en KV-cache-længde på 5000.
Figuren ovenfor viser den samlede tid brugt på ét MoE Transformer-lag og latensandelen for forskellige typer kerner. Undtagen Dispatch, Combine og GroupGEMM bør udførelsestiden for andre kerner være ens i EP8-, EP128 NoOverlap- og EP128 DispatchOverlap-serierne, fordi batchstørrelsen er den samme.
Overlappende
Lad os først sammenligne effekterne af de tre overlappende metoder. NoOverlap tog 2667 µs i alt, DispatchOverlap tog 2651 µs, hvilket sparer 16 µs eller kun 0,6%. MicroBatch viste en meget betydelig forbedring og tog 1896 µs, en hastighedsforøgelse på 29%. Både Dispatch- og Combine-tiden blev reduceret markant. Dispatch faldt fra 593 µs til 367 µs, og Combine fra 1012 µs til 237 µs.
Bemærk, at for beregningskerner øger opdeling af en batch på størrelse 128 i to batches på størrelse 64 den samlede udførelsestid. Selvom tiden brugt på kommunikation blev reduceret med 1001 µs, blev den samlede tid derfor kun reduceret med 771 µs. Vi vil forklare årsagen ved hjælp af Roofline-modellen i det følgende afsnit.
Af denne grund forbedrer mikrobatcing ikke altid ydeevnen.
Figuren ovenfor viser ydeevneforbedringen for Microbatch sammenlignet med DispatchOverlap for batchstørrelser 4-128. Når batchstørrelsen er mindre end 32, forringer Microbatch ydeevnen med 5%-40%. Når batchstørrelsen er større end eller lig med 32, kan Microbatch forbedre ydeevnen med 10%-35%.
EP8 vs EP128
Lad os vende tilbage til den forrige figur og sammenligne EP8 og EP128 Microbatch. EP8 tog 1802 µs i alt, lidt mindre end EP128's 1896 µs. Ud over den øgede kerneudførelsestid bragt af Microbatch nævnt ovenfor er de vigtigste forskelle i GroupGEMM, der bruges til MoE-beregning, og de to kommunikationskerner, Dispatch og Combine.
EP8's GroupGEMM tog 555 µs, mens EP128's GroupGEMM tog 270 µs, hvilket er en halvering. Dette er den kernefordel ved multi-node-implementering.
Desværre steg den tid, der blev brugt på kommunikation, med 213 µs, hvilket i høj grad opvejede fordelen ved GroupGEMM. I separate ydeevnetests af vores kommunikationskerner fandt vi ud af, at de kun kan opnå halvdelen af Infiniband-båndbredden. Vi vil fortsætte med at optimere vores kommunikationskerner.
En anden kerne, der halter betydeligt bagefter, er GEMM. Microbatch øgede GEMM med 95 µs. Vi vil analysere GEMM mere dybdegående i Roofline-afsnittet nedenfor. Vi mener, at den nuværende GEMM-implementering endnu ikke har opnået optimal ydeevne.
Roofline
Roofline-modellen er et godt værktøj til at analysere kernerydeevne. Dens vandrette akse er Aritmetisk Intensitet, forholdet mellem FLOP og hukommelses-I/O-bytes. Værdien på den vandrette akse kan beregnes direkte ud fra kernens semantik. Den lodrette akse repræsenterer opnået ydeevne, beregnet ved at dividere FLOP med benchmarklatens.
Den teoretiske øvre grænse for kernerydeevne bestemmes direkte af GPU'ens specifikationer. H100's FP8-toppræstation er 1979 TFLOP/s, repræsenteret som en vandret linje i Roofline-modellen. H100's hukommelsesbåndbredde er 3,35 TB/s, repræsenteret som hældningen af en linje, der går gennem origo. De to linjer giver ydeevnegrænserne for henholdsvis beregningsbundne og hukommelsesbundne kerner.
Nedenfor diskuterer vi ydeevnen for GroupGEMM- og GEMM-kernerne.
GroupGEMM
GroupGEMM-kernen i MoE udfører følgende beregning: Der er g grupper i alt, den i-te gruppe har m_i tokens, og udfører en matrixmultiplikation af [m_i, k] x [k, n] -> [m_i, n]. I ydeevnetest antager vi, at antallet af tokens i hver gruppe er det samme, betegnet som m_i = m. Så er FLOP-antallet for GroupGEMM 2 * g * m * k * n, og hukommelses-I/O-bytes er g * (m * k + n * k + m * n).
I DeepSeek-V3/R1-modellen er der 256 eksperter, og hver token sendes til 8 eksperter til beregning. Forudsat en batchstørrelse på 128, forespørgselslængde på 2, ved brug af EP128 DP128-konfiguration, er det gennemsnitlige antal tokens modtaget af hver ekspert (dvs. m) 128 * 2 * 8 * 128 / 256 = 1024. Tilsvarende kan vi beregne m for andre konfigurationer og batchstørrelser.
Vi brugte DeepGEMM's GroupGEMM-implementering til ydeevnetest. Testpunkter dækkede kombinationer af EP8-, EP16-, EP32-, EP64-, EP128-konfigurationer med TP1 og batchstørrelser 1-128.
Figuren ovenfor viser Roofline-modellen for GroupGEMM under forskellige EP-konfigurationer. Forskellig EP svarer til forskellige antal grupper. Figuren illustrerer næsten overlappende ydeevnelinjer, hvilket indikerer, at GroupGEMM-ydeevnen overvejende bestemmes af det samlede tokenantal (repræsenteret som g * m).
Stjernerne markerer datapunkterne svarende til en batchstørrelse på 128 pr. GPU for hver EP-konfiguration. Når man sammenligner disse stjernemarkerede datapunkter, kan vi se, at efterhånden som EP stiger (og DP stiger synkront), stiger antallet af tokens pr. ekspert m også. Ved EP8 er m=128, mens ved EP128 er m=2048.
Når m stiger, stiger den Aritmetiske Intensitet også. I de fleste konfigurationer er GroupGEMM begrænset af hukommelsesbåndbredde, så øget m forbedrer ydeevnen.
GEMM
GEMM-kernen svarer til Linear-projektioner i modellen, såsom Q/K/V/O-projektion. For en matrixmultiplikation af [m, k] x [k, n] -> [m, n] er FLOP-antallet 2 * m * k * n, og hukommelses-I/O-bytes er m * k + n * k + m * n. Vi kan også teste latensen for batchstørrelser 1-128.
Figuren ovenfor viser Roofline-modellen for GEMM under forskellige EP-konfigurationer. Vi kan se, at GEMM-ydeevnen er begrænset af hukommelsesbåndbredde. I takt med at batchstørrelsen stiger, stiger den Aritmetiske Intensitet også og forbedrer dermed ydeevnen.
Microbatch
Når vi bruger mikrobatcing, opdeler vi batchen jævnt i to dele. Fra de to ovenstående figurer kan vi se, at når m bliver m/2, falder effektiviteten af matrixmultiplikation. Derfor tager det længere tid at udføre to matrixmultiplikationer af størrelse m/2 end at udføre én matrixmultiplikation af størrelse m.
Multi-Token Prediction
Gennem denne artikel har vi antaget brugen af Multi-Token Prediction (MTP) til spekulativ afkodning. MTP ændrer forespørgselslængden pr. forespørgsel fra 1 til 2. For matrixmultiplikation svarer dette til at ændre m til m * 2, hvorved effektiviteten af matrixmultiplikation øges. På den anden side, hvis vi tegner Roofline-modellen for MLA, ville vi finde ud af, at øget forespørgselslængde øger MLA-kerneffektiviteten markant.
Derfor spiller brugen af MTP en vigtig rolle for modeleffektiviteten.
Implementering & optimeringer
I dette afsnit vil vi introducere nogle implementerings- og optimeringsdetaljer for vores DeepSeek-V3/R1-model.
Kvantisering
DeepSeek-V3/R1 blev oprindeligt trænede på FP8 ved hjælp af et per-block-kvantiseringsskema, hvor vægte kvantiseres statisk og aktiveringer kvantiseres on-the-fly. I stedet for at beregne en skaleringsfaktor pr. kanal eller pr. matrix statisk, beregnes skaleringsfaktorer på tværs af 128-elements vektorer for aktiveringer og 128x128 elements fliser for matrikser, hvilket begrænser nøjagtighedsforringelsen på grund af kvantisering.
Hos Perplexity stoler vi på en blanding af CUDA- og Triton-kerner til at understøtte inferens, hvor CUDA bruges til de mest ydeevnefølsomme og sjældent modificerede kerner (såsom opmærksomhed og GEMM), og hvor Triton implementerer en lang række aktiverings-, normaliserings- og hjælpekerner. Triton tillod os hurtigt at tilpasse kernerne til blokkvantiseringsskemaet.
For lineære og MoE-lag blander vi Deep GEMM-kernerne med vores egne Triton GEMM-kerner, da vi har bemærket, at for visse matrixdimensioner og lave batchstørrelser leverer Split-K lavere latens. Hvis det ukvantiserede lag udfører en (M, K) x (K, N)-multiplikation, behøver det (M x ceil_div(K, 128)) x (ceil_div(K, 128), ceil_div(N, 128)) skaleringsfaktor til blokkvantisering. Til blokkvantisering beregnes skaleringsfaktorerne for aktiveringer on-the-fly i stedet for at blive prækalibrerede. Da aktiveringsskaleringsfaktorer kun aggregeres langs K- og ikke langs M-dimensionen, kræver kernerne kun små ændringer for at understøtte skemaet.
SiLU-aktiveringsfunktionen, der bruges af DeepSeek-V3/R1, krævede væsentlige ændringer for at understøtte CUDA-grafer, blokkvantisering og dynamisk routerede token-antal. Blokkvantisering kan være problematisk, da det introducerer vandrette reduktioner, men kernen opdelte allerede aktiveringer langs deres skjulte dimension i blokke på 1024 elementer. Inden for én blok blev tensoren, der skulle kvantiseres, opdelt yderligere i blokke på 128 for at beregne den største absolutte værdi, hvor Triton genererede effektive cross-warp max-reduktioner, hvilket tilføjede minimalt overhead.
For at understøtte MoE-routing under CUDA-grafer skal kernerne være opmærksomme på routinginformationen, der angiver antallet af tokens pr. ekspert, i stedet for at planlægge arbejde baseret på størrelsen af de buffere, der blev tildelt til at rumme den øvre grænse for token-antallet. Vi kan ikke opdele problemet baseret på inputtensorernes dimensioner, så vi lancerer et fast antal vedholdende kerner, der læser routinginformationen for at bestemme, hvor mange tokens der er udfyldt, og opdeler arbejdet med at behandle aktiveringerne mellem dem dynamisk.
Vi har allerede upstreamet nogle af vores kerner til FlashInfer-projektet, og i fremtiden vil vi open-source mere af vores kode.
MLA-lag
Vi bruger FlashInfer til MLA-beregning. FlashInfer understøtter fleksible Pagtabel-indstillinger og ekstremt høj ydeevne.
Vi fusionerede q_a_proj og kv_a_proj til én enkelt qkv_a_proj. Latensen faldt fra 15,4 µs + 14,8 µs = 30,2 µs til 16,7 µs.
Vi dekomponerede kv_b_proj i to matrikser, k_b_proj og v_b_proj. Vi skrev en FP8 Block Quantized BMM-kerne til beregninger relateret til disse to matrikser.
Cuda Graph
Cuda Graph kan reducere kerne-lanceringsoverhead markant, hvilket er afgørende for ydeevnen. Vi opretter en Cuda Graph for hver batchstørrelse.
Før vi udviklede vores AllToAll-kerne, brugte vi torch.all_to_all_single() til AllToAll-kommunikation. Denne operation kræver, at alle GPU'er bruger den samme batchstørrelse. Forskellige DP-grupper kan dog køre med forskellige batchstørrelser.
For at sikre, at all_to_all_single() er kompatibel med forskellige DP-grupper, der bruger forskellige batchstørrelser, brugte vi først en allreduce()-operation før hver modelkørsel for at få den maksimale batchstørrelse blandt alle DP-grupper. Derefter fik vi alle DP-grupper til at bruge denne batchstørrelse til at køre.
Selvom denne tilgang sikrer, at vi kan bruge Cuda Graph, har den tre ulemper. For det første kræver den en yderligere allreduce()-operation. For det andet tvinges DP-grupper med mindre batchstørrelser til at udfylde. For det tredje gør den vores implementeringskode kompleks.
Efter at have implementeret vores egen AllToAll-kerne behøver vi ikke længere kræve, at alle GPU'er bruger den samme batchstørrelse. Derfor behøver vi ikke længere udføre yderligere allreduce()-operationer eller udfylde batchstørrelser.
MoE-router
MoE-routeren er implementeret i Triton og er afhængig af en modificeret sortering afledt af standardbiblioteket, som også holder styr på indeksene for de sorterede elementer. Implementeringen deles på tværs af alle MoE-modeller, da Mixtral-routing er et særligt tilfælde af DeepSeek-ruterne, hvor Top-K-gruppen er den samme som gruppen af alle eksperter. De sparse kerner forbruger Top-K-indeksene og scorene direkte, hvorimod dense dispatch/combine-skemaer, der er afhængige af all-to-all, kræver, at routinginformation aggregeres pr. ekspert i stedet for på et pr. token-basis.
Fremtidigt arbejde
I fremtidigt arbejde planlægger vi yderligere at optimere ydeevnen af DeepSeek-modellen.
Den vigtigste næste optimering er Prefill Disaggregation. Prefill-fasen og Decode-fasen i DeepSeek-V3/R1-modellen har meget forskellige beregningskarakteristika. Begge kan bruge forskellige optimeringsstrategier og implementeringsskemaer.
For MLA-laget i Decode-fasen bruger vi Matrix Absorption til at reducere FLOP-antallet af MLA-beregning. I Prefill-fasen ville det fungere bedre først at projicere den latente vektor ind i K/V-rum og derefter beregne i Multi-Head Attention (MHA)-form.
Hvis Prefill og Decode kører på den samme GPU, for at reducere påvirkningen af Prefill på Decode-udgangshastigheden, bruger vi typisk chunked prefill til at opdele forespørgslen i flere bidder til Prefill. Da KV-cachen gemmer den latente vektor, bliver det vanskeligt at konvertere MLA til MHA-form.
For MoE-laget i Decode-fasen bruger vi så store EP og DP som muligt for at øge antallet af inputtokens pr. ekspert og derved forbedre GroupGEMM-ydeevnen. I Prefill-fasen, fordi antallet af tokens allerede er stort nok, er GroupGEMM allerede beregningsbundet. Derfor kan vi for Prefill bruge mindre EP og DP.
Hvis Prefill og Decode kører på den samme GPU, vil latensen af MoE-lag på alle GPU'er stige, så længe en vilkårlig DP-gruppe udfører Prefill, hvilket påvirker Decode-udgangshastigheden markant.
Ud over Prefill Disaggregation planlægger vi også at optimere følgende aspekter:
AllToAll-ydeevne: Vores AllToAll-kerne kan i øjeblikket kun opnå 1/3 af Infiniband-båndbredden. Vi vil fortsætte med at optimere denne kerne.
EAGLE-stil spekulativ afkodning: I ovenstående data antog vi brug af spekulativ afkodning til at forudsige 1 token. EAGLE kan bruge en træstruktur til at forudsige flere tokens, hvilket forbedrer acceptlængden, hvilket kan øge udgangshastigheden markant.
GEMM-kerne: I den tidligere viste Roofline-model kan vi finde ud af, at effektiviteten af GEMM-kernen stadig er langt fra den teoretiske grænse. Vi vil fortsætte med at optimere denne kerne.
GB200 NVL72: I NVIDIA's seneste GB200 NVL72-løsning er 72 Blackwell GPU'er forbundet via højhastigheds-NVLink. For MoE-arkitekturmodeller er dette en meget stor mulighed og udfordring.
Konklusion
Multi-node-implementering af DeepSeek MoE-modeller opnår det, der typisk er umuligt med dense LLM'er: samtidig forbedring af både throughput og latens. Ved at distribuere eksperter på flere GPU'er reducerer vi presset på hukommelsesbåndbredden pr. enhed, hvilket muliggør hurtigere behandling og højere system-throughput. Vores eksperimenter viser EP128-konfigurationer, der opnår op til 5x højere throughput ved tilsvarende udgangshastigheder sammenlignet med single-node-implementeringer.
Overlappende teknikker til beregning og kommunikation som mikrobatcing reducerer overhead ved multi-node-kommunikation markant, hvor vores implementering viser op til 40% hastighedsforøgelse. Vores tilpassede AllToAll-kommunikationskerner og optimerede kerneimplementeringer har muliggjort effektiv implementering af modellen med 671B parametre.
Da MoE-arkitekturer vinder popularitet for deres kapacitet, giver disse implementeringsstrategier værdifuld indsigt i effektiv skalering af sådanne modeller.
Referencer
Oversigt over DeepSeek-V3/R1-inferenssystem
Megatron-LM: Træning af sprogmodeller med flere milliarder parametre ved hjælp af modelparallelisme
EAGLE: Spekulativ sampling kræver nytænkning af usikkerhed i features
Citering
@online{perplexity2025LowerLatencyAndHigherThroughputWithMultiNodeDeepseekDeployment,
author = {{Perplexity} and Lequn Chen and Nandor Licker and Erin McKnight},
title = {{Lower latency and higher throughput with multi-node DeepSeek deployment}},
date = {2025-04-18},
url = {https://perplexity.coolkeypoint.com/hub/blog/lower-latency-and-higher-throughput-with-multi-node-deepseek-deployment}
}