TensorFlow Profiler ile TensorFlow GPU performansını optimize edin

Genel Bakış

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

Profiler'da yeniyseniz:

Hesaplamaların GPU'ya aktarılmasının özellikle küçük modeller için her zaman faydalı olmayabileceğini unutmayın. Aşağıdaki nedenlerden dolayı 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ılavuzda, tek bir GPU ile başlayıp daha sonra birden fazla GPU'lu tek bir ana bilgisayara geçiş yaparak performans sorunlarının nasıl ayıklanacağı açıklanmaktadır.

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

  1. Tek bir GPU'daki performansı optimize edin ve hata 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 bilgisayardaki performansı optimize edin ve hata ayıklayın.

Örneğin, birden fazla GPU'ya sahip tek bir ana bilgisayarda bir modeli eğitmek için TensorFlow dağıtım stratejisi kullanıyorsanız ve optimumun altında GPU kullanımı fark ederseniz, çoklu GPU sisteminde hata ayıklamadan önce ilk olarak bir GPU'nun performansını optimize etmeli ve hatalarını ayıklamalısınız.

GPU'larda performanslı kod elde etmek için bir temel olarak bu kılavuz, halihazırda tf.function kullandığınızı varsaymaktadır. Keras Model.compile ve Model.fit API'leri tf.function otomatik olarak kullanacaktır. tf.GradientTape ile özel bir eğitim döngüsü yazarken, tf.function s'nin nasıl etkinleştirileceğini öğrenmek için tf.function ile daha iyi performans bölümüne bakın.

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

1. Bir GPU'nun performansını optimize edin

İdeal durumda, programınızın yüksek GPU kullanımına sahip olması, CPU'dan (ana bilgisayar) GPU'ya (cihaz) minimum düzeyde iletişim kurması ve giriş hattında herhangi bir ek yük olmaması gerekir.

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

Modelinizin profil çalıştırması sırasında nasıl performans gösterdiğine dair üst düzey bir görünüm gösteren TensorBoard'ın 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 önemli rakamlar şunlardır:

  1. Adım süresinin ne kadarı gerçek cihaz uygulamasından kaynaklanıyor?
  2. Cihaza ve ana makineye yerleştirilen işlemlerin yüzdesi
  3. Kaç tane çekirdek fp16 kullanıyor?

Optimum performansa ulaşmak, her üç durumda da bu sayıları en üst düzeye çıkarmak anlamına gelir. Programınızı derinlemesine anlamak için TensorBoard'un Profiler izleme görüntüleyicisine aşina olmanız gerekir. Aşağıdaki bölümlerde performans darboğazlarını teşhis ederken aramanız gereken bazı genel iz görüntüleyici modelleri gösterilmektedir.

Aşağıda bir GPU'da çalışan model izleme görünümünün görüntüsü bulunmaktadır. TensorFlow Name Scope ve TensorFlow Ops bölümlerinden ileri geçiş, kayıp işlevi, geri 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 Stream öğesinin yanında GPU üzerinde çalışan operasyonları da sağlayabilirsiniz. Her akış belirli görevler için kullanılır. Bu izlemede Stream#118 , bilgi işlem çekirdeklerini ve aygıttan aygıta kopyaları başlatmak için kullanılır. Stream#119, ana bilgisayardan cihaza kopyalama için ve Stream#120, cihazdan ana bilgisayara kopyalama için 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 sayıda kopya vardır ve adımlar arasında da minimum boşluk vardır. Programınız için Profiler'ı ç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ş 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 Profiler'ın TensorBoard üzerindeki Giriş hattı analizörünü kullanmaktır; bu, giriş hattında harcanan süreye genel bir bakış sağlar.

