在tensorflow的訓練中,分佈式可以大大的加快模型訓練速度,但是分佈式怎麼分配和參數設定,都和SyncReplicasOptimizer這個函數有很大關係。
操作系統:Ubuntu16.04
運行環境:python3.6,nvidia384(4塊),tensorflow-gpu1.10+cuda+cudnn(根據自己實際gpu配置)
現在我們看看SyncReplicasOptimizer這個函數的源碼解讀
首先這個SyncReplicasOptimizer函數是專門出來分佈式深度學習中的同步梯度下降的(要用異步梯度的可以直接無視)
def __init__(self,
opt: Any,
replicas_to_aggregate: Any,
total_num_replicas: Any = None,
variable_averages: Any = None,
variables_to_average: Any = None,
use_locking: bool = False,
name: str = "sync_replicas") -> None
Construct a sync_replicas optimizer.
Params:
opt – The actual optimizer that will be used to compute and apply the gradients. Must be one of the Optimizer classes.
replicas_to_aggregate – number of replicas to aggregate for each variable update.
total_num_replicas – Total number of tasks/workers/replicas, could be different from replicas_to_aggregate. If total_num_replicas > replicas_to_aggregate: it is backup_replicas + replicas_to_aggregate. If total_num_replicas replicas_to_aggregate: Replicas compute multiple batches per update to variables.
variable_averages – Optional `ExponentialMovingAverage` object, used to maintain moving averages for the variables passed in `variables_to_average`.
variables_to_average – a list of variables that need to be averaged. Only needed if variable_averages is passed in.
use_locking – If True use locks for update operation.
name – string. Optional name of the returned operation.
opt:將用於計算和應用梯度的實際優化器。必須是Optimizer類之一。
variable_averages:可選的`ExponentialMovingAverage`對象,用於保持傳入的變量的移動平均值
variables_to_average:需要平均的變量列表。只要如果傳入variable_averages則需要。
use_locking:如果True使用鎖定進行更新操作。
name:string。返回操作的可選名稱。
除開opt之外,其他可以先不指定,我們這裏重點看看replicas_to_aggregate和total_num_replicas這兩個參數,這是非常重要的。
replicas_to_aggregate:是指我們所需要通過分佈式的worker計算完成之後所需要的副本數,這裏可以認爲就是梯度的個數
total_num_replicas:是指我們指定出入計算樣本的數量(幾個機器就分配幾個batch_size)
我們看看網上針對SyncReplicasOptimizer用比較多的代碼這一段:
代碼出處:https://blog.csdn.net/guotong1988/article/details/53927424
#同步模式計算更新梯度
rep_op = tf.train.SyncReplicasOptimizer(optimizer,
replicas_to_aggregate=len(
worker_hosts),
total_num_replicas=len(
worker_hosts),
use_locking=True)
我們可以看出,replicas_to_aggregate和 total_num_replicas都是等於集羣中worker的數量的,但是源碼中對於這兩個參數又添加了額外的解釋,(replicas_to_aggregate以下簡稱副本數,total_num_replicas以下簡稱計算數)
replicas_to_aggregate: number of replicas to aggregate for each variable
update.
total_num_replicas: Total number of tasks/workers/replicas, could be
different from replicas_to_aggregate.
If total_num_replicas > replicas_to_aggregate: it is backup_replicas +
replicas_to_aggregate.
If total_num_replicas < replicas_to_aggregate: Replicas compute
multiple batches per update to variables.
什麼意思呢?意思就是說,副本數可以和計算數可以是不相等的。就好比有三個人交了三張試卷一樣,三個人就是計算數,三張試卷就是副本數。
源碼中說,If total_num_replicas > replicas_to_aggregate: it is backup_replicas + replicas_to_aggregate.
這是指如果計算數大於副本數,那麼多的那個就是backup worker,即備份工作節點。
比如:四個人交了三張試卷,沒交試卷的我們就認爲是備份工作節點
那這又是什麼玩意兒呢,圖啥呢?
在同步梯度下降中,所有worker都要等大家一起計算完成之後才能進行計算,因此會出現等待機制。就像四個人做試卷,但是每個人的速度不一樣,但是要同時交卷,所以我們要等待交卷最慢的那個人算完之後才能算完,這樣很浪費算的很快的那個人的能力,所以就有了backup的提出,4個人交卷我們只要三個人的試卷,最慢的那個我們不要了,直接清除掉,開始下一輪的考試~
因此,加入backup worker的方法可以加速分佈式同步梯度下法的訓練模型,那麼backup取幾個呢?Revisiting Distributed Synchronous SGD這篇論文中認爲是20:1的比例。
backup worker論文出處:鏈接:https://pan.baidu.com/s/1R22sfGTZcAy_5KEysJGX7Q 提取碼:26zi
還有一種情況,那就是計算數大於副本數。當計算數小於副本數,那麼他會多計算其他worker的樣本,就好比三個人(給三人一人發一個試卷,分配的是沒多餘的),但是要交四份試卷,那就先各算各的,先計算完成的再從已知的三份試卷中拿一個計算,然後再等着這三個人一共上交了四份試卷之後,這樣就ok了。有什麼用呢?我也不清楚,我們看下一步
當我們說這計算數和副本數的時候總是和機器的物理數量有關係(gpu數量),那麼其實這兩個都可以不等於機器的物理數量。例如:
gpu數量:3 那麼len(worker)就是3
計算數:10 那麼這10就指的是一次給分10個batch_size,然後讓3個worker去算
副本數:8 那麼這是個batch_size算完之後我只要8個梯度,然後平均,參數服務器的什麼後續操作
如果有什麼問題和不對的地方請留言指正,謝謝