Optimizacija sklepanja je ključni del generativnih aplikacij umetne inteligence, ki se uporabljajo v proizvodnji. Učinkovita uporaba LLM v velikem obsegu je izziv, zato so bile v zadnjih letih razvite številne tehnike za hitrejše in cenejše sklepanje. V tem članku si oglejmo te tehnike.
Vsi veliki jezikovni modeli (LLM) temeljijo na arhitekturi transformatorja, ki so jo leta 2017 izumili Vaswani et al. Arhitektura transformatorja dosega vrhunsko natančnost, učenje z nekaj posnetki in skoraj človeške sposobnosti pri različnih jezikovnih nalogah. Vendar je te temeljne modele, ki pogosto vsebujejo od desetine do stotine milijard parametrov, drago usposabljati, med sklepanjem pa zahtevajo veliko virov. Stroški sklepanja se povečajo pri dolgih vhodnih kontekstih, ki zaradi velikih vhodnih podatkov zahtevajo veliko procesorske moči. Zato je učinkovito sklepanje ključni izziv, zlasti pri upravljanju pomnilnika in računalniških virov.

Natančneje, večina znanih LLM je samo dekodirnih LLM, kot so GPT-3, GPT-4, LLaMA, Mistral, DeepSeek itd. Ti modeli so predhodno usposobljeni za nalogo vzročnega modeliranja in delujejo kot napovedovalci naslednje besede. Obdelajo zaporedje žetonov kot vhod in avtoregresivno ustvarijo naslednje žetone, dokler ni dosežen pogoj za ustavitev.
Ugotavljanje LLM v modelih samo z dekoderjem vključuje dve ključni fazi: fazo predizpolnjevanja in fazo dekodiranja. V fazi predizpolnjevanja model obdela vhodne žetone, da izračuna vmesna stanja (ključe in vrednosti) za generiranje prvega novega žetona. Ta faza, ki spominja na operacijo matrika-matrika, je močno paralelizirana in učinkovito izkorišča zmogljivosti grafičnih procesorjev. Nasprotno pa faza dekodiranja generira žetone, enega za drugim, pri čemer se opira na stanja prejšnjih žetonov. Ta matrično-vektorska operacija je vezana na pomnilnik, saj prenos podatkov na GPU namesto hitrosti izračuna določa predvsem zakasnitev, kar vodi do premalo izkoriščene računske moči GPU.
Optimizacija faze dekodiranja je osrednja točka za reševanje izzivov pri sklepanju. Rešitve vključujejo razvoj učinkovitih mehanizmov pozornosti ter boljše upravljanje ključev in vrednosti za zmanjšanje ozkih grl v pomnilniku. V prispevku so poudarjeni praktični pristopi za izboljšanje učinkovitosti sklepanja, ob predpostavki, da imajo bralci osnovno razumevanje arhitekture transformatorja in mehanizmov pozornosti. Te optimizacije so ključnega pomena za izboljšanje prepustnosti in zmanjšanje zakasnitev v resničnih namestitvah LLM.
Dodaten zaplet povzroča uporaba različnih označevalnikov v različnih programih LLM, kar vpliva na primerljivost označevalnikov. Žetoni, ki so približno enakovredni štirim angleškim znakom, se glede na tokenizator razlikujejo v predstavitvi, zato so neposredne primerjave zmogljivosti sklepanja (npr. žetoni na sekundo) zavajajoče. Ta spremenljivost poudarja potrebo po standardiziranih metrikah za ocenjevanje, da bi lahko natančno ocenili in primerjali učinkovitost LLM med sklepanjem.
Razdelitev v serije je ključna strategija za izboljšanje izkoriščenosti in prepustnosti grafičnih procesorjev v velikih jezikovnih modelih (LLM). S hkratno obdelavo več zahtevkov z uporabo istega modela se stroški pomnilnika za uteži modela porazdelijo med zahtevke, kar omogoča, da se pri večjih serijah uporabi več računske moči GPU. Vendar pa je velikost serije omejena, saj lahko prevelike serije zaradi pomnilniških zahtev modelov LLM, zlasti povezanih s predpomnilnikom ključ-vrednost (KV) (več o tem pozneje), povzročijo preveliko količino pomnilnika.

