深度學習應用到實際問題中,一個很是棘手的問題是訓練模型時計算量太大。爲了加速訓練,TensorFlow能夠利用GPU或/和分佈式計算進行模型訓練。app
TensorFlow能夠經過td.device函數來指定運行每一個操做的設備,這個設備能夠是本設備的CPU或GPU,也能夠是遠程的某一臺設備。異步
TF生成會話的時候,可願意經過設置tf.log_device_placemaent參數來打印每個運算的設備。分佈式
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= tf.add_n([a,b],name="c") with tf.Session(config=tf.ConfigProto(log_device_placement = True)) as sess: print(sess.run(c)) ######## Device mapping: no known devices. c: (AddN): /job:localhost/replica:0/task:0/device:CPU:0 b: (Const): /job:localhost/replica:0/task:0/device:CPU:0 a: (Const): /job:localhost/replica:0/task:0/device:CPU:0 [2. 4. 6.]
在配置好了GPU環境的TensorFlow中,若是沒有明確指明運行設備,TF會優先選擇GPU。函數
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= tf.add_n([a,b],name="c") with tf.Session(config=tf.ConfigProto(log_device_placement = True)) as sess: print(sess.run(c)) ######## Device mapping: no known devices. c: (AddN): /job:localhost/replica:0/task:0/device:GPU:0 b: (Const): /job:localhost/replica:0/task:0/device:GPU:0 a: (Const): /job:localhost/replica:0/task:0/device:GPU:0 [2. 4. 6.]
能夠經過tf.device 來制定運行操做的設備。性能
import tensorflow as tf 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:0"): c= tf.add_n([a,b],name="c") with tf.Session(config=tf.ConfigProto(log_device_placement = True)) as sess: print(sess.run(c))
某些數據類型是不被GPU所支持的。強制指定設備會報錯。爲了不解決這個問題。在建立會還時能夠指定參數allow_soft_placement 。當allow_soft_placement爲True的時候,若是運算沒法在GPU上運行,TF會自動將其放在CPU 上運行。學習
a_cpu = tf.Variable(0,name='a_cpu') with tf.device('/gpu:0'): a_gpu = tf.Variable(0,name='a_gpu') sess = tf.Session(config=tf.ConfigProto(log_device_placement=True,allow_soft_placement = True)) sess.run(tf.global_variables_initializer())
a_gpu: (VariableV2): /job:localhost/replica:0/task:0/device:CPU:0 a_gpu/read: (Identity): /job:localhost/replica:0/task:0/device:CPU:0 a_gpu/Assign: (Assign): /job:localhost/replica:0/task:0/device:CPU:0 init/NoOp_1: (NoOp): /job:localhost/replica:0/task:0/device:CPU:0 a_cpu: (VariableV2): /job:localhost/replica:0/task:0/device:CPU:0 a_cpu/read: (Identity): /job:localhost/replica:0/task:0/device:CPU:0 a_cpu/Assign: (Assign): /job:localhost/replica:0/task:0/device:CPU:0 init/NoOp: (NoOp): /job:localhost/replica:0/task:0/device:CPU:0 init: (NoOp): /job:localhost/replica:0/task:0/device:CPU:0 a_gpu/initial_value: (Const): /job:localhost/replica:0/task:0/device:CPU:0 a_cpu/initial_value: (Const): /job:localhost/replica:0/task:0/device:CPU:0
實踐經驗:將計算密集型的操做放在GPU上。爲了提升程序運行速度,儘可能將相關操做放在同一臺設備上。this
經常使用的並行化深度學習模型的方法有兩種:同步模式和異步模式。spa
在異步模式下,不一樣設備之間是徹底獨立的。code
異步模型流程圖:server
同步模型流程圖:
同步模式時,單個設備不會單獨對參數進行更新,而會等待全部設備都完成反向傳播以後再統一更新參數。
同步模式解決了異步模式中存在參數更新的問題,然而同步模式的效率卻低於異步模式。
通常來講,一臺機器上的多個GPU性能類似,因此在這種設置下跟多的是採用同步模式訓練甚多學習模型。
經過多GPU並行的方式當然能夠達到很好的訓練效果,可是一臺機器上畢竟GPU的個數是有限的。若是須要記憶不提高深度學習模型的訓練效果,就須要將TensorFlow分佈式的運行在多臺計算機上。
在第二個小結中,介紹了分佈式TensorFlow訓練甚多學習模型的理論。本小節將具體介紹如何使用TF在分佈式集羣中訓練深度學習模型。TensorFlow集羣經過一系列的任務(tasks)來執行TF計算圖中的運算。通常來講,不一樣的任務跑在不一樣的機器上。固然,使用GPU時,不一樣任務可使用用一太機器上的不一樣GPU。TF中的任務能夠聚合成工做。每一個工做能夠包含一個或多個任務。當一個TF集羣有多個任務的時候,須要使用tf.train.ClusterSpec來指定運行每個人物的機器。
配置第一個任務集羣
import tensorflow as tf c = tf.constant('Hello ,this is the server1!') #生成一個有兩我的物的集羣,一個任務跑在本地的2222端口,另外一個跑在本地的2223端口 cluster = tf.train.ClusterSpec({"local":['localhost:2998','localhost2999']}) #經過上面生成的集羣配置生成Server。並經過job_name和task_index指定當前啓動的任務。 server = tf.train.Server(cluster,job_name='local',task_index=0) #經過server.target生成會話來使用來使用TF集羣中的資源。經過log_device_placement能夠看到執行每個操做的任務 sess = tf.Session(server.target,config=tf.ConfigProto(log_device_placement = True)) print(sess.run(c))
配置第二個任務,使用一樣的集羣配置
import tensorflow as tf c = tf.constant('Hello ,this is the server2!') #和第一個任務同樣的集羣配置 cluster = tf.train.ClusterSpec({"local":['localhost:2998','localhost2999']}) #指定task_index = 1,因此第二個任務是運行在2999端口上 server = tf.train.Server(cluster,job_name='local',task_index=0) sess = tf.Session(server.target,config=tf.ConfigProto(log_device_placement = True)) print(sess.run(c))
當只啓動第一個任務時,程序會停下來等待第二個任務啓動。並且持續輸出failed to connect to 「ipv4:127.0.0.1:2999」,當第二個任務啓動後,纔會輸出第一個任務的結果。