Моделі та платформи ШІ

Оптимізація розгортання LLM: vLLM PagedAttention і майбутнє ефективного обслуговування AI

mm
Додайте Unite.AI до бажаних джерел у Google

Великі мовні моделі (LLM) розгортання в реальних додатках представляють унікальні виклики, особливо у сфері обчислювальних ресурсів, затримки та ефективності витрат. У цьому комплексному посібнику ми дослідимо ландшафт обслуговування LLM, з особливим акцентом на vLLM (векторна мова модель), рішення, яке змінює спосіб нашого розгортання та взаємодії з цими потужними моделями.

Виклики обслуговування великих мовних моделей

Перед тим, як зануритися в конкретні рішення, давайте розглянемо ключові виклики, які роблять обслуговування LLM складним завданням:

Обчислювальні ресурси

LLM відомі своїми величезними параметрами, які варіюються від мільярдів до сотень мільярдів. Наприклад, GPT-3 має 175 мільярдів параметрів, а більш недавні моделі, такі як GPT-4, оцінюються в ще більшу кількість параметрів. Ця величезна кількість параметрів перекладується в значні обчислювальні вимоги для висновку.

Приклад:
Розглянемо відносно скромну LLM з 13 мільярдами параметрів, chẳng hạn як LLaMA-13B. Навіть ця модель вимагає:

– Приблизно 26 ГБ пам’яті лише для зберігання параметрів моделі (при умові 16-бітної точності)
– Додаткової пам’яті для активації, механізмів уваги та проміжних обчислень
– Значної потужності GPU для реального висновку

Затримка

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

Приклад:
Уявіть собі чат-бот для обслуговування клієнтів, який працює на основі LLM. Якщо кожна відповідь займає кілька секунд для генерації, розмова буде відчуватися нерівномірною та розчаровуючою для користувачів.

Витрати

Апаратне забезпечення, необхідне для роботи LLM у масштабі, може бути дуже дорогим. Часто необхідні високопродуктивні GPU або TPU, а енергоспоживання цих систем є суттєвим.

Приклад:
Розгортання кластера GPU NVIDIA A100 (часто використовується для висновку LLM) може коштувати тисяч доларів на добу у вигляді.cloud-витрат.

Традиційні підходи до обслуговування LLM

Перед тим, як дослідити більш просунуті рішення, давайте коротко розглянемо традиційні підходи до обслуговування LLM:

Просте розгортання з Hugging Transformers

Бібліотека Hugging Face Transformers забезпечує простий спосіб розгортання LLM, але вона не оптимізована для високопродуктивного обслуговування.

Приклад коду:

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

<p>model_name = "meta-llama/Llama-2-13b-hf"
model = AutoModelForCausalLM.from_pretrained(model_name, device_map="auto")
tokenizer = AutoTokenizer.from_pretrained(model_name)</p>

<p>def generate_text(prompt, max_length=100):
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
outputs = model.generate(**inputs, max_length=max_length)
return tokenizer.decode(outputs[0], skip_special_tokens=True)</p>

<p>print(generate_text("The future of AI is"))

Хоча цей підхід працює, він не підходить для додатків з високим трафіком через неефективне використання ресурсів і відсутність оптимізацій для обслуговування.

Використання TorchServe або подібних фреймворків

Фреймворки, такі як TorchServe, забезпечують більш надійні можливості обслуговування, включаючи балансування навантаження та версіонування моделей. Однак вони все ще не вирішують конкретні виклики обслуговування LLM, такі як ефективне управління пам’яттю для великих моделей.

Розуміння управління пам’яттю в обслуговуванні LLM

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

Сегментована пам’ять проти пам’яті сторінок

Ці два діаграми порівнюють техніки управління пам’яттю сегментованої пам’яті та пам’яті сторінок, які зазвичай використовуються в операційних системах (ОС).

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

Управління пам’яттю в ОС проти vLLM