Tradicionalno ali statično združevanje ima omejitve, saj zahteve znotraj serije pogosto ustvarijo različno število žetonov dokončanja, kar vodi do različnih časov izvajanja. Zaradi tega vsi zahtevki čakajo na dokončanje najpočasnejšega, kar je lahko problematično, če se dolžina generiranja močno razlikuje. Za reševanje tega problema so bile razvite napredne tehnike, kot je paketno izbiranje med letom, ki optimizirajo zmogljivost.
Doziranje med letom, znano tudi kot neprekinjeno doziranje, rešuje izzive, ki jih prinaša dinamična narava delovnih obremenitev LLM, ki lahko segajo od preprostih odzivov klepetalnikov do zapletenega povzemanja dokumentov ali generiranja kode. Ta opravila ustvarjajo izide zelo različnih velikosti, zato je zahtevke težko učinkovito vzporedno razvrščati v serije in izvajati. V nasprotju s statičnim paketnim izvajanjem omogoča paketno izvajanje med letom strežniku, da dokončane sekvence takoj izloči iz paketa in začne obdelovati nove zahteve, medtem ko druge še vedno potekajo. Ta pristop znatno poveča izkoriščenost grafičnih procesorjev, saj se prilagaja različnim časom izvajanja zahtevkov v resničnih scenarijih.
Paralelizacija modelov je ključna strategija za upravljanje pomnilniških in računskih zahtev obsežnih modelov strojnega učenja z njihovo porazdelitvijo med več grafičnih procesorjev. Ta pristop omogoča obdelavo večjih modelov ali vhodnih paketov, ki presegajo pomnilniško zmogljivost posamezne naprave, zaradi česar je bistvenega pomena tako za učenje kot sklepanje, kadar so pomnilniške omejitve stroge. Obstajajo različne tehnike za razdelitev uteži modelov, vključno s paralelizmom cevovodov, tenzorskim paralelizmom in paralelizmom zaporedij, pri čemer vsaka obravnava različne vidike porazdelitve modelov. Za razliko od podatkovnega paralelizma, ki se osredotoča na razmnoževanje modelskih uteži po napravah za obdelavo večjih vhodnih serij med usposabljanjem, so te metode pomembnejše za zmanjšanje pomnilniških odtisov med usposabljanjem in sklepanjem.

