Имате проблеми с ИИ или разработката на пълен пакет? Нашите експерти са тук, за да ви напътстват: индивидуални съвети, техническа интеграция и др. Свържете се с [email protected].

Техники за оптимизация на LLM изводите

Оптимизацията на изводите е важна част от генеративните приложения за изкуствен интелект, които се използват в производството. Ефективното използване на LLM в голям мащаб е предизвикателство и през последните години бяха разработени много техники за по-бързо и по-евтино извеждане на изводи. Нека разгледаме тези техники в тази статия.

Техники за оптимизация на LLM изводите

Фокус върху архитектурата на LLM

Всички големи езикови модели (LLM) се основават на архитектурата на трансформатора, изобретена през 2017 г. от Vaswani и др. Архитектурата на трансформатора постига превъзходна точност, обучение с няколко изстрела и способности, близки до човешките, при различни езикови задачи. Въпреки това тези основополагащи модели, които често се състоят от десетки до стотици милиарди параметри, са скъпи за обучение и ресурсоемки по време на извеждането. Разходите за извод се увеличават при дълги входни контексти, които изискват значителна изчислителна мощност поради големите входни данни. Това превръща ефективното извеждане в критично предизвикателство, особено при управлението на паметта и изчислителните ресурси.

Архитектурата на трансформатора
Архитектурата на трансформатора

По-конкретно, най-известните LLM са LLM само за декодиране, като GPT-3, GPT-4, LLaMA, Mistral, DeepSeek и др. Тези модели са предварително обучени по задача за каузално моделиране, функционирайки като предсказатели на следваща дума. Те обработват последователност от лексеми като вход и произвеждат следващите лексеми авторегресивно до достигане на условие за спиране.

Изводът на LLM в моделите само с декодер включва две основни фази: фаза на предварително попълване и фаза на декодиране. Във фазата на предварителното попълване моделът обработва входните лексеми, за да изчисли междинни състояния (ключове и стойности) за генериране на първата нова лексема. Тази фаза, наподобяваща операция "матрица-матрица", е силно паралелизирана и ефективно използва възможностите на графичния процесор. Обратно, фазата на декодиране генерира токени един по един, като разчита на състоянията на предишните токени. Тази матрично-векторна операция е обвързана с паметта, тъй като прехвърлянето на данни към графичния процесор, а не скоростта на изчисленията, диктува основно закъснението, което води до недостатъчно използване на изчислителната мощ на графичния процесор.

Оптимизирането на фазата на декодиране е основна точка за справяне с предизвикателствата при изводите. Решенията включват разработване на ефективни механизми за внимание и по-добро управление на ключовете и стойностите за намаляване на затрудненията в паметта. В публикацията са изтъкнати практически подходи за повишаване на производителността на изводите, като се предполага, че читателите имат основни познания за архитектурата на трансформатора и механизмите за внимание. Тези оптимизации са от решаващо значение за подобряване на пропускателната способност и намаляване на латентността в реални внедрявания на LLM.

Допълнително усложнение възниква от използването на различни токенизатори в различните LLM, което влияе на сравнимостта на токените. Токените, приблизително еквивалентни на четири английски символа, се различават по представяне в зависимост от токенизатора, което прави директните сравнения на производителността на изводите (напр. токени в секунда) подвеждащи. Тази променливост подчертава необходимостта от стандартизирани показатели за оценка, за да се оцени и сравни точно производителността на LLM по време на извеждането.

Дозиране

Пакетирането е ключова стратегия за подобряване на използването на графичните процесори и производителността на големи езикови модели (LLM). Чрез едновременна обработка на множество заявки, използващи един и същ модел, пакетната обработка разпределя разходите за памет на тежестите на модела между заявките, което позволява на по-големите партиди да използват повече изчислителна мощ на GPU. Въпреки това има ограничение за размера на партидите, тъй като прекалено големите партиди могат да предизвикат препълване на паметта поради изискванията на LLM към паметта, особено свързани с кеширането на ключове и стойности (KV) (повече за това по-късно).

Техники за дозиране
Техники за дозиране

