Accelerate documentation
Accelerate ile Yerel SGD Kullanımı
Accelerate ile Yerel SGD Kullanımı
Local SGD, gradyanların her adımda senkronize edilmediği dağıtık eğitim tekniğidir. Bu nedenle, her işlem kendi model ağırlıkları sürümünü günceller ve belirli bir adım sayısından sonra bu ağırlıklar, tüm işlemler arasında ortalama alınarak senkronize edilir. Bu, iletişim verimliliğini artırır ve özellikle NVLink gibi daha hızlı bir bağlantıya sahip olmayan bilgisayarlarda önemli ölçüde eğitim hızlanmasına yol açabilir. Gradyan biriktirme (iletişim verimliliğini artırmak için etkin batch boyutunun artırılmasını gerektiren) aksine, Local SGD, batch boyutunu veya öğrenme oranını / zamanlamasını değiştirmeyi gerektirmez. Ancak gerekirse, Local SGD gradyan biriktirme ile de birleştirilebilir.
Bu eğitimde, Local SGD Accelerate'yi nasıl hızlıca kuracağınızı göreceksiniz. Standart bir Accelerate kurulumuna kıyasla, bunun için yalnızca iki ekstra satır kod gereklidir.
Bu örnek, her iki batch'te bir gradyan biriktirme (gradient accumulation) yapan son derece basit bir PyTorch eğitim döngüsü kullanacaktır:
device = "cuda"
model.to(device)
gradient_accumulation_steps = 2
for index, batch in enumerate(training_dataloader):
inputs, targets = batch
inputs = inputs.to(device)
targets = targets.to(device)
outputs = model(inputs)
loss = loss_function(outputs, targets)
loss = loss / gradient_accumulation_steps
loss.backward()
if (index + 1) % gradient_accumulation_steps == 0:
optimizer.step()
scheduler.step()
optimizer.zero_grad()Bunu Accelerate'e dönüştürme
Önce daha önce gösterilen kod, ne bir LocalSGD ne de bir gradyan biriktirme yardımcısı kullanacak şekilde Accelerate ile kullanılmak üzere dönüştürülecektir:
+ from accelerate import Accelerator
+ accelerator = Accelerator()
+ model, optimizer, training_dataloader, scheduler = accelerator.prepare(
+ model, optimizer, training_dataloader, scheduler
+ )
for index, batch in enumerate(training_dataloader):
inputs, targets = batch
- inputs = inputs.to(device)
- targets = targets.to(device)
outputs = model(inputs)
loss = loss_function(outputs, targets)
loss = loss / gradient_accumulation_steps
+ accelerator.backward(loss)
if (index+1) % gradient_accumulation_steps == 0:
optimizer.step()
scheduler.step()Model senkronizasyonunu Accelerate'in yönetmesi
Artık geriye kalan tek şey, model parametre senkronizasyonunu ve gradyan birikimini bizim için Accelerate'ın halletmesini sağlamaktır. Basitlik adına, her 8 adımda bir senkronizasyona ihtiyaç duyduğumuzu varsayalım. Bu, her optimizör adımından sonra bir with LocalSGD ifadesi ve bir local_sgd.step() çağrısı eklenerek sağlanır:
+local_sgd_steps=8
+with LocalSGD(accelerator=accelerator, model=model, local_sgd_steps=8, enabled=True) as local_sgd:
for batch in training_dataloader:
with accelerator.accumulate(model):
inputs, targets = batch
outputs = model(inputs)
loss = loss_function(outputs, targets)
accelerator.backward(loss)
optimizer.step()
scheduler.step()
optimizer.zero_grad()
+ local_sgd.step()Arka planda, Local SGD kodu otomatik gradyan senkronizasyonunu devre dışı bırakır (ancak birikim hâlâ beklenildiği gibi çalışır!). Bunun yerine, model parametrelerini her local_sgd_steps adımda (ve eğitim döngüsünün sonunda) ortalama alır.
Kısıtlamalar
Mevcut uygulama, örneğin DeepSpeed olmadan yalnızca temel çoklu GPU (veya çoklu CPU) eğitimiyle çalışır.
Referanslar
Bu basit yaklaşımın gerçek kökenlerinden haberdar olmamakla birlikte, yerel SGD fikri oldukça eski olup en azından şu tarihlere kadar uzanır:
Zhang, J., De Sa, C., Mitliagkas, I., & Ré, C. (2016). Parallel SGD: Ortalama ne zaman işe yarar? arXiv ön baskı arXiv:1606.07365.
Local SGD terimini aşağıdaki makaleye atfederiz (farkında olmadığımız daha eski referanslar olabilir).
Stich, Sebastian Urban. “Local SGD Hızlı Yakınsar ve Az İletişim Kurar.” ICLR 2019-International Conference on Learning Representations. No. CONF. 2019.
Update on GitHub