Vzporednost cevovodov model vertikalno razdeli na zaporedne dele, pri čemer vsak del vsebuje podmnožico slojev, dodeljenih ločeni napravi. Na primer, pri štirismerni postavitvi cevovoda vsaka naprava obdeluje četrtino slojev modela in izhode zaporedno posreduje naslednji napravi. To sicer znatno zmanjša potrebe po pomnilniku na napravo, vendar pa uvaja neučinkovitosti, znane kot "mehurčki cevovoda", pri katerih lahko naprave med čakanjem na izhode iz prejšnjih slojev delujejo v prostem teku. Mikrobatching, ki vhodne serije razdeli na manjše podserije za zaporedno obdelavo, lahko te mehurčke zmanjša, vendar jih ne odpravi v celoti, saj časi mirovanja ostanejo med prehodi naprej in nazaj.
Tenzorski paralelizem pa posamezne plasti horizontalno razdeli na manjše računske bloke, ki se lahko izvajajo neodvisno na različnih napravah. To je še posebej učinkovito za komponente transformatorjev, kot so bloki pozornosti in večplastni perceptroni (MLP), kjer se lahko na primer različne glave pozornosti dodelijo ločenim napravam za vzporedno izračunavanje. Vendar pa je tenzorski paralelizem manj učinkovit pri operacijah, kot sta LayerNorm in Dropout, ki jih ni mogoče enostavno razdeliti in jih je treba replicirati po napravah, kar vodi do odvečne uporabe pomnilnika za shranjevanje aktivacij. Ta omejitev poudarja potrebo po dopolnilnih pristopih za optimizacijo učinkovitosti pomnilnika.
Paralelizem zaporedja odpravlja pomnilniško neučinkovitost operacij, kot sta LayerNorm in Dropout, tako da jih razdeli vzdolž dimenzije vhodnega zaporedja in izkoristi njihovo neodvisnost od elementov zaporedja. Ta metoda zmanjša pomnilniški odtis odvečnih aktivacij, zaradi česar je dragoceno dopolnilo tenzorskemu paralelizmu. Te tehnike paralelizacije se med seboj ne izključujejo in jih je mogoče kombinirati za nadaljnjo optimizacijo velikih jezikovnih modelov (LLM). Poleg tega lahko posebne strategije optimizacije za modul pozornosti povečajo skalabilnost in zmanjšajo pomnilniške zahteve na procesor, kar omogoča učinkovitejše usposabljanje in sklepanje za velike modele.
V članku *Attention Is All You Need* iz leta 2017, ki so ga napisali Vaswani in drugi, je bil predstavljen model Transformer, katerega temelj je bila samopozornost. Samopozornost modelu omogoča, da oceni pomembnost različnih besed v stavku glede ena na drugo, kar izboljša razumevanje konteksta za naloge, kot je obdelava naravnega jezika. Članek je formaliziral samopozornost, zlasti z mehanizmom SDPA (scaled dot-product attention), ki kartira pare poizvedba in ključ-vrednost v izhod, zaradi česar je ključna sestavina sodobnih nevronskih mrež. V nadaljevanju so predstavljene nekatere najpomembnejše tehnike za optimizacijo izračunov pozornosti:

Večglava pozornost (MHA) nadgrajuje SDPA z vzporednim izvajanjem več operacij pozornosti, pri čemer se vsaka izvaja z različnimi projekcijami matrik poizvedb, ključev in vrednosti. Te vzporedne operacije ali "glave" se osredotočajo na različne reprezentacijske podprostore, s čimer model obogati svoje razumevanje vhodnih podatkov. Rezultati teh glav so združeni in linearno projicirani, pri čemer se z zmanjšanjem dimenzionalnosti vsake glave (npr. z deljenjem dimenzije modela s številom glav, npr. 8) ohrani računska učinkovitost, primerljiva z učinkovitostjo pozornosti z eno glavo.
Pozornost na več poizvedb (MQA) optimizira MHA za sklepanje z delitvijo projekcij ključev in vrednosti med več glavami pozornosti, pri čemer ohranja projekcije več poizvedb. S tem se zmanjšajo potrebe po pomnilniški pasovni širini in velikost predpomnilnika ključ-vrednost (KV), kar omogoča večje serije in boljši izkoristek računala. Vendar pa lahko MQA nekoliko zmanjša natančnost, modeli, ki ga uporabljajo, pa zahtevajo usposabljanje ali natančno nastavitev z omogočenim MQA, da se ohrani zmogljivost.
Pozornost na skupinske poizvedbe (GQA) usklajuje MHA in MQA z združevanjem glav poizvedb in deljenjem projekcij ključnih vrednosti znotraj vsake skupine, s čimer doseže kakovost, ki je blizu MHA, z računsko učinkovitostjo, ki je bližje MQA. Modeli, kot je Llama 2 70B, uporabljajo GQA, modeli, ki so bili usposobljeni za MHA, pa se lahko prilagodijo na GQA z minimalnim dodatnim usposabljanjem. Tako MQA kot GQA zmanjšata potrebe po pomnilniku predpomnilnika KV, čeprav so potrebne nadaljnje optimizacije pri upravljanju predpomnilnika.
FlashAttention izboljšuje mehanizme pozornosti s spreminjanjem vrstnega reda izračunov za učinkovitejše izkoriščanje hierarhij pomnilnika GPU. Za razliko od tradicionalne obdelave po plasteh FlashAttention združuje operacije in uporablja "tiling" za izračunavanje majhnih delov izhodne matrike naenkrat, kar zmanjšuje operacije branja/pisanja v pomnilnik. Ta algoritem natančne pozornosti, ki upošteva vhodno-izhodni sistem, se brez težav vključi v obstoječe modele brez spreminjanja in z optimizacijo premikanja podatkov omogoča znatno povečanje hitrosti.
Predpomnilnik KV je ključna optimizacijska tehnika, ki se uporablja v fazi dekodiranja velikih jezikovnih modelov (LLM) za izboljšanje učinkovitosti izračunov samopozornosti. V tej fazi je vsak ustvarjen žeton odvisen od tenzorjev ključa (K) in vrednosti (V) vseh prejšnjih žetonov, vključno s tistimi, ki so bili izračunani v fazi predizpolnjevanja in naslednjih korakih dekodiranja. Namesto da bi te tenzorje za vsak žeton v vsakem časovnem koraku ponovno izračunali, jih predpomnilnik KV shrani v pomnilnik grafičnega procesorja in v predpomnilnik doda nove tenzorje, ko so izračunani. Običajno se za vsako plast modela vzdržuje ločen predpomnilnik KV, kar znatno zmanjša odvečne izračune in pospeši postopek dekodiranja.

