Aðskilin forskráning og afkóðun

Aðskilnaður forskráningar og afkóðunar milli tækja flýtir fyrir LLM-ályktun og bætir afköst

HöfundarPerplexity Research

Til að búa til úttakstákn úr inntaksbeiðni er LLM-ályktun skipt í tvö stig: forskráningu (prefill) og afkóðun (decode). Forskráning keyrir á inntakstáknum, útbýr KV-skyndiminni, áður en farið er í afkóðunarstigið sem býr til tákn eitt af öðru. Þótt ein afkóðunarskref taki venjulega tugi millisekúndna tekur forskráning töluvert lengri tíma. Ef þetta er keyrt á sömu tækjum dregur blöndun forskráningar og afkóðunar úr afköstum afkóðunar. Í þessari grein skoðum við viðurkennda lausn þar sem forskráning og afkóðun eru aðskilin og keyrð á sitthvorum tækjunum til að hámarka bæði afköst forskráningar og töf afkóðunar.

Afköst forskráningrar vs. afkóðunar

Í dæmigerðum LLM-þjónustuvél velur lotuáætlunariðbeiðnir til úrvinnslu í hverju keyrsluskrefi líkansins. Þegar keyrt er á einu tæki eða hnút eru bæði forskráningar- og afkóðunarbeiðnir settar í lotur saman. Kostnaður við athygli (attention), sem safnast saman eftir lengd raðarinnar, vex fyrir bæði forskráningu og afkóðun, í hlutfalli við lengd færslna í KV-skyndiminni (kv_len). Afkóðunarbeiðnir senda venjulega áfram stakt tákn (qo_len=1), með lágmarkskostnaði í gegnum önnur lög sem vinna sjálfstætt við tákn raðar. Forskráningarbeiðnir senda áfram þúsundir eða tíu þúsundir tákna með miklum kostnaði í gegnum þétt lög (stort qo_len).

Töf á framsendingu hefur meiri áhrif af fjölda sjálfstæðra tákna sem fara í gegnum þétt lög (qo_len) heldur en fjölda tákna sem sótt eru úr KV-skyndiminni við athygli (kv_len). Athygli getur dreift vinnslu bæði yfir fjölda beiðna og kv_len í hlutfalli við lengd raða og náð góðri nýtingu. Forskráning er takmörkuð af tölvuvinnslu: qo_len er hátt, GEMM-kjarnar geta úthlutað nægilegum blokkum meðfram M-víddinni til að nýta til fulls tölvuvinnslugetu nútíma GPU-skjákorta. Afkóðun er takmörkuð af minni: vegna venjulega lítilla lotustærða er fjöldi inntaka meðfram M yfirleitt lítill, nægilegur fyrir aðeins eina blokk. Þótt Split-K GEMM-kjarnar geti bætt SM-nýtingu fyrir litlar lotustærðir tákna, eru skyndiminni og fylkismargföldunareiningar yfirleitt vannýttar.

Lotaskipting í gegnum umbreytiklög, sem sýnir fyrirspurnar- og lykill/gildi vörpunir, athygli og uppfærslur á KV-biðminni.

Þegar þeim er blandað saman verða lotur sem innihalda beiðnir um forskráningu fyrir meiri töfum í framsendingu, sem hefur neikvæð áhrif á afköst afkóðunar alls tilviksins. Þótt blöndun forskráningarbeiðna við afkóðunarbeiðnir eða notkun skiptrar forskráningar geti bætt afkóðun af nokkru leyti, er erfitt að viðhalda nægilegum afköstum forskráningar til að vinna úr nægilegum fjölda beiðna á tilviki til að hámarka afköst afkóðunar. Í tilviki stórra líkana, með dæmigerðum úttakslengdum, til að viðhalda stórri lotustærð fyrir afkóðun, verður að framkvæma forskráningu oft genug til þess að það rýrir meðaltöf verulega og veldur hiksti í úttakinu.

Samsett áætlanagerð fyrir prefill og decode fyrir þrjár beiðnir, sem sýnir prefill- og decode-bil á sameiginlegri tímalínu.
Afmörkuð áætlanagerð fyrir prefill og decode, með sérstöku prefiller-þrepi sem fæðir decode-vinnu fyrir þrjár beiðnir.

