在 Tensorflow 中训练期间的 GPU 使用率非常低

Posted

技术标签:

【中文标题】在 Tensorflow 中训练期间的 GPU 使用率非常低【英文标题】:Very low GPU usage during training in Tensorflow 【发布时间】:2018-02-19 04:01:09 【问题描述】:

我正在尝试为 10 类图像分类任务训练一个简单的多层感知器,这是 Udacity 深度学习课程作业的一部分。更准确地说,任务是对各种字体渲染的字母进行分类(数据集称为 notMNIST)。

我最终得到的代码看起来相当简单,但无论如何我在训练期间总是得到非常低的 GPU 使用率。我用 GPU-Z 测量负载,结果显示只有 25-30%。

这是我当前的代码:

graph = tf.Graph()
with graph.as_default():
    tf.set_random_seed(52)

    # dataset definition
    dataset = Dataset.from_tensor_slices('x': train_data, 'y': train_labels)
    dataset = dataset.shuffle(buffer_size=20000)
    dataset = dataset.batch(128)
    iterator = dataset.make_initializable_iterator()
    sample = iterator.get_next()
    x = sample['x']
    y = sample['y']

    # actual computation graph
    keep_prob = tf.placeholder(tf.float32)
    is_training = tf.placeholder(tf.bool, name='is_training')

    fc1 = dense_batch_relu_dropout(x, 1024, is_training, keep_prob, 'fc1')
    fc2 = dense_batch_relu_dropout(fc1, 300, is_training, keep_prob, 'fc2')
    fc3 = dense_batch_relu_dropout(fc2, 50, is_training, keep_prob, 'fc3')
    logits = dense(fc3, NUM_CLASSES, 'logits')

    with tf.name_scope('accuracy'):
        accuracy = tf.reduce_mean(
            tf.cast(tf.equal(tf.argmax(y, 1), tf.argmax(logits, 1)), tf.float32),
        )
        accuracy_percent = 100 * accuracy

    with tf.name_scope('loss'):
        loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y))

    update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
    with tf.control_dependencies(update_ops):
        # ensures that we execute the update_ops before performing the train_op
        # needed for batch normalization (apparently)
        train_op = tf.train.AdamOptimizer(learning_rate=1e-3, epsilon=1e-3).minimize(loss)

with tf.Session(graph=graph) as sess:
    tf.global_variables_initializer().run()
    step = 0
    epoch = 0
    while True:
        sess.run(iterator.initializer, feed_dict=)
        while True:
            step += 1
            try:
                sess.run(train_op, feed_dict=keep_prob: 0.5, is_training: True)
            except tf.errors.OutOfRangeError:
                logger.info('End of epoch #%d', epoch)
                break

        # end of epoch
        train_l, train_ac = sess.run(
            [loss, accuracy_percent],
            feed_dict=x: train_data, y: train_labels, keep_prob: 1, is_training: False,
        )
        test_l, test_ac = sess.run(
            [loss, accuracy_percent],
            feed_dict=x: test_data, y: test_labels, keep_prob: 1, is_training: False,
        )
        logger.info('Train loss: %f, train accuracy: %.2f%%', train_l, train_ac)
        logger.info('Test loss: %f, test accuracy: %.2f%%', test_l, test_ac)

        epoch += 1

到目前为止,这是我尝试过的:

    我将输入管道从简单的feed_dict 更改为tensorflow.contrib.data.Dataset。据我了解,它应该负责输入的效率,例如在单独的线程中加载数据。所以不应该有任何与输入相关的瓶颈。

    我按照这里的建议收集了痕迹:https://github.com/tensorflow/tensorflow/issues/1824#issuecomment-225754659 然而,这些痕迹并没有真正显示出任何有趣的东西。 >90% 的训练步骤是 matmul 操作。

    更改了批量大小。当我将其从 128 更改为 512 时,负载从 ~30% 增加到 ~38%,当我将其进一步增加到 2048 时,负载增加到 ~45%。我有 6Gb GPU 内存,数据集是单通道 28x28 图像。我真的应该使用这么大的批量吗?我应该进一步增加它吗?

一般来说,我应该担心低负荷,这真的是我训练效率低下的标志吗?

这是 GPU-Z 截图,其中包含 128 张图片。当我在每个 epoch 之后测量整个数据集的准确度时,您会看到负载低,偶尔会达到 100%。

【问题讨论】:

【参考方案1】:

MNIST 规模的网络很小,很难为它们实现高 GPU(或 CPU)效率,我认为 30% 对您的应用程序来说并不罕见。更大的批大小将获得更高的计算效率,这意味着您每秒可以处理更多示例,但您也会获得较低的统计效率,这意味着您需要处理更多示例才能达到目标准确度。所以这是一个权衡。对于像您这样的小型字符模型,统计效率在 100 之后会迅速下降,因此可能不值得尝试增加批量大小进行训练。对于推理,您应该尽可能使用最大的批大小。

【讨论】:

感谢您的快速回复!雅罗斯拉夫,你能告诉我为什么会这样吗?我的假设如下:只要当时只完成一个训练步骤,就没有足够的计算来饱和所有 GPU 内核?因此,当我提供 128 张图像批次时,它已经尽可能并行运行,但它可以做的更多。 是的,没有足够的计算使内核饱和。此外,如果计算量相对于所需的内存带宽或内核启动的开销来说很小,那么事情的效率就会很低。更需要注意的是整体效率而不是 GPU 占用率。 TitanX 大型 matmul 获得 10 T ops/秒,但在许多应用程序中,网络运行速度低于 1 T ops/秒,因此不到峰值效率的 10% @Yaroslav Bulatov,如果有免费的 CUDA 内核,为什么 TensorFlow 不能将网络加倍,并行运行两次以使用更多内核,并在两者之间选择最佳参数集一次迭代?【参考方案2】:

在我的 nVidia GTX 1080 上,如果我在 MNIST 数据库上使用卷积神经网络,GPU 负载约为 68%。

如果我切换到一个简单的非卷积网络,那么 GPU 负载约为 20%。

您可以通过在教程Building Autoencoders in Keras by Francis Chollet 中构建更高级的模型来复制这些结果。

【讨论】:

以上是关于在 Tensorflow 中训练期间的 GPU 使用率非常低的主要内容,如果未能解决你的问题,请参考以下文章

TensorFlow 在训练期间没有使用我的 M1 MacBook GPU

GPU 在执行 Tensorflow 或 Theano 代码期间丢失

如何使TensorFlow使用100%的GPU?

训练 TensorFlow 期间面临的问题(BatchNormV3 错误)

keras-gpu的安装与配置

在 tensorflow 训练和测试中显示不同的结果