2017-03-27 60 views
8

Çoklu GPU ile eğitim yaparken toplu istatistikleri senkronize ederek toplu normalleştirme katmanları uygulamak için olası yolları bilmek istiyorum. Belki de link gibi bazı caffe çeşitleri yapabilrsiniz. Ama BN katmanı için benim anlayışım, hala sadece katmanların çıktılarını değil, araçların çıktılarını senkronize etmesidir. Belki MPI araçları ve varsları senkronize edebilir ama bence MPI'nin uygulanması biraz zor.Senkronizasyon araçları ile çok-GPU BN katmanları uygulamak için yollar ve var var

Ben running_mean ve running_var senkronize ama toplu demek ve toplu var olamaz ya senkronize etmek zor olduğunu düşünüyorum olabilir göstermek bazı yorumlar here ve here, gördüğüm Meşale.

Tensorflow Normal olarak, kafein ve meşale ile aynıdır. BN'nin uygulanması, this'u ifade eder. Tensorflow'un bir işlemi tf.device() ile belirtilen herhangi bir cihaza dağıtabileceğini biliyorum. Ama araçlarının hesaplama ve vars BN tabakasının ortasında, yani cpu içinde araç ve değişkenler toplarsak, benim kod şöyle olacaktır: sadece bir BN tabakasında içindir

cpu_gather = [] 
label_batches = [] 
for i in range(num_gpu): 
    with tf.device('/gpu:%d' % i): 
     with tf.variable_scope('block1', reuse=i > 0): 
      image_batch, label_batch = cifar_input.build_input('cifar10', train_data_path, batch_size, 'train') 
      label_batches.append(label_batch) 

      x = _conv('weights', image_batch, 3, 3, 16, _stride_arr(1)) 
      block1_gather.append(x) 

with tf.device('/cpu:0'): 
    print block1_gather[0].get_shape() 
    x1 = tf.concat(block1_gather, 0) 
    # print x1.get_shape() 
    mean, variance = tf.nn.moments(x1, [0, 1, 2], name='moments') 

for i in range(num_gpu): 
    with tf.device('/gpu:%d' % i): 
     with tf.variable_scope('block2', reuse=i > 0): 
      shape = cpu_gather[i].get_shape().as_list() 
      assert len(shape) in [2, 4] 
      n_out = shape[-1] 
      beta, gamma, moving_mean, moving_var = get_bn_variables(n_out, True, True) 

      x = tf.nn.batch_normalization(
       cpu_gather[i], mean, variance, beta, gamma, 0.00001) 

      x = _relu(x) 

. CPU'da istatistik toplamak için kodu kırmam gerekiyor. 100'den fazla BN katmanım varsa, bu hantal olacaktır.

Bu kütüphanelerde uzman değilim, belki de bazı yanlış anlaşılmalar var, hatalarıma işaret etmekte çekinmeyin.

Eğitim hızı hakkında fazla bir şey umrumda değil. Çok fazla GPU belleği tüketen görüntü bölümlemesi yapıyorum ve kararlı istatistikler için BN'nin makul bir parti büyüklüğüne (örneğin 16'dan büyük) ihtiyacı var. Bu yüzden çoklu GPU kullanmak kaçınılmaz. Benim düşünceme göre, tensorflow en iyi seçim olabilir ama kırma kod problemini çözemiyorum. Diğer kütüphaneler ile çözüm de memnuniyetle karşılanacaktır.

+0

Herhangi bir yorum için teşekkür ederiz – Seven

+0

Görünüşe göre [sync_bn_layer] (https://github.com/yjxiong/caffe/blob/action_recog/src/caffe/layers/sync_bn_layer.cu) bunu caffe'de yapabilir. – Seven

cevap

2

Sorunuzu tam olarak anlayabildiğimden emin değilim, ancak değişken kapsamınızı doğru bir şekilde ayarlamanız koşuluyla, tf.GraphKeys.UPDATE_OPS koleksiyonu otomatik olarak her bir kule için batch_norm için güncelleme görevlerine sahip olmalıdır. Tüm update_ops eşzamanlı olarak uygulanmışsa, bunlar parametre sunucusu tarafından örtük olarak ortalaması alınır, yapmanız gereken tek şey güncellemelerin ortalamadan önce uygulandığından ve degradeleri uyguladığınızdan emin olmanızdır. (Eğer niyetlerini doğru anlarsam).

Değişken kapsamı nedeniyle, her bir güncelleme döngüsü kümesi aynı değişkenleri güncelleştirir, böylece güncelleme işlemlerini senkronize etmek için tüm yapmanız gereken, tüm güncelleme ops kümesinde degrade hesabınızı kapatmaktır. Ayrıca, UPDATE_OPS numaranızdaki herhangi bir dışlama işleminden kaçınmak için tüm parti norm katmanlarınızı tek bir name_scope içine de eklemelisiniz. Aşağıdaki kod iskelet: istediğin bazı mevcut kod bu denerseniz

update_ops = [] 
for i, device in enumerate(devices): 
    with tf.variable_scope('foo', reuse=bool(i > 0)): 
    with tf.name_scope('tower_%d' % i) as name_scope: 
     with tf.device(device): 
     # Put as many batch_norm layers as you want here 
     update_ops.extend(tf.get_collection(tf.GraphKeys.UPDATE_OPS, 
              name_scope)) 
# make gradient calculation ops here 
with tf.device(averaging_device): 
    with tf.control_dependencies(update_ops): 
    # average and apply gradients. 

, sadece burada if i == 0 hattını silmeyi deneyin: https://github.com/tensorflow/models/blob/master/tutorials/image/cifar10_estimator/cifar10_main.py#L115

Sen yavaşlayan görmeye gidiyoruz (genellikle sadece bir kulesini kullanabilir Bu sebeple toplu iş istatistikleri hesaplamak için), ama istediğini yapmalı.

+0

Teşekkürler Eli Bixby.BN eğitimini birden fazla GPU ile başardınız mı? Lütfen benim soruma bakın ve bana biraz yorum https://stackoverflow.com/questions/48150720/how-to-update-variable-of-batchnorm-in-multiple-gpus-in-tensorflow – Jame

+0

Teşekkürler @Eli Bixby sizin için Cevap, ama üzgünüm bazı hatalar olabilir. BN için, sadece birikmesi gereken veya güncellenmesi gereken "istatistikler" yoktur. Geri yayılan her zaman degradeler de dikkate alınmalıdır. Küçük parti boyutu kullanılıyorsa, gradyanlar hiç de sabit değildir. Burada önerdiğiniz şey sadece yönlendirme içindir, geriye doğru otomatik farklılaşma ile hesaplanır ve doğru yapılmaz. – Seven

+0

Her GPU'nun doygun olduğu yeterince büyük bir toplu boyut kullanmalısınız. Deneyimlerimizde bu, GPU'lar arasında, batch_norm için kararlı gradyanlar üretme konusunda bile, deneyimimizdeki tek bir GPU parçacığından yalnızca gradyanları yaymak suretiyle bile yeterince büyük (bağlandığım kodlara bakın). Gözden geçirme AFAICT, uygulamadan önce parti normu renk geçişlerini mevcut yüksek seviyeli parti norm fonksiyonları ile ortalamanın bir yolu yoktur, bunu düşük seviyeli TF'de uygulamanız gerekir. –