TensorFlow Profiler ile TensorFlow GPU performansını optimize edin

genel bakış

Bu kılavuz, GPU'larınız hakkında fikir edinmek ve bunlardan maksimum performansı elde etmek için TensorFlow Profiler'ı TensorBoard ile nasıl kullanacağınızı ve bir veya daha fazla GPU'nuz yeterince kullanılmadığında hata ayıklamayı gösterecektir.

Profiler'da yeniyseniz:

Hesaplamaların GPU'ya yüklenmesinin, özellikle küçük modeller için her zaman faydalı olmayabileceğini unutmayın. Aşağıdakiler nedeniyle ek yük olabilir:

  • Ana bilgisayar (CPU) ve cihaz (GPU) arasında veri aktarımı; ve
  • Ana bilgisayar GPU çekirdeklerini başlattığında ortaya çıkan gecikme nedeniyle.

Performans optimizasyonu iş akışı

Bu kılavuz, performans sorunlarının tek bir GPU ile başlayıp ardından birden çok GPU'lu tek bir ana bilgisayara nasıl geçileceğini özetlemektedir.

Performans sorunlarının aşağıdaki sırayla hata ayıklaması önerilir:

  1. Performansı tek bir GPU'da optimize edin ve hatalarını ayıklayın:
    1. Giriş boru hattının bir darboğaz olup olmadığını kontrol edin.
    2. Bir GPU'nun performansında hata ayıklayın.
    3. Karışık hassasiyeti etkinleştirin ( fp16 (float16) ile) ve isteğe bağlı olarak XLA'yı etkinleştirin.
  2. Çoklu GPU'lu tek ana bilgisayarda performansı optimize edin ve hata ayıklayın.

Örneğin, birden çok GPU'lu tek bir ana bilgisayar üzerinde bir modeli eğitmek için bir TensorFlow dağıtım stratejisi kullanıyorsanız ve optimal olmayan GPU kullanımını fark ederseniz, çoklu GPU sisteminde hata ayıklamadan önce bir GPU için performansı optimize etmeli ve hatalarını ayıklamalısınız.

GPU'larda performans kodu almak için bir temel olarak, bu kılavuz zaten tf.function kullandığınızı varsayar. Model.compile ve Model.fit API'leri, başlık altında otomatik olarak tf.function kullanacaktır. tf.GradientTape ile özel bir eğitim döngüsü yazarken, tf.function s'nin nasıl etkinleştirileceğiyle ilgili olarak tf.function ile daha iyi performansa bakın.

Sonraki bölümlerde, performans darboğazlarını belirlemeye ve düzeltmeye yardımcı olmak için yukarıdaki senaryoların her biri için önerilen yaklaşımlar tartışılmaktadır.

1. Performansı bir GPU'da optimize edin

İdeal bir durumda, programınızın yüksek GPU kullanımı, minimum CPU (ana bilgisayar) ile GPU (aygıt) iletişimi olması ve giriş hattından ek yük olmaması gerekir.

Performansı analiz etmenin ilk adımı, tek GPU ile çalışan bir model için bir profil elde etmektir.

TensorBoard'un bir profil çalıştırması sırasında modelinizin nasıl performans gösterdiğinin üst düzey bir görünümünü gösteren Profiler genel bakış sayfası , programınızın ideal senaryodan ne kadar uzakta olduğuna dair bir fikir verebilir.

TensorFlow Profiler Overview Page

Genel bakış sayfasında dikkat edilmesi gereken anahtar numaralar şunlardır:

  1. Adım süresinin ne kadarı gerçek cihaz yürütmesinden geliyor
  2. Cihaza karşı ana bilgisayara yerleştirilen işlemlerin yüzdesi
  3. Kaç tane çekirdek fp16 kullanıyor?

Optimum performansa ulaşmak, her üç durumda da bu sayıları maksimize etmek anlamına gelir. Programınızı derinlemesine anlamak için TensorBoard'un Profiler iz görüntüleyicisine aşina olmanız gerekir. Aşağıdaki bölümler, performans darboğazlarını teşhis ederken aramanız gereken bazı yaygın iz görüntüleyici kalıplarını göstermektedir.

