异步训练如何在分布式 TensorFlow 中工作?

How does asynchronous training work in distributed Tensorflow?

我读过 Distributed Tensorflow Doc,它提到在异步训练中,

each replica of the graph has an independent training loop that executes without coordination.

据我了解,如果我们使用具有数据并行架构的参数服务器,则意味着每个工作人员计算梯度并更新自己的权重,而无需关心其他工作人员对分布式训练神经网络的更新。由于所有权重都在参数服务器 (ps) 上共享,我认为 ps 仍然需要以某种方式协调(或聚合)来自所有 worker 的权重更新。我想知道聚合在异步训练中是如何工作的。或者更笼统地说,异步训练在分布式 TensorFlow 中是如何工作的?

查看文档中的示例,您 link 可以:

with tf.device("/job:ps/task:0"):
  weights_1 = tf.Variable(...)
  biases_1 = tf.Variable(...)

with tf.device("/job:ps/task:1"):
  weights_2 = tf.Variable(...)
  biases_2 = tf.Variable(...)

with tf.device("/job:worker/task:7"):
  input, labels = ...
  layer_1 = tf.nn.relu(tf.matmul(input, weights_1) + biases_1)
  logits = tf.nn.relu(tf.matmul(layer_1, weights_2) + biases_2)
  # ...
  train_op = ...

with tf.Session("grpc://worker7.example.com:2222") as sess:
  for _ in range(10000):
    sess.run(train_op)

您可以看到训练分布在三台机器上,它们都共享相同权重的副本,但正如示例下方所述:

In the above example, the variables are created on two tasks in the ps job, and the compute-intensive part of the model is created in the worker job. TensorFlow will insert the appropriate data transfers between the jobs (from ps to worker for the forward pass, and from worker to ps for applying gradients).

也就是说,一个gpu用于计算forward pass,然后将结果传给另外两台机器,而另外两台机器分别计算一部分权重的back propagation,然后发送结果到其他机器,这样他们就可以适当地更新他们的权重。

GPU 用于加速矩阵乘法和并行数学运算,这些运算对于前向传播和反向传播都非常密集。所以分布式训练只是意味着你将这些操作分布在许多 GPU 上,模型仍然在机器之间同步,但是现在可以并行计算不同权重的反向传播,并且可以计算不同 mini-batch 上的前向传播与前一个小批量的反向传播的时间仍在计算中。分布式训练并不意味着你在每台机器上都有完全独立的模型和权重。

在异步训练中,worker 之间的权重不同步。权重存储在参数服务器上。每个工作人员彼此独立地加载和更改共享权重。这样,如果一个 worker 比其他 worker 更快地完成迭代,它会不等待地继续下一个迭代。 worker只与共享参数服务器交互,彼此之间不交互。

总体而言,它可以(取决于任务)显着加快计算速度。然而,结果有时比使用较慢的同步更新获得的结果更差。

当您在分布式 TensorFlow 中进行异步训练时,特定工作器会执行以下操作:

  1. worker 从 PS 任务并行读取 所有共享模型参数,并将它们复制到 worker 任务.这些读取与任何并发写入不协调,并且不获取任何锁:特别是工作人员可能会看到来自一个或多个其他工作人员的部分更新(例如,可能已经应用了来自另一个工作人员的更新的子集,或者元素的子集在变量中可能已经更新)。

  2. worker 在本地计算 梯度,基于一批输入数据和它在步骤 1 中读取的参数值。

  3. 工作人员将每个变量的梯度发送到适当的PS任务,然后应用使用由优化算法(例如 SGD、带动量的 SGD、Adagrad、Adam 等)确定的更新规则,对它们各自变量的梯度。更新规则通常使用(大约)commutative 操作,因此它们可以独立应用于每个 worker 的更新,并且每个变量的状态将是 运行 聚合收到的更新顺序。

在异步训练中,worker 的每个更新都是同时应用的,如果在初始化相应的优化器(例如 tf.train.GradientDescentOptimizer)时设置了可选的 use_locking=True 标志,则更新可能会有所协调.但是请注意,这里的锁定只为两个并发更新提供互斥,并且(如上所述)读取不获取锁;锁定不提供整个更新集的原子性。

(相比之下,在同步训练中,像 tf.train.SyncReplicasOptimizer 这样的实用程序将确保所有工作人员为每个模型参数读取相同的最新值;并且所有更新同步步骤在应用于基础变量之前聚合。为此,工作人员通过屏障同步,他们在发送梯度更新后进入屏障,并在聚合更新应用于所有变量后离开。)