Боретеся зі штучним інтелектом або повним циклом розробки? Наші експерти допоможуть вам: індивідуальні консультації, технічна інтеграція та багато іншого. Звертайтеся за адресою [email protected].

Методи оптимізації виведення LLM

Оптимізація висновків є критично важливою частиною генеративних додатків ШІ, що розгортаються у виробництві. Ефективне використання LLM у великих масштабах є складним завданням, і за останні роки було розроблено багато методів, щоб зробити висновок швидшим і дешевшим. Давайте розглянемо ці методи в цій статті.

Методи оптимізації виведення LLM

Зосередження на архітектурі магістерських програм

Всі великі мовні моделі (ВМ) базуються на трансформаторній архітектурі, винайденій у 2017 році Васвані та ін. Трансформаторна архітектура забезпечує чудову точність, навчання за кілька спроб і майже людські здібності в різноманітних мовних завданнях. Однак ці базові моделі, які часто складаються з десятків і сотень мільярдів параметрів, є дорогими для навчання і ресурсомісткими під час виведення. Витрати на виведення зростають з довгими вхідними контекстами, які вимагають значної обчислювальної потужності через великі обсяги вхідних даних. Це робить ефективне виведення критично важливим завданням, особливо в управлінні пам'яттю та обчислювальними ресурсами.

Трансформаторна архітектура
Трансформаторна архітектура

Зокрема, найвідоміші ЛНМ - це ЛНМ, що працюють лише з декодером, такі як GPT-3, GPT-4, LLaMA, Mistral, DeepSeek тощо. Ці моделі попередньо навчені на задачі каузального моделювання, функціонуючи як предиктори наступного слова. Вони обробляють послідовність лексем на вході і виробляють наступні лексеми в авторегресії, доки не буде досягнуто умови зупинки.

LLM-виведення в моделях, що використовують лише декодер, включає дві ключові фази: фазу попереднього заповнення та фазу декодування. На етапі попереднього заповнення модель обробляє вхідні лексеми для обчислення проміжних станів (ключів і значень) для генерації першої нової лексеми. Ця фаза, що нагадує операцію "матриця-матриця", є високо розпаралелеленою і ефективно використовує можливості графічного процесора. І навпаки, фаза декодування генерує токени по одному, покладаючись на стан попередніх токенів. Ця матрично-векторна операція прив'язана до пам'яті, оскільки передача даних на GPU, а не швидкість обчислень, в першу чергу диктує затримку, що призводить до недовикористання обчислювальної потужності GPU.

Оптимізація фази декодування є ключовим моментом у вирішенні проблем виведення. Рішення включають розробку ефективних механізмів уваги та краще управління ключами і значеннями для зменшення вузьких місць у пам'яті. У цій статті висвітлюються практичні підходи до підвищення продуктивності виведення за умови, що читачі мають базове розуміння архітектури трансформатора та механізмів уваги. Ці оптимізації мають вирішальне значення для підвищення пропускної здатності та зменшення затримок у реальних розгортаннях LLM.

Ще одне ускладнення виникає через використання різних токенізаторів у різних LLM, що впливає на порівнянність токенів. Токени, приблизно еквівалентні чотирьом англійським символам, відрізняються за представленням залежно від токенізатора, що робить пряме порівняння продуктивності виведення (наприклад, токенів за секунду) оманливим. Ця варіативність підкреслює потребу в стандартизованих метриках оцінювання для точної оцінки та порівняння продуктивності LLM під час виведення.

Дозування

Пакетна обробка - це ключова стратегія для покращення використання графічного процесора та пропускної здатності у великих мовних моделях (LLM). Обробляючи кілька запитів одночасно з використанням однієї моделі, пакетна обробка розподіляє витрати пам'яті на вагу моделі між запитами, дозволяючи більшим партіям використовувати більше обчислювальної потужності графічного процесора. Однак існує обмеження на розмір пакетів, оскільки надто великі пакети можуть спричинити переповнення пам'яті через вимоги LLM до пам'яті, особливо пов'язані з кешуванням ключ-значення (KV) (докладніше про це пізніше).

Технології дозування
Технології дозування

Традиційна або статична пакетна обробка має обмеження, оскільки запити в пакеті часто генерують різну кількість маркерів завершення, що призводить до різного часу виконання. Це призводить до того, що всі запити чекають завершення найповільнішого з них, що може бути проблематично, коли тривалість генерації значно відрізняється. Щоб вирішити цю проблему, були розроблені передові методи, такі як пакетна обробка в польоті, для оптимізації продуктивності.

Пакетна обробка в польоті, також відома як безперервна обробка, вирішує проблеми, пов'язані з динамічним характером робочих навантажень LLM, які можуть варіюватися від простих відповідей чат-ботів до складних узагальнень документів або генерації коду. Ці завдання створюють вихідні дані дуже різного розміру, що ускладнює пакетне та паралельне ефективне виконання запитів. На відміну від статичної пакетної обробки, пакетна обробка в польоті дозволяє серверу негайно вилучати завершені послідовності з пакету і починати обробку нових запитів, поки інші все ще виконуються. Такий підхід значно підвищує завантаження графічного процесора, адаптуючись до різного часу виконання запитів у реальних сценаріях.