image

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

  • Giriş hattınızda nasıl hata ayıklayacağınızı öğrenmek için tf.data özel 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 gerek duymadan rastgele oluşturulmuş giriş verilerini kullanmaktır. Burada bu tekniğin ResNet modeli için kullanılmasına ilişkin bir örnek verilmiştir . Giriş hattı optimalse, gerçek verilerle ve oluşturulan rastgele/sentetik verilerle benzer performansı deneyimlemelisiniz. Sentetik veri durumundaki tek ek yük, yine önceden alınabilen ve optimize edilebilen girdi verileri 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ıklama

Düşük GPU kullanımına katkıda bulunabilecek çeşitli faktörler vardır. Aşağıda , izleme görüntüleyiciye ve olası çözümlere bakarken yaygın olarak gözlemlenen bazı senaryolar yer almaktadır.

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

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

image

İzleme 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ş hattınızda hata ayıklamayla ilgili önceki bölüme başvurmalısınız.

Bununla birlikte, optimize edilmiş bir giriş hattında 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ı, verilerin kopyalanması veya GPU işlemlerinin planlanması gibi her adımın başında gerçekleşen GPU ana bilgisayar tarafı etkinliğine müdahale edebilir.

Bu işlemleri GPU'da planlayan ana bilgisayar tarafında büyük boşluklar fark ederseniz, TF_GPU_THREAD_MODE=gpu_private ortam değişkenini 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şluklara metrik hesaplamalar, Keras geri aramaları veya ana bilgisayarda çalışan tf.function dışındaki işlemler de neden olabilir. Bu operasyonlar TensorFlow grafiğindeki operasyonlar kadar iyi performansa sahip değil. Ek olarak, bu operasyonlardan bazıları CPU üzerinde çalışır ve tensörleri GPU'dan ileri geri kopyalar.

Giriş hattınızı optimize ettikten sonra, izleme görüntüleyicideki adımlar arasında hala boşluklar olduğunu fark ederseniz, adımlar arasındaki model koduna bakmalı ve geri aramaları/ölçümleri devre dışı bırakmanın performansı artırıp artırmadığını kontrol etmelisiniz. Bu operasyonların bazı ayrıntıları aynı zamanda izleme görüntüleyicisinde de bulunur (hem cihaz hem de ana bilgisayar tarafında). Bu senaryodaki öneri, bu operasyonların yükünü, bunları 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ılacak şekilde sıraya koyar, ancak çekirdekler GPU'da gerçekten yürütülmeden önce bir gecikme (yaklaşık 20-40 μs) vardır. İdeal bir durumda, ana bilgisayar, GPU üzerinde yeterli sayıda çekirdeği sıraya alır, böylece GPU, ana bilgisayarın daha fazla çekirdeği sıraya koyması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ı beklemek nedeniyle 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 işlem başlatıldığında (örneğin, 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österiyor. Bu nedenle, her bir çekirdek yaklaşık 21,9 μs'dir ve bu çok küçüktür (başlatma gecikmesiyle hemen hemen aynı zamanda) ve potansiyel olarak ana bilgisayar çekirdeğinin başlatılmasında gecikmelere 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, GPU'yu daha uzun süre meşgul edecektir.
  • TensorFlow grafikleri oluşturmak için tf.function kullandığınızdan emin olun, böylece işlemleri saf istekli modda çalıştırmazsınız. Model.fit kullanıyorsanız ( tf.GradientTape ile özel bir eğitim döngüsünün aksine), 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 amacıyla XLA'nın nasıl etkinleştirileceğini öğrenmek için aşağıdaki Karma hassasiyeti ve XLA'yı etkinleştirme bölümüne gidin. Bu özellik yüksek cihaz kullanımına yol açabilir.
2. TensorFlow operasyon yerleşimi

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

image

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

Modelinizdeki işlemlerin ve tensörlerin hangi cihazlara atandığını bulmak için tf.debugging.set_log_device_placement(True) değerini programınızın ilk ifadesi olarak 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 bir şekilde yerleştirilmesine neden olabilir.

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

image

Bu kopyalar bazen GPU çekirdeklerinin çalışmasını engellerse performansa zarar verebilir. İzleme 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, bellek kopyasının her adımda aynı konumda olup olmadığını kontrol etmek için yakındaki operasyonlara bakmak faydalı olacaktır.