Традиционното или статичното групиране има ограничения, тъй като заявките в рамките на една група често генерират различен брой маркери за завършване, което води до различно време за изпълнение. Това кара всички заявки да изчакват завършването на най-бавната, което може да бъде проблем, когато продължителността на генериране варира значително. За да се справим с това, са разработени усъвършенствани техники, като например пакетно изпълнение по време на полет, за да се оптимизира производителността.

Пакетирането по време на полет, известно още като непрекъснато пакетиране, се справя с предизвикателствата, породени от динамичното естество на работните натоварвания на LLM, които могат да варират от прости отговори на чатбот до сложно обобщаване на документи или генериране на код. Тези задачи произвеждат изходи с много различни размери, което затруднява ефективното паралелно дозиране и изпълнение на заявките. За разлика от статичното пакетиране, пакетирането в полет позволява на сървъра незабавно да извежда завършените последователности от пакета и да започва да обработва нови заявки, докато други все още са в процес на изпълнение. Този подход значително повишава използването на графичния процесор, като се адаптира към различното време за изпълнение на заявките в реални сценарии.

Разгръщане на няколко графични процесора с паралелизация на модела

Паралелизирането на моделите е критична стратегия за управление на паметта и изчислителните изисквания на широкомащабни модели за машинно обучение чрез разпределянето им между множество графични процесори. Този подход позволява обработката на по-големи модели или входни партиди, които надхвърлят капацитета на паметта на едно устройство, което го прави от съществено значение както за обучението, така и за изводите, когато ограниченията на паметта са строги. Съществуват различни техники за разделяне на тежестите на моделите, включително паралелизъм на конвейера, тензорен паралелизъм и паралелизъм на последователността, като всяка от тях разглежда различни аспекти на разпределението на моделите. За разлика от паралелизма на данните, който се фокусира върху репликирането на тежестите на модела между устройствата с цел обработка на по-големи входни партиди по време на обучението, тези методи са по-подходящи за намаляване на отпечатъка от паметта както по време на обучението, така и при изводите.

Множество графични процесори NVIDIA
Множество графични процесори NVIDIA

Паралелизмът на тръбопроводите разделя модела вертикално на последователни части, като всяка част съдържа подмножество от слоеве, назначени на отделно устройство. Например при четирипосочна конвейерна конфигурация всяко устройство обработва една четвърт от слоевете на модела, като предава изходите на следващото устройство в последователност. Макар че това значително намалява изискванията за памет за всяко устройство, то въвежда неефективност, известна като "балони на конвейера", при които устройствата могат да бездействат, докато чакат изходи от предишните слоеве. Микродпакетирането, което разделя входните партиди на по-малки подпартиди за последователна обработка, може да намали тези балони, но не и да ги премахне напълно, тъй като времето на престой се запазва по време на преките и обратните преходи.

Тензорният паралелизъм, напротив, разделя отделните слоеве хоризонтално на по-малки изчислителни блокове, които могат да се изпълняват независимо на различни устройства. Това е особено ефективно за трансформаторни компоненти като блокове за внимание и многослойни перцептрони (MLP), при които например различни глави за внимание могат да бъдат назначени на отделни устройства за паралелни изчисления. Тензорният паралелизъм обаче е по-малко ефективен за операции като LayerNorm и Dropout, които не могат да бъдат лесно разделени и трябва да бъдат репликирани на различни устройства, което води до излишно използване на паметта за съхраняване на активациите. Това ограничение подчертава необходимостта от допълнителни подходи за оптимизиране на ефективността на паметта.

Паралелизмът на последователността е насочен към неефективността на паметта на операции като LayerNorm и Dropout чрез разделянето им по размер на входната последователност, като се използва тяхната независимост между елементите на последователността. Този метод намалява отпечатъка от паметта на излишните активации, което го прави ценно допълнение към тензорния паралелизъм. Тези техники за паралелизация не се изключват взаимно и могат да се комбинират за по-нататъшно оптимизиране на големи езикови модели (LLM). Освен това специфичните стратегии за оптимизация на модула за внимание могат да подобрят мащабируемостта и да намалят изискванията за памет на GPU, което позволява по-ефективно обучение и извод за големи модели.

Оптимизиране на вниманието