Розгортання на декількох графічних процесорах з розпаралелюванням моделі

Розпаралелювання моделей - це важлива стратегія управління пам'яттю та обчислювальними вимогами великомасштабних моделей машинного навчання шляхом розподілу їх між кількома графічними процесорами. Цей підхід дозволяє обробляти більші моделі або партії вхідних даних, які перевищують обсяг пам'яті одного пристрою, що робить його важливим як для навчання, так і для висновків, коли пам'ять обмежена. Існують різні методи розподілу ваг моделей, зокрема конвеєрний паралелізм, тензорний паралелізм і паралелізм послідовностей, кожен з яких стосується різних аспектів розподілу моделей. На відміну від паралелізму даних, який фокусується на реплікації ваг моделей між пристроями для обробки більших партій вхідних даних під час навчання, ці методи є більш актуальними для зменшення обсягу пам'яті як під час навчання, так і під час виведення.

Кілька графічних процесорів NVIDIA
Кілька графічних процесорів NVIDIA

Паралельність конвеєра ділить модель по вертикалі на послідовні частини, кожна з яких містить підмножину шарів, призначених для окремого пристрою. Наприклад, у чотиристоронньому конвеєрі кожен пристрій обробляє чверть шарів моделі, послідовно передаючи вихідні дані наступному пристрою. Хоча це значно зменшує вимоги до пам'яті для кожного пристрою, це призводить до неефективності, відомої як "бульбашки в конвеєрі", коли пристрої можуть простоювати, очікуючи на вихідні дані з попередніх шарів. Мікроблок, який розділяє вхідні партії на менші підпакети для послідовної обробки, може зменшити ці "бульбашки", але не усунути їх повністю, оскільки час простою зберігається під час прямих і зворотних проходів.

Тензорний паралелізм, навпаки, розбиває окремі шари по горизонталі на менші обчислювальні блоки, які можуть виконуватися незалежно на різних пристроях. Це особливо ефективно для трансформаторних компонентів, таких як блоки уваги та багатошарові персептрони (MLP), де, наприклад, різні головки уваги можуть бути призначені окремим пристроям для паралельних обчислень. Однак тензорний паралелізм менш ефективний для таких операцій, як LayerNorm і Dropout, які не можуть бути легко розділені і повинні бути репліковані на різних пристроях, що призводить до надлишкового використання пам'яті для зберігання активацій. Це обмеження підкреслює потребу в додаткових підходах для оптимізації ефективності використання пам'яті.

Паралелізм послідовностей вирішує проблему неефективності використання пам'яті такими операціями, як LayerNorm та Dropout, розбиваючи їх вздовж розмірності вхідної послідовності, використовуючи їхню незалежність між елементами послідовності. Цей метод зменшує використання пам'яті надлишковими активаціями, що робить його цінним доповненням до тензорного паралелізму. Ці методи розпаралелювання не є взаємовиключними і можуть комбінуватися для подальшої оптимізації великих мовних моделей (LLM). Крім того, спеціальні стратегії оптимізації для модуля уваги можуть покращити масштабованість та зменшити вимоги до пам'яті на GPU, що дозволить ефективніше навчати та робити висновки для великих моделей.

Оптимізація уваги

У статті 2017 року *Attention Is All You Need* Васвані та ін. представили модель Transformer, наріжним каменем якої є самоуважність. Самоуважність дозволяє моделі оцінювати релевантність різних слів у реченні відносно один одного, покращуючи контекстне розуміння для таких завдань, як обробка природної мови. У статті формалізовано самоувагу, зокрема, за допомогою механізму масштабованої точкової уваги (SDPA), який відображає запит і пари ключ-значення у вихідні дані, що робить її ключовим компонентом сучасних нейронних мереж. Ось деякі з найважливіших методів оптимізації обчислень з увагою:

Документ до уваги
Документ до уваги

Багатоголова увага (MHA) ґрунтується на SDPA шляхом паралельного виконання декількох операцій уваги, кожна з яких має окремі проекції матриць запитів, ключів і значень. Ці паралельні операції, або "голови", фокусуються на різних підпросторах представлення, збагачуючи розуміння моделлю вхідних даних. Виходи з цих головок об'єднуються і лінійно проектуються, зберігаючи обчислювальну ефективність, порівнянну з увагою однієї головки, завдяки зменшенню розмірності кожної головки (наприклад, діленням розмірності моделі на кількість головок, наприклад, на 8).

Багатозапиткова увага (MQA) оптимізує MHA для виведення, розподіляючи проекції ключів і значень між кількома головами уваги, зберігаючи при цьому кілька проекцій запитів. Це зменшує вимоги до пропускної здатності пам'яті та розмір кешу ключ-значення (KV), що дозволяє обробляти більші партії даних і краще використовувати обчислювальні ресурси. Однак MQA може дещо знизити точність, і моделі, що використовують його, потребують навчання або доопрацювання з увімкненим MQA, щоб підтримувати продуктивність.

