1. 程式人生 > >TensorFlow多GPU並行的實現

TensorFlow多GPU並行的實現

深度學習演算法由於資料量非常大、演算法複雜度高等特點,常常需要採用並行機制。
常用的並行化深度學習模型訓練方式有兩種:同步模式和非同步模式。

深度模型訓練方法

深度學習模型的訓練是一個迭代的過程,在每一輪迭代過程中,前向傳播演算法會根據當前引數的取值,計算出在一小部分訓練資料上的預測值,然後反向傳播演算法,再根據損失函式計算引數的梯度並且更新引數。
這裡寫圖片描述

非同步模式訓練方法

在並行化地訓練深度學習模型時,不同裝置(GPU或CPU)可以再不同訓練資料上,執行整個迭代的過程,而不同並行模式的區別在於不同的引數更新方式。
非同步模式訓練流程圖如下:
這裡寫圖片描述
* 在每一輪迭代時,不同裝置會讀取引數最新的取值
* 因為裝置不同,讀取引數取值時間不一樣,所以得到的值也可能不一樣
* 根據當前引數的取值,和隨機獲取的一小部分訓練資料,不同裝置各自執行反向傳播的過程,並且獨立地更新引數
* 可以認為非同步模式,就是單機模式複製了多份,每一份使用不同的訓練資料進行訓練。
* 在非同步模式下,不同裝置之前是完全獨立的

同步模式訓練方法

在同步模式下,所有的裝置同時讀取引數的取值,並且當反向傳播演算法完成之後同步更新引數的取值,單個裝置不會單獨對引數進行更新,而會等所有裝置都完成反向傳播之後再統一更新引數。
同步模式訓練流程圖如下:
這裡寫圖片描述
* 圖中在迭代每一輪時,不同裝置首先統一讀取當前引數的取值,並隨機獲取一小部分資料
* 然後在不同裝置上執行反向傳播過程得到在各自訓練資料上的引數的梯度
* 注意:雖然所有裝置使用的引數是一致的,但是因為訓練資料不同,所以得到的引數的梯度可能不一樣
* 當所有裝置完成反向傳播的計算之後,需要計算出不同裝置上引數梯度的平均值
* 最後再根據平均值對引數進行更新

同步/非同步優劣比較

  • 同步模式解決了非同步模式中存在的引數更新問題,然而同步模式的效率卻低於非同步模式
  • 在同步模式下,每一輪迭代都需要裝置統一開始、統一結束
  • 如果裝置的執行速度不一致,那麼每一輪訓練都需要等待最慢的裝置結束才能開始更新引數,於是很多時間將被花在等待上
  • 雖然理論上非同步模式存在缺陷,但是因為訓練深度學習模型時,使用的隨機梯度下降本身就是梯度下降的一個近似解法,而且即使是梯度下降也無法保證達到全域性最優
  • 所以在實際應用中,相同時間內,使用非同步模式訓練的模型不一定比同步模式差

程式碼示例

#將神經網路的優化過程跑在不同的GPU上
for i in range(N_GPU):
    with
tf.debice('/gpu:%d'%i) with tf.name_scope('GPU_%d'%i) as scope: cur_loss = get_loss(x,y_regularizer,scope) #tf.get_variable的名稱空間 tf.get_variable_scope().reuse_variables() #使用當前gpu計算所有變數的梯度 grads= opt.compute_gradients(cur_loss) tower_grads.append(grads) #計算變數的平均梯度 grads = average_gradients(tower_grads) #使用平均梯度更新引數 apply_gradient_op = opt.apply_gradients(grads,global_step = global)