Hægt er að leysa þessi vandamál með því að nota aðskilið safn hnúta til að framkvæma forskráningu og afkóðun. Með því að tengja forskráningarhnút við marga afkóðunarhnúta er hægt að tímasetja nægilegar beiðnir um forskráningu til að hámarka afköst og viðhalda nægilega mörgum samideðjum á afkóðunarhnútunum til að hámarka einnig afköst afkóðunar. Forskráningarhnútarnir fylla KV-skyndiminnið, sem er síðan flutt á afkóðunarhnútana. Þar sem afkóðararnir þurfa ekki lengur að gera hlé vegna forskráningar verða tafirnar mun ákveðnari, þar sem heildaráhrif vaxandi kv_len virkra beiðna eru mun minni. Kostnaðurinn birtist í auknum tíma að fyrsta tákni (TTFT), þar sem flutningur KV-skyndiminnis um netið getur tekið tugi til hundruð millisekúndna.

KV Messenger

Hjá Perplexity er útfærsla okkar fyrir aðskilda forskráningu og afkóðun byggð í kringum KV-skilaboðamiðlara sem hefur samskipti við LLM-vélina til að stýra flutningi KV-skyndiminnis frá forskráningarhnútum til afkóðunarhnúta í gegnum net. Hinu megin við forskráninguna tekur skilaboðamiðlarinn við beiðnum frá afkóðunarhnútum, afhendir þær lotuáætlunaranum og fylgist með keyrslu framsendingar til að senda KV-skyndiminni af stað með sem minnstri töf. Hinu megin við afkóðunina, eftir að síður sem ekki er hægt að vísa út eru úthlutaðar, stöðvar skilaboðamiðlarinn beiðnina um að vera tímasett til afkóðunar þar til hann fær tilkynningu um að flutningi KV-skyndiminnis og afkóðunarsamhengis sé lokið.

Afmörkuð lífsferilsferill beiðna, sem sýnir samhæfingu milli decoder og prefiller og flutning á KV-biðminnisgögnum.

Aðskilnaður forskráningar krefst mikilla afkasta og lágtafatengingar, þess vegna er útfærsla okkar sniðin að RDMA, sem styður bæði EFA og ConnectX Network Interface Controllers (NIC). KV Messenger er byggt á libfabric, og notar fabric-lib umbúðir okkar til að bjóða upp á hærra stigs lágtafaabstraktioner yfir RDMA-grunneiningar (Remote Direct Memory Access), sem útfæra skilvirkan flutning á síðum og lýsigögnum ásamt lágtafamerkjagjöf. Í bakgrunni samræmir fabric-lib GPU-skjákort og beintengda NIC-millistykki þess til að afrita gögn frá forskráningarhnút yfir á afkóðunarhnút.

Við móttöku úthlutar forskráningarhnúturinn samsvarandi safni upprunalegra KV-síðna og áætlar beiðnina um forskráningu með staðbundinni vél sinni. Til að lágmarka töf bíða flutningar ekki eftir framsendingu: í staðinn eru afritanir KV-síðna settar af stað um leið og líkanið klárar að bæta við KV-skyndiminni í KV-skyndiminni fyrir stök lög. Þar sem hægt er að skipta forskráningarbeiðnum upp tilkynnir lotuáætlunarið KV-skilaboðamiðlaranum um þær sneiðar sem nú þegar eru áætlaðar fyrir keyrslu. Til að styðja CUDA-myndrit en geta samt fylgst með lögum heldur skilaboðamiðlarinn úti sérstökum þræði sem kannar teljara sem hækkar eftir úttaksbörpun athyglar. Teljarinn er aðeins viðhaldið á aðalhnút í skiptu umhverfi: þótt færslur KV-skyndiminnis séu gildar eftir viðbót og fyrir athygli, er úttaksbörpunin dregin saman þvert á röðum, sem samstillir þær óbeint. Þegar breyting sést á teljaranum fær skilaboðamiðlarinn tilkynningu og kallar á fabric-lib til að hefja flutning á lagi.

KV-biðminnisflutningar lag fyrir lag, sem sýna skiptis- og einskiptisritanir og lokatalninga milli prefiller og decoder.

Eftir að flutningi síðustu sneiðar er lokið eru öll viðbótarlýsigögn einnig afrituð yfir: spekúlatíf afkóðun eða MTP krefjast þess að logits og faldar stöður séu fluttar til afkóðarans. Þessar afritunaraðgerðir eru einnig framkvæmdar í gegnum RDMA, í og úr fyrirfram úthlutaðum biðminnum.

Við lok allra biðflutninga á síðustu sneið eyðir forskráningarhnúturinn úthlutun KV-síðnanna og klárar beiðnina. Afkóðunarhnúturinn fær ekki beina tilkynningu: í staðinn notar hann milliteljara til að fylgjast með fjölda lokinna aðgerða. Fjöldi RDMA-aðgerða á forskráningarhliðinni er í hlutfalli við fjölda fluttra síðna. Við lok hins þekkta fjölda síðu- og samhengisafritunar kallar fabric-lib á KV-skilaboðamiðlarann til að gefa til kynna að beiðni sé tilbúin til afkóðunar. Skilaboðamiðlarinn felldar niður úthlutun alls samhengis og afhendir beiðnina til LLM-vélarinnar.