Pomnilniške zahteve za LLM na grafičnih procesorjih določata predvsem dve komponenti: uteži modela in predpomnilnik KV. Modelske uteži, ki so sestavljene iz parametrov modela, zasedajo precej pomnilnika; na primer model s 7 milijardami parametrov, kot je Llama 2 7B v 16-bitni natančnosti, potrebuje približno 14 GB. Predpomnilnik KV pa shranjuje tenzorje lastne pozornosti, da se izogne ponovnemu izračunavanju, njegovo velikost pa določajo dejavniki, kot so število plasti, glave pozornosti, dimenzije glav in natančnost. Za vsak žeton se velikost predpomnilnika izračuna kot 2 * število_plastov * (število_glav * dim_glava) * natančnost_v_bajtih, pri čemer faktor 2 upošteva matrike K in V. Za serijo vhodov se skupna velikost predpomnilnika KV povečuje z velikostjo serije in dolžino zaporedja ter lahko doseže velike velikosti, kot je ~2 GB za model Llama 2 7B z dolžino zaporedja 4 096 in velikostjo serije 1.
Učinkovito upravljanje predpomnilnika KV predstavlja izziv zaradi njegove linearne rasti z velikostjo serije in dolžino zaporedja, kar lahko omejuje prepustnost in otežuje obdelavo vhodov z dolgim kontekstom. Pogosta neučinkovitost je posledica statične prevelike rezervacije, pri kateri je pomnilnik rezerviran za največjo podprto dolžino zaporedja (npr. 2 048 žetonov), ne glede na dejansko velikost vhoda. To vodi v znatno izgubo pomnilnika ali razdrobljenost, saj velik del rezerviranega prostora pogosto ostane neizkoriščen ves čas trajanja zahtevka, kar pomeni, da so dragoceni pomnilniški viri grafičnega procesorja zasedeni.
Algoritem PagedAttention za odpravo teh neučinkovitosti uvaja nov pristop, ki se zgleduje po pagingu operacijskega sistema. Predpomnilnik KV razdeli na bloke fiksne velikosti, od katerih vsak predstavlja določeno število žetonov, ki jih je mogoče neskladno shraniti v pomnilnik. Blokovna tabela sledi tem blokom in jih po potrebi prikliče med izračunavanjem pozornosti. Ko se ustvarijo novi žetoni, se dinamično dodelijo dodatni bloki. Ta metoda zmanjšuje izgubo pomnilnika, saj odpravlja potrebo po contiguous dodeljevanju in pretiranem dodeljevanju, omogoča večje velikosti serij in izboljšuje prepustnost, s čimer predstavlja pomemben napredek pri upravljanju predpomnilnika predpomnilnika KV za LLM.
V tem razdelku obravnavamo različne tehnike za optimizacijo velikih jezikovnih modelov (LLM), da bi zmanjšali njihovo porabo pomnilnika in izboljšali zmogljivost na grafičnih procesorjih. Ključne metode vključujejo kvantizacijo, redkost in destilacijo, pri čemer se vsaka osredotoča na različne vidike učinkovitosti modela. Te tehnike spreminjajo uteži modelov, izkoriščajo pospeševanje strojne opreme GPU in prenašajo znanje na manjše modele, kar omogoča, da se večji modeli izvajajo na omejeni strojni opremi in hkrati ohranjajo zmogljivost. Te metode lahko zmanjšajo natančnost modela, zato jih je treba uporabljati previdno.
Kvantizacija zmanjša natančnost uteži in aktivacij modela, običajno z 32 ali 16 bitov na 8 ali manj bitov, kar modelom omogoča, da zasedejo manj pomnilnika in učinkoviteje prenašajo podatke. Medtem ko je kvantizacija uteži enostavna zaradi njihove fiksne narave po usposabljanju, je kvantizacija aktivacij bolj zapletena zaradi odstopanj, ki širijo njihovo dinamično območje. Tehnike, kot je LLM.int8(), to rešujejo s selektivno uporabo višje natančnosti za določene aktivacije ali s ponovno uporabo dinamičnega razpona kvantiziranih uteži za aktivacije, čeprav lahko grafični procesorji zahtevajo pretvorbo uteži nazaj v višjo natančnost za operacije.
Redkost vključuje obrezovanje vrednosti modela blizu nič, s čimer se ustvarijo redke matrike, ki zahtevajo manj pomnilnika. Grafični procesorji podpirajo strukturirano redkost, na primer tako, da dve od štirih vrednosti predstavijo kot ničle, kar pospeši izračune. Kombinacija redkosti s kvantizacijo lahko še poveča hitrost izvajanja. Raziskave nadaljujejo z raziskovanjem optimalnih redkih predstavitev za LLM, kar kaže na obetavno pot za izboljšanje hitrosti sklepanja.
Destilacija prenaša znanje iz večjega modela "učitelja" na manjši model "učenca", s čimer se zmanjša velikost in hkrati ohrani zmogljivost. DistilBERT na primer doseže 40-odstotno zmanjšanje velikosti in 60-odstotno povečanje hitrosti v primerjavi z BERT, pri čemer ohrani 97 % svojih zmogljivosti. Destilacija lahko vključuje posnemanje rezultatov učitelja ali uporabo podatkov, ki jih je ustvaril učitelj, za učenje, pri čemer metode, kot je "Distiliranje po korakih!", vključujejo utemeljitve za učinkovito učenje. Vendar pa omejujoče licence za številne napredne programe vseživljenjskega učenja omejujejo razpoložljivost primernih modelov učiteljev za destilacijo.
Špekulativno sklepanje, znano tudi kot špekulativno vzorčenje ali asistirano generiranje, je metoda za paralelizacijo izvajanja avtoregresivnih modelov velikega jezika (LLM), kot so modeli v slogu GPT, ki običajno generirajo besedilo žeton za žetonom. Pri standardnem izvajanju je vsak žeton za kontekst odvisen od vseh predhodnih žetonov, kar onemogoča vzporedno generiranje, saj mora biti n-ti žeton generiran pred (n+1)-im. Špekulativno sklepanje to rešuje z uporabo "cenejšega" osnutka modela za hkratno napovedovanje več prihodnjih žetonov, ki jih nato glavni model vzporedno preveri ali zavrne, kar omogoča hitrejše generiranje besedila.
Postopek vključuje ustvarjanje osnutka nadaljevanja več žetonov z metodo, ki zahteva manj virov, čemur sledi vzporedno preverjanje glavnega modela z uporabo osnutka kot spekulativnega konteksta. Če se model preverjanja ujema z osnutkom žetonov, so ti sprejeti, v nasprotnem primeru se neujemajoči se žetoni in naslednji zavrnejo, postopek pa se ponovi z novim osnutkom. Osnutki žetonov se lahko ustvarijo z različnimi pristopi, kot so usposabljanje več modelov, natančna nastavitev več glav na predhodno usposobljenem modelu za napovedovanje prihodnjih žetonov ali uporaba manjšega modela osnutka skupaj z večjim, sposobnejšim modelom preverjanja, pri čemer ima vsak svoje kompromise.
Razdeljeno sklepanje je tehnika, pri kateri so računska opravila razdeljena na različno strojno opremo, da se optimizirajo zmogljivost, stroški in uporaba virov. Natančneje, ločuje faze predhodnega polnjenja in dekodiranja. Z razdružitvijo teh faz se lahko vsaka od njih dodeli strojni opremi, ki je najprimernejša za njene računske zahteve, kar izboljša učinkovitost in razširljivost.