През 2017 г. статията *Attention Is All You Need* на Vaswani et al. представя модела Transformer, в чиято основа е самовниманието. Самонаблюдението позволява на модела да оценява значимостта на различни думи в изречението една спрямо друга, което подобрява контекстуалното разбиране за задачи като обработката на естествен език. В статията е формализирано самовниманието, по-специално чрез механизма на мащабираното внимание на точката-продукт (SDPA), който съпоставя двойките заявка и ключ-стойност към изхода, което го превръща в ключов компонент в съвременните невронни мрежи. Ето някои от най-важните техники за оптимизиране на изчисленията на вниманието:

Документът за внимание
Документът за внимание

Многоглавото внимание (MHA) надгражда SDPA, като изпълнява паралелно множество операции за внимание, всяка от които има различни проекции на матриците на заявките, ключовете и стойностите. Тези паралелни операции, или "глави", се фокусират върху различни репрезентативни подпространства, като обогатяват разбирането на модела за входните данни. Резултатите от тези глави се конкатенират и се проектират линейно, като се поддържа изчислителна ефективност, сравнима с тази на вниманието с една глава, чрез намаляване на размерността на всяка глава (например разделяне на размерността на модела на броя на главите, например 8).

Вниманието с много заявки (MQA) оптимизира MHA за изводи чрез споделяне на ключови и стойностни проекции в множество глави за внимание, като същевременно се запазват множество проекции на заявките. По този начин се намаляват изискванията за широчина на лентата на паметта и размерът на кеша ключ-стойност (КС), което позволява по-големи размери на партидите и по-добро използване на изчислителните мощности. Въпреки това MQA може леко да намали точността и моделите, които я използват, изискват обучение или фина настройка с включена MQA, за да се поддържа производителността.

Вниманието при групирани заявки (GQA) балансира MHA и MQA чрез групиране на главите на заявките и споделяне на проекциите на ключови стойности във всяка група, като се постига качество, близко до MHA, с изчислителна ефективност, близка до MQA. Модели като Llama 2 70B използват GQA, а тези, които са обучени с MHA, могат да бъдат адаптирани към GQA с минимално допълнително обучение. Както MQA, така и GQA намаляват нуждите от кеш памет на KV, въпреки че остават необходими допълнителни оптимизации в управлението на кеша.

FlashAttention подобрява механизмите за внимание чрез промяна на реда на изчисленията, за да се използват по-ефективно йерархиите на паметта на GPU. За разлика от традиционната обработка слой по слой, FlashAttention обединява операциите и използва "плочки" за изчисляване на малки части от изходната матрица наведнъж, като свежда до минимум операциите за четене/запис в паметта. Този алгоритъм за точното внимание, съобразено с входно-изходните операции, се интегрира безпроблемно в съществуващи модели без модификации, като предлага значително ускорение чрез оптимизиране на движението на данните.

Кеширане на ключове и стойности

Кеширането на KV е важна техника за оптимизация, използвана по време на фазата на декодиране на големи езикови модели (LLM), за да се подобри ефективността на изчисленията за самонаблюдение. В тази фаза всяка генерирана лексема зависи от тензорите за ключ (K) и стойност (V) на всички предишни лексеми, включително тези, изчислени по време на етапа на предварително попълване и последващите стъпки на декодиране. Вместо да се преизчисляват тези тензори за всеки токен на всяка стъпка, KV кеширането ги съхранява в паметта на графичния процесор, като добавя нови тензори към кеша, когато те са изчислени. Обикновено за всеки слой на модела се поддържа отделен KV кеш, което значително намалява излишните изчисления и ускорява процеса на декодиране.

Кеширане на ключове и стойности
Кеширане на ключове и стойности

Изискванията към паметта за LLM на графични процесори се определят основно от два компонента: тежести на моделите и кеш на KV. Теглата на моделите, които се състоят от параметрите на модела, заемат значителна част от паметта; например модел със 7 милиарда параметри като Llama 2 7B с 16-битова точност изисква приблизително 14 GB. Кешът KV, от друга страна, съхранява тензори за самонаблюдение, за да се избегне преизчисляване, като размерът му се определя от фактори като броя на слоевете, главите за внимание, размерите на главите и точността. За всеки токен размерът на кеша се изчислява като 2 * num_layers * (num_heads * dim_head) * precision_in_bytes, където коефициентът 2 отчита както K, така и V матриците. За партида от входове общият размер на КВ кеша се увеличава с размера на партидата и дължината на последователността, като потенциално може да достигне значителни размери, например ~2 GB за модел Llama 2 7B с дължина на последователността 4096 и размер на партидата 1.