3. GPU'larda daha verimli çekirdekler

Programınızın GPU kullanımı kabul edilebilir seviyeye geldiğinde, bir sonraki adım Tensör Çekirdekleri veya birleştirme işlemlerini kullanarak GPU çekirdeklerinin verimliliğini artırmaya çalışmaktı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 Karma Hassasiyeti Etkinleştirme bölümüne bakın), programınızın Genel Matris Çarpması (GEMM) çekirdeklerinin (matmul ops) Tensör Çekirdeğini kullanmasını sağlamanın bir yoludur. Hassasiyet fp16 olduğunda ve giriş/çıkış tensör boyutları 8 veya 16'ya bölünebildiğinde ( int8 için) GPU çekirdekleri 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çacak şekilde 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 hassasiyeti ve XLA'yı etkinleştirin

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

1. Karma hassasiyeti etkinleştirin

TensorFlow Mixed hassaslık kılavuzu, GPU'larda fp16 hassasiyetinin nasıl etkinleştirileceğini gösterir. Tensor Çekirdeklerini kullanmak için NVIDIA® GPU'larda AMP'yi etkinleştirin ve Volta ve daha yeni GPU mimarilerinde yalnızca fp32 (float32) hassasiyeti kullanmaya kıyasla 3 kata kadar genel hızlanma elde edin.

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

CuDNN v7.6.3 ve sonraki sürümlerde, Tensör Çekirdeklerinden yararlanmak için evrişim boyutlarının gerekli olduğu yerlerde 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 karşılık gelen fp16 sürümünü kullanmalıdır. Ancak bazı durumlarda bu gerçekleşmez ve programınız verimsiz uygulamaya geri döndüğü için fp16 etkinleştirdiğinizde beklenen hızlanmayı yaşamazsınız.

image

GPU çekirdek istatistikleri sayfası, hangi operasyonların Tensor Core'a uygun olduğunu ve hangi çekirdeklerin gerçekte verimli Tensor Core'u 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örülecektir, çünkü artık işlemler yarı yarıya sürecektir.

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

Düşük hassasiyet nedeniyle yetersiz akışı önlemek için fp16 kullanılırken kayıp ölçeklendirmesi gereklidir. Her ikisi de Karma Hassasiyet kılavuzunda daha ayrıntılı olarak açıklanan dinamik ve statik olmak üzere iki tür kayıp ölçeklendirme 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çeklendirmenin ana bilgisayarda çalışan ek koşullu işlemler getirebileceğini ve izleme görüntüleyicideki adımlar arasında görülebilecek boşluklara yol açabileceğini unutmamak önemlidir. Öte yandan, statik kayıp ölçeklendirmenin bu tür ek yükleri yoktur ve doğru statik kayıp ölçeği 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, XLA'yı etkinleştirmeyi deneyebilirsiniz; bu, işlemleri birleştirir ve daha iyi cihaz kullanımına ve daha düşük bellek alanına yol açar. Programınızda XLA'yı tf.function(jit_compile=True) veya otomatik kümeleme ile nasıl etkinleştireceğinize ilişkin ayrıntılar için XLA kılavuzuna bakın.

Genel JIT düzeyini -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 bilgisayardaki performansı optimize edin