Aşağıda, bir GPU üzerinde çalışan bir model izleme görünümünün bir görüntüsü bulunmaktadır. TensorFlow Ad Kapsamı ve TensorFlow Ops bölümlerinden, ileriye geçiş, kayıp işlevi, geriye doğru geçiş/gradyan hesaplaması ve optimize edici ağırlık güncellemesi gibi modelin farklı bölümlerini tanımlayabilirsiniz. Ayrıca, CUDA akışlarına atıfta bulunan her Akışın yanındaki GPU'da operasyonların çalışmasını sağlayabilirsiniz. Her akış belirli görevler için kullanılır. Bu izlemede, hesaplama çekirdeklerini ve cihazdan cihaza kopyaları başlatmak için Stream#118 kullanılır. Ana bilgisayardan cihaza kopyalama için Akış #119 ve cihazdan ana bilgisayara kopyalama için Akış#120 kullanılır.

Aşağıdaki iz, performans gösteren bir modelin ortak özelliklerini göstermektedir.

image

Örneğin, GPU hesaplama zaman çizelgesi ( Stream#118 ) çok az boşlukla "meşgul" görünüyor. Ana bilgisayardan cihaza ( Akış #119 ) ve cihazdan ana bilgisayara ( Akış # 120 ) minimum kopya sayısı ve adımlar arasında minimum boşluk vardır. Profiler'ı programınız için çalıştırdığınızda, bu ideal özellikleri izleme görünümünüzde tanımlayamayabilirsiniz. Bu kılavuzun geri kalanı, yaygın senaryoları ve bunların nasıl düzeltileceğini kapsar.

1. Giriş işlem hattında hata ayıklayın

GPU performansında hata ayıklamanın ilk adımı, programınızın girdiye bağlı olup olmadığını belirlemektir. Bunu anlamanın en kolay yolu, TensorBoard'da, giriş hattında harcanan zamana genel bir bakış sağlayan Profiler'in Giriş-boru hattı analizörünü kullanmaktır.

image

Giriş hattınız adım zamanına önemli ölçüde katkıda bulunuyorsa, aşağıdaki olası eylemleri gerçekleştirebilirsiniz:

  • Giriş işlem hattınızda nasıl hata ayıklayacağınızı öğrenmek için tf.data kılavuzu kullanabilirsiniz.
  • Giriş hattının darboğaz olup olmadığını kontrol etmenin bir başka hızlı yolu, herhangi bir ön işleme gerektirmeyen rastgele oluşturulmuş giriş verilerini kullanmaktır. İşte bir ResNet modeli için bu tekniği kullanmanın bir örneği . Giriş ardışık düzeni optimalse, gerçek verilerle ve oluşturulan rastgele/sentetik verilerle benzer performansı deneyimlemeniz gerekir. Sentetik veri durumundaki tek ek yük, yine önceden alınabilen ve optimize edilebilen girdi veri kopyasından kaynaklanacaktır.

Ayrıca , giriş verileri ardışık düzenini optimize etmeye yönelik en iyi uygulamalara bakın.

2. Bir GPU'nun performansında hata ayıklayın

Düşük GPU kullanımına katkıda bulunabilecek birkaç faktör vardır. Aşağıda, iz görüntüleyiciye bakıldığında yaygın olarak gözlemlenen bazı senaryolar ve olası çözümler bulunmaktadır.

1. Adımlar arasındaki boşlukları analiz edin

Programınız en iyi şekilde çalışmadığında yaygın bir gözlem, eğitim adımları arasındaki boşluklardır. Aşağıdaki izleme görünümünün görüntüsünde, 8. ve 9. adımlar arasında büyük bir boşluk vardır, bu da GPU'nun bu süre boyunca boşta olduğu anlamına gelir.

image

İz görüntüleyiciniz adımlar arasında büyük boşluklar gösteriyorsa, bu, programınızın girdiye bağlı olduğunun bir göstergesi olabilir. Bu durumda, henüz yapmadıysanız, giriş boru hattınızda hata ayıklama ile ilgili önceki bölüme başvurmalısınız.

Bununla birlikte, optimize edilmiş bir giriş hattıyla bile, CPU iş parçacığı çekişmesi nedeniyle bir adımın sonu ile diğerinin başlangıcı arasında hala boşluklar olabilir. tf.data , ardışık düzen işlemeyi paralelleştirmek için arka plan iş parçacıklarını kullanır. Bu iş parçacıkları, veri kopyalama veya GPU işlemlerini zamanlama gibi her adımın başında gerçekleşen GPU ana bilgisayar tarafı etkinliğine müdahale edebilir.

Bu işlemleri GPU'da zamanlayan ana bilgisayar tarafında büyük boşluklar fark ederseniz, ortam değişkenini TF_GPU_THREAD_MODE=gpu_private olarak ayarlayabilirsiniz. Bu, GPU çekirdeklerinin kendi özel iş parçacıklarından başlatılmasını ve tf.data çalışmasının arkasında sıraya girmemesini sağlar.

Adımlar arasındaki boşluklar, ana bilgisayarda çalışan metrik hesaplamalar, Keras geri aramaları veya tf.function dışındaki işlemlerden de kaynaklanabilir. Bu operasyonlar, bir TensorFlow grafiği içindeki operasyonlar kadar iyi performansa sahip değildir. Ek olarak, bu işlemlerin bazıları CPU üzerinde çalışır ve tensörleri GPU'dan ileri geri kopyalar.

Giriş işlem hattınızı optimize ettikten sonra hala izleme görüntüleyicide adımlar arasında boşluklar fark ederseniz, adımlar arasındaki model koduna bakmalı ve geri aramaları/metrikleri devre dışı bırakmanın performansı iyileştirip iyileştirmediğini kontrol etmelisiniz. Bu operasyonların bazı detayları da iz görüntüleyicide (hem cihaz hem de ana bilgisayar tarafında) bulunur. Bu senaryodaki tavsiye, bu operasyonların ek yükünü, her adım yerine sabit sayıda adımdan sonra yürüterek amorti etmektir. tf.keras API'sinde Model.compile yöntemini kullanırken, steps_per_execution bayrağının ayarlanması bunu otomatik olarak yapar. Özel eğitim döngüleri için tf.while_loop kullanın.

2. Daha yüksek cihaz kullanımı elde edin

1. Küçük GPU çekirdekleri ve ana bilgisayar çekirdeği başlatma gecikmeleri

Ana bilgisayar, çekirdekleri GPU'da çalıştırılmak üzere sıraya koyar, ancak çekirdekler gerçekte GPU'da yürütülmeden önce bir gecikme (yaklaşık 20-40 μsn) söz konusudur. İdeal bir durumda, ana bilgisayar GPU'da yeterli sayıda çekirdeği kuyruğa alır, böylece GPU, ana bilgisayarın daha fazla çekirdeği kuyruğa almasını beklemek yerine, zamanının çoğunu yürütmeye harcar.

Profiler'ın TensorBoard'daki genel bakış sayfası , ana bilgisayarın çekirdekleri başlatmasını beklemekten dolayı GPU'nun ne kadar süre boşta kaldığını gösterir. Aşağıdaki resimde, GPU, çekirdeklerin başlatılmasını bekleyen adım süresinin yaklaşık %10'u boyunca boştadır.

image

Aynı programın izleme görüntüleyicisi , ana bilgisayarın GPU'da çekirdekleri başlatmakla meşgul olduğu çekirdekler arasındaki küçük boşlukları gösterir.

image

GPU'da çok sayıda küçük operasyon başlatarak (örneğin bir skaler ekleme gibi), ana bilgisayar GPU'ya ayak uyduramayabilir. Aynı Profil için TensorBoard'daki TensorFlow İstatistikleri aracı, 2,77 saniye süren 126.224 Mul işlemini gösterir. Bu nedenle, her bir çekirdek yaklaşık 21.9 μs'dir, bu çok küçüktür (başlatma gecikmesiyle yaklaşık aynı zamanda) ve potansiyel olarak ana bilgisayar çekirdeği başlatma gecikmelerine neden olabilir.

image

İzleme görüntüleyiciniz , yukarıdaki resimde olduğu gibi GPU'daki işlemler arasında çok sayıda küçük boşluk gösteriyorsa, şunları yapabilirsiniz:

  • Küçük tensörleri birleştirin ve vektörleştirilmiş operasyonları kullanın veya başlatılan her çekirdeğin daha fazla iş yapmasını sağlamak için daha büyük bir toplu iş boyutu kullanın, bu da GPU'yu daha uzun süre meşgul tutacaktır.
  • İşlemleri salt istekli modda çalıştırmamak için TensorFlow grafikleri oluşturmak için tf.function kullandığınızdan emin olun. Model.fit kullanıyorsanız ( tf.GradientTape ile özel bir eğitim döngüsünün tf.GradientTape ), tf.keras.Model.compile bunu sizin için otomatik olarak yapacaktır.
  • tf.function(jit_compile=True) veya otomatik kümeleme ile XLA kullanarak çekirdekleri birleştirin. Daha fazla ayrıntı için, daha yüksek performans elde etmek üzere XLA'yı nasıl etkinleştireceğinizi öğrenmek için aşağıdaki Karma hassasiyeti ve XLA'yı etkinleştir bölümüne gidin. Bu özellik, yüksek cihaz kullanımına yol açabilir.
2. TensorFlow op yerleşimi

Profiler genel bakış sayfası , ana bilgisayara karşı cihaza yerleştirilen operasyonların yüzdesini gösterir ( izleme görüntüleyiciye bakarak belirli operasyonların yerleşimini de doğrulayabilirsiniz. Aşağıdaki resimde olduğu gibi, ana bilgisayardaki operasyonların yüzdesini istiyorsunuz. cihaza göre çok küçük.

image

İdeal olarak, yoğun işlem gerektiren işlemlerin çoğu GPU'ya yerleştirilmelidir.

Modelinizdeki işlemlerin ve tensörlerin hangi cihazlara atandığını bulmak için, programınızın ilk ifadesi olarak tf.debugging.set_log_device_placement(True) ayarlayın.

Bazı durumlarda, belirli bir cihaza yerleştirilecek bir op belirtseniz bile, uygulamasının bu koşulu geçersiz kılabileceğini unutmayın (örnek: tf.unique ). Tek GPU eğitimi için bile, tf.distribute.OneDeviceStrategy gibi bir dağıtım stratejisi belirlemek, operasyonların cihazınıza daha belirleyici yerleştirilmesine neden olabilir.

İşlemlerin çoğunluğunun GPU'ya yerleştirilmesinin bir nedeni, ana bilgisayar ile cihaz arasında aşırı bellek kopyalarını önlemektir (ana bilgisayar ile cihaz arasındaki model giriş/çıkış verileri için bellek kopyaları beklenir). Aşırı kopyalama örneği, #167 , #168 ve #169 GPU akışlarında aşağıdaki izleme görünümünde gösterilmektedir.

image

Bu kopyalar, GPU çekirdeklerinin yürütülmesini engellerlerse bazen performansa zarar verebilir. İz görüntüleyicideki bellek kopyalama işlemleri, bu kopyalanan tensörlerin kaynağı olan işlemler hakkında daha fazla bilgiye sahiptir, ancak bir memCopy'yi bir işlemle ilişkilendirmek her zaman kolay olmayabilir. Bu durumlarda, hafıza kopyasının her adımda aynı yerde olup olmadığını kontrol etmek için yakındaki operasyonlara bakmak faydalı olur.

3. GPU'larda daha verimli çekirdekler

Programınızın GPU kullanımı kabul edilebilir olduğunda, bir sonraki adım, Tensör Çekirdeklerini veya birleştirme işlemlerini kullanarak GPU çekirdeklerinin verimliliğini artırmaya bakmaktır.

1. Tensör Çekirdeklerini Kullanın

Modern NVIDIA® GPU'lar, uygun çekirdeklerin performansını önemli ölçüde artırabilen özel Tensör Çekirdeklerine sahiptir.

Hangi GPU çekirdeklerinin Tensor Çekirdeğine uygun olduğunu ve hangi çekirdeklerin Tensor Çekirdeklerini kullandığını görselleştirmek için TensorBoard'un GPU çekirdek istatistiklerini kullanabilirsiniz. fp16 etkinleştirmek (aşağıdaki Karışık Hassasiyeti Etkinleştirme bölümüne bakın), programınızın Genel Matris Çarpma (GEMM) çekirdeklerinin (matmul ops) Tensör Çekirdeğini kullanmasını sağlamanın bir yoludur. GPU çekirdekleri, hassasiyet fp16 olduğunda ve giriş/çıkış tensör boyutları 8 veya 16'ya bölünebildiğinde ( int8 için) Tensör Çekirdeklerini verimli bir şekilde kullanır.

Çekirdeklerin GPU'lar için nasıl verimli hale getirileceğine ilişkin diğer ayrıntılı öneriler için NVIDIA® derin öğrenme performans kılavuzuna bakın.

2. Sigorta işlemleri

Önemli performans kazanımlarına yol açan daha büyük çekirdekler oluşturmak üzere daha küçük operasyonları birleştirmek için tf.function(jit_compile=True) kullanın. Daha fazla bilgi edinmek için XLA kılavuzuna bakın.

3. Karma hassasiyet ve XLA'yı etkinleştirin

Yukarıdaki adımları izledikten sonra, karışık hassasiyet ve XLA'yı etkinleştirmek, performansı daha da iyileştirmek için atabileceğiniz iki isteğe bağlı adımdır. Önerilen yaklaşım, bunları birer birer etkinleştirmek ve performans faydalarının beklendiği gibi olduğunu doğrulamaktır.

1. Karışık hassasiyeti etkinleştirin

TensorFlow Karışık hassaslık kılavuzu, GPU'larda fp16 hassasiyetinin nasıl etkinleştirileceğini gösterir. Volta ve daha yeni GPU mimarilerinde yalnızca fp32 (float32) hassasiyetini kullanmaya kıyasla, NVIDIA® GPU'larda AMP'yi Tensör Çekirdeklerini kullanmak ve 3 kata kadar genel hız artışı gerçekleştirmek için etkinleştirin.

Matris/tensör boyutlarının, Tensör Çekirdeklerini kullanan çekirdekleri çağırma gereksinimlerini karşıladığından emin olun. GPU çekirdekleri, hassasiyet fp16 olduğunda ve giriş/çıkış boyutları 8 veya 16'ya bölünebildiğinde (int8 için) Tensör Çekirdeklerini verimli bir şekilde kullanır.

cuDNN v7.6.3 ve sonraki sürümlerde, Tensör Çekirdeklerinden yararlanmak için gerektiğinde evrişim boyutlarının otomatik olarak doldurulacağını unutmayın.

fp16 hassasiyetinin performans avantajlarını en üst düzeye çıkarmak için aşağıdaki en iyi uygulamaları izleyin.

1. Optimum fp16 çekirdeklerini kullanın

fp16 etkinleştirildiğinde, programınızın matris çarpımları (GEMM) çekirdekleri, Tensör Çekirdeklerini kullanan ilgili fp16 sürümünü kullanmalıdır. Ancak, bazı durumlarda bu olmaz ve programınız verimsiz uygulamaya geri döndüğü için fp16 etkinleştirmekten beklenen hızlanmayı yaşamazsınız.

image

GPU çekirdek istatistikleri sayfası, hangi operasyonların Tensör Çekirdeği için uygun olduğunu ve hangi çekirdeklerin aslında verimli Tensör Çekirdeği kullandığını gösterir. Derin öğrenme performansına ilişkin NVIDIA® kılavuzu, Tensör Çekirdeklerinden nasıl yararlanılacağına ilişkin ek öneriler içerir. Ek olarak, fp16 kullanmanın faydaları, daha önce belleğe bağlı olan çekirdeklerde de gösterilecektir, çünkü şimdi işlemler yarı yarıya sürecektir.

2. Dinamik ve statik kayıp ölçeklendirmesi

Düşük hassasiyet nedeniyle taşmayı önlemek için fp16 kullanılırken kayıp ölçeklendirmesi gereklidir. Her ikisi de Karışık Hassasiyet kılavuzunda daha ayrıntılı olarak açıklanan dinamik ve statik olmak üzere iki tür kayıp ölçeklendirmesi vardır. Keras iyileştirici içinde kayıp ölçeklendirmeyi otomatik olarak etkinleştirmek için mixed_float16 ilkesini kullanabilirsiniz.

Performansı optimize etmeye çalışırken, dinamik kayıp ölçeklendirmesinin ana bilgisayar üzerinde çalışan ek koşullu işlemler sunabileceğini ve iz görüntüleyicide adımlar arasında görünür olacak boşluklara yol açabileceğini unutmamak önemlidir. Öte yandan, statik kayıp ölçeklemenin bu tür genel giderleri yoktur ve doğru statik kayıp ölçek değerini belirtmeniz gereken yakalama ile performans açısından daha iyi bir seçenek olabilir.

2. XLA'yı tf.function(jit_compile=True) veya otomatik kümeleme ile etkinleştirin

Tek bir GPU ile en iyi performansı elde etmenin son adımı olarak, işlemleri birleştirecek ve daha iyi cihaz kullanımına ve daha düşük bellek ayak izine yol açacak XLA'yı etkinleştirmeyi deneyebilirsiniz. tf.function(jit_compile=True) veya otomatik kümeleme ile programınızda XLA'yı nasıl etkinleştireceğinizle ilgili ayrıntılar için XLA kılavuzuna bakın.

Global JIT seviyesini -1 (kapalı), 1 veya 2 olarak ayarlayabilirsiniz. Daha yüksek bir düzey daha agresiftir ve paralelliği azaltabilir ve daha fazla bellek kullanabilir. Bellek kısıtlamalarınız varsa değeri 1 olarak ayarlayın. XLA derleyicisinin yeni şekillerle karşılaştığında çekirdekleri derlemeye devam etmesi gerekeceğinden, XLA'nın değişken giriş tensörü şekillerine sahip modeller için iyi performans göstermediğini unutmayın.

2. Çoklu GPU'lu tek ana bilgisayarda performansı optimize edin

tf.distribute.MirroredStrategy API, model eğitimini tek bir ana bilgisayardaki bir GPU'dan birden çok GPU'ya ölçeklendirmek için kullanılabilir. (TensorFlow ile dağıtılmış eğitimin nasıl yapılacağı hakkında daha fazla bilgi için TensorFlow ile Dağıtılmış eğitim , GPU kullanın ve TPU'ları kullanma kılavuzlarına ve Keras ile Dağıtılmış eğitim eğitimine bakın.)

Bir GPU'dan birden fazla GPU'ya geçiş ideal olarak kutudan çıkar çıkmaz ölçeklenebilir olsa da, bazen performans sorunlarıyla karşılaşabilirsiniz.

Tek bir GPU ile eğitimden aynı ana bilgisayar üzerinde birden fazla GPU'ya geçerken, ideal olarak, yalnızca gradyan iletişiminin ek yükü ve artan ana bilgisayar iş parçacığı kullanımı ile performans ölçeklendirmesini deneyimlemelisiniz. Bu ek yük nedeniyle, örneğin 1 GPU'dan 2 GPU'ya geçerseniz tam 2 kat hızlanma elde edemezsiniz.

Aşağıdaki izleme görünümü, birden fazla GPU'da eğitim yaparken ek iletişim yükünün bir örneğini gösterir. Gradyanları birleştirmek, bunları replikalar arasında iletmek ve ağırlık güncellemesini yapmadan önce bölmek için bir miktar ek yük vardır.

image

Aşağıdaki kontrol listesi, çoklu GPU senaryosunda performansı optimize ederken daha iyi performans elde etmenize yardımcı olacaktır:

  1. Daha yüksek cihaz kullanımına yol açacak ve birden çok GPU'da iletişim maliyetlerini amorti edecek olan parti boyutunu en üst düzeye çıkarmaya çalışın. Bellek profili oluşturucuyu kullanmak, programınızın en yüksek bellek kullanımına ne kadar yakın olduğunu anlamanıza yardımcı olur. Daha yüksek bir parti boyutunun yakınsamayı etkileyebileceğini, ancak bunun genellikle performans avantajlarından daha ağır bastığını unutmayın.
  2. Tek bir GPU'dan birden çok GPU'ya geçerken, aynı ana bilgisayarın artık çok daha fazla girdi verisini işlemesi gerekiyor. Bu nedenle (1)'den sonra, giriş boru hattı performansının yeniden kontrol edilmesi ve bunun bir darboğaz olmadığından emin olunması önerilir.
  3. Programınızın izleme görünümündeki GPU zaman çizelgesini gereksiz AllReduce çağrıları için kontrol edin, çünkü bu, tüm cihazlar arasında bir senkronizasyona neden olur. Yukarıda gösterilen izleme görünümünde, AllReduce, NCCL çekirdeği aracılığıyla yapılır ve her adımdaki gradyanlar için her GPU'da yalnızca bir NCCL çağrısı vardır.
  4. Minimuma indirilebilecek gereksiz D2H, H2D ve D2D kopyalama işlemlerini kontrol edin.
  5. Her bir kopyanın aynı işi yaptığından emin olmak için adım süresini kontrol edin. Örneğin, bir GPU'ya (genellikle GPU0 ) fazla abone olunabilir, çünkü ana bilgisayar yanlışlıkla üzerinde daha fazla çalışma yapar.
  6. Son olarak, sırayla yürütülen herhangi bir işlem için izleme görünümünüzdeki tüm GPU'lardaki eğitim adımını kontrol edin. Bu genellikle, programınız bir GPU'dan diğerine kontrol bağımlılıkları içerdiğinde olur. Geçmişte, bu durumda performansta hata ayıklama, duruma göre çözülmüştür. Programınızda bu davranışı gözlemlerseniz, izleme görünümünüzün görüntüleri ile bir GitHub sorunu bildirin .

1. Gradyan AllReduce'u optimize edin

Senkronize bir strateji ile eğitim yaparken, her cihaz giriş verilerinin bir kısmını alır.

Model üzerinden ileri ve geri geçişleri hesapladıktan sonra, her cihazda hesaplanan gradyanların toplanması ve azaltılması gerekir. Bu AllReduce gradyanı, her cihazdaki gradyan hesaplamasından sonra ve optimize edici model ağırlıklarını güncellemeden önce gerçekleşir.

Her GPU, önce model katmanları arasındaki degradeleri birleştirir, bunları tf.distribute.CrossDeviceOps ( tf.distribute.NcclAllReduce varsayılandır) kullanarak GPU'lar arasında iletir ve ardından katman başına azaltmadan sonra degradeleri döndürür.

Optimize edici, modelinizin ağırlıklarını güncellemek için bu azaltılmış gradyanları kullanacaktır. İdeal olarak, herhangi bir ek yükü önlemek için bu işlem tüm GPU'larda aynı anda gerçekleşmelidir.

AllReduce süresi yaklaşık olarak şu şekilde olmalıdır:

(number of parameters * 4bytes)/ (communication bandwidth)

Bu hesaplama, dağıtılmış bir eğitim işini yürütürken sahip olduğunuz performansın beklendiği gibi olup olmadığını veya daha fazla performans hata ayıklaması yapmanız gerekip gerekmediğini anlamak için hızlı bir kontrol olarak kullanışlıdır. Modelinizdeki parametre sayısını Model.summary .

TensorFlow, gradyanları iletmek için fp32 (float32) kullandığından, her model parametresinin boyutu 4 bayttır. fp16 etkinleştirmiş olsanız bile, NCCL AllReduce fp32 parametrelerini kullanır.

Ölçeklendirmenin avantajlarından yararlanmak için, adım süresinin bu genel giderlere kıyasla çok daha yüksek olması gerekir. Bunu başarmanın bir yolu, toplu iş boyutu adım süresini etkilediğinden, ancak iletişim ek yükünü etkilemediğinden daha yüksek bir toplu iş boyutu kullanmaktır.

2. GPU ana bilgisayar iş parçacığı çekişmesi

Birden fazla GPU çalıştırırken, CPU'nun görevi, GPU çekirdeklerini aygıtlar arasında verimli bir şekilde başlatarak tüm aygıtları meşgul etmektir.

Bununla birlikte, CPU'nun bir GPU üzerinde planlayabileceği çok sayıda bağımsız işlem olduğunda, CPU bir GPU'yu meşgul etmek için çok sayıda ana bilgisayar iş parçacığını kullanmaya karar verebilir ve ardından çekirdekleri deterministik olmayan bir sırayla başka bir GPU'da başlatabilir. . Bu, performansı olumsuz yönde etkileyebilecek bir çarpıklığa veya negatif ölçeklemeye neden olabilir.

Aşağıdaki iz görüntüleyici , GPU1 boşta olduğundan ve ardından GPU2 başladıktan sonra operasyonları çalıştırmaya başladığından, CPU GPU çekirdeğini verimsiz bir şekilde başlattığında ek yükü gösterir.

image

Ana bilgisayarın izleme görünümü, ana bilgisayarın çekirdekleri GPU2 başlatmadan önce GPU1 başlattığını gösterir (aşağıdaki tf_Compute* işlemlerinin CPU iş parçacıklarının göstergesi olmadığını unutmayın).

image

Programınızın izleme görünümünde GPU çekirdeklerinde bu tür bir şaşırtmayla karşılaşırsanız, önerilen eylem şudur:

  • TensorFlow ortam değişkenini TF_GPU_THREAD_MODE olarak gpu_private olarak ayarlayın. Bu ortam değişkeni, ana bilgisayara bir GPU için iş parçacıklarını gizli tutmasını söyler.
  • Varsayılan olarak, TF_GPU_THREAD_MODE=gpu_private iş parçacığı sayısını 2'ye ayarlar, bu çoğu durumda yeterlidir. Ancak bu sayı, TensorFlow ortam değişkeni TF_GPU_THREAD_COUNT istenen iş parçacığı sayısına ayarlayarak değiştirilebilir.