Modele i platformy AI
Optymalizacja wdroÅženia modeli LLM: vLLM PagedAttention i przyszÅoÅÄ wydajnego serwowania AI
WdroÅženie modeli jÄzykowych (LLM) w aplikacjach Åwiata rzeczywistego stwarza unikalne wyzwania, szczegÃģlnie w zakresie zasobÃģw obliczeniowych, opÃģÅšnieÅ i efektywnoÅci kosztowej. W tym kompleksowym przewodniku, bÄdziemy badaÄ krajobraz serwowania LLM, ze szczegÃģlnym uwzglÄdnieniem vLLM (wektorowy model jÄzykowy), rozwiÄ zania, ktÃģre zmienia sposÃģb, w jaki wdraÅžamy i korzystamy z tych potÄÅžnych modeli.
Wyzwania serwowania modeli jÄzykowych
Przed przejÅciem do konkretnych rozwiÄ zaÅ, rozwaÅžmy kluczowe wyzwania, ktÃģre sprawiajÄ , Åže serwowanie LLM jest zÅoÅžonym zadaniem:
Zasoby obliczeniowe
LLM sÄ znane ze swoich ogromnych liczb parametrÃģw, siÄgajÄ cych od miliardÃģw do setek miliardÃģw. Na przykÅad, GPT-3 ma 175 miliardÃģw parametrÃģw, podczas gdy nowsze modele, takie jak GPT-4 majÄ jeszcze wiÄcej. Ten ogromny rozmiar przekÅada siÄ na znaczne wymagania obliczeniowe dla inferencji.
PrzykÅad:
RozwaÅžmy stosunkowo skromny LLM z 13 miliardami parametrÃģw, takim jak LLaMA-13B. Nawet ten model wymaga:
â OkoÅo 26 GB pamiÄci, aby przechowaÄ parametry modelu (przy zaÅoÅženiu 16-bitowej precyzji)
â Dodatkowej pamiÄci dla aktywacji, mechanizmÃģw uwagi i obliczeÅ poÅrednich
â Znacznej mocy obliczeniowej GPU dla inferencji w czasie rzeczywistym
OpÃģÅšnienia
W wielu aplikacjach, takich jak czatboty lub generacja treÅci w czasie rzeczywistym, niskie opÃģÅšnienia sÄ kluczowe dla dobrego doÅwiadczenia uÅžytkownika. Jednak zÅoÅžonoÅÄ LLM moÅže prowadziÄ do znacznych czasÃģw przetwarzania, szczegÃģlnie dla dÅuÅžszych sekwencji.
PrzykÅad:
WyobraÅšmy sobie czatbota obsÅugiwanego przez LLM. JeÅli kaÅžda odpowiedÅš zajmuje kilka sekund, rozmowa bÄdzie wyglÄ
daÄ nienaturalnie i frustrujÄ
co dla uÅžytkownikÃģw.
Koszt
SprzÄt niezbÄdny do uruchomienia LLM w skali moÅže byÄ bardzo drogi. CzÄsto wymagane sÄ wysokiej jakoÅci GPU lub TPU, a zuÅžycie energii przez te systemy jest znaczne.
PrzykÅad:
Uruchomienie klastra NVIDIA A100 GPU (czÄsto uÅžywanych do inferencji LLM) moÅže kosztowaÄ tysiÄ
ce dolarÃģw dziennie w opÅatach za chmurÄ obliczeniowÄ
.
Tradycyjne podejÅcia do serwowania LLM
Przed zbadaniem bardziej zaawansowanych rozwiÄ zaÅ, krÃģtko przeglÄ dnijmy tradycyjne podejÅcia do serwowania LLM:
Proste wdroÅženie z Hugging Transformers
Biblioteka Hugging Face Transformers zapewnia prosty sposÃģb wdroÅženia LLM, ale nie jest zoptymalizowana do serwowania o wysokiej wydajnoÅci.
PrzykÅad kodu:
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"))
ChociaÅž to podejÅcie dziaÅa, nie jest odpowiednie dla aplikacji o wysokim ruchu ze wzglÄdu na niewydajne wykorzystanie zasobÃģw i brak optymalizacji do serwowania.
UÅžycie TorchServe lub podobnych frameworkÃģw
Frameworki takie jak TorchServe zapewniajÄ bardziej solidne moÅžliwoÅci serwowania, w tym rÃģwnowaÅženie obciÄ Åženia i wersjonowanie modelu. Jednak nadal nie rozwiÄ zujÄ specyficznych wyzwaÅ serwowania LLM, takich jak efektywne zarzÄ dzanie pamiÄciÄ dla duÅžych modeli.
Zrozumienie zarzÄ dzania pamiÄciÄ w serwowaniu LLM
Efektywne zarzÄ dzanie pamiÄciÄ jest kluczowe dla serwowania duÅžych modeli jÄzykowych (LLM) ze wzglÄdu na ogromne wymagania obliczeniowe. PoniÅžsze obrazy ilustrujÄ rÃģÅžne aspekty zarzÄ dzania pamiÄciÄ , ktÃģre sÄ integralne dla optymalizacji wydajnoÅci LLM.
Segmentowana a pamiÄÄ stronicowana
Te dwa diagramy porÃģwnujÄ techniki zarzÄ dzania pamiÄciÄ segmentowanÄ i stronicowanÄ , powszechnie uÅžywane w systemach operacyjnych (OS).
- PamiÄÄ segmentowana: Ta technika dzieli pamiÄÄ na rÃģÅžne segmenty, z ktÃģrych kaÅždy odpowiada rÃģÅžnemu programowi lub procesowi. Na przykÅad, w kontekÅcie serwowania LLM, rÃģÅžne segmenty mogÄ byÄ przydzielone do rÃģÅžnych komponentÃģw modelu, takich jak tokenizacja, osadzanie i mechanizmy uwagi. KaÅždy segment moÅže rosnÄ Ä lub kurczyÄ siÄ niezaleÅžnie, zapewniajÄ c elastycznoÅÄ, ale potencjalnie prowadzÄ c do fragmentacji, jeÅli segmenty nie sÄ odpowiednio zarzÄ dzane.
- PamiÄÄ stronicowana: Tutaj pamiÄÄ jest podzielona na strony o staÅym rozmiarze, ktÃģre sÄ mapowane na pamiÄÄ fizycznÄ . Strony mogÄ byÄ wymieniane w razie potrzeby, umoÅžliwiajÄ c efektywne wykorzystanie zasobÃģw pamiÄci. W serwowaniu LLM moÅže to byÄ kluczowe dla zarzÄ dzania duÅžymi iloÅciami pamiÄci wymaganymi do przechowywania wag modelu i obliczeÅ poÅrednich.
ZarzÄ dzanie pamiÄciÄ w systemie operacyjnym vs. vLLM
Ten obraz kontrastuje tradycyjne zarzÄ dzanie pamiÄciÄ w systemie operacyjnym z podejÅciem do zarzÄ dzania pamiÄciÄ uÅžywanym w vLLM.
- ZarzÄ dzanie pamiÄciÄ w systemie operacyjnym: W tradycyjnych systemach operacyjnych, procesy (np. Proces A i Proces B) sÄ przydzielane strony pamiÄci (Strona 0, Strona 1 itd.) w pamiÄci fizycznej. To przydzielanie moÅže prowadziÄ do fragmentacji z czasem, gdy procesy ÅžÄ dajÄ i zwalniajÄ pamiÄÄ.
- ZarzÄ dzanie pamiÄciÄ w vLLM: Framework vLLM wykorzystuje pamiÄÄ podrÄcznÄ Key-Value (KV), aby zarzÄ dzaÄ pamiÄciÄ w sposÃģb bardziej efektywny. ÅŧÄ dania (np. ÅŧÄ danie A i ÅŧÄ danie B) sÄ przydzielane bloki pamiÄci podrÄcznej KV (Blok 0, Blok 1 itd.). To podejÅcie pomaga minimalizowaÄ fragmentacjÄ i optymalizowaÄ wykorzystanie pamiÄci, umoÅžliwiajÄ c szybsze i bardziej efektywne serwowanie modelu.
Mechanizm uwagi w LLM
Mechanizm uwagi jest podstawowym komponentem modeli transformatorowych, ktÃģre sÄ powszechnie uÅžywane w LLM. Ten diagram ilustruje wzÃģr uwagi i jego skÅadniki:
- Zapytanie (Q): Nowy token w kroku dekodera lub ostatni token, ktÃģry model widziaÅ.
- Klucz (K): Poprzedni kontekst, do ktÃģrego model powinien siÄ odnosiÄ.
- WartoÅÄ (V): UwzglÄdniona suma poprzedniego kontekstu.
WzÃģr oblicza wyniki uwagi, biorÄ c iloczyn skalarny zapytania z kluczami, skalujÄ c przez pierwiastek kwadratowy wymiaru klucza, stosujÄ c funkcjÄ softmax i biorÄ c iloczyn skalarny z wartoÅciami. Ten proces pozwala modelowi koncentrowaÄ siÄ na istotnych czÄÅciach sekwencji wejÅciowej podczas generowania kaÅždego tokenu.
PorÃģwnanie przepustowoÅci serwowania
Ten obraz przedstawia porÃģwnanie przepustowoÅci serwowania miÄdzy rÃģÅžnymi frameworkami (HF, TGI i vLLM) przy uÅžyciu modeli LLaMA na rÃģÅžnych konfiguracjach sprzÄtu.
- LLaMA-13B, A100-40GB: vLLM osiÄ ga 14-krotnie do 24-krotnie wyÅžszÄ przepustowoÅÄ niÅž Hugging Face Transformers (HF) i 2,2-krotnie do 2,5-krotnie wyÅžszÄ przepustowoÅÄ niÅž Hugging Face Text Generation Inference (TGI).
- LLaMA-7B, A10G: Obserwuje siÄ podobne trendy, z vLLM znacznie przewyÅžszajÄ c zarÃģwno HF, jak i TGI.
vLLM: Nowa architektura serwowania LLM
vLLM, opracowany przez badaczy z UC Berkeley, reprezentuje znaczny krok naprzÃģd w technologii serwowania LLM. Przeanalizujmy jego kluczowe funkcje i innowacje:
PagedAttention
W sercu vLLM leÅžy PagedAttention, nowy algorytm uwagi zainspirowany zarzÄ dzaniem pamiÄciÄ wirtualnÄ w systemach operacyjnych. Oto, jak to dziaÅa:
â PodziaÅ pamiÄci podrÄcznej Key-Value (KV): Zamiast przechowywaÄ caÅÄ
pamiÄÄ podrÄcznÄ
KV w pamiÄci w sposÃģb ciÄ
gÅy, PagedAttention dzieli jÄ
na bloki o staÅym rozmiarze.
â Przechowywanie nieciÄ
gÅe: Te bloki mogÄ
byÄ przechowywane w pamiÄci w sposÃģb nieciÄ
gÅy, umoÅžliwiajÄ
c bardziej elastyczne zarzÄ
dzanie pamiÄciÄ
.
â Przydzielanie na ÅžÄ
danie: Bloki sÄ
przydzielane tylko wtedy, gdy sÄ
potrzebne, redukujÄ
c marnowanie pamiÄci.
â Wygodne udostÄpnianie: Wiele sekwencji moÅže udostÄpniaÄ bloki, umoÅžliwiajÄ
c optymalizacjÄ dla technik takich jak prÃģbkowanie rÃģwnolegÅe i wyszukiwanie promieniowe.
Ilustracja:
â`
Tradycyjna pamiÄÄ podrÄczna KV:
[Token 1 KV][Token 2 KV][Token 3 KV]âĶ[Token N KV]
(Przechowywanie ciÄ
gÅe)
â`
PagedAttention pamiÄÄ podrÄczna KV:
[Blok 1] -> Adres fizyczny A
[Blok 2] -> Adres fizyczny C
[Blok 3] -> Adres fizyczny B
âĶ
(Przechowywanie nieciÄ
gÅe)
â`
To podejÅcie znacznie redukuje fragmentacjÄ pamiÄci i pozwala na znacznie bardziej efektywne wykorzystanie pamiÄci GPU.
CiÄ gÅe grupowanie
vLLM wdraÅža ciÄ gÅe grupowanie, ktÃģre dynamicznie przetwarza ÅžÄ dania w momencie ich przybycia, zamiast czekania na utworzenie partii o staÅym rozmiarze. To prowadzi do niÅžszych opÃģÅšnieÅ i wyÅžszej przepustowoÅci.
PrzykÅad:
WyobraÅšmy sobie strumieÅ przychodzÄ
cych ÅžÄ
daÅ:
â`
Czas 0ms: ÅŧÄ
danie A przychodzi
Czas 10ms: RozpoczÄcie przetwarzania ÅŧÄ
dania A
Czas 15ms: ÅŧÄ
danie B przychodzi
Czas 20ms: RozpoczÄcie przetwarzania ÅŧÄ
dania B (w rÃģwnolegle z A)
Czas 25ms: ÅŧÄ
danie C przychodzi
âĶ
â`
Z ciÄ gÅym grupowaniem vLLM moÅže rozpoczÄ Ä przetwarzanie kaÅždego ÅžÄ dania natychmiast, zamiast czekaÄ na utworzenie partii o okreÅlonym rozmiarze.
Wygodne prÃģbkowanie rÃģwnolegÅe
Dla aplikacji, ktÃģre wymagajÄ wielu prÃģbek wyjÅciowych na kaÅžde wejÅcie (np. asystentÃģw tworzenia treÅci), moÅžliwoÅci udostÄpniania pamiÄci vLLM sÄ szczegÃģlnie przydatne. MoÅže generowaÄ wiele wyjÅÄ, jednoczeÅnie ponownie wykorzystujÄ c pamiÄÄ podrÄcznÄ KV dla wspÃģlnych prefiksÃģw.
PrzykÅad kodu przy uÅžyciu vLLM:
from vllm import LLM, SamplingParams
<p>llm = LLM(model="meta-llama/Llama-2-13b-hf")
prompts = ["PrzyszÅoÅÄ AI jest"]</p>
<p># Generuj 3 prÃģbki dla kaÅždego wejÅcia
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"Prompt: {output.prompt}")
for i, out in enumerate(output.outputs):
print(f"PrÃģbka {i + 1}: {out.text}")</p>
Ten kod efektywnie generuje wiele prÃģbek dla danego wejÅcia, wykorzystujÄ c optymalizacje vLLM.
Testowanie wydajnoÅci vLLM
Aby naprawdÄ doceniÄ wpÅyw vLLM, przyjrzyjmy siÄ porÃģwnaniom wydajnoÅci:
PorÃģwnanie przepustowoÅci
Na podstawie podanych informacji, vLLM znacznie przewyÅžsza inne rozwiÄ zania serwowania:
â Do 24-krotnie wyÅžsza przepustowoÅÄ w porÃģwnaniu z Hugging Face Transformers
â 2,2-krotnie do 3,5-krotnie wyÅžsza przepustowoÅÄ niÅž Hugging Face Text Generation Inference (TGI)
Ilustracja:
â`
PrzepustowoÅÄ (Tokeny/sekunda)
|
| ****
| ****
| ****
| **** ****
| **** **** ****
| **** **** ****
|ââââââââ
HF TGI vLLM
â`
EfektywnoÅÄ pamiÄci
PagedAttention vLLM prowadzi do prawie optymalnego wykorzystania pamiÄci:
â Tylko okoÅo 4% marnowania pamiÄci, w porÃģwnaniu z 60-80% w tradycyjnych systemach
â Ta efektywnoÅÄ pozwala na serwowanie wiÄkszych modeli lub obsÅugÄ wiÄkszej liczby rÃģwnoczesnych ÅžÄ
daÅ przy uÅžyciu tego samego sprzÄtu.
RozpoczÄcie pracy z vLLM
Teraz, gdy juÅž zbadaliÅmy zalety vLLM, przejdÅšmy przez proces instalacji i korzystania z niego w Twoich projektach.
6.1 Instalacja
Instalacja vLLM jest prosta przy uÅžyciu pip:
!pip install vllm
6.2 Podstawowe uÅžycie do inferencji offline
Oto prosty przykÅad uÅžycia vLLM do generacji tekstu offline:
from vllm import LLM, SamplingParams
<p># Zainicjuj model
llm = LLM(model="meta-llama/Llama-2-13b-hf")</p>
<p># Przygotuj wejÅcia
prompts = [
"Napisz krÃģtki wiersz o sztucznej inteligencji:",
"WyjaÅnij kwantowÄ
komputacjÄ w prosty sposÃģb:"
]</p>
<p># Ustaw parametry prÃģbkowania
sampling_params = SamplingParams(temperature=0.8, max_tokens=100)</p>
<p># Wygeneruj odpowiedzi
outputs = llm.generate(prompts, sampling_params)</p>
<p># Wypisz wyniki
for output in outputs:
print(f"Prompt: {output.prompt}")
print(f"Wygenerowany tekst: {output.outputs[0].text}\n")</p>
Ten skrypt demonstruje, jak zaÅadowaÄ model, ustawiÄ parametry prÃģbkowania i wygenerowaÄ tekst dla wielu wejÅÄ.
6.3 Konfigurowanie serwera vLLM
Dla serwowania online, vLLM zapewnia serwer API zgodny z OpenAI. Oto, jak go skonfigurowaÄ:
1. Uruchom serwer:
python -m vllm.entrypoints.openai.api_server --model meta-llama/Llama-2-13b-hf
2. WyÅlij ÅžÄ danie do serwera przy uÅžyciu curl:
curl http://localhost:8000/v1/completions \
-H "Content-Type: application/json" \
-d '{"model": "meta-llama/Llama-2-13b-hf", "prompt": "KorzyÅci z sztucznej inteligencji to:", "max_tokens": 100, "temperature": 0.7}'
Ten zestaw pozwala na serwowanie Twojego LLM z interfejsem zgodnym z API OpenAI, co uÅatwia integracjÄ z istniejÄ cymi aplikacjami.
Zaawansowane tematy na temat vLLM
ChociaÅž vLLM oferuje znaczne ulepszenia w serwowaniu LLM, istniejÄ dodatkowe rozwaÅžania i zaawansowane tematy do zbadania:
7.1 Kwantyzacja modelu
Dla jeszcze bardziej efektywnego serwowania, szczegÃģlnie na sprzÄcie z ograniczonÄ pamiÄciÄ , moÅžna zastosowaÄ techniki kwantyzacji. ChociaÅž vLLM sam w sobie nie obsÅuguje kwantyzacji, moÅže byÄ uÅžywany w poÅÄ czeniu z zkwantyfikowanymi modelami:
from transformers import AutoModelForCausalLM, AutoTokenizer import torch <p># ZaÅaduj zkwantyfikowany model 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># UÅžyj zkwantyfikowanego modelu z vLLM from vllm import LLM</p> <p>llm = LLM(model=model, tokenizer=tokenizer)
7.2 Rozproszone inferencje
Dla bardzo duÅžych modeli lub aplikacji o wysokim ruchu, rozproszone inferencje na wielu GPU lub maszynach mogÄ byÄ konieczne. ChociaÅž vLLM nie obsÅuguje tego natywnie, moÅže byÄ integrowany z systemami rozproszonymi przy uÅžyciu frameworkÃģw takich jak Ray:
import ray
from vllm import LLM
<p>@ray.remote(num_gpus=1)
class DistributedLLM:
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># Zainicjuj rozproszone LLM
llm1 = DistributedLLM.remote("meta-llama/Llama-2-13b-hf")
llm2 = DistributedLLM.remote("meta-llama/Llama-2-13b-hf")</p>
<p># UÅžyj ich w rÃģwnolegle
result1 = llm1.generate.remote("Prompt 1", sampling_params)
result2 = llm2.generate.remote("Prompt 2", sampling_params)</p>
<p># Pobierz wyniki
print(ray.get([result1, result2]))
7.3 Monitorowanie i obserwowalnoÅÄ
Podczas serwowania LLM w produkcji, monitorowanie jest kluczowe. ChociaÅž vLLM nie zapewnia wbudowanego monitorowania, moÅžna go zintegrowaÄ z narzÄdziami takimi jak Prometheus i Grafana:
from prometheus_client import start_http_server, Summary
from vllm import LLM
<p># Zdefiniuj metryki
REQUEST_TIME = Summary('request_processing_seconds', 'Czas przetwarzania ÅžÄ
dania')</p>
<p># Zainicjuj vLLM
llm = LLM(model="meta-llama/Llama-2-13b-hf")</p>
<p># UdostÄpnij metryki
start_http_server(8000)</p>
<p># UÅžyj modelu z monitorowaniem
@REQUEST_TIME.time()
def process_request(prompt):
return llm.generate(prompt)</p>
# Twoja pÄtla serwowania tutaj
Ten zestaw pozwala ÅledziÄ metryki takie jak czas przetwarzania ÅžÄ dania, ktÃģre mogÄ byÄ wizualizowane w dashboardach Grafana.
Podsumowanie
Serwowanie duÅžych modeli jÄzykowych w sposÃģb efektywny jest zÅoÅžonym, ale kluczowym zadaniem w erze AI. vLLM, z jego innowacyjnym algorytmem PagedAttention i zoptymalizowanÄ implementacjÄ , reprezentuje znaczny krok naprzÃģd w czynieniu wdroÅženia LLM bardziej dostÄpnym i efektywnym kosztowo.
Poprzez dramatyczne poprawienie przepustowoÅci, redukcjÄ marnowania pamiÄci i umoÅžliwienie bardziej elastycznego serwowania, vLLM otwiera nowe moÅžliwoÅci integracji potÄÅžnych modeli jÄzykowych w szeroki zakres aplikacji. NiezaleÅžnie od tego, czy budujesz czatbota, system generacji treÅci, czy jakÄ kolwiek innÄ aplikacjÄ napÄdzanÄ NLP, zrozumienie i wykorzystanie narzÄdzi takich jak vLLM bÄdzie kluczem do sukcesu.
















