【问题标题】:What can I do to run specific TensorFlow calculations on a CPU as part of a GPU implementation?作为 GPU 实现的一部分,我可以做些什么来在 CPU 上运行特定的 TensorFlow 计算?
【发布时间】:2016-09-16 13:48:19
【问题描述】:

我很困惑如何有效地将我的 TensorFlow 操作和变量分配给设备。很明显,至少对于我实现的基本卷积神经网络而言,在 GPU 上放置尽可能多的操作是可取的。但是我目前可以访问的 GPU 内存有限,并导致许多表单警告

Ran out of memory trying to allocate 2.60GiB. The caller indicates that this is not a failure, but may mean that there could be performance gains if more memory is available.

以及某些特定操作的偶尔崩溃,例如

Ran out of memory trying to allocate 83.74MiB.  See logs for memory state.
Resource exhausted: OOM when allocating tensor with shape[28000,1,28,28]

这些可以通过在 CPU 上放置变量来避免,但在我的实现中,这会导致训练 epoch 需要 10 倍的计算时间。

显然,理想的策略是识别产生错误的特定代码块,并尝试仅将这些代码块放在 CPU 上。但我不清楚如何做到这一点,因为这些计算无法与其他需要 GPU 放置以实现效率的计算隔离开来。

例如,简单地使用类似的东西在测试集上生成预测

evals = sess.run(tf.argmax(y, 1), feed_dict={x: use_x_all})

其中x 是我模型的输入tf.placeholder,y 是我的网络的输出激活,当use_x_all 是一个大数组时会产生上述错误(这里有28000 示例) .尝试将此计算单独放在 CPU 上失败,可能是因为生成 y 的网络评估在 GPU 上。

因此,我(似乎)需要采用类似的方法

use_x_all, _ = data_loader.stack_data(use_data, as_cols=False)
use_x_split = np.split(use_x_all, splits)
for use_x in use_x_split:
    # ... (full example below)
    evals_part = sess.run(tf.argmax(y, 1), feed_dict={x: use_x})
    # accumulate evals

这显然无法扩展。

有没有更好的方法?具体来说:

  • 有没有一种方法可以将上述计算放在 CPU 上,并且仍然在 GPU 上运行相同图形(例如训练)的这些计算?

或者,或者

  • 是否有一种习惯用法(如批处理)可以更轻松地应用于此类情况以减少此类计算的内存需求?

实际上,我很惊讶后者不是 TensorFlow API 的一部分。不应该可以automatically break up calculations 不适合设备,而不需要上面的代码吗?


我的代码中的完整示例:

f = open('{0:s}/{1:s}_{2:3.0f}.csv'.format(FLAGS.pred_dir, FLAGS.session_name,
                                                       10000*float(sess.run(accuracy, feed_dict=valid_feed))), 'w')
f.write('ImageId,Label\n')
use_x_all, _ = data_loader.stack_data(use_data, as_cols=False)
            use_x_split = np.split(use_x_all, splits)
last = 0
buff = ''
for use_x in use_x_split:
    evals = sess.run(tf.argmax(y, 1), feed_dict={x: use_x})
    f.write('\n'.join('{0},{1}'.format(r[0]+ last, r[1]) for r in enumerate(evals, start=1)))
    last += int(len(use_x_all)/splits)
    if last < len(use_x_all):
        f.write('\n')
f.close()

【问题讨论】:

标签: memory-management out-of-memory gpu tensorflow


【解决方案1】:

有没有一种方法可以将上述计算放在 CPU 上,并且仍然在 GPU 上运行相同图形(例如训练)的这些计算?

您可以使用显式和嵌套的设备放置。使用日志记录查看操作的位置。

config = tf.ConfigProto()
config.log_device_placement = True
s = tf.InteractiveSession(config=config)

with tf.device("/gpu:0"):
    m = tf.matmul(tf.constant([[1,2,3,4]]), tf.constant([[1],[1],[1],[1]]))
    with tf.device("/cpu:0"):
        m = m + 1

s.run(m)

【讨论】:

  • 不,如问题所述,问题在于图形在 GPU 上,并且尝试在图形的 CPU 上的输出上运行 argmax 失败(它停留在 GPU 上)。
  • 不清楚你在问什么。您发布的代码不完整。请发布一个可以运行的代码来重现您的问题。检查你的代码,记住你不能在 tensorflow 中断开可训练操作。
【解决方案2】:

简答: 您可以拆分计算,但您需要考虑一下正确的方法。 此外,小批量是一个合理的习惯用法。

长答案:

异类放置是可能的,但我认为它比你想象的要复杂一些。考虑以下(抽象的、简化的)设置:

这里的问题是评估这个网络所需的所有张量都不适合我们的 GPU。不幸的是,它不像“识别产生错误的特定代码块”那么简单,因为内存分配问题通常是一个聚合问题。即,错误只是总数太大的症状,而不是表明特定分配太大——可以这么说,你只是看到压垮骆驼的最后一根稻草。

正如您所指出的,我们希望在 GPU 上运行计算以获得更好的吞吐量,但随意分配会在 PCI 接口上移动大量数据,从而放弃我们本应获得的任何性能提升:

在左侧分区方案中,与右侧相比,我们通过接口移动的数据要少得多。

除了有无数其他方法可以划分计算图以实现不同的平衡...

并且它们中的每一个在性能方面都会表现出不同的表现。这就是 TF 不自动分区图表的原因。在一般情况下,这实际上不是一个简单的问题。

分区计算技巧

回到你的具体问题。您的方法(小批量)是一种可行的方法。如果有效地缩小了 all 分配请求的大小。正如其他人所建议的那样,对其进行分区也可能是一种可行的方法,但您应该明智地进行。尝试最小化设备间的内存移动,并尝试将计算密集的图形片段(如一大块卷积层)放在同一设备上。

一种有用的策略可能是计算(手动或使用张量板)图表不同部分中张量的大小。这应该让您了解网络的各个部分之间的相对关系。这反过来又为如何对其进行分区提供了合理的指导。

最后,如果您只进行推理(不进行训练),另一种解决方案是一次只评估部分网络。这是使用小批量的双重方法:您可以使用一些小网络和一些大批量,而不是使用具有许多小批量的大型网络。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-29
    • 2019-12-04
    • 1970-01-01
    • 1970-01-01
    • 2017-04-05
    • 1970-01-01
    • 2015-07-16
    • 2019-10-23
    相关资源
    最近更新 更多