Це зображення порівнює традиційне управління пам’яттю ОС з підходом управління пам’яттю, використовуваним у vLLM.

  • Управління пам’яттю ОС: У традиційних операційних системах процеси (наприклад, Процес А і Процес Б) виділяються сторінки пам’яті (Сторінка 0, Сторінка 1 тощо) у фізичній пам’яті. Це виділення може призвести до фрагментації з часом, оскільки процеси запитують і звільняють пам’ять.
  • Управління пам’яттю vLLM: Фреймворк vLLM використовує кеш ключ-значення (KV) для управління пам’яттю більш ефективно. Запити (наприклад, Запит А і Запит Б) виділяються блоки кешу KV (Блок 0, Блок 1 тощо). Цей підхід допомагає мінімізувати фрагментацію та оптимізувати використання пам’яті, забезпечуючи швидше та більш ефективне обслуговування моделі.

Механізм уваги в LLM

Механізм уваги в LLM

Механізм уваги в LLM

Механізм уваги є фундаментальним компонентом моделей трансформерів, які зазвичай використовуються для LLM. Ця діаграма ілюструє формулу уваги та її компоненти:

  • Запит (Q): Новий токен на етапі декодування або останній токен, який бачила модель.
  • Ключ (K): Попередній контекст, до якого модель повинна звернутися.
  • Значення (V): Важена сума над попереднім контекстом.

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

Порівняння пропускної здатності обслуговування

vLLM: легке, швидке та дешеве обслуговування LLM з PagedAttention

vLLM: легке, швидке та дешеве обслуговування LLM з PagedAttention

Це зображення представляє порівняння пропускної здатності обслуговування між різними фреймворками (HF, TGI та vLLM) за допомогою моделей LLaMA на різних апаратних конфігураціях.

  • LLaMA-13B, A100-40GB: vLLM досягає 14-кратної та 24-кратної вищої пропускної здатності порівняно з Hugging Face Transformers (HF) та 2,2-кратної та 2,5-кратної вищої пропускної здатності порівняно з Hugging Face Text Generation Inference (TGI).
  • LLaMA-7B, A10G: Подібні тенденції спостерігаються, при цьому vLLM значно перевершує як HF, так і TGI.

vLLM: нова архітектура обслуговування LLM

vLLM, розроблений дослідниками з Університету Каліфорнії, Берклі, представляє значний крок вперед у технології обслуговування LLM. Давайте розглянемо його ключові функції та інновації:

PagedAttention

У серці vLLM лежить PagedAttention, новий алгоритм уваги, натхненний управлінням віртуальною пам’яттю в операційних системах. Ось як це працює:

Поділення кешу ключ-значення: Замість зберігання всього кешу ключ-значення послідовно в пам’яті, PagedAttention розділяє його на фіксовані блоки.
Непослідовне зберігання: Ці блоки можуть зберігатися непослідовно в пам’яті, забезпечуючи більш гнучке управління пам’яттю.
Відкладене виділення: Блоки виділяються лише при необхідності, зменшуючи витрату пам’яті.
Ефективне спільне використання: Багатьох послідовностей можна спільно використовувати блоки, забезпечуючи оптимізацію для технік, таких як паралельне вибіркове зразкування та пошук по проміжній області.

Ілюстрація:

“`
Традиційний кеш ключ-значення:
[Токен 1 KV][Токен 2 KV][Токен 3 KV]…[Токен N KV]
(Послідовне виділення пам’яті)
“`

PagedAttention кеш ключ-значення:
[Блок 1] -> Фізична адреса А
[Блок 2] -> Фізична адреса С
[Блок 3] -> Фізична адреса Б

(Непослідовне виділення пам’яті)
“`

Цей підхід значно зменшує фрагментацію пам’яті та дозволяє більш ефективно використовувати пам’ять GPU.

Континуальне пакетування

vLLM реалізує континуальне пакетування, яке динамічно обробляє запити по мірі їх надходження, а не чекає формування фіксованих пакетів. Це призводить до нижчої затримки та вищої пропускної здатності.

Приклад:
Уявіть собі потік надходящих запитів:

“`
Час 0мс: Запит А надходить
Час 10мс: Починається обробка запиту А
Час 15мс: Запит Б надходить
Час 20мс: Починається обробка запиту Б (паралельно з А)
Час 25мс: Запит В надходить