Flutningur á skiptu KV-skyndiminni

Ef forskráningarhnútur og afkóðunarhnútur reiða sig á Tensor Parallelism (TP) og skipta eða endurtaka KV-skyndiminnið eins, samræmir ein flutningsvél mörg tæki til að senda og taka móti síðum allra afrita. Til þess að geta notað einn skilaboðamiðlara og flutningsvél þrátt fyrir að keyrsluforrit líkansins sé endurtekið yfir mörg tæki og ferla, eru cuMem og cuMemImportFromShareableHandle notuð til að úthluta tækjamenninu sem stendur á bak við KV-skyndiminnið og kortleggja það inn í aðalferlið. Flutningsvélin skoðar netkerfisskipulag hnútsins til að finna NIC-millistykki og örgjörva í næsta NUMA-hnúti til að nota fyrir flutning á hverjum hlut KV-skyndiminnis.

Ef uppruna- og áfangastaður skiptast eins eru flutningar einfaldir þar sem eitt-á-móti-einu kortlagning er til staðar frá tækjum og síðum uppruna og áfangastaðar. Í þessari stöðu hjálpar skiptingin óbeint við flutningstafir: með því að nota fleiri GPU-skjákort er hægt að nota fleiri tengd NIC-millistykki, sem nær nær fullri bandbreiddarnýtingu. Hins vegar, ef misræmi er til staðar, verður flutningsvélin að skipta eða endurbyggja síður eftir hlutfalli milli uppruna- og áfangastaðarsneiða.

Flutningatopólógía KV-biðminnis milli TP/EP prefiller og DP/EP decoders, sem sýnir tengingar NIC.

Ef forskráningarhnúturinn skiptir KV-skyndiminni yfir á fleiri tæki eru fullar síður endurbyggðar á afkóðaranum með því að senda samsvarandi helminga út frá forskráningartækjunum. Ef afkóðarinn er með fleiri sneiðar tekur hann við síðum frá mörgum upprunum. Afkóðarinn þarf að vita af skiptingarkerfi forskráningarhnútsins til að geta reiknað út fjölda RDMA-skrifa sem hann á von á að fá. Ef endurtekning kemur við sögu flokkar forskráningarhnúturinn tækin í afritasett sem endurtaka fullt KV-skyndiminni innan sín. Áfangastaðarafritasettum er úthlutað af handahófi einu af upprunasettunum til að nota öll tiltæk tæki til að hefja RDMA-skrif.

NHD- og HND-uppsetningar KV-biðminnis, sem andstæða röð tokna og hausa innan hvers lags og hverrar síðu.

Skiptir flutningar krefjast lítillar breytingar á KV-skyndiminni. Sjálfgefið er að FlashInfer reiðir sig á NHD-skipulagið, sem raðar táknum innan síðu innan hausanna. Þar sem skyndiminni eru líklega skipt meðfram fjölda athyglishausa veldur þetta ósamfellu innan hausanna. RDMA-flutningar styðja ekki óbeint milliskrif, sem krefst einnar aðgerðar á haus til að framkvæma flutninginn. Í staðinn, til að fækka samskiptum við libfabric, skipuleggjum við KV-skyndiminni með því að nota HND-skipulagið sem staðsetur hausvíddina á undan fjölda tákna. Þetta tryggir samfellu og gerir kleift að afrita síðu með einni skrifaðgerð.

Spekúlatíf afkóðun

Spekúlatíf afkóðun krefst smávægilegra breytinga á aðskilinni forskráningu og afkóðun. Í útfærslu okkar er forskráningarhnútum ekki leyft að taka úrtak úr táknum. Þar sem Sonar-líkön Perplexity styðja skipulagt úttak viljum við ekki taka á okkur þá flækju að samstilla útfærslur skemaörgjörva milli forskráningar og afkóðunar. Í MTP og spekúlatífum afkóðunarkerfum felur forskráning dráttarlíkansins upp að síðasta tákninu í sér að taka úrtak úr marklíkaninu.

Tilgátuleg afkóðun milli prefiller og decoder, sem sýnir lengd KV-biðminnis, logits og sýnatöku á táknum.

