Viktöverföring för RL-postträning på under 2 sekunder
Ultrasnabb modellsynk mellan GPU:er
Vi uppnådde nyligen 1,3 sekunders parameteruppdateringar mellan maskiner för Kimi-K2 (1T-parametrar) genom att överföra vikter från 256 tränings-GPU:er (BF16) till 128 inferens-GPU:er (FP8).
Vid finjustering med asynkron förstärkningsinlärning körs träning och inferens på separata GPU:er. Efter varje träningssteg måste nya vikter skickas till inferensnoder. Många befintliga ramverk tar flera sekunder – eller till och med minuter – för modeller med biljoner parametrar.
Genom att utnyttja RDMA-punkt-till-punkt-kommunikation kan vi göra viktöverföringen blixtsnabb utan att ändra inferensmotorn, samt göra koden enklare att skriva och underhålla.
RDMA WRITE: ensidiga överföringar
Vår lösning är byggd på RDMA WRITE, en ensidig primitiv där källan direkt skriver till destinationens GPU-minne.
def rdma_write(src_ptr, dst_ptr, size, src_mr, dst_mr):
# Write from local [src_ptr, src_ptr+size) to remote [dst_ptr, dst_ptr+size).
# src_mr and dst_mr contains Memory Region metadata of both sides.
...Destinationssidan får inte ens en meddelandenotis om överföringen. Detta ger oss överföringar med låg latens, hög genomströmning och noll kopiering som styrs av träningsnoderna utan kontrolllogik på inferensnoderna.
Övergripande arbetsflöde
Metadatainsamling – Kontrollern samlar in parametermetadata från alla tränings- och inferens-GPU:er.
Schemaberäkning – Kontrollern beräknar ett statiskt schema för viktöverföring som mappar vilken tränings-GPU som skickar vilken parameter till vilken inferens-GPU, och i vilken ordning.
Schemadistribution – Kontrollern skickar schemat till alla tränings-GPU:er.
Utförande – Efter varje träningssteg signalerar kontrollern till tränings-GPU:erna att starta överföringarna.
Utförande av viktöverföring
Med det övergripande arbetsflödet definierat är den stora utmaningen hur man utför viktöverföringar effektivt i en skala med biljoner parametrar. Här beskriver vi detaljerna för exekveringsvägen.
DeviceMesh och Mesh-grupper
Parametrar i träning distribueras enligt FSDP-placeringar. Genom att använda full_tensor() kan alla GPU:er i ett DeviceMesh återskapa hela parametern, och därmed kan alla fungera som källa för viktöverföring.
Flera disjunkta DeviceMesh bildar en mesh-grupp. Eftersom DeviceMesh i samma grupp är disjunkta stör inte deras överföringar varandra och kan köras helt parallellt. Mellan mesh-grupper infogar vi en global barriär för att säkerställa ordningsföljd.
Uppgiftspipeline
Vi behandlar överföringen av varje parametertensor som en uppgift. Viktöverföringsprocessen använder flera typer av hårdvarukällor, vilket är anledningen till att vi delar upp en viktöverföringsuppgift i olika pipelinesteg som överlappar i tid:
Host-till-enhet-memcpy – Om FSDP offloadar vikt till CPU
Parameterförberedelse – Återskapa full vikt med full_tensor(), tillämpa projektionsfusion, kvantisera vid behov.
RDMA-överföring – Nollkopieringsskrivning till fjärrminnet för inferens-GPU
Global barriär – När alla full_tensor()-anrop är klara, synkronisera över mesh-grupper med GLOO via Ethernet.
Vid implementering underhåller vi en FIFO-kö med uppgifter för varje pipelinesteg. När den främsta uppgiften i kön slutför steget flyttas den till slutet av nästa stegs kö.
Kontroll av GPU-minnesanvändning
full_tensor() och andra GPU-operationer introducerar extra GPU-minnesanvändning. För att undvika slut-på-minne-fel (OOM) startar vi utförandet av en uppgift endast om de aktuella pågående uppgifterna upptar mindre tillfälligt GPU-minne än en konfigurerbar tröskel.
Varför det är snabbt och enkelt
Flera designval gör vårt system betydligt snabbare att köra och enklare att underhålla än vanliga open source-lösningar.
Punkt-till-punkt-kommunikation
Ett vanligt mönster är att kanalisera alla parametrar genom rang-0-GPU:er: samla in på tränings-rang-0, skicka till inferens-rang-0 och sedan sprida ut igen. Detta blir snabbt en flaskhals, begränsad av en enda GPU:s PCIe-bandbredd och NIC (t.ex. 400 Gbps ≈ 50 GB/s).
Vår punkt-till-punkt-konfiguration tillåter däremot varje tränings-GPU att skicka direkt till varje inferens-GPU, vilket mättar hela nätverksstrukturen snarare än en enskild länk.
Ensidig dataöverföring
Vissa system förlitar sig på att anropa inferensmotorns metod update_weight() för varje tensor. Det innebär påträngande ändringar i inferenskoden samt omkostnader från RPC:er, serialisering och kontrollplanskoordinering.
Med RDMA WRITE-primitiven uppdaterar vi vikter tyst i inferens-GPU-minnet utan extra kopior. Inget kontrollplansmeddelande och ingen CPU-kontrolllogik är involverad. Ingen modifiering av inferensmotorn krävs.
Pipelining
Viktöverföringsprocessen kan utnyttja fyra typer av hårdvaruresurser: (1) Dataflytt mellan värd och enhet (2) GPU-beräkning för projektionsfusion och kvantisering (3) RDMA-nätverk för dataplan (4) Ethernet för kontrollplan.
Vår design delar upp viktöverföringsuppgifter i pipelinesteg, vilket möjliggör enkel överlappning mellan olika hårdvaruresurser.
Statiskt schema
Vissa implementeringar beräknar om ett överföringsschema vid varje träningssteg genom att upprepade gånger samla in metadata och distribuera instruktioner. Detta lägger till onödig latens i kontrollplanet.
Vårt schema beräknas en gång vid initiering. Varje träningsiteration spelar helt enkelt upp planerna igen: kontrollern utfärdar en ”kör”-signal och GPU:erna följer sina förutbestämda vägar. Utförandet är förutsägbart och lättviktsorienterat.
Ren separation
Det är frestande att fläta in hela viktuppdateringsprocessen i en enda monolitisk funktion: samla in metadata, namnmatchning, samling inom noden, projektionsfusion, kvantisering, uppdelning av kommunikationsvärlden och nätverksöverföring mellan noder. Det är svårt att programmera korrekt och ännu svårare att optimera.
I vår konstruktion separerar vi dessa steg som individuella komponenter. Varje komponent kan enhetstestas, analyseras och optimeras isolerat.
Slutsats
Snabb och tillförlitlig viktöverföring är en kritisk byggsten för storskalig RL-finjustering. Genom att kombinera RDMA WRITE-primitiven, ett statiskt överföringsschema och pipelined exekvering reducerade vi uppdateringar av biljoner parametrar till endast 1,3 sekunder på Kimi-K2. Tillvägagångssättet är enkelt att resonera kring, lätt att underhålla och undviker flaskhalsarna i traditionella designer.
Citat
@online{perplexity2025WeightTransferForRlPostTrainingInUnder2Seconds,
author = {{Perplexity} and Lequn Chen and Erin McKnight and Vivian Wang},
title = {{Weight transfer for RL post-training in under 2 seconds}},
date = {2025-09-24},
url = {https://www.perplexity.ai/hub/blog/weight-transfer-for-rl-post-training-in-under-2-seconds}
}