AI-modellen en platforms
Optimalisatie van LLM-implementatie: vLLM PagedAttention en de toekomst van efficiënte AI-implementatie
Grote taalmodellen (LLM’s) implementeren in real-world applicaties stelt unieke uitdagingen, met name op het gebied van computationele middelen, latentie en kostenefficiëntie. In deze uitgebreide gids zullen we het landschap van LLM-implementatie onderzoeken, met een speciale focus op vLLM (vector Language Model), een oplossing die de manier waarop we met deze krachtige modellen omgaan, fundamenteel verandert.
De uitdagingen van het implementeren van grote taalmodellen
Voordat we specifieke oplossingen onderzoeken, laten we de belangrijkste uitdagingen onderzoeken die LLM-implementatie een complexe taak maken:
Computationele middelen
LLM’s zijn berucht om hun enorme parameteraantallen, variërend van miljarden tot honderden miljarden. Bijvoorbeeld, GPT-3 heeft 175 miljard parameters, terwijl recentere modellen zoals GPT-4 nog meer parameters hebben. Deze enorme omvang vertaalt zich in significante computationele vereisten voor inferentie.
Voorbeeld:
Overweeg een relatief bescheiden LLM met 13 miljard parameters, zoals LLaMA-13B. Zelfs dit model vereist:
– Ongeveer 26 GB aan geheugen om alleen al de modelparameters op te slaan (bij 16-bits precisie)
– Extra geheugen voor activaties, aandachtmecanismen en tussenberekeningen
– Aanzienlijke GPU-rekenkracht voor real-time inferentie
Latentie
In veel applicaties, zoals chatbots of real-time inhoudsgeneratie, is lage latentie cruciaal voor een goede gebruikerservaring. Echter, de complexiteit van LLM’s kan leiden tot significante verwerkingstijden, vooral voor langere sequenties.
Voorbeeld:
Stel je een klantenservice-chatbot voor die wordt aangedreven door een LLM. Als elke reactie enkele seconden nodig heeft om te genereren, zal het gesprek onnatuurlijk en frustrerend zijn voor gebruikers.
Kosten
De hardware die nodig is om LLM’s op grote schaal uit te voeren, kan extreem duur zijn. High-end GPU’s of TPU’s zijn vaak noodzakelijk, en het energieverbruik van deze systemen is aanzienlijk.
Voorbeeld:
Het uitvoeren van een cluster van NVIDIA A100 GPU’s (vaak gebruikt voor LLM-inferentie) kan duizenden dollars per dag kosten in cloud-computingkosten.
Traditionele benaderingen van LLM-implementatie
Voordat we geavanceerdere oplossingen onderzoeken, laten we eerst enkele traditionele benaderingen van LLM-implementatie onderzoeken:
Eenvoudige implementatie met Hugging Transformers
De Hugging Face Transformers-bibliotheek biedt een eenvoudige manier om LLM’s te implementeren, maar het is niet geoptimaliseerd voor high-throughput-implementatie.
Voorbeeldcode:
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("De toekomst van AI is"))
Hoewel deze benadering werkt, is het niet geschikt voor high-traffic-applicaties vanwege het inefficiënte gebruik van middelen en het ontbreken van optimalisaties voor implementatie.
Gebruik van TorchServe of soortgelijke frameworks
Frameworks zoals TorchServe bieden robuustere implementatiemogelijkheden, waaronder load balancing en modelversiebeheer. Echter, ze lossen de specifieke uitdagingen van LLM-implementatie, zoals efficiënte geheugenbeheer voor grote modellen, nog niet op.
Geheugenbeheer in LLM-implementatie
Efficiënt geheugenbeheer is cruciaal voor het implementeren van grote taalmodellen (LLM’s) vanwege de uitgebreide computationele middelen die nodig zijn. De volgende afbeeldingen illustreren verschillende aspecten van geheugenbeheer, die essentieel zijn voor het optimaliseren van LLM-prestaties.
Segmented vs. Paged Memory
Deze twee diagrammen vergelijken segmented memory- en paged memory-technieken, die gewoonlijk in besturingssystemen (OS) worden gebruikt.
- Segmented Memory: Deze techniek deelt geheugen op in verschillende segmenten, elk overeenkomend met een ander programma of proces. In een LLM-implementatiecontext kunnen verschillende segmenten bijvoorbeeld worden toegewezen aan verschillende componenten van het model, zoals tokenisatie, embedding en aandachtmecanismen. Elk segment kan onafhankelijk groeien of krimpen, waardoor flexibiliteit ontstaat, maar mogelijk ook fragmentatie als segmenten niet goed worden beheerd.
- Paged Memory: Hier wordt geheugen opgedeeld in vaste-grootte pagina’s, die worden toegewezen aan fysiek geheugen. Pagina’s kunnen worden ingewisseld als nodig, waardoor een efficiënt gebruik van geheugensources mogelijk wordt. In LLM-implementatie kan dit cruciaal zijn voor het beheren van de grote hoeveelheden geheugen die nodig zijn voor het opslaan van modelgewichten en tussenberekeningen.
Geheugenbeheer in OS vs. vLLM
Deze afbeelding toont het contrast tussen traditioneel OS-geheugenbeheer en de geheugenbeheerbenadering die in vLLM wordt gebruikt.
- OS-geheugenbeheer: In traditionele besturingssystemen worden processen (bijv. Proces A en Proces B) pagina’s van geheugen toegewezen (Pagina 0, Pagina 1, enz.) in fysiek geheugen. Deze toewijzing kan leiden tot fragmentatie na verloop van tijd als processen geheugen aanvragen en vrijgeven.
- vLLM-geheugenbeheer: Het vLLM-framework gebruikt een Key-Value (KV)-cache om geheugen efficiënter te beheren. Aanvragen (bijv. Aanvraag A en Aanvraag B) worden blokken van de KV-cache toegewezen (KV-blok 0, KV-blok 1, enz.). Deze benadering helpt fragmentatie te minimaliseren en optimaliseert geheugengebruik, waardoor snellere en efficiëntere modelimplementatie mogelijk wordt.
Aandachtmecanisme in LLM’s
Het aandachtmecanisme is een fundamenteel onderdeel van transformermodellen, die vaak voor LLM’s worden gebruikt. Deze afbeelding illustreert de aandachtformule en de onderdelen ervan:
- Vraag (Q): Een nieuw token in de decoderstap of het laatste token dat het model heeft gezien.
- Sleutel (K): Voorgaande context waarop het model moet letten.
- Waarde (V): Gewogen som over de voorgaande context.
De formule berekent de aandachtscores door het dotproduct van de vraag met de sleutels te nemen, geschaald door de vierkantswortel van de sleutelafmeting, een softmax-functie toe te passen en tenslotte het dotproduct met de waarden te nemen. Dit proces stelt het model in staat om relevante delen van de invoersequentie te benadrukken bij het genereren van elk token.
Implementatie-doorvoer-vergelijking
Deze afbeelding toont een vergelijking van implementatie-doorvoer tussen verschillende frameworks (HF, TGI en vLLM) met behulp van LLaMA-modellen op verschillende hardware-configuraties.
- LLaMA-13B, A100-40GB: vLLM bereikt 14x – 24x hogere doorvoer dan HuggingFace Transformers (HF) en 2,2x – 2,5x hogere doorvoer dan HuggingFace Text Generation Inference (TGI).
- LLaMA-7B, A10G: Vergelijkbare trends worden waargenomen, waarbij vLLM zowel HF als TGI significant overtreft.
vLLM: Een nieuwe LLM-implementatie-architectuur
vLLM, ontwikkeld door onderzoekers aan de UC Berkeley, vertegenwoordigt een significante stap voorwaarts in LLM-implementatietechnologie. Laten we de belangrijkste functies en innovaties ervan onderzoeken:
PagedAttention
In het hart van vLLM ligt PagedAttention, een novaal aandachtmecanisme geïnspireerd door virtueel geheugenbeheer in besturingssystemen. Hieronder volgt een overzicht van hoe het werkt:
– Key-Value (KV)-cache-partitie: In plaats van de hele KV-cache aaneengesloten in geheugen op te slaan, deelt PagedAttention deze op in vaste-grootte blokken.
– Niet-aaneengesloten opslag: Deze blokken kunnen niet-aaneengesloten in geheugen worden opgeslagen, waardoor flexibeler geheugenbeheer mogelijk wordt.
– Op-aanvraag-toewijzing: Blokken worden alleen toegewezen als ze nodig zijn, waardoor geheugensverspilling wordt verminderd.
– Efficiënte deling: Meerdere sequenties kunnen blokken delen, waardoor optimalisaties voor technieken zoals parallel sampling en beam search mogelijk worden.
Illustratie:
“`
Traditionele KV-cache:
[Token 1 KV][Token 2 KV][Token 3 KV]…[Token N KV]
(Aaneengesloten geheugentoewijzing)
“`
PagedAttention KV-cache:
[Block 1] -> Fysiek adres A
[Block 2] -> Fysiek adres C
[Block 3] -> Fysiek adres B
…
(Niet-aaneengesloten geheugentoewijzing)
“`
Deze benadering reduceert geheugenfragmentatie aanzienlijk en stelt een veel efficiënter gebruik van GPU-geheugen mogelijk.
Continue batching
vLLM implementeert continue batching, waarmee aanvragen dynamisch worden verwerkt zodra ze binnenkomen, in plaats van te wachten tot vaste batches zijn gevormd. Dit leidt tot lagere latentie en hogere doorvoer.
Voorbeeld:
Stel je een stroom van binnenkomende aanvragen voor:
“`
Tijd 0ms: Aanvraag A komt binnen
Tijd 10ms: Start verwerking van Aanvraag A
Tijd 15ms: Aanvraag B komt binnen
Tijd 20ms: Start verwerking van Aanvraag B (parallel aan A)
Tijd 25ms: Aanvraag C komt binnen
…
“`
Met continue batching kan vLLM elke aanvraag onmiddellijk verwerken, in plaats van te wachten tot ze in vooraf gedefinieerde batches zijn gegroepeerd.
Efficiënte parallelle sampling
Voor toepassingen die meerdere uitvoersteekproeven per prompt vereisen (bijv. creatieve schrijfassistenten), blinkt vLLM’s geheugendelingsmogelijkheden uit. Het kan meerdere uitvoer genereren terwijl het de KV-cache voor gedeelde prefixes hergebruikt.
Voorbeeldcode met vLLM:
from vllm import LLM, SamplingParams
<p>llm = LLM(model="meta-llama/Llama-2-13b-hf")
prompts = ["De toekomst van AI is"]</p>
<p># Genereer 3 steekproeven per prompt
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"Steekproef {i + 1}: {out.text}")
Deze code genereert efficiënt meerdere steekproeven voor de gegeven prompt, waarbij vLLM’s optimalisaties worden gebruikt.
Benchmarken van vLLM-prestaties
Om de impact van vLLM echt te waarderen, laten we enkele prestatieverbeteringen onderzoeken:
Doorvoer-vergelijking
Op basis van de verstrekte informatie, overtreft vLLM andere implementatie-oplossingen aanzienlijk:
– Tot 24x hogere doorvoer in vergelijking met Hugging Face Transformers
– 2,2x tot 3,5x hogere doorvoer dan Hugging Face Text Generation Inference (TGI)
Illustratie:
“`
Doorvoer (tokens per seconde)
|
| ****
| ****
| ****
| **** ****
| **** **** ****
|————————
HF TGI vLLM
“`
Geheugenefficiëntie
vLLM’s PagedAttention resulteert in bijna-optimale geheugengebruik:
– Slechts ongeveer 4% geheugensverspilling, in vergelijking met 60-80% in traditionele systemen
– Deze efficiëntie stelt het mogelijk om grotere modellen te implementeren of meer gelijktijdige aanvragen te verwerken met dezelfde hardware
Aan de slag met vLLM
Nu we de voordelen van vLLM hebben onderzocht, laten we de stappen doorlopen om het op te zetten en te gebruiken in uw projecten.
6.1 Installatie
Het installeren van vLLM is eenvoudig met pip:
!pip install vllm
6.2 Basisgebruik voor offline-inferentie
Hieronder volgt een eenvoudig voorbeeld van het gebruik van vLLM voor offline-tekstgeneratie:
from vllm import LLM, SamplingParams
<p># Initialiseer het model
llm = LLM(model="meta-llama/Llama-2-13b-hf")</p>
<p># Bereid prompts voor
prompts = [
"Schrijf een kort gedicht over kunstmatige intelligentie:",
"Leg kwantumcomputing uit in eenvoudige bewoordingen:"
]</p>
<p># Stel steekproefparameters in
sampling_params = SamplingParams(temperature=0.8, max_tokens=100)</p>
<p># Genereer antwoorden
outputs = llm.generate(prompts, sampling_params)</p>
<p># Druk de resultaten af
for output in outputs:
print(f"Prompt: {output.prompt}")
print(f"Gegenereerde tekst: {output.outputs[0].text}\n")
Deze script demonstreert hoe u een model laadt, steekproefparameters instelt en tekst genereert voor meerdere prompts.
6.3 Opzetten van een vLLM-server
Voor online-implementatie biedt vLLM een OpenAI-compatibele API-server. Hieronder volgt een overzicht van hoe u deze opzet:
1. Start de server:
python -m vllm.entrypoints.openai.api_server --model meta-llama/Llama-2-13b-hf
2. Verzoek de server met curl:
curl http://localhost:8000/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "meta-llama/Llama-2-13b-hf",
"prompt": "De voordelen van kunstmatige intelligentie omvatten:",
"max_tokens": 100,
"temperature": 0.7
}'
Deze setup stelt u in staat om uw LLM te implementeren met een interface die compatibel is met de OpenAI-API, waardoor het gemakkelijk is om deze in bestaande applicaties te integreren.
Geavanceerde onderwerpen over vLLM
Terwijl vLLM aanzienlijke verbeteringen biedt in LLM-implementatie, zijn er aanvullende overwegingen en geavanceerde onderwerpen om te onderzoeken:
7.1 Model-quantificatie
Voor nog efficiëntere implementatie, vooral op hardware met beperkt geheugen, kunnen quantificatietechnieken worden toegepast. Hoewel vLLM zelf geen quantificatie ondersteunt, kan het worden gebruikt in combinatie met gequantificeerde modellen:
from transformers import AutoModelForCausalLM, AutoTokenizer import torch <p># Laad een gequantificeerd 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># Gebruik het gequantificeerde model met vLLM from vllm import LLM</p> <p>llm = LLM(model=model, tokenizer=tokenizer)
7.2 Gedistribueerde inferentie
Voor extreem grote modellen of high-traffic-applicaties kan gedistribueerde inferentie over meerdere GPU’s of machines noodzakelijk zijn. Hoewel vLLM dit native niet ondersteunt, kan het worden geïntegreerd in gedistribueerde systemen met behulp van frameworks zoals 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># Initialiseer gedistribueerde LLM's
llm1 = DistributedLLM.remote("meta-llama/Llama-2-13b-hf")
llm2 = DistributedLLM.remote("meta-llama/Llama-2-13b-hf")</p>
<p># Gebruik ze in parallel
result1 = llm1.generate.remote("Prompt 1", sampling_params)
result2 = llm2.generate.remote("Prompt 2", sampling_params)</p>
<p># Haal resultaten op
print(ray.get([result1, result2]))
7.3 Monitoring en observatie
Bij het implementeren van LLM’s in productie is monitoring cruciaal. Hoewel vLLM geen ingebouwde monitoring biedt, kan het worden geïntegreerd met tools zoals Prometheus en Grafana:
from prometheus_client import start_http_server, Summary
from vllm import LLM
<p># Definieer metrics
REQUEST_TIME = Summary('request_processing_seconds', 'Time spent processing request')</p>
<p># Initialiseer vLLM
llm = LLM(model="meta-llama/Llama-2-13b-hf")</p>
<p># Exposeer metrics
start_http_server(8000)</p>
<p># Gebruik het model met monitoring
@REQUEST_TIME.time()
def process_request(prompt):
return llm.generate(prompt)</p>
# Uw serving-loop hier
Deze setup stelt u in staat om metrics zoals verwerkingstijd van aanvragen te volgen, die kunnen worden gevisualiseerd in Grafana-dashboards.
Conclusie
Het efficiënt implementeren van grote taalmodellen is een complexe maar cruciale taak in de leeftijd van AI. vLLM, met zijn innovatieve PagedAttention-algoritme en geoptimaliseerde implementatie, vertegenwoordigt een significante stap voorwaarts in het maken van LLM-implementatie toegankelijker en kostenefficiënter.
Door de doorvoer aanzienlijk te verbeteren, geheugensverspilling te reduceren en flexibele implementatie-opties mogelijk te maken, opent vLLM nieuwe mogelijkheden voor het integreren van krachtige taalmodellen in een breed scala aan applicaties. Of u nu een chatbot, een inhoudsgeneratiesysteem of een andere NLP-aangedreven applicatie bouwt, het begrijpen en benutten van tools zoals vLLM zal cruciaal zijn voor succes.
















