A következtetések optimalizálása a termelésben alkalmazott generatív AI-alkalmazások kritikus része. Az LLM-ek hatékony, méretarányos használata kihívást jelent, és az elmúlt években számos technikát fejlesztettek ki a következtetés gyorsabbá és olcsóbbá tételére. Tekintsük át ezeket a technikákat ebben a cikkben.
A nagy nyelvi modellek (LLM) mind a 2017-ben Vaswani et al. által feltalált transzformátor architektúrán alapulnak. A transzformátor architektúra kiváló pontosságot, kevés tanulást és emberközeli képességeket ér el a különböző nyelvi feladatokban. Azonban ezeket az alapmodelleket, amelyek gyakran több tíz- és százmilliárd paraméterből állnak, költséges betanítani és erőforrás-igényesek a következtetés során. A következtetési költségek hosszú bemeneti kontextusok esetén eszkalálódnak, amelyek a nagy bemeneti adatok miatt jelentős feldolgozási teljesítményt igényelnek. Ez a hatékony következtetést kritikus kihívássá teszi, különösen a memória- és számítási erőforrások kezelésében.
Pontosabban, a legtöbb jól ismert LLM csak dekódolós LLM, mint például a GPT-3, GPT-4, LLaMA, Mistral, DeepSeek stb. Ezeket a modelleket előzetesen egy ok-okozati modellezési feladatra trenírozzák, és a következő szó prediktoraiként működnek. Ezek bemenetként tokenek egy sorozatát dolgozzák fel, és autoregresszív módon termelik a következő tokeneket, amíg el nem érnek egy megállási feltételt.
A csak dekódolós modellekben az LLM következtetés két kulcsfontosságú fázist foglal magában: az előfeltöltési és a dekódolási fázist. Az előkitöltési fázisban a modell a bemeneti tokeneket feldolgozza, hogy az első új token generálásához köztes állapotokat (kulcsokat és értékeket) számítson ki. Ez a mátrix-mátrix műveletre hasonlító fázis nagymértékben párhuzamosított, és hatékonyan használja ki a GPU képességeit. Ezzel szemben a dekódolási fázis egyenként generálja a tokeneket, a korábbi tokenek állapotaira támaszkodva. Ez a mátrix-vektor művelet memóriaköteles, mivel a GPU-ra történő adatátvitel, nem pedig a számítási sebesség határozza meg elsősorban a késleltetést, ami a GPU számítási teljesítményének kihasználatlanságához vezet.
A dekódolási fázis optimalizálása a következtetési kihívások kezelésének egyik központi eleme. A megoldások közé tartozik a hatékony figyelemmechanizmusok kifejlesztése, valamint a kulcsok és értékek jobb kezelése a memória szűk keresztmetszeteinek csökkentése érdekében. A bejegyzés a következtetési teljesítmény növelésének gyakorlati megközelítéseit emeli ki, feltételezve, hogy az olvasók alapvetően ismerik a transzformátor architektúráját és a figyelmi mechanizmusokat. Ezek az optimalizálások kulcsfontosságúak az átviteli teljesítmény javításához és a késleltetés csökkentéséhez a valós LLM-használatokban.
További bonyodalmat okoz, hogy az egyes LLM-ek különböző tokenizátorokat használnak, ami befolyásolja a tokenek összehasonlíthatóságát. A nagyjából négy angol karakterrel egyenértékű tokenek a tokenizálótól függően eltérő ábrázolásúak, ami félrevezetővé teszi a következtetési teljesítmény (pl. tokenek másodpercenként) közvetlen összehasonlítását. Ez a változékonyság hangsúlyozza, hogy szabványosított értékelési mérőszámokra van szükség az LLM teljesítményének pontos értékeléséhez és összehasonlításához a következtetés során.
A kötegelés kulcsfontosságú stratégia a GPU-k kihasználtságának és teljesítményének javítására a nagyméretű nyelvi modellek (LLM) esetében. A több kérés egyidejű feldolgozásával ugyanazon modell felhasználásával a kötegelés elosztja a modellsúlyok memóriaköltségét a kérések között, így a nagyobb kötegek nagyobb GPU számítási teljesítményt használhatnak ki. A kötegelés méretének azonban van egy határa, mivel a túl nagy kötegek az LLM-ek memóriaigénye miatt memóriatúlcsordulást okozhatnak, különösen a kulcs-érték (KV) gyorsítótárazással kapcsolatban (erről később).
A hagyományos vagy statikus kötegelésnek vannak korlátai, mivel a kötegen belüli kérések gyakran különböző számú befejezési tokeneket generálnak, ami eltérő végrehajtási időkhöz vezet. Ez azt eredményezi, hogy az összes kérés a leglassabb befejezésére vár, ami problémás lehet, ha a generálás hossza jelentősen változik. Ennek megoldására olyan fejlett technikákat fejlesztettek ki, mint a menet közbeni kötegelés a teljesítmény optimalizálására.
A menet közbeni kötegelés, más néven folyamatos kötegelés megoldja az LLM-munkaterhelések dinamikus jellege által támasztott kihívásokat, amelyek az egyszerű chatbot-válaszoktól az összetett dokumentum-összefoglalásig vagy kódgenerálásig terjedhetnek. Ezek a feladatok nagyon különböző méretű kimeneteket produkálnak, ami megnehezíti a kérések hatékony, párhuzamos kötegelését és végrehajtását. A statikus kötegeléssel ellentétben a menet közbeni kötegelés lehetővé teszi a kiszolgáló számára, hogy a befejezett szekvenciákat azonnal kilakoltassa a kötegből, és elkezdje az új kérések feldolgozását, miközben mások még folyamatban vannak. Ez a megközelítés jelentősen növeli a GPU-kihasználtságot azáltal, hogy alkalmazkodik a kérések változó végrehajtási idejéhez a valós forgatókönyvekben.
A modellpárhuzamosítás kritikus stratégia a nagyméretű gépi tanulási modellek memória- és számítási igényeinek kezelésére, több GPU-ra való elosztásukkal. Ez a megközelítés lehetővé teszi olyan nagyobb modellek vagy bemeneti tételek kezelését, amelyek meghaladják egyetlen eszköz memóriakapacitását, így a memóriakorlátok szűkössége esetén mind a képzéshez, mind a következtetések levonásához elengedhetetlen. A modellsúlyok felosztására különböző technikák léteznek, köztük a csővezeték-párhuzamosság, a tenzorpárhuzamosság és a szekvencia-párhuzamosság, amelyek mindegyike a modellelosztás különböző aspektusait kezeli. Az adatpárhuzamossággal ellentétben, amely a modellsúlyok eszközök közötti replikálására összpontosít, hogy nagyobb bemeneti tételeket dolgozzon fel a képzés során, ezek a módszerek inkább a memória lábnyomának csökkentése szempontjából relevánsak mind a képzés, mind a következtetés során.
A csővezeték-párhuzamosítás a modellt vertikálisan szekvenciális darabokra osztja, és minden darab a rétegek egy részhalmazát tartalmazza, amely egy külön eszközhöz van rendelve. Például egy négyutas csővezetékes elrendezésben minden eszköz a modell rétegeinek egynegyedét kezeli, és a kimeneteket a sorban következő eszköznek adja át. Ez ugyan jelentősen csökkenti az eszközonkénti memóriaigényt, de a "csővezeték buborékok" néven ismert nem hatékony működést eredményez, amikor az eszközök tétlenül várakozhatnak az előző rétegek kimeneteire. A mikrodobozolás, amely a bemeneti tételeket kisebb altételekre osztja a szekvenciális feldolgozáshoz, csökkentheti ezeket a buborékokat, de nem szüntetheti meg teljesen, mivel az üresjárati idők az előre és visszafelé történő átmenetek során is fennmaradnak.
A tenzorpárhuzamosság ezzel szemben az egyes rétegeket vízszintesen kisebb számítási blokkokra bontja, amelyek egymástól függetlenül, több eszközön is elvégezhetők. Ez különösen hatékony az olyan transzformációs komponenseknél, mint a figyelemblokkok és a többrétegű perceptronok (MLP-k), ahol például a különböző figyelemfejek külön eszközökhöz rendelhetők a párhuzamos számításhoz. A tenzorpárhuzamosság azonban kevésbé hatékony az olyan műveletek esetében, mint a LayerNorm és a Dropout, amelyeket nem lehet könnyen megosztani, és amelyeket az eszközök között kell replikálni, ami redundáns memóriahasználatot eredményez az aktiválások tárolására. Ez a korlátozás rávilágít arra, hogy kiegészítő megközelítésekre van szükség a memóriahatékonyság optimalizálása érdekében.
A szekvencia-párhuzamosítás a LayerNorm és a Dropout műveletek memóriahatékonysági hiányosságait úgy kezeli, hogy a bemeneti szekvencia dimenzió mentén particionálja őket, kihasználva a szekvenciaelemek közötti függetlenséget. Ez a módszer csökkenti a redundáns aktiválások memóriaigényét, így értékes kiegészítője a tenzorpárhuzamosításnak. Ezek a párhuzamosítási technikák nem zárják ki egymást, és kombinálhatók a nagy nyelvi modellek (LLM) további optimalizálása érdekében. Emellett a figyelemmodulra vonatkozó speciális optimalizálási stratégiák fokozhatják a skálázhatóságot és csökkenthetik a GPU-nkénti memóriaigényt, lehetővé téve a nagy modellek hatékonyabb képzését és következtetését.
Vaswani et al. 2017-es *Attention Is All You Need* című tanulmánya bemutatta a Transformer modellt, amelynek sarokköve az önfigyelem. Az önfigyelem lehetővé teszi a modell számára, hogy felmérje a mondatban lévő különböző szavak egymáshoz viszonyított relevanciáját, így javítva a kontextuális megértést olyan feladatokhoz, mint a természetes nyelvi feldolgozás. A tanulmány formalizálta az önfigyelést, különösen a skálázott pont-produktum figyelem (SDPA) mechanizmuson keresztül, amely a lekérdezés és a kulcs-érték párokat egy kimenetre képezi le, így a modern neurális hálózatok egyik központi eleme. Íme néhány a figyelemszámítások optimalizálásának legfontosabb technikái közül:
A többfejű figyelem (MHA) az SDPA-ra épül azáltal, hogy több figyelemműveletet futtat párhuzamosan, a lekérdezési, kulcs- és értékmátrixok különböző vetületeivel. Ezek a párhuzamos műveletek, vagy "fejek", különböző reprezentációs altérre összpontosítanak, gazdagítva a modell bemenetről alkotott képét. E fejek kimenetei össze vannak fűzve és lineárisan vetítve, az egyfejű figyelemhez hasonló számítási hatékonyságot fenntartva az egyes fejek dimenziójának csökkentésével (pl. a modell dimenziójának a fejek számával való elosztásával, például 8 fejjel).
A többlekérdezéses figyelem (MQA) optimalizálja az MHA-t a következtetéshez azáltal, hogy a kulcs- és értékvetületeket több figyelemfej között osztja meg, miközben több lekérdezési vetületet tart meg. Ez csökkenti a memória sávszélesség igényét és a kulcs-érték (KV) gyorsítótár méretét, ami nagyobb kötegméreteket és jobb számítási kihasználtságot tesz lehetővé. Az MQA azonban némileg csökkentheti a pontosságot, és az azt kihasználó modellek a teljesítmény fenntartása érdekében az MQA engedélyezésével képzést vagy finomhangolást igényelnek.
A csoportosított lekérdezési figyelem (GQA) egyensúlyt teremt az MHA és az MQA között a lekérdezőfejek csoportosításával és az egyes csoportokon belüli kulcsérték-projekciók megosztásával, így a MHA-közeli minőséget az MQA-hoz közelebb álló számítási hatékonysággal éri el. Az olyan modellek, mint a Llama 2 70B a GQA-t használják, és az MHA-val képzett modellek minimális további képzéssel átállíthatók a GQA-ra. Mind az MQA, mind a GQA csökkenti a KV gyorsítótár memóriaigényét, bár a gyorsítótár-kezelés további optimalizálása továbbra is szükséges.
A FlashAttention a GPU memóriahierarchiájának hatékonyabb kihasználása érdekében a számítások újrarendezésével javítja a figyelmi mechanizmusokat. A hagyományos rétegenkénti feldolgozástól eltérően a FlashAttention egyesíti a műveleteket, és "csempézéssel" egyszerre számítja ki a kimeneti mátrix kis részeit, minimalizálva a memóriaolvasási/írási műveleteket. Ez az I/O-tudatos, pontos figyelem algoritmus módosítások nélkül, zökkenőmentesen integrálható a meglévő modellekbe, és az adatmozgások optimalizálásával jelentős sebességnövekedést kínál.
A KV caching egy kritikus optimalizálási technika, amelyet a nagy nyelvi modellek (LLM) dekódolási fázisában használnak az önfigyelő számítások hatékonyságának javítására. Ebben a fázisban minden egyes generált token függ az összes korábbi token kulcs- (K) és értéktenzorától (V), beleértve az előkitöltési szakaszban és a későbbi dekódolási lépések során kiszámítottakat is. Ahelyett, hogy ezeket a tenzorokat minden egyes tokenhez minden egyes időlépéskor újraszámítanánk, a KV-tárolás a GPU memóriájában tárolja őket, és a számítás során új tenzorokat csatol a gyorsítótárba. Általában a modell minden egyes rétegéhez külön KV-cache-t tartanak fenn, ami jelentősen csökkenti a redundáns számításokat és felgyorsítja a dekódolási folyamatot.
Az LLM-ek memóriaigényét GPU-kon elsősorban két komponens határozza meg: a modellsúlyok és a KV cache. A modell súlyai, amelyek a modell paramétereiből állnak, jelentős memóriát foglalnak el; például egy 7 milliárd paraméteres modell, mint a Llama 2 7B 16 bites pontossággal körülbelül 14 GB-ot igényel. A KV gyorsítótár ezzel szemben az újraszámítás elkerülése érdekében az önfigyelem tenzorokat tárolja, amelynek méretét olyan tényezők határozzák meg, mint a rétegek száma, a figyelemfejek, a fejméretek és a pontosság. Minden egyes token esetében a gyorsítótár mérete a következőképpen kerül kiszámításra: 2 * num_layers * (num_heads * dim_head) * precision_in_bytes, ahol a 2 faktor figyelembe veszi mind a K, mind a V mátrixokat. Egy bemeneti tétel esetében a KV gyorsítótár teljes mérete a tétel méretével és a szekvencia hosszával együtt nő, és potenciálisan jelentős méreteket érhet el, például ~2 GB-ot egy Llama 2 7B modell esetében, amelynek szekvencia hossza 4096 és tételmérete 1.
A KV gyorsítótár hatékony kezelése kihívást jelent a tételek méretével és a szekvencia hosszával való lineáris növekedése miatt, ami korlátozhatja az áteresztőképességet és megnehezítheti a hosszú kontextusú bemenetek kezelését. Gyakori hatástalanságot okoz a statikus túlbiztosítás, amikor a memória a maximálisan támogatott szekvenciahosszra (pl. 2048 token) van lefoglalva, függetlenül a tényleges bemeneti mérettől. Ez jelentős memóriapazarláshoz vagy töredezettséghez vezet, mivel a lefoglalt hely nagy része gyakran kihasználatlan marad a kérés teljes élettartama alatt, és értékes GPU-memóriaforrásokat köt le.
E hiányosságok kiküszöbölésére a PagedAttention algoritmus az operációs rendszer lapozásából inspirálódó új megközelítést vezet be. A KV gyorsítótárat fix méretű blokkokra osztja, amelyek mindegyike meghatározott számú tokent képvisel, és amelyek nem egybefüggően tárolhatók a memóriában. Egy blokk-táblázat követi ezeket a blokkokat, és a figyelemszámítások során szükség szerint lekérdezi őket. Ahogy új tokenek keletkeznek, további blokkok dinamikusan kerülnek kiosztásra. Ez a módszer minimalizálja a memóriapazarlást azáltal, hogy kiküszöböli az összefüggő kiosztás és a túlellátás szükségességét, nagyobb tételméreteket tesz lehetővé és javítja az áteresztőképességet, így jelentős előrelépést jelent az LLM-ek KV cache-memóriájának kezelésében.
Ebben a szakaszban a nagyméretű nyelvi modellek (LLM) optimalizálásának különböző technikáit tárgyaljuk, hogy csökkentsük a memóriafogyasztásukat és növeljük a GPU-k teljesítményét. A legfontosabb módszerek közé tartozik a kvantálás, a ritkítás és a desztillálás, amelyek mindegyike a modell hatékonyságának különböző aspektusait célozza. Ezek a technikák módosítják a modell súlyait, kihasználják a GPU hardveres gyorsítását, és átadják a tudást a kisebb modelleknek, lehetővé téve a nagyobb modellek korlátozott hardveren történő futtatását a teljesítmény fenntartása mellett. Ezek a módszerek ronthatják a modell pontosságát, ezért óvatosan kell használni őket.
A kvantálás csökkenti a modell súlyainak és aktivációinak pontosságát, jellemzően 32 vagy 16 bitről 8 vagy kevesebb bitre, így a modellek kevesebb memóriát foglalnak és hatékonyabban továbbíthatják az adatokat. Míg a súlyok kvantálása egyszerű a képzés utáni fix jellegük miatt, az aktivációk kvantálása bonyolultabb a dinamikai tartományt bővítő kiugró értékek miatt. Az olyan technikák, mint az LLM.int8(), ezt úgy kezelik, hogy bizonyos aktiválásokra szelektíven nagyobb pontosságot alkalmaznak, vagy a kvantált súlyok dinamikus tartományát újra felhasználják az aktiválásokhoz, bár a GPU-kon a műveletekhez a súlyokat vissza kell konvertálni nagyobb pontosságúra.
A ritkaság a modell nullához közeli értékeinek metszését jelenti, ami ritkább mátrixokat hoz létre, amelyek kevesebb memóriát igényelnek. A GPU-k támogatják a strukturált ritkaságot, például azt, hogy minden négy értékből kettőt nullaként ábrázoljanak, ami felgyorsítja a számításokat. A ritkaság kvantálással való kombinálása tovább növelheti a végrehajtási sebességet. A kutatás továbbra is folytatja az LLM-ek optimális ritka reprezentációinak vizsgálatát, ami ígéretes utat mutat a következtetési sebesség javítására.
A disztilláció a tudást egy nagyobb "tanári" modellből egy kisebb "tanulói" modellbe helyezi át, így csökkentve a méretet, miközben megőrzi a teljesítményt. A DistilBERT például 40%-os méretcsökkentést és 60%-os sebességnövekedést ér el a BERT-hez képest, miközben 97%-ban megtartja a képességeit. A distillálás magában foglalhatja a tanár kimeneteinek utánzását vagy a tanár által generált adatok felhasználását a képzéshez, az olyan módszerek, mint a "Distilling Step by Step!", a hatékony tanuláshoz szükséges racionalitást tartalmazzák. Azonban számos fejlett LLM-re vonatkozó korlátozó licencek korlátozzák a desztillációra alkalmas tanári modellek elérhetőségét.
A spekulatív következtetés, más néven spekulatív mintavételezés vagy segédgenerálás, egy módszer az autoregresszív nagy nyelvi modellek (LLM), például a GPT-stílusú modellek végrehajtásának párhuzamosítására, amelyek jellemzően tokenenként generálják a szöveget. A standard végrehajtás során minden egyes token az összes korábbi tokentől függ a kontextus szempontjából, ami lehetetlenné teszi a párhuzamos generálást, mivel az n-edik tokent az (n+1)-edik előtt kell generálni. A spekulatív következtetés ezt úgy oldja meg, hogy egy "olcsóbb" vázlatmodell segítségével egyszerre több jövőbeli tokent jósol meg, amelyeket aztán a fő modell párhuzamosan ellenőriz vagy elutasít, ami gyorsabb szöveggenerálást tesz lehetővé.
A folyamat során egy kevésbé erőforrás-igényes módszerrel több tokenből álló folytatás-tervezetet generálnak, majd a fő modellel párhuzamosan a tervezetet spekulatív kontextusként használva verifikálják. Ha az ellenőrző modell egyezik a tervezet tokenjeivel, akkor azok elfogadásra kerülnek; ellenkező esetben a nem egyező tokeneket és az utána következő tokeneket elvetjük, és a folyamat egy új tervezettel megismétlődik. A vázlatjegyek különböző megközelítésekkel generálhatók, például több modell betanításával, több fej finomhangolásával egy előzetesen betanított modellen a jövőbeli jegyek előrejelzésére, vagy egy kisebb vázlatmodell alkalmazásával egy nagyobb, nagyobb képességű verifikációs modell mellett, mindegyiknek megvannak a maga kompromisszumai.
A disaggregált következtetés olyan technika, amelynél a számítási feladatokat különböző hardverekre osztják a teljesítmény, a költségek és az erőforrás-felhasználás optimalizálása érdekében. Konkrétabban az előtöltési és a dekódolási fázisokat választja szét. E fázisok szétválasztásával mindegyiket a számítási igényeiknek legjobban megfelelő hardverhez lehet rendelni, ami javítja a hatékonyságot és a skálázhatóságot.
Az előtöltés számításigényes, mivel jelentős mátrixszorzásokat igényel a teljes bemeneti prompt feldolgozásához és a KV-cache-ek előállításához. Ebben a fázisban nagy teljesítményű hardverek, például GPU-k vagy TPU-k használhatók, amelyek párhuzamos számításokban jeleskednek. Mivel az előtöltés következtetési kérésenként egyszeri feladat, az ilyen munkaterhelésre optimalizált, nagy teljesítményű központi számítási csomópontra tehető. Ez a beállítás lehetővé teszi a nagyméretű kérések gyorsabb feldolgozását, és csökkenti a kevésbé alkalmas eszközök terhelését, így ideális felhőalapú vagy adatközpontos környezetekbe, ahol nagy teljesítményű hardver áll rendelkezésre.
A dekódolás ezzel szemben memóriaköteles, és iteratív tokengenerálást foglal magában, ami nagymértékben támaszkodik a KV gyorsítótárak elérésére. Kevesebb számítási teljesítményt igényel, de gyors memóriaelérést igényel, így kevésbé erős, memóriára optimalizált hardverekhez, például CPU-khoz vagy éles eszközökhöz alkalmas. Azáltal, hogy a dekódolás külön hardverre kerül - amely potenciálisan közelebb van a végfelhasználóhoz, például helyben lévő szerverekre vagy peremeszközökre -, a szétbontott következtetés csökkenti a késleltetési időt és a hálózati sávszélesség-igényt. Ez a szétválasztás rugalmas telepítést tesz lehetővé, ahol az előtöltés nagy teljesítményű felhőszervereken, a dekódolás pedig helyi vagy peremeszközökön történik, optimalizálva az erőforrás-elosztást és lehetővé téve a hatékony skálázást olyan alkalmazások számára, mint a valós idejű chatbotok vagy az interaktív AI-rendszerek.
A közelmúltban számos következtetés-optimalizálási technikát találtak ki az LLM-ek teljesítményének javítása érdekében.
Ezeknek a technikáknak az implementálása az LLM architektúra és a használt hardver mélyreható ismeretét igényli, ezért általában egyszerűbb egy olyan meglévő következtetőmotort használni, amely már implementálta ezeket a technikákat, például a vLLM, TensorRT-LLM, LMDeploy stb. Mi valójában ezeket a technikákat implementáltuk a saját inferencia motorunkban az NLP Cloudnál, és írtunk egy blogbejegyzést az inferencia motorokról, ha saját modelleket szeretne telepíteni: itt olvashatja el.
Ha nem tudja vagy nem akarja saját LLM-eket telepíteni, használhatja az NLP Cloudot, és a gyors generatív AI-modelleket a termelésben is kihasználhatja. Próbáld ki a gyors következtetést az NLP Cloudon most!
Ha kérdései vannak a következtetési motorokkal kapcsolatban, kérjük, ne habozzon, kérdezzen minket, mindig örömmel adunk tanácsot!
Julien
CTO az NLP Cloudnál