【问题标题】:How does asynchronous training work in distributed Tensorflow?分布式 Tensorflow 中的异步训练如何工作?
【发布时间】:2017-08-26 02:58:46
【问题描述】:

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

图的每个副本都有一个独立的训练循环,无需协调即可执行。

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

【问题讨论】:

    标签: python asynchronous tensorflow neural-network distributed


    【解决方案1】:

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

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

    2. worker 根据一批输入数据及其在步骤 1 中读取的参数值在本地计算梯度。

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

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

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

    【讨论】:

    • 非常感谢您的精彩回答!!!我这里还有 2 个问题 - 1. 对于异步训练,由于每个工作人员独立计算和更新权重,因此共享的权重在训练期间不会同步。我想知道我们是否必须编写一个单独的方法来在训练后手动同步或汇总所有工人的权重。 2.在性能(速度和训练精度)方面,这里有什么权衡吗?谢谢!
    • 1.每个变量的更新直接应用于该变量的单个实例,该实例存储在 PS 任务上:本质上,每个工作人员对每个工作执行更新 v -= learning_rate * grad_of_loss_wrt_v 的 SGD(或其他优化算法的更高级的)变量v。您不需要做任何额外的事情来同步或聚合权重,因为只有一个共享副本!
    • 2.异步训练通常比同步训练实现更高的吞吐量(就每单位时间消耗的训练数据而言),因为它永远不需要阻塞另一个工作线程。但是,这是否会导致更快的准确率取决于模型和网络的性能,因为在进行异步训练时可能需要运行更多的步骤才能达到与同步训练过程相同的准确率.
    • 2. (续)许多人已经观察到(paper 1paper 2),借助现代 GPU 集群和快速互连,可以使同步训练运行得快得可以接受,因此(对于某些问题)使用它比异步训练。
    • @mrry:您能否更全面地解释第 3 步中的语句:“并将渐变应用于它们各自的变量”?该语句的主题是什么:工作者或参数服务器任务?如果是worker应用了更新规则,那么同步训练也是这样吗?
    【解决方案2】:

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

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

    【讨论】:

    • 哦,真的吗??我对异步训练进行了验证测试,发现所有工人的权重在某些方面仍然是同步的。真正让我困惑的是这些权重是如何在异步训练中同步的。我在 TF doc 及其代码上找不到答案,但我很确定它们已同步。
    • @RuofanKong 他们没有同步,他们只是读取梯度并将梯度发送到存储在 ps 上的相同变量。它们独立工作,但它们都读取和写入 ps 上的相同变量。每个工作人员将具有非常相似的权重,因为他们从 ps 上读取相同的参数,但是当一个工作人员更新 ps 上的权重时,其他工作人员只有在再次从 ps 中读取变量时才会看到变化。
    • 使用异步模式时更推荐使用较小的学习率?
    【解决方案3】:

    查看您链接到的文档中的示例:

    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)
    

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

    在上面的示例中,变量是在 ps 作业中的两个任务上创建的,而模型的计算密集型部分是在 worker 作业中创建的。 TensorFlow 将在作业之间插入适当的数据传输(从 ps 到 worker 用于前向传递,从 worker 到 ps 用于应用梯度)。

    也就是说,一个gpu用于计算前向传播,然后将结果传输给另外两台机器,而其他机器分别计算一部分权重的反向传播,然后将结果发送到其他机器,以便它们都可以适当地更新它们的权重。

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

    【讨论】:

    • 感谢您的回答!由于异步训练仍然需要在工作人员之间同步权重,我想知道在训练速度方面与同步训练是否有任何性能差异。或者换句话说,哪种方式更受欢迎?
    • 对于足够小的模型,在单个 GPU 中执行会更好,但是一旦模型变得足够大,异步会快得多,因为执行所有反向传播是速度瓶颈,而同步权重相对较快相比下。通常,您希望在 4 个 GPU 而不是 1 个 GPU 上进行 2 到 3 倍的加速。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-08
    • 1970-01-01
    • 2020-02-09
    • 2023-01-22
    • 1970-01-01
    • 2020-10-22
    • 1970-01-01
    相关资源
    最近更新 更多