1. 程式人生 > >Tensorflow並行GPU計算

Tensorflow並行GPU計算

Tensorflow使用GPU

Tensorflow程式可以通過tf.device函式來指定執行每一個操作的裝置,這個裝置可以是本地CPU或GPU,也可以是某一臺遠端伺服器。

tf.device函式可以通過裝置的名稱來指定執行運算的裝置。

  • 如CPU在tensorflow中的名稱為/cpu:0。在預設情況下,即使機器有很多個CPU,tensorflow也不會區分它們,所有的CPU都使用/cpu:0作為名稱。
  • 而一臺機器上不同GPU的名稱是不同的,第n個GPU在tensorflow中的名稱為/gpu:n。

tensorflow提供了一個會計的方式來檢視執行每一個運算的裝置。在生成會話時,可以通過設定log_device_placement引數來列印執行每一個運算的裝置。

import tensorflow as tf 
a=tf.constant([1.0,2.0,3.0],shape=[3],name='a')
b=tf.constant([1.0,2.0,3.0],shape=[3],name='b')
c=a+b
#通過log_device_placement引數來輸出執行每一個運算的裝置
sess=tf.Session(config=tf.ConfigProto(log_device_placement=True))
print (sess.run(c))

在以上程式碼中,tensorflow程式生成會話時加入了引數log_device_placement=True,所以程式會將執行每一個操作的裝置輸出到螢幕。

在配置好GPU的環境中,如果操作沒有明確指定執行裝置,那麼tensorflow會優先選擇GPU。但是,儘管有4個GPU,在預設情況下,tensorflow只會將運算優先放到/gpu:0上。如果需要將某些運算放到不同的GPU或CPU上,就需要通過tf.device來手工指定。

import tensorflow as tf

#通過tf.device將運算指定到特定的裝置上
with tf.device('/cpu:0'):
    a=tf.constant([1.0,2.0,3.0],shape=[3],name='a')
    b=tf.constant([1.0,2.0,3.0],shape=[3],name='b')
with tf.device('/gpu:1'):
    c=a+b
sess=tf.Session(config=tf.ConfigProto(log_device_placement=True))
print(sess.run(c))

在以上程式碼中可以看到生成常量a和b的操作被載入到CPU上,而加法操作被放到第二個GPU上。在tensorflow中,不是所有的操作都可以被放在GPU上,如果強行將無法放在GPU上的操作指定到GPU上,程式就會報錯。
在GPU上,tf.Variable操作只支援實數型(float16 float32 double)的引數。不支援整數型引數。tensorflow在生成會話時可以指定allow_soft_placement引數。當這個引數設定為True時,如果運算無法由GPU執行,那麼tensorflow會自動將它放到CPU上執行。

import tensorflow as tf

a=tf.Variable(0,name='a')
with tf.device('/gpu:0'):
    b=tf.Variable(0,name='b')
#通過allow_soft_placement引數自動將無法放在GPU上的操作放回CPU上
sess=tf.Session(config=tf.ConfigProto(allow_soft_placement=True,log_device_placement=True))
sess.run(tf.initialize_all_variables()

深度學習訓練並行模式

tensorflow可以很容易得利用單個GPU加速深度學習模型的訓練過程,但要利用更多的GPU或者機器,需要了解如何並行化訓練深度學習模型。常用的並行化深度學習模型訓練方式有兩種:同步模式、非同步模式。

在這裡插入圖片描述
上圖是深度學習模型的訓練流程圖。深度學習模型的訓練是一個迭代的過程。在每一輪迭代中,前向傳播演算法會根據當前引數的取值計算出在一小部分訓練資料上的預測值,然後反向傳播演算法再根據損失函式計算引數的梯度並更新引數。在並行化訓練深度學習模型時,不同裝置(GPU CPU)可以在不同訓練資料上執行這個迭代過程,而不同並行模式的區別在於不同的引數更新方式。

在這裡插入圖片描述
上圖展示了非同步模式的訓練流程圖。從圖中可以看出,在每一次迭代時,不同裝置會讀取引數最新的取值,但因為不同裝置讀取引數取值的時間不一樣,所以得到的值也有可能不一樣。根據當前引數的取值和隨機獲取的一小部分訓練資料,不同裝置各自執行反向傳播的過程並獨立地更新引數。可以簡單地認為非同步模式就是單機模式複製了多份,每一份使用不同的訓練資料進行訓練。在非同步模式下,不同裝置之間是完全獨立的。

然鵝使用非同步模式訓練的深度學習模型有可能無法達到較優的訓練結果。
在這裡插入圖片描述
為了避免更新不同步的問題,可以使用同步模式。在同步模式下,所有的裝置同事讀取引數的取值,並且當反向傳播演算法完成之後同步更新引數的取值。單個裝置不會單獨對引數進行更新,而等待所有裝置都完成反向傳播之後再同意更新引數。
上圖展示了同步模式的訓練過程。在每一輪迭代時,不同裝置首先同意讀取當前引數的取值,並隨機獲取一小部分資料。然後在不同裝置上運城反向傳播過程得到在各自訓練資料上引數的梯度。注意雖然所有裝置使用的引數是一致的,但是因為訓練資料不同,所以得到引數的梯度可能不一樣。當所有裝置完成反向傳播的計算之後,需要計算出不同裝置上引數梯度的平均值,最後再根據平均值對引數進行更新。

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

多GPU並行

給出具體程式碼,在一臺機器上的多個GPU上並行訓練深度學習模型。一般來說一臺機器上的多個GPU效能相似,所以在這種設定下更多采用同步模式訓練深度學習模型。
在這裡插入圖片描述在這裡插入圖片描述在這裡插入圖片描述在這裡插入圖片描述在這裡插入圖片描述在這裡插入圖片描述在這裡插入圖片描述在這裡插入圖片描述在這裡插入圖片描述在這裡插入圖片描述

分散式tensorflow

後續再增加,目前只用到並行GPU