“`

З континуальним пакетуванням vLLM може почати обробку кожного запиту негайно, а не чекати формування попередньо визначених пакетів.

Ефективне паралельне вибіркове зразкування

Для додатків, які вимагають декілька вивідних зразків на промпт (наприклад, творчі помічники з написання), можливості спільного використання пам’яті vLLM особливо корисні. Він може генерувати декілька вивідних зразків, повторно використовуючи кеш ключ-значення для спільних префіксів.

Приклад коду за допомогою vLLM:


from vllm import LLM, SamplingParams

<p>llm = LLM(model="meta-llama/Llama-2-13b-hf")
prompts = ["Майбутнє штучного інтелекту"]</p>

<p># Генерувати 3 зразки на промпт
sampling_params = SamplingParams(n=3, temperature=0.8, max_tokens=100)
outputs = llm.generate(prompts, sampling_params)</p>

<p>for output in outputs:
print(f"Промпт: {output.prompt}")
for i, out in enumerate(output.outputs):
print(f"Зразок {i + 1}: {out.text}")

Цей код ефективно генерує декілька зразків для заданого промпту, використовуючи оптимізації vLLM.

Бенчмаркінг продуктивності vLLM

Щоб повністю оцінити вплив vLLM, давайте розглянемо деякі порівняння продуктивності:

Порівняння пропускної здатності

На основі наданої інформації vLLM значно перевершує інші рішення обслуговування:

– До 24-кратної вищої пропускної здатності порівняно з Hugging Face Transformers
– 2,2-кратної та 3,5-кратної вищої пропускної здатності порівняно з Hugging Face Text Generation Inference (TGI)

Ілюстрація:

“`
Пропускна здатність (токенів/секунда)
|
| ****
| ****
| ****
| **** ****
| **** **** ****
| **** **** ****
|————————
HF TGI vLLM
“`

Ефективність пам’яті

PagedAttention vLLM призводить до майже оптимального використання пам’яті:

– Лише близько 4% витрати пам’яті, порівняно з 60-80% у традиційних системах
– Ця ефективність дозволяє обслуговувати більші моделі або обробляти більше одночасних запитів на одній і тій же апаратній конфігурації

Початок роботи з vLLM

Тепер, коли ми розглянули переваги vLLM, давайте пройдемо процес його налаштування та використання у ваших проектах.

6.1 Встановлення

Встановлення vLLM просте за допомогою pip:


!pip install vllm

6.2 Основне використання для офлайн-виводу

Ось простий приклад використання vLLM для офлайн-генерації тексту:

from vllm import LLM, SamplingParams

<p># Ініціалізація моделі
llm = LLM(model="meta-llama/Llama-2-13b-hf")</p>

<p># Підготовка промптів
prompts = [
"Напишіть коротку поему про штучний інтелект:",
"Поясніть квантові обчислення простими словами:"
]</p>

<p># Налаштування параметрів вибіркового зразкування
sampling_params = SamplingParams(temperature=0.8, max_tokens=100)</p>

<p># Генерування відповідей
outputs = llm.generate(prompts, sampling_params)</p>

<p># Друк результатів
for output in outputs:
print(f"Промпт: {output.prompt}")
print(f"Генерований текст: {output.outputs[0].text}\n")

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

6.3 Налаштування сервера vLLM

Для онлайн-обслуговування vLLM забезпечує сервер API, сумісний з OpenAI. Ось як його налаштувати:

1. Почніть сервер:

python -m vllm.entrypoints.openai.api_server --model meta-llama/Llama-2-13b-hf

2. Запитайте сервер за допомогою curl:

curl http://localhost:8000/v1/completions \
-H "Content-Type: application/json" \
-d '{"model": "meta-llama/Llama-2-13b-hf", "prompt": "Переваги штучного інтелекту включають:", "max_tokens": 100, "temperature": 0.7}'

Ця настройка дозволяє вам обслуговувати вашу LLM з інтерфейсом, сумісним з API OpenAI, що полегшує інтеграцію в існуючі додатки.

Розширені теми щодо vLLM

Хоча vLLM пропонує значні поліпшення обслуговування LLM, є додаткові розгляди та розширені теми для дослідження:

7.1 Квантування моделі

Для ще більш ефективного обслуговування, особливо на апаратному забезпеченні з обмеженою пам’яттю, можна застосовувати техніки квантування. Хоча vLLM сам по собі не підтримує квантування, його можна використовувати разом з квантованими моделями:

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

<p># Завантаження квантованої моделі
model_name = "meta-llama/Llama-2-13b-hf"
model = AutoModelForCausalLM.from_pretrained(model_name, device_map="auto", load_in_8bit=True)
tokenizer = AutoTokenizer.from_pretrained(model_name)</p>

<p># Використання квантованої моделі з vLLM
from vllm import LLM</p>

<p>llm = LLM(model=model, tokenizer=tokenizer)

7.2 Розподілений висновок

Для дуже великих моделей або додатків з високим трафіком може бути необхідним розподілений висновок на декількох GPU або машинах. Хоча vLLM не підтримує це нативно, його можна інтегрувати в розподілені системи за допомогою фреймворків, таких як Ray:

import ray
from vllm import LLM

<p>@ray.remote(num_gpus=1)
class DistributedLLM:</p>

<p>def __init__(self, model_name):
self.llm = LLM(model=model_name)</p>

<p>def generate(self, prompt, params):
return self.llm.generate(prompt, params)</p>

<p># Ініціалізація розподілених LLM
llm1 = DistributedLLM.remote("meta-llama/Llama-2-13b-hf")
llm2 = DistributedLLM.remote("meta-llama/Llama-2-13b-hf")</p>

<p># Використання їх паралельно
result1 = llm1.generate.remote("Промпт 1", sampling_params)
result2 = llm2.generate.remote("Промпт 2", sampling_params)</p>

<p># Отримання результатів
print(ray.get([result1, result2]))

7.3 Моніторинг та спостереження

Під час обслуговування LLM у виробництві моніторинг є важливим. Хоча vLLM не забезпечує вбудований моніторинг, його можна інтегрувати з інструментами, такими як Prometheus та Grafana:

from prometheus_client import start_http_server, Summary
from vllm import LLM

<p># Визначення метрик
REQUEST_TIME = Summary('request_processing_seconds', 'Час обробки запиту')</p>

<p># Ініціалізація vLLM
llm = LLM(model="meta-llama/Llama-2-13b-hf")</p>

<p># Експонування метрик
start_http_server(8000)</p>

<p>@REQUEST_TIME.time()
def process_request(prompt):
return llm.generate(prompt)</p>

# Ваш цикл обслуговування тут

Ця настройка дозволяє вам відстежувати метрики, такі як час обробки запиту, які можна візуалізувати в панелях Grafana.

Висновок

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

Здійснюючи значне поліпшення пропускної здатності, зниження витрат пам’яті та забезпечення більш гнучких варіантів обслуговування, vLLM відкриває нові можливості для інтеграції потужних мовних моделей у широкий спектр додатків. Чи будуєте ви чат-бота, систему генерації контенту чи будь-який інший додаток, що використовує NLP, розуміння та використання інструментів, таких як vLLM, будуть ключем до успіху.

Я провів останні п'ять років, занурючись у захопливий світ машинного навчання та глибокого навчання. Моя пристрасть та експертиза привели мене до внеску у понад 50 різних проектів програмної інженерії, з особливим акцентом на AI/ML. Моя тривала цікавість також привела мене до природної обробки мови, галузі, яку я бажаю дослідити далі.