1. 程式人生 > >tensorflow原始碼學習之五 -- 同步訓練和非同步訓練

tensorflow原始碼學習之五 -- 同步訓練和非同步訓練

 同步和非同步訓練是由optimizer來決定的。

        1. 同步訓練

        同步訓練需要使用SyncReplicasOptimizer,參考https://www.tensorflow.org/api_docs/python/tf/train/SyncReplicasOptimizer 。其他optimizer都屬於非同步訓練方式。

        同步訓練實現在sync_replicas_optimizer.py檔案中的def apply_gradient()方法中。假設有n個引數:

        對於PS,需要建立n個引數收集器(每個引數對應一個收集器),每一個worker將自己計算得到的grad梯度推送到收集器上(推送是使用Send/Recv OP實現的)。每個引數收集器收集到所有的worker的推送值時,對所有的值求平均,然後更新引數的值。當所有的引數都更新完成之後,對global_step加1,並將global_step推送到每個worker的token_queue中,worker更新global_step,開始下一次訓練。

       對於Worker,從PS拉取需要的引數,計算grad梯度值,然後將grad推送到相應的引數收集器。推送之後從token_queue中拉取新的global_step(拉取不到新的global_step 就等待?),繼續下一次訓練。

 

        2. 非同步訓練

         訓練程式碼中使用的是GradientDescentOptimizer(繼承了Optimizer),呼叫其minimize()方法,minimize()方法就是先呼叫compute_gradients()然後呼叫apply_gradient()方法。

         非同步訓練的實現在optimizer.py檔案中的def apply_gradient()方法中(GradientDescentOptimizer沒有重寫Optimizer的apply_gradient()方法)。參考

https://stackoverflow.com/questions/43147435/how-does-asynchronous-training-work-in-distributed-tensorflow

         對於Worker,worker從PS拉取需要的引數,拉取過程是沒有鎖的,因此拉取的值可能包含了其他worker的修改,也可能沒包含。計算gard梯度值,然後將grad梯度值傳送給相應PS。

         對於PS,ps收到grad值之後根據優化演算法(如,SGD, SGD with Momentum, Adagrad, Adam, etc.)來更新引數。

         :在非同步訓練中,假設worker1讀取引數w1,worker2再讀取引數w1,然後worker1更新梯度,worker2再更新梯度,worker1更新的梯度就被worker2覆蓋掉了。如果想對修改做同步,GradientDescentOptimizer的建構函式提供了use_locking引數。

 

參考:
[1] http://jcf94.com/2018/01/13/2018-01-13-tfunpacking/   (session.run())
[2] http://jcf94.com/2018/01/23/2018-01-23-tfunpacking2/ (tf資料流模型和自動求導)
[3] http://jcf94.com/2018/02/28/2018-02-28-tfunpacking3/ (graph和node)
[4] http://jcf94.com/2018/03/07/2018-03-07-tfunpacking4/ (device)
[5] http://jcf94.com/2018/03/09/2018-03-09-tfunpacking5/ (distributed)
[6] https://www.tensorflow.org/deploy/distributed               (distributed tensorflow)
[7] https://stackoverflow.com/questions/43147435/how-does-asynchronous-training-work-in-distributed-tensorflow (asynchronous training in distributed tensorflow)