Ефективното управление на кеша на KV представлява предизвикателство поради линейното му нарастване с размера на партидата и дължината на последователността, което може да ограничи производителността и да усложни обработката на входни данни с дълъг контекст. Често срещана неефективност се дължи на статично свръхзапазване, при което паметта се запазва за максималната поддържана дължина на последователността (напр. 2 048 символа), независимо от действителния размер на входа. Това води до значително разхищение или фрагментиране на паметта, тъй като голяма част от резервираното пространство често остава неизползвано през целия живот на заявката, ангажирайки ценни ресурси на паметта на графичния процесор.

За да се справи с тези неефективности, алгоритъмът PagedAttention въвежда нов подход, вдъхновен от странирането на операционната система. Той разделя KV кеша на блокове с фиксиран размер, всеки от които представлява определен брой маркери, които могат да се съхраняват несвързано в паметта. Таблицата с блокове проследява тези блокове, като ги извлича при необходимост по време на изчисленията на вниманието. Когато се генерират нови маркери, динамично се разпределят допълнителни блокове. Този метод свежда до минимум разхищението на памет, като елиминира необходимостта от съседно разпределение и свръхпредлагане, позволявайки по-големи размери на партидите и подобрявайки пропускателната способност, като по този начин го прави значителен напредък в управлението на КВ кеш паметта за LLM.

Оптимизиране на модела

В този раздел обсъждаме различни техники за оптимизиране на големи езикови модели (LLM), за да намалим потреблението им на памет и да подобрим производителността им на графични процесори. Основните методи включват квантуване, рядкост и дестилация, като всеки от тях е насочен към различни аспекти на ефективността на модела. Тези техники променят теглата на моделите, използват хардуерното ускорение на графичните процесори и прехвърлят знания към по-малки модели, което позволява на по-големите модели да работят на ограничен хардуер, като същевременно запазват производителността си. Тези методи могат да влошат точността на модела, така че трябва да се използват с повишено внимание.

Квантуването намалява точността на теглата и активациите на модела, обикновено от 32 или 16 бита до 8 или по-малко бита, което позволява на моделите да заемат по-малко памет и да прехвърлят данни по-ефективно. Докато квантуването на теглата е лесно поради фиксирания им характер след обучението, квантуването на активациите е по-сложно поради отклоненията, които разширяват динамичния им обхват. Техники като LLM.int8() се справят с този проблем чрез селективно прилагане на по-висока точност към определени активации или чрез повторно използване на динамичния обхват на квантуваните тежести за активациите, въпреки че за операциите на графичните процесори може да се наложи конвертиране на тежестите обратно към по-висока точност.

Разнообразието включва изрязване на стойностите на модела, близки до нула, като по този начин се създават разредени матрици, които изискват по-малко памет. Графичните процесори поддържат структурирана рядкост, като например представяне на две от всеки четири стойности като нули, което ускорява изчисленията. Комбинирането на рядкост с квантуване може допълнително да увеличи скоростта на изпълнение. Изследванията продължават да проучват оптималните разредени представяния за LLM, което показва обещаващ път за подобряване на скоростта на изводите.

Дестилацията прехвърля знания от по-голям модел на "учител" към по-малък модел на "ученик", като по този начин намалява размера и същевременно запазва производителността. Например DistilBERT постига 40% намаляване на размера и 60% увеличение на скоростта в сравнение с BERT, като запазва 97% от възможностите си. Дистилирането може да включва имитиране на резултатите на учителя или използване на данни, генерирани от учителя, за обучение, като методи като "Дистилиране стъпка по стъпка!" включват обосновки за ефективно обучение. Ограничителните лицензи на много усъвършенствани LLM обаче ограничават наличието на подходящи модели на учители за дестилация.

Спекулативен извод