Predizpolnjevanje je računsko intenzivno, saj je za obdelavo celotnega vhodnega poziva in izdelavo predpomnilnikov KV potrebnih veliko matričnih množenj. V tej fazi je koristna visoko zmogljiva strojna oprema, kot so grafični procesorji ali enote TPU, ki se odlikujejo pri vzporednih izračunih. Ker je predizpolnjevanje enkratno opravilo na zahtevo za sklepanje, ga je mogoče prenesti na centralizirano, zmogljivo računsko vozlišče, ki je optimizirano za take obremenitve. Takšna nastavitev omogoča hitrejšo obdelavo velikih poizvedb in zmanjša obremenitev manj zmogljivih naprav, zato je idealna za okolja v oblaku ali podatkovnih centrih, kjer je na voljo zmogljiva strojna oprema.
Dekodiranje pa je vezano na pomnilnik in vključuje iterativno generiranje žetonov, pri čemer se močno zanaša na dostop do predpomnilnikov KV. Zahteva manj računske moči, vendar potrebuje hiter dostop do pomnilnika, zaradi česar je primerno za manj zmogljivo, pomnilniško optimizirano strojno opremo, kot so procesorji ali robne naprave. S prenosom dekodiranja na ločeno strojno opremo - potencialno bližje končnemu uporabniku, kot so lokalni strežniki ali robne naprave - razčlenjeno sklepanje zmanjša zakasnitve in zahteve po omrežni pasovni širini. Ta ločitev omogoča prilagodljivo uvajanje, pri katerem se predizpolnjevanje izvaja na vrhunskih strežnikih v oblaku, dekodiranje pa na lokalnih ali robnih napravah, kar optimizira dodeljevanje virov in omogoča učinkovito skaliranje za aplikacije, kot so klepetalni boti v realnem času ali interaktivni sistemi umetne inteligence.
V zadnjem času so bile izumljene številne tehnike optimizacije sklepanja, da bi izboljšali učinkovitost LLM.
Izvajanje teh tehnik zahteva poglobljeno razumevanje arhitekture LLM in strojne opreme, ki jo uporabljate, zato je na splošno lažje uporabiti obstoječi inferenčni mehanizem, ki je te tehnike že izvedel, kot so vLLM, TensorRT-LLM, LMDeploy itd. Te tehnike smo dejansko implementirali v lastnem inferenčnem motorju v podjetju NLP Cloud in napisali prispevek na blogu o inferenčnih motorjih, če želite namestiti lastne modele: preberete jo lahko tukaj..
Če ne morete ali ne želite sami uvajati lastnih modelov LLM, lahko uporabite NLP Cloud in uporabite hitre generativne modele umetne inteligence v velikem obsegu v produkciji. Preizkusite hitro sklepanje v oblaku NLP Cloud zdaj!
Če imate vprašanja o inferenčnih motorjih na splošno, nas vprašajte, saj vam vedno z veseljem svetujemo!
Julien
Tehnični direktor v podjetju NLP Cloud