Згрупована увага до запитів (GQA) балансує між MHA і MQA, групуючи заголовки запитів і обмінюючись проекціями ключових значень у кожній групі, досягаючи якості, близької до MHA, з обчислювальною ефективністю, наближеною до MQA. Такі моделі, як Llama 2 70B, використовують GQA, і ті, хто пройшов навчання з MHA, можуть бути адаптовані до GQA з мінімальним додатковим навчанням. Як MQA, так і GQA зменшують вимоги до кеш-пам'яті KV, хоча подальша оптимізація управління кешем залишається необхідною.

FlashAttention покращує механізми уваги, змінюючи порядок обчислень для більш ефективного використання ієрархії пам'яті графічного процесора. На відміну від традиційної пошарової обробки, FlashAttention об'єднує операції і використовує "тайлінг" для одночасного обчислення невеликих частин вихідної матриці, мінімізуючи операції читання/запису в пам'ять. Цей алгоритм точної уваги до вводу/виводу легко інтегрується в існуючі моделі без модифікацій, пропонуючи значне прискорення за рахунок оптимізації руху даних.

Кешування ключ-значення

Кешування KV - це метод критичної оптимізації, який використовується на етапі декодування великих мовних моделей (ВММ) для підвищення ефективності обчислень з самоуважністю. На цьому етапі кожен згенерований лексема залежить від тензорів ключа (K) і значення (V) всіх попередніх лексем, включаючи ті, що були обчислені на етапі попереднього заповнення та наступних етапах декодування. Замість того, щоб повторно обчислювати ці тензори для кожного токена на кожному кроці, KV-кешування зберігає їх у пам'яті графічного процесора, додаючи нові тензори до кешу в міру їх обчислення. Зазвичай для кожного шару моделі підтримується окремий KV-кеш, що значно зменшує надлишкові обчислення і пришвидшує процес декодування.

Кешування ключ-значення
Кешування ключ-значення

Вимоги до пам'яті для МНК на графічних процесорах в основному визначаються двома компонентами: вагами моделі та кешем KV. Ваги моделі, які складаються з параметрів моделі, займають значний обсяг пам'яті; наприклад, модель з 7 мільярдами параметрів, така як Llama 2 7B з 16-бітною точністю, вимагає приблизно 14 ГБ. Кеш KV, з іншого боку, зберігає тензори самоуваги, щоб уникнути повторних обчислень, причому його розмір визначається такими факторами, як кількість шарів, головок уваги, розміри головок і точність. Для кожного токена розмір кешу обчислюється як 2 * num_layers * (num_heads * dim_head) * precision_in_bytes, де множник 2 враховує як K, так і V матриці. Для пакету вхідних даних загальний розмір кешу KV залежить від розміру пакету та довжини послідовності, потенційно досягаючи значних розмірів, наприклад, ~2 ГБ для моделі Llama 2 7B з довжиною послідовності 4096 та розміром пакету 1.

Ефективне керування кешем KV створює проблеми через його лінійне зростання з розміром партії та довжиною послідовності, що може обмежувати пропускну здатність та ускладнювати обробку довгих контекстних вхідних даних. Поширеною причиною неефективності є статичне надмірне резервування, коли пам'ять резервується для максимальної підтримуваної довжини послідовності (наприклад, 2,048 токенів), незалежно від фактичного розміру вхідних даних. Це призводить до значних втрат пам'яті або фрагментації, оскільки велика частина зарезервованого простору часто залишається невикористаною протягом усього часу виконання запиту, зв'язуючи цінні ресурси пам'яті графічного процесора.

Щоб усунути ці недоліки, алгоритм PagedAttention впроваджує новий підхід, натхненний пейджингом операційної системи. Він розділяє кеш KV на блоки фіксованого розміру, кожен з яких представляє певну кількість токенів, які можуть зберігатися в пам'яті не суміжно. Таблиця блоків відстежує ці блоки, витягуючи їх за необхідності під час обчислень, що потребують уваги. Коли генеруються нові токени, додаткові блоки виділяються динамічно. Цей метод мінімізує втрати пам'яті, усуваючи потребу в суміжному виділенні та надмірному резервуванні, дозволяючи працювати з великими партіями та покращуючи пропускну здатність, що робить його значним кроком вперед в управлінні кеш-пам'яттю KV для LLM.

Оптимізація моделі

У цьому розділі ми обговоримо різні методи оптимізації великих мовних моделей (ВММ) для зменшення їхнього споживання пам'яті та підвищення продуктивності на графічних процесорах. Ключові методи включають квантування, розрідженість та дистиляцію, кожен з яких спрямований на різні аспекти ефективності моделі. Ці методи змінюють вагу моделі, використовують апаратне прискорення GPU і переносять знання на менші моделі, дозволяючи більшим моделям працювати на обмеженому апаратному забезпеченні, зберігаючи при цьому продуктивність. Ці методи можуть погіршити точність моделі, тому їх слід використовувати з обережністю.

Квантування знижує точність ваг та активацій моделі, як правило, з 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