Спекулативният извод, известен също като спекулативна извадка или асистирано генериране, е метод за паралелизиране на изпълнението на авторегресивни модели на големи езици (LLM), като например модели в стил GPT, които обикновено генерират текст символ по символ. При стандартното изпълнение всеки токен зависи от всички предишни токени за контекст, което прави паралелното генериране невъзможно, тъй като n-тият токен трябва да бъде генериран преди (n+1)-тия. Спекулативното извеждане решава този проблем, като използва "по-евтин" проектомодел за едновременно предсказване на множество бъдещи токени, които след това се проверяват или отхвърлят паралелно от основния модел, което позволява по-бързо генериране на текст.

Процесът включва генериране на чернова на продължението на няколко токена с помощта на по-малко ресурсоемък метод, последван от паралелна проверка от основния модел, като се използва чернова като спекулативен контекст. Ако моделът за проверка съвпада с черновата на токените, те се приемат; в противен случай несъответстващите токени и следващите се отхвърлят и процесът се повтаря с нова чернова. Черновите маркери могат да бъдат генерирани чрез различни подходи, като например обучение на няколко модела, фина настройка на няколко глави на предварително обучен модел, за да се предвидят бъдещи маркери, или използване на по-малък модел на чернова заедно с по-голям, по-способен модел за проверка, като всеки от тях има свои собствени компромиси.

Дезагрегиран извод

Дезагрегираният извод е техника, при която изчислителните задачи се разделят на различен хардуер, за да се оптимизират производителността, разходите и използването на ресурсите. По-конкретно, тя разделя фазите на предварително попълване и декодиране. Чрез дезагрегирането на тези фази всяка от тях може да бъде възложена на хардуер, който е най-подходящ за нейните изчислителни изисквания, което подобрява ефективността и мащабируемостта.

Дезагрегиран извод
Дезагрегиран извод

Предварителното попълване е изчислително интензивно, тъй като изисква значителни матрични умножения за обработване на цялата входна подсказка и създаване на кешове на KV. Тази фаза се възползва от високопроизводителен хардуер като GPU или TPU, които са отлични в паралелните изчисления. Тъй като предварителното попълване е еднократна задача за заявка за извод, то може да бъде прехвърлено на централизиран, мощен изчислителен възел, оптимизиран за такива натоварвания. Тази настройка позволява по-бърза обработка на големи подсказки и намалява натоварването на по-малко способните устройства, което я прави идеална за среди, базирани на облак или центрове за данни, където е наличен хардуер с висока производителност.

За разлика от това декодирането е свързано с паметта и включва итеративно генериране на символи, като се разчита в голяма степен на достъпа до кеша на KV. То изисква по-малка изчислителна мощност, но се нуждае от бърз достъп до паметта, което го прави подходящо за по-малко мощен, оптимизиран за памет хардуер като процесори или крайни устройства. Чрез преместване на декодирането в отделен хардуер - потенциално по-близо до крайния потребител, като локални сървъри или крайни устройства - дезагрегираното извеждане намалява латентността и изискванията за широчина на мрежовата лента. Това разделяне позволява гъвкаво внедряване, при което предварителното попълване се изпълнява на високотехнологични облачни сървъри, а декодирането се извършва на локални или крайни устройства, като се оптимизира разпределението на ресурсите и се дава възможност за ефективно мащабиране на приложения като чатботове в реално време или интерактивни системи с изкуствен интелект.

Заключение

Напоследък са измислени много техники за оптимизиране на изводите с цел подобряване на работата на LLM.

Прилагането на тези техники изисква задълбочено разбиране на архитектурата на LLM и хардуера, който използвате, така че обикновено е по-лесно да използвате съществуващ двигател за изводи, който вече е приложил тези техники, като vLLM, TensorRT-LLM, LMDeploy и др. Всъщност ние сме внедрили тези техники в нашата собствена машина за изводи в NLP Cloud и сме написали статия в блога за машините за изводи, ако искате да внедрите свои собствени модели: можете да го прочетете тук.

Ако не можете или не искате сами да внедрявате свои собствени LLM, можете да използвате NLP Cloud и да използвате бързи генеративни модели с изкуствен интелект в производствен мащаб. Опитайте бързото извеждане на изводи в NLP Cloud сега!

Ако имате въпроси относно двигателите за изводи като цяло, моля, не се колебайте да ни попитате, за нас винаги е удоволствие да ви посъветваме!

Julien
Технически директор в NLP Cloud