AI-modeller och plattformar
Optimering av minne fÃķr stora sprÃĨkmodeller fÃķr inferens och finjustering
Stora sprÃĨkmodeller (LLM) som GPT-4, Bloom och LLaMA har uppnÃĨtt anmÃĪrkningsvÃĪrda fÃķrmÃĨgor genom att skala upp till miljarder parametrar. Det ÃĪr dock utmanande att distribuera dessa massiva modeller fÃķr inferens eller finjustering pÃĨ grund av deras enorma minneskrav. I den hÃĪr tekniska bloggen kommer vi att utforska tekniker fÃķr att uppskatta och optimera minnesanvÃĪndning under LLM-inferens och finjustering Ãķver olika maskinvarukonfigurationer.
FÃķrstÃĨ minneskrav
Minnet som krÃĪvs fÃķr att ladda en LLM bestÃĪms frÃĪmst av antalet parametrar och den numeriska precision som anvÃĪnds fÃķr att lagra parametrarna. En enkel tumregel ÃĪr:
- Att ladda en modell med X miljarder parametrar krÃĪver ungefÃĪr 4X GB VRAM i 32-bit flyttalsprecision
- Att ladda en modell med X miljarder parametrar krÃĪver ungefÃĪr 2X GB VRAM i 16-bit bfloat16/float16 precision
Till exempel skulle laddning av 175B parameter GPT-3-modellen krÃĪva cirka 350 GB VRAM i bfloat16 precision. FÃķr nÃĪrvarande erbjuder de stÃķrsta kommersiellt tillgÃĪngliga GPU:erna, som NVIDIA A100 och H100, endast 80 GB VRAM, vilket krÃĪver tensorparallelism och modellparallelismstekniker.
Under inferens domineras minnesavtrycket av modellparametrarna och de tillfÃĪlliga aktiverings tensorer som produceras. En hÃķgnivÃĨuppskattning fÃķr toppminnesanvÃĪndning under inferens ÃĪr summan av minnet som krÃĪvs fÃķr att ladda modellparametrarna och minnet fÃķr aktiveringar.
Kvantifiering av inferensminne
LÃĨt oss kvantifiera minneskraven fÃķr inferens med hjÃĪlp av OctoCode-modellen, som har cirka 15 miljarder parametrar i bfloat16-format (~ 31 GB). Vi kommer att anvÃĪnda Transformers-biblioteket fÃķr att ladda modellen och generera text:
from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline import torch <p>model = AutoModelForCausalLM.from_pretrained("bigcode/octocoder", torch_dtype=torch.bfloat16, device_map="auto", pad_token_id=0) tokenizer = AutoTokenizer.from_pretrained("bigcode/octocoder") pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)</p> <p>prompt = "FrÃĨga: VÃĪnligen skriv en Python-funktion fÃķr att konvertera byte till gigabyte.\n\nSvar:" result = pipe(prompt, max_new_tokens=60)[0]["generated_text"][len(prompt):]</p> <p>def bytes_to_gigabytes(bytes): return bytes / 1024 / 1024 / 1024</p> <p>bytes_to_gigabytes(torch.cuda.max_memory_allocated())
Utdata:
29.0260648727417ToppminnesanvÃĪndningen pÃĨ GPU ÃĪr cirka 29 GB, vilket ÃķverensstÃĪmmer med vÃĨr uppskattning pÃĨ 31 GB fÃķr att ladda modellparametrarna i bfloat16-format.
Optimering av inferensminne med kvantisering
Medan bfloat16 ÃĪr den vanliga precisionen som anvÃĪnds fÃķr att trÃĪna LLM, har forskare funnit att kvantisering av modellvikter till lÃĪgre precision datatyper som 8-bitars heltal (int8) eller 4-bitars heltal kan minska minnesanvÃĪndningen avsevÃĪrt med minimal fÃķrlust av noggrannhet fÃķr inferenstyper som textgenerering.
LÃĨt oss se minnessparandet frÃĨn 8-bitars och 4-bitars kvantisering av OctoCode-modellen:
&lt;/div&gt; # 8-bitars kvantisering model = AutoModelForCausalLM.from_pretrained("bigcode/octocoder", load_in_8bit=True, pad_token_id=0) pipe = pipeline("text-generation", model=model, tokenizer=tokenizer) result = pipe(prompt, max_new_tokens=60)[0]["generated_text"][len(prompt):] bytes_to_gigabytes(torch.cuda.max_memory_allocated())</pre>
Utdata:
15.219234466552734# 4-bitars kvantisering model = AutoModelForCausalLM.from_pretrained("bigcode/octocoder", load_in_4bit=True, low_cpu_mem_usage=True, pad_token_id=0) pipe = pipeline("text-generation", model=model, tokenizer=tokenizer) result = pipe(prompt, max_new_tokens=60)[0]["generated_text"][len(prompt):] bytes_to_gigabytes(torch.cuda.max_memory_allocated())
Utdata:
9.543574333190918Med 8-bitars kvantisering minskar minneskravet frÃĨn 31 GB till 15 GB, medan 4-bitars kvantisering minskar det ytterligare till endast 9,5 GB! Detta mÃķjliggÃķr kÃķrning av 15B parameter OctoCode-modellen pÃĨ konsument-GPU:er som RTX 3090 (24 GB VRAM).
Men observera att mer aggressiv kvantisering som 4-bitars kan ibland leda till fÃķrsÃĪmrad noggrannhet jÃĪmfÃķrt med 8-bitars eller bfloat16 precision. Det finns en avvÃĪgning mellan minnessparande och noggrannhet som anvÃĪndare bÃķr utvÃĪrdera fÃķr sin anvÃĪndning.
Kvantisering ÃĪr en kraftfull teknik som kan mÃķjliggÃķra distribution av LLM pÃĨ resursbegrÃĪnsade miljÃķer som molninstanser, edge-enheter eller till och med mobiltelefoner genom att drastiskt minska minnesavtrycket.
Uppskattning av minne fÃķr finjustering
Medan kvantisering frÃĪmst anvÃĪnds fÃķr effektiv inferens, ÃĪr tekniker som tensorparallelism och modellparallelism avgÃķrande fÃķr att hantera minneskrav under trÃĪning eller finjustering av stora sprÃĨkmodeller.
ToppminnesanvÃĪndningen under finjustering ÃĪr vanligtvis 3-4 gÃĨnger hÃķgre ÃĪn under inferens pÃĨ grund av ytterligare minneskrav fÃķr:
- Gradient
- OptimeringslÃĪgen
- Aktiveringar frÃĨn framÃĨtpassagen som lagras fÃķr bakÃĨtpassagen
En konservativ uppskattning ÃĪr att finjustering av en LLM med X miljarder parametrar krÃĪver cirka 4 * (2X) = 8X GB VRAM i bfloat16 precision.
Till exempel skulle finjustering av 7B parameter LLaMA-modellen krÃĪva cirka 7 * 8 = 56 GB VRAM per GPU i bfloat16 precision. Detta Ãķverstiger minneskapaciteten hos nuvarande GPU:er, vilket krÃĪver distribuerad finjusteringsteknik.
Distribuerad finjusteringsteknik
Flera distribuerade finjusteringsmetoder har fÃķreslagits fÃķr att Ãķvervinna GPU-minnesbegrÃĪnsningar fÃķr stora modeller:
- Data Parallelism: Den klassiska data parallelism-metoden replikerar hela modellen Ãķver flera GPU:er medan datatoken ÃĪr uppdelade och distribuerade. Detta minskar trÃĪningsÂtiden linjÃĪrt med antalet GPU:er men minskar inte toppminneskravet pÃĨ varje GPU.
- ZeRO Stage 3: En avancerad form av data parallelism som partitionerar modellparametrar, gradient och optimeringslÃĪgen Ãķver GPU:er. Det minskar minnet jÃĪmfÃķrt med klassisk data parallelism genom att endast behÃĨlla den partitionerade datan som behÃķvs pÃĨ varje GPU under olika trÃĪningsfaser.
- Tensor Parallelism: IstÃĪllet fÃķr att replikera modellen, delar tensorparallelism modellparametrarna i rader eller kolumner och distribuerar dem Ãķver GPU:er. Varje GPU arbetar med en partitionerad uppsÃĪttning parametrar, gradient och optimeringslÃĪgen, vilket leder till betydande minnessparande.
- Pipeline Parallelism: Denna teknik partitionerar modellÂlagren Ãķver olika GPU:er/arbetare, dÃĪr varje enhet kÃķr en delmÃĪngd av lagren. Aktiveringar skickas mellan arbetare, vilket minskar toppminnet men Ãķkar kommunikationsÂÃķverÂhuvudet.
Att uppskatta minnesanvÃĪndning fÃķr dessa distribuerade metoder ÃĪr inte trivialt, eftersom fÃķrdelningen av parametrar, gradient, aktiveringar och optimeringslÃĪgen varierar mellan tekniker. Dessutom kan olika komponenter som transformerÂkroppen och sprÃĨkÂmodellÂhuvudet visa olika minnesÂallokeringsÂbeteende.
LLMem-lÃķsningen
Forskare har nyligen fÃķreslagit LLMem, en lÃķsning som noggrant uppskattar GPU-minnesanvÃĪndning nÃĪr distribuerade finjusteringsmetoder tillÃĪmpas pÃĨ LLM:er Ãķver flera GPU:er.
LLMem tar hÃĪnsyn till faktorer som omkombinering av parametrar fÃķre berÃĪkning (ZeRO Stage 3), utgÃĨngssamling i bakÃĨtpassagen (tensorparallelism) och olika minnesallokeringsstrategier fÃķr transformerÂkroppen och sprÃĨkÂmodellÂhuvudet.
Experimentella resultat visar att LLMem kan uppskatta topp-GPU-minnesanvÃĪndning fÃķr finjustering av LLM:er pÃĨ en enda GPU med felÂfrekvenser pÃĨ upp till 1,6 %, vilket ÃķvertrÃĪffar den tidigare bÃĪsta DNNMem:s genomsnittliga felÂfrekvens pÃĨ 42,6 %. NÃĪr distribuerad finjustering tillÃĪmpas pÃĨ LLM:er med Ãķver en miljard parametrar pÃĨ flera GPU:er uppnÃĨr LLMem en imponerande genomsnittlig felÂfrekvens pÃĨ 3,0 %.













