Yapay Zekâ
Büyük Dil Modellerinin Tahmin ve İyileştirme için Bellek Optimizasyonu
Büyük dil modelleri (LLM’ler) gibi GPT-4, Bloom ve LLaMA, milyarlarca parametre ile ölçeklenerek dikkat çekici yetenekler elde etti. Ancak, bu devasa modelleri tahmine veya iyileştirmeye dağıtmak, muazzam bellek gereksinimleri nedeniyle zorlu bir görevdir. Bu teknik blogda, LLM’lerin tahmine ve iyileştirmesi sırasında bellek tüketimini tahmin etme ve optimize etme tekniklerini keşfedeceğiz.
Bellek Gereksinimlerini Anlama
Bir LLM’i yüklemek için gereken bellek, öncelikle parametre sayısı ve parametreleri depolamak için kullanılan sayısal kesinlik tarafından belirlenir. Bir kural olarak:
- X milyar parametreli bir modeli yüklemek için yaklaşık 4X GB VRAM gerekir 32-bit float精度de
- X milyar parametreli bir modeli yüklemek için yaklaşık 2X GB VRAM gerekir 16-bit bfloat16/float16精度de
Örneğin, 175B parametreli GPT-3 modelini yüklemek için yaklaşık 350GB VRAM gerekir bfloat16精度de. Bugün, en büyük ticari olarak disponible GPU’lar gibi NVIDIA A100 ve H100 sadece 80GB VRAM sunar, bu da tensor paralellik ve model paralellik tekniklerini gerektirir.
Tahmin sırasında, bellek ayak izi, model parametreleri ve geçici aktivasyon tensörleri tarafından domine edilir. Tahmin sırasında zirve bellek kullanımının yüksek bir tahmini, model parametrelerini yüklemek için gereken bellek ve aktivasyonlar için belleğin toplamıdır.
Tahmin Belleğini nicelendirme
OctoCode modelini kullanarak, yaklaşık 15 milyar parametre ve bfloat16 formatında (~ 31GB) tahmine bellek gereksinimlerini nicelendirelim. Transformers kütüphanesini kullanarak modeli yükleyerek ve metin oluşturacağız:
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 = "Soru: Python'da baytları gigabayta dönüştürmek için bir fonksiyon yazın.\n\nCevap:" 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())
Çıktı:
29.0260648727417Zirve GPU bellek kullanımı yaklaşık 29GB’dir, bu da bfloat16 formatında model parametrelerini yüklemek için我们的 tahmini 31GB ile uyumlu.
Tahmin Belleğini nicelendirme ile Quantization
Bfloat16, LLM’lerin eğitimi için yaygın olarak kullanılan bir精度dir, ancak araştırmacılar, model ağırlıklarını daha düşük精度 veri türlerine (8-bit tam sayılar veya 4-bit tam sayılar) nicelendirdiklerinde, tahmine görevleri için önemli bellek kullanımını azaltabileceğini keşfettiler.
OctoCode modelinin 8-bit ve 4-bit nicelendirmesinden bellek tasarrufunu görelim:
&lt;/div&gt; # 8-bit nicelendirme 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>
Çıktı:
15.219234466552734# 4-bit nicelendirme 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())
Çıktı:
9.5435743331909188-bit nicelendirmesiyle, bellek gereksinimi 31GB’den 15GB’ye düşer, 4-bit nicelendirmesiyle ise 9.5GB’ye düşer! Bu, 15B parametreli OctoCode modelini tüketici GPU’ları gibi RTX 3090 (24GB VRAM) üzerinde çalıştırma olanağı sağlar.
Ancak, daha agresif nicelendirme gibi 4-bit’in bazen 8-bit veya bfloat16精度ye göre doğruluk kaybına neden olabileceğini unutmayın. Kullanıcılar, kullanım durumları için bellek tasarrufu ve doğruluk arasında bir denge kurmalıdır.
Nicelendirme, LLM’lerin dağıtımını kaynak kısıtlı ortamlarda, bulut örneklerinde, kenar cihazlarında veya hatta cep telefonlarında ermögelenerek bellek kullanımını önemli ölçüde azaltabilen güçlü bir tekniktir.
İyileştirme için Bellek Tahmini
Nicelendirme, verimli tahmine için kullanılırken, tensor paralellik ve model paralellik gibi teknikler, büyük dil modellerinin eğitimi veya iyileştirmesi sırasında bellek gereksinimlerini yönetmek için kritiktir.
İyileştirme sırasında zirve bellek tüketimi, genellikle tahmine göre 3-4 kat daha yüksektir ve şunlar için ek bellek gereksinimlerini içerir:
- Gradyanlar
- Optimizer durumları
- İleri geçişten geri yayılım için depolanan aktivasyonlar
Muhafazakar bir tahmin, X milyar parametreli bir LLM’yi iyileştirmek için yaklaşık 4 * (2X) = 8X GB VRAM gerekir bfloat16精度de.
Örneğin, 7B parametreli LLaMA modelini iyileştirmek için yaklaşık 7 * 8 = 56GB VRAM gerekir her GPU için bfloat16精度de. Bu, mevcut GPU’ların bellek kapasitesini aşar ve dağıtılmış iyileştirme tekniklerini gerektirir.
Dağıtılmış İyileştirme Teknikleri
Birkaç dağıtılmış iyileştirme yöntemi, büyük modeller için GPU bellek kısıtlamalarını aşmak için önerilmiştir:
- Veri Paralellik: Klasik veri paralellik yaklaşımı, tüm modeli birden fazla GPU’ya kopyalar ve eğitim veri partilerini dağıtır. Bu, eğitim süresini GPU sayısıyla lineer olarak azaltır, ancak her GPU’daki zirve bellek gereksinimini azaltmaz.
- ZeRO Stage 3: Gelişmiş bir veri paralellik biçimi, model parametrelerini, gradyanları ve optimizer durumlarını GPU’lar arasında böler. Bu, her GPU’da yalnızca gerekli paylaşılan verileri tutarak klasik veri paralellikten daha az bellek kullanır.
- Tensor Paralellik: Modeli kopyalamak yerine, tensor paralellik, model parametrelerini satırlara veya sütunlara böler ve bunları GPU’lar arasında dağıtır. Her GPU, parametrelerin, gradyanların ve optimizer durumlarının bir paylaşılan kümesini işler, bu da önemli bellek tasarrufu sağlar.
- Boru Hattı Paralellik: Bu teknik, model katmanlarını farklı GPU’lar veya işçiler arasında böler, her cihazın bir alt küme katmanları çalıştırır. Aktivasyonlar işçiler arasında geçirilir, bu da zirve belleği azaltır, ancak iletişim yükünü artırır.
Bu dağıtılmış yöntemler için bellek kullanımını tahmin etmek zorlu bir görevdir, çünkü parametreler, gradyanlar, aktivasyonlar ve optimizer durumlarının dağılımı tekniklere göre değişir. Ayrıca, transformer gövdesi ve dil modeli başlığı gibi farklı bileşenler, farklı bellek ayırma davranışları gösterebilir.
LLMem Çözümü
Araştırmacılar, LLMem’i önerdiler, bu da LLM’lerin dağıtılmış iyileştirme yöntemleri uygulanırken GPU bellek tüketimini doğru bir şekilde tahmin eden bir çözümdür.
LLMem, hesaplamadan önce parametreleri birleştirmek (ZeRO Stage 3), geri yayılım sırasında çıktı toplamak (tensor paralellik) ve transformer gövdesi ve dil modeli başlığı için farklı bellek ayırma stratejileri gibi faktörleri dikkate alır.
Deneysel sonuçlar, LLMem’in tek bir GPU’da LLM’lerin iyileştirilmesi için zirve GPU bellek kullanımını %1,6’nın altında bir hata oranıyla tahmin edebileceğini, bu da DNNMem’in ortalama %42,6’lık hata oranını aşar. LLM’lerin birden fazla GPU’da dağıtılmış iyileştirme yöntemleri uygulandığında, LLMem %3,0’lık ortalama bir hata oranıyla başarılı olur.













