我正在尝试通过Tensorflow的多个GPU启动代码(在一台机器上)。我很困惑,因为据我所知,我们从不同的塔(又称GPU)中获得了多次损失,但评估的loss
变量似乎只是最后一个塔而不是所有塔的损失总和: / p>
for step in xrange(FLAGS.max_steps):
start_time = time.time()
_, loss_value = sess.run([train_op, loss])
duration = time.time() - start_time
最后为每个塔专门定义loss
:
for i in xrange(FLAGS.num_gpus):
with tf.device('/gpu:%d' % i):
with tf.name_scope('%s_%d' % (inception.TOWER_NAME, i)) as scope:
# Force all Variables to reside on the CPU.
with slim.arg_scope([slim.variables.variable], device='/cpu:0'):
# Calculate the loss for one tower of the ImageNet model. This
# function constructs the entire ImageNet model but shares the
# variables across all towers.
loss = _tower_loss(images_splits[i], labels_splits[i], num_classes,
scope)
有人可以解释一下这个步骤将不同塔的损失结合起来吗?或者我们只是单一塔损失代表其他塔的损失?
这里是代码的链接: https://github.com/tensorflow/models/blob/master/inception/inception/inception_train.py#L336
答案 0 :(得分:1)
出于监测目的,考虑到所有塔的工作符合预期,单塔的损失与所有塔的损失平均值一样具有代表性。这是因为它被分配给批次和塔之间没有关系。
但train_op
使用所有塔的渐变,按照line 263,278,因此技术培训会考虑所有塔的批次,应该如此。
请注意,损失的平均值将比单塔的损失具有更低的差异,但它们将具有相同的预期。
答案 1 :(得分:1)
是的,根据此代码,损失不会在整个gpus中求和或平均。每个gpu(塔)内部使用每个gpu的损失进行梯度计算。只有渐变是同步的。所以isnan测试仅针对最后一个gpu处理的数据部分进行。这不是至关重要的,但可能是一种限制。
如果真的需要,我认为你可以按照以下方式做到平均损失交叉gpus:
per_gpu_loss = []
for i in xrange(FLAGS.num_gpus):
with tf.device('/gpu:%d' % i):
with tf.name_scope('%s_%d' % (inception.TOWER_NAME, i)) as scope:
...
per_gpu_loss.append(loss)
mean_loss = tf.reduce_mean(per_gpu_loss, name="mean_loss")
tf.summary.scalar('mean_loss', mean_loss)
然后将sess.run中的loss替换为mean_loss:
_, loss_value = sess.run([train_op, mean_loss])
loss_value现在是所有gpus处理的损失的平均值。