我写了一个简单的测试代码来测试两台机器之间的tf.control_dependencies()
。我认为代码总是必须返回相同的结果,但结果并不一致。
有两个主机,每个主机都有自己的变量。其中一个通过SGD更新其变量,当它结束时,另一个主机将结果变量复制到它自己的变量。
### test.py ###
import tensorflow as tf
tf.app.flags.DEFINE_integer('task_id', 0, 'Unique task ID. One of 0 or 1.')
FLAGS = tf.app.flags.FLAGS
cluster = tf.train.ClusterSpec({'hosts': ['10.0.0.1:7001', '10.0.0.2:7001']})
server = tf.train.Server(cluster, task_index=FLAGS.task_id, protocol='grpc')
# Host 1 is passive
if FLAGS.task_id == 1:
server.join()
# Host 0 builds the operation graph
opt = tf.train.GradientDescentOptimizer(0.1)
with tf.device('/task:1/device:CPU:0'):
# Task 1 optimizes its own variable
var1 = tf.Variable(0, dtype=tf.float32)
apply_op = opt.minimize(tf.square(var1 - 2.))
with tf.device('/task:0/device:CPU:0'):
# Task 0 copies the optimized result to its own variable
var0 = tf.Variable(0, dtype=tf.float32)
with tf.control_dependencies([apply_op]):
new_var0 = tf.assign(var0, var1)
sess = tf.Session(target=server.target)
# initialize variables
sess.run(tf.global_variables_initializer())
# expected: [0.4, 0.4]
print(sess.run([new_var0, var1]))
我通过在主机0(10.0.0.1)上键入python test.py --task_id=0
和在主机1(10.0.0.2)上键入python test.py --task_id=1
来执行此代码。
我希望打印[0.4, 0.4]
,因为var1
已通过apply_op
更新,结果var1
会复制到var0
,因此var0
{1}}和var1
已更新值。但是,结果是[0.0, 0.4]
或[0.4, 0.0]
或[0.4, 0.4]
之一,每次执行代码时都会更改。为什么会这样?
如果我对两个变量都使用'/task:0/device:CPU:0'
,结果总是[0.4, 0.4]
,这可能表明问题来自机器之间的通信。
此外,如果我对这两个变量使用'/task:1/device:CPU:0'
,则结果为[0.4, 0]
或[0.4, 0.4]
之一。
Linux Ubuntu 16.04.1,CUDA 8.0,
TensorFlow r1.1,GPU版本,从源
安装(commit 1ec6ed51182adf8f1b03a3188c16cd8a45ca6c85)
答案 0 :(得分:1)
我怀疑你的问题是tf.Variable
获取变量的缓存快照。这是一种优化,可以最大限度地减少分布式培训中的转移,但可能会产生一些令人惊讶的影响。
尝试使用tf.Variable.read_value()
抓取最新副本。
请参阅value()
和read_value()
的文档:
https://www.tensorflow.org/api_docs/python/tf/Variable#value
https://www.tensorflow.org/api_docs/python/tf/Variable#read_value
希望有所帮助!