Til að vinna framhjá þessum vandamálum tekur forskráning ekki með síðasta tákn inntaksraðarinnar. Í staðinn eru faldar stöður eða logits úr forskráningu á undan síðasta tákni fluttar og það er meðhöndlað sem afkóðunartákn í næsta skrefi á afkóðaranum. Þótt þetta auki tafir lítillega, þar sem fullt afkóðunarskref verður að fara fram eftir forskráningu til að gefa út fyrsta táknið, minnkar flækja útfærslunnar til muna.

Aðskildar útgáfur

Við höfum sett upp eða gert tilraunir með margar aðskildar uppsetningar með mismunandi líkönum, til að styðja annað hvort framleiðsluumferð eða innri matsvinnuálag. Miðað við stærð og athygliskerfi líkana völdum við hentug skiptingarkerfi fyrir forskráningar- og afkóðunarhnúta til að nýta GPU-skjákort sem best.

DeepSeek-R1

Með DeepSeek skoðuðum við bæði Tensor-Parallel (TP) og Data-Parallel (DP) uppsetningar. Eins og fjallað hefur verið um í fyrri bloggfærslum veita TP-uppsetningar betri töf og kostnað vegna minni afkösta, og krefjast fleiri GPU-skjákorta til að þjóna mikilli umferð. DP-uppsetningar skalast mun betur með álagi, þó eru hámarksafköst þeirra lægri vegna kostnaðar við samskipti milli tækja eða hnúta.

DeepSeek reiðir sig á Multi-Head Latent Attention og þjappar saman KV-skyndiminni. Þar sem öllum KV-hausum er þjappað saman í einn duldann vigur getur TP ekki skipt KV-skyndiminni, þar sem það verður í staðinn að endurtaka duldu vigrana á öllum röðum. Skipting á sér stað eftir þjöppun, þar sem hver röð getur dregið út mismunandi hausa úr sömu duldustu framsetningu. Þess af leiðandi eru öll KV-skyndiminni sneiðar eins á milli bæði forskráningar- og afkóðunarsneiða.

Með TP-uppsetningu innan hnúts eru bæði forskráningar og afkóðarar skiptir eins. Flutningar eru sendir frá öllum röðum til að nýta öll tiltæk NIC-millistykki til fulls. Hins vegar, með DP-uppsetningu, þar sem TP-raðastærðin er minni eða hverri DP-röð er úthlutað á eitt GPU-skjákort, getur hvaða forskráningartæki sem er sem geymir endurtekið afrit af KV-skyndiminni sent það. Til að jafna beiðnir yfir öll tiltæk NIC-millistykki veljum við af handahófi GPU-skjákort og NIC-millistykki til að senda KV-skyndiminnið frá forskráningarhnút til afkóðunarhnúts.

Með blandaðri forskráningu og afkóðun átti R1-uppsetning okkar í erfiðleikum með að fara stöðugt yfir 50 TPS vegna tíðra forskráningarhlés upp á hundruð millisekúndna. Aftur á móti, með því að aðgreina forskráningu, urðum við fyrir um 100ms refsingu á TTFT fyrir hverja beiðni, en einn forskráningarhnútur gæti haldið stöðugum lotustærðum á 3 afkóðunarhnútum ogilað út afköst yfir 90 TPS á meðan hann tók við álagi um það bil 1 QPS á hvern afkóðunarhnút. Með gagnaparruppsetningum voru TPS nokkuð lægri í kringum 50, en tilvikin gátu tekist á við álag upp á 1 QPS á röð, með 8 röðum á einn hnút.

Qwen3-Coder

Þetta 480B líkan notar Grouped-Query Attention (GQA), þannig að auðvelt er að skipta athygli og hún getur notið góðs af tensor-samsvörun án þess að fórna minni fyrir KV-skyndiminni. Þess vegna gátum við skipt líkaninu yfir 8 GPU-skjákort fyrir bæði forskráningu og afkóðun, og parað um 3 afkóðunarhnúta við einn forskráningarhnút. Þar sem athygli er skipt reiðum við okkur á HND KV-skyndiminni skipulagið til að skipta forskráningar- og afkóðunar KV-skyndiminni, para forskráningarraðir við afkóðunarraðir og nýta öll NIC-millistykki til fulls til að flytja sneiðar samhliða.

Tilvitnun

BibTeX
@online{perplexity2025DisaggregatedPrefillAndDecode,
  author = {{Perplexity} and Nandor Licker and Lequn Chen and Kevin Hu and Erin McKnight and Phi Hoang},
  title = {{Disaggregated prefill and decode}},
  date = {2025-08-01},
  url = {https://perplexity.coolkeypoint.com/hub/blog/disaggregated-prefill-and-decode}
}