tf.distribute.MirroredStrategy API, model eğitimini tek bir GPU'dan tek bir ana bilgisayardaki birden fazla GPU'ya ölçeklendirmek için kullanılabilir. (TensorFlow ile dağıtılmış eğitimin nasıl yapılacağı hakkında daha fazla bilgi edinmek için TensorFlow ile Dağıtılmış eğitim , GPU Kullanma 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şin ideal olarak kutudan çıktığı haliyle ölçeklenebilir olması gerekmesine rağmen bazen performans sorunlarıyla karşılaşabilirsiniz.

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

Aşağıdaki izleme görünümü, birden fazla GPU üzerinde eğitim sırasında oluşan ekstra iletişim yükünün bir örneğini göstermektedir. Ağırlık güncellemesini yapmadan önce degradeleri birleştirmek, bunları kopyalar arasında iletmek ve 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. Toplu iş boyutunu en üst düzeye çıkarmaya çalışın; bu, daha yüksek cihaz kullanımına yol açacak ve birden fazla GPU arasındaki iletişim maliyetlerini azaltacaktır. Bellek profili oluşturucuyu kullanmak, programınızın bellek kullanımını en üst düzeye ne kadar yaklaştığına dair bir fikir edinmenize yardımcı olur. Daha yüksek bir toplu iş boyutunun yakınsamayı etkileyebileceğini ancak performans avantajlarının genellikle buna ağır bastığını unutmayın.
  2. Tek bir GPU'dan birden fazla GPU'ya geçerken, aynı ana bilgisayarın artık çok daha fazla giriş verisi işlemesi gerekiyor. Dolayısıyla (1)'den sonra giriş hattı performansının yeniden kontrol edilmesi ve bunun bir darboğaz olmadığından emin olunması önerilir.
  3. Gereksiz AllReduce çağrıları için programınızın izleme görünümündeki GPU zaman çizelgesini kontrol edin; bu, tüm cihazlar arasında senkronizasyonla sonuçlanır. Yukarıda gösterilen izleme görünümünde AllReduce, NCCL çekirdeği aracılığıyla yapılır ve her adımdaki degradeler için her GPU'da yalnızca bir NCCL çağrısı vardır.
  4. En aza indirilebilecek gereksiz D2H, H2D ve D2D kopyalama işlemlerini kontrol edin.
  5. Her kopyanın aynı işi yaptığından emin olmak için adım süresini kontrol edin. Örneğin, ana bilgisayarın yanlışlıkla daha fazla iş yapması nedeniyle bir GPU'ya (tipik olarak GPU0 ) fazla abone olunabilir.
  6. Son olarak, sırayla yürütülen tüm işlemler 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 meydana gelir. Geçmişte, bu durumda performansın hatalarını ayıklamak duruma göre çözülüyordu. Programınızda bu davranışı gözlemlerseniz izleme görünümünüzün resimlerini içeren bir GitHub sorunu bildirin .

1. AllReduce degradesini optimize edin

Senkronize bir stratejiyle eğitim sırasında her cihaz, giriş verilerinin bir kısmını alır.

Modeldeki ileri ve geri geçişler hesaplandıktan sonra, her cihazda hesaplanan eğimlerin toplanması ve azaltılması gerekir. Bu degrade AllReduce, her cihazdaki degrade hesaplamasından sonra ve optimize edici model ağırlıklarını güncellemeden önce gerçekleşir.

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

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

AllReduce'a kadar olan süre yaklaşık olarak şu şekilde olmalıdır:

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

Bu hesaplama, dağıtılmış bir eğitim işini çalıştırırken elde ettiğiniz 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 adresinden alabilirsiniz.

TensorFlow degradeleri iletmek için fp32 (float32) kullandığından her model parametresinin boyutunun 4 bayt olduğunu unutmayın. fp16 etkinleştirdiğinizde 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 iş parçacığı çekişmesi

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

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

Aşağıdaki izleme görüntüleyici, GPU1 boşta kalması ve GPU2 başladıktan sonra işlemleri çalıştırmaya başlaması nedeniyle CPU'nun GPU çekirdeğini verimsiz bir şekilde başlatmasını şaşırtması durumunda ortaya çıkan ek yükü gösterir.

image

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

image

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

  • TensorFlow ortam değişkeni TF_GPU_THREAD_MODE gpu_private olarak ayarlayın. Bu ortam değişkeni, ana bilgisayara bir GPU için iş parçacıklarını özel tutmasını söyleyecektir.
  • 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 ayarlanmasıyla değiştirilebilir.