我已阅读Distributed TensorFlow Doc和this question on StackOverflow,但我仍然对使用TensorFlow及其参数服务器架构可以完成的分布式培训背后的动态有所怀疑。 这是来自Distributed TensorFlow Doc的代码剪切:
if FLAGS.job_name == "ps":
server.join()
elif FLAGS.job_name == "worker":
# Assigns ops to the local worker by default.
with tf.device(tf.train.replica_device_setter(
worker_device="/job:worker/task:%d" % FLAGS.task_index,
cluster=cluster)):
# Build model...
loss = ...
global_step = tf.contrib.framework.get_or_create_global_step()
train_op = tf.train.AdagradOptimizer(0.01).minimize(
loss, global_step=global_step)
这是我读过的StackOverflow问题的部分答案:
worker从并行读取所有共享模型参数 PS任务,并将它们复制到工作人员任务。这些读物是 与任何并发写入不协调,并且不获取锁定: 特别是工人可能会看到一个或多个部分更新 其他工作人员(例如,来自另一名工人的更新的子集可能 已应用,或变量中的元素子集可能具有 已更新)。
工作人员根据批次在本地计算渐变 输入数据及其在步骤1中读取的参数值。
在 worker将每个变量的渐变发送到适当的PS 任务,并使用渐变将渐变应用于它们各自的变量 由优化算法确定的更新规则(例如, 新元,新元与动量,阿达格拉德,亚当等)。更新规则 通常使用(近似)可交换操作,因此它们可能是 独立应用于每个工人和州的更新 每个变量将是序列的运行聚合 收到的更新。
我必须在另一个环境中重现这种参数服务器体系结构,我需要深入了解TensorFlow框架内worker和PS任务如何相互交互。 我的问题是,PS任务在收到工作人员的价值后是否会进行某种合并或更新操作,或者只存储最新值?存储最新值可以是合理的吗?看一下TensorFlow文档中的代码,我看到PS任务只是做一个join(),我想知道这个方法调用背后是PS任务的完整行为。
还有一个问题,计算渐变和应用渐变之间有什么区别?
答案 0 :(得分:5)
让我们按相反的顺序从你的上一个问题开始:计算渐变和应用渐变之间有什么区别?
计算渐变意味着在计算损失后在网络上运行反向传递。对于梯度下降,这意味着估计下面公式中的gradients
值(注意:这是计算梯度实际需要的巨大简化,查看更多关于反向传播和梯度下降的信息解释这是如何工作的)。 应用渐变意味着根据刚刚计算的渐变更新参数。对于梯度下降,这(大致)意味着执行以下操作:
weights = weights - (learning_step * gradients)
请注意,根据learning_step
的值,weights
的新值取决于先前的值和计算的权重。
考虑到这一点,理解PS / worker架构更容易。让我们简单地假设只有一个PS(我们稍后会看到如何扩展到多PS)
PS(参数服务器)在内存中保存weights
(即参数)并接收gradients
,运行我在上面的代码中编写的更新步骤。它每次从工人那里收到渐变时就会这样做。
另一方面,工作人员查找PS中weights
的当前值,在本地复制它,运行前向和后向传递网络上的一批数据并获得新的gradients
,然后发送回PS。
注意强调“当前”:工人和PS之间没有锁定或进程间同步。如果工作人员在更新过程中读取weights
(例如,一半已经有新值,一半仍在更新),那就是他将用于下一次迭代的权重。这样可以保持快速。
如果有更多PS会怎么样?没问题!网络的参数在PS之间进行分区,工作人员只需联系所有参数即可获得每个参数块的新值,并仅返回与每个特定PS相关的梯度。