分配带有形状的张量时理解ResourceExhaustedError:OOM
tensorflow
5
0

我正在尝试使用tensorflow实现跳过思想模型,并在此处放置了当前版本。 在此处输入图片说明

目前,我使用机器上的一个GPU(总共2个GPU),并且GPU信息为

2017-09-06 11:29:32.657299: I tensorflow/core/common_runtime/gpu/gpu_device.cc:940] Found device 0 with properties:
name: GeForce GTX 1080 Ti
major: 6 minor: 1 memoryClockRate (GHz) 1.683
pciBusID 0000:02:00.0
Total memory: 10.91GiB
Free memory: 10.75GiB

但是,当我尝试将数据馈送到模型时,出现了OOM。我尝试如下调试:

我在运行sess.run(tf.global_variables_initializer())之后立即使用以下代码段

    logger.info('Total: {} params'.format(
        np.sum([
            np.prod(v.get_shape().as_list())
            for v in tf.trainable_variables()
        ])))

并得到了2017-09-06 11:29:51,333 INFO main main.py:127 - Total: 62968629 params ,大致约240Mb ,如果全部使用tf.float32tf.global_variables的输出是

[<tf.Variable 'embedding/embedding_matrix:0' shape=(155229, 200) dtype=float32_ref>,
 <tf.Variable 'encoder/rnn/gru_cell/gates/kernel:0' shape=(400, 400) dtype=float32_ref>,
 <tf.Variable 'encoder/rnn/gru_cell/gates/bias:0' shape=(400,) dtype=float32_ref>,
 <tf.Variable 'encoder/rnn/gru_cell/candidate/kernel:0' shape=(400, 200) dtype=float32_ref>,
 <tf.Variable 'encoder/rnn/gru_cell/candidate/bias:0' shape=(200,) dtype=float32_ref>,
 <tf.Variable 'decoder/weights:0' shape=(200, 155229) dtype=float32_ref>,
 <tf.Variable 'decoder/biases:0' shape=(155229,) dtype=float32_ref>,
 <tf.Variable 'decoder/previous_decoder/rnn/gru_cell/gates/kernel:0' shape=(400, 400) dtype=float32_ref>,
 <tf.Variable 'decoder/previous_decoder/rnn/gru_cell/gates/bias:0' shape=(400,) dtype=float32_ref>,
 <tf.Variable 'decoder/previous_decoder/rnn/gru_cell/candidate/kernel:0' shape=(400, 200) dtype=float32_ref>,
 <tf.Variable 'decoder/previous_decoder/rnn/gru_cell/candidate/bias:0' shape=(200,) dtype=float32_ref>,
 <tf.Variable 'decoder/next_decoder/rnn/gru_cell/gates/kernel:0' shape=(400, 400) dtype=float32_ref>,
 <tf.Variable 'decoder/next_decoder/rnn/gru_cell/gates/bias:0' shape=(400,) dtype=float32_ref>,
 <tf.Variable 'decoder/next_decoder/rnn/gru_cell/candidate/kernel:0' shape=(400, 200) dtype=float32_ref>,
 <tf.Variable 'decoder/next_decoder/rnn/gru_cell/candidate/bias:0' shape=(200,) dtype=float32_ref>,
 <tf.Variable 'global_step:0' shape=() dtype=int32_ref>]

用我的训练短语,我有一个数据数组,其形状为(164652, 3, 30) ,即sample_size x 3 x time_step ,这里的3表示前一个句子,当前句子和下一个句子。该训练数据的大小约为57Mb ,并存储在loader 。然后我使用编写一个生成器函数来获取句子,看起来像

def iter_batches(self, batch_size=128, time_major=True, shuffle=True):

    num_samples = len(self._sentences)
    if shuffle:
        samples = self._sentences[np.random.permutation(num_samples)]
    else:
        samples = self._sentences

    batch_start = 0
    while batch_start < num_samples:
        batch = samples[batch_start:batch_start + batch_size]

        lens = (batch != self._vocab[self._vocab.pad_token]).sum(axis=2)
        y, x, z = batch[:, 0, :], batch[:, 1, :], batch[:, 2, :]
        if time_major:
            yield (y.T, lens[:, 0]), (x.T, lens[:, 1]), (z.T, lens[:, 2])
        else:
            yield (y, lens[:, 0]), (x, lens[:, 1]), (z, lens[:, 2])
        batch_start += batch_size

训练循环看起来像

for epoch in num_epochs:
    batches = loader.iter_batches(batch_size=args.batch_size)
    try:
        (y, y_lens), (x, x_lens), (z, z_lens) =  next(batches)
        _, summaries, loss_val = sess.run(
        [train_op, train_summary_op, st.loss],
        feed_dict={
            st.inputs: x,
            st.sequence_length: x_lens,
            st.previous_targets: y,
            st.previous_target_lengths: y_lens,
            st.next_targets: z,
            st.next_target_lengths: z_lens
        })
    except StopIteraton:
        ...

然后我得到了OOM。如果我注释掉整个try正文(不提供数据),则脚本运行良好。

我不知道为什么要在这么小的数据范围内获得OOM。我总是使用nvidia-smi

Wed Sep  6 12:03:37 2017
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 384.59                 Driver Version: 384.59                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 108...  Off  | 00000000:02:00.0 Off |                  N/A |
|  0%   44C    P2    60W / 275W |  10623MiB / 11172MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   1  GeForce GTX 108...  Off  | 00000000:03:00.0 Off |                  N/A |
|  0%   43C    P2    62W / 275W |  10621MiB / 11171MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID  Type  Process name                               Usage      |
|=============================================================================|
|    0     32748    C   python3                                      10613MiB |
|    1     32748    C   python3                                      10611MiB |
+-----------------------------------------------------------------------------+

无法看到脚本的实际 GPU使用情况,因为tensorflow总是在开始时就窃取了所有内存。而这里的实际问题是我不知道如何调试它。

我已经在StackOverflow上阅读了一些有关OOM的文章。大多数情况发生在将大量测试集数据输入模型中并小批量输入数据可以避免此问题的时候。但是我不明白为什么这么小的数据和参数组合会吸引我的11Gb 1080Ti,因为它会错误地尝试分配大小为[3840 x 155229]的矩阵。 (解码器的输出矩阵3840 = 30(time_steps) x 128(batch_size)155229是vocab_size)。

2017-09-06 12:14:45.787566: W tensorflow/core/common_runtime/bfc_allocator.cc:277] ********************************************************************************************xxxxxxxx
2017-09-06 12:14:45.787597: W tensorflow/core/framework/op_kernel.cc:1158] Resource exhausted: OOM when allocating tensor with shape[3840,155229]
2017-09-06 12:14:45.788735: W tensorflow/core/framework/op_kernel.cc:1158] Resource exhausted: OOM when allocating tensor with shape[3840,155229]
     [[Node: decoder/previous_decoder/Add = Add[T=DT_FLOAT, _device="/job:localhost/replica:0/task:0/gpu:0"](decoder/previous_decoder/MatMul, decoder/biases/read)]]
2017-09-06 12:14:45.790453: I tensorflow/core/common_runtime/gpu/pool_allocator.cc:247] PoolAllocator: After 2857 get requests, put_count=2078 evicted_count=1000 eviction_rate=0.481232 and unsatisfied allocation rate=0.657683
2017-09-06 12:14:45.790482: I tensorflow/core/common_runtime/gpu/pool_allocator.cc:259] Raising pool_size_limit_ from 100 to 110
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 1139, in _do_call
    return fn(*args)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 1121, in _run_fn
    status, run_metadata)
  File "/usr/lib/python3.6/contextlib.py", line 88, in __exit__
    next(self.gen)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/errors_impl.py", line 466, in raise_exception_on_not_ok_status
    pywrap_tensorflow.TF_GetCode(status))
tensorflow.python.framework.errors_impl.ResourceExhaustedError: OOM when allocating tensor with shape[3840,155229]
     [[Node: decoder/previous_decoder/Add = Add[T=DT_FLOAT, _device="/job:localhost/replica:0/task:0/gpu:0"](decoder/previous_decoder/MatMul, decoder/biases/read)]]
     [[Node: GradientDescent/update/_146 = _Recv[client_terminated=false, recv_device="/job:localhost/replica:0/task:0/cpu:0", send_device="/job:localhost/replica:0/task:0/gpu:0", send_device_incarnation=1, tensor_name="edge_2166_GradientDescent/update", tensor_type=DT_FLOAT, _device="/job:localhost/replica:0/task:0/cpu:0"]()]]

During handling of the above exception, another exception occurred:

任何帮助将不胜感激。提前致谢。

参考资料:
Stack Overflow
收藏
评论
共 3 个回答
高赞 时间 活跃

您正在耗尽内存,可以减小批次大小,这会减慢训练过程的速度,但可以容纳数据。

收藏
评论

从技术上讲这可能没有意义,但是经过一段时间的试验,我发现了这一点。

环境:Ubuntu 16.04


When you run the command

英伟达

您将获得已安装的Nvidia图形卡的总内存消耗。一个例子如下图所示在此处输入图片说明

运行神经网络后,您的消费量可能会改变为在此处输入图片说明

内存消耗通常提供给python。由于某些奇怪的原因,如果此过程无法成功终止,则永远不会释放内存。如果尝试运行神经网络应用程序的另一个实例,则可能会收到内存分配错误。困难的方法是尝试找出一种使用进程ID终止此进程的方法。例如,使用进程ID 2794,您可以执行

sudo kill -9 2794

简单的方法是重新启动计算机,然后重试。但是,如果它是与代码相关的错误,则将无法使用。

如果上述过程不起作用,则可能是您使用的数据批量大小无法容纳在GPU或CPU内存中。

您可以做的是减小输入数据的批量大小或空间尺寸(长度,宽度和深度)。这可能有效,但是您可能用完了RAM。

节省RAM的最可靠方法是使用函数生成器,这本身就是主题。

收藏
评论

让我们将问题一一划分:

关于tensorflow预先分配所有内存,您可以使用以下代码片段让tensorflow随时分配内存。这样您就可以了解事情的进展。

gpu_options = tf.GPUOptions(allow_growth=True)
session = tf.InteractiveSession(config=tf.ConfigProto(gpu_options=gpu_options))

如果您愿意, tf.InteractiveSession()tf.Session()而不是tf.InteractiveSession()

关于大小的第二件事,由于没有有关您的网络大小的信息,因此我们无法估算出问题所在。但是,您也可以逐步调试所有网络。例如,创建仅包含一层的网络,获取其输出,一次创建会话和提要值,并可视化消耗多少内存。迭代此调试会话,直到看到内存不足的地方。

请注意,3840 x 155229的输出确实非常大。这意味着约600M神经元,每层仅约2.22GB。如果您有任何相似的大小图层,所有这些图层都会加起来以非常快地填充您的GPU内存。

此外,这仅用于正向,如果您正在使用此层进行训练,则优化器添加的反向传播和层会将此大小乘以2。因此,对于训练,仅消耗约5 GB的输出层。

我建议您修改网络并尝试减少批处理大小/参数数量以使模型适合GPU

收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题

关于我们

常见问题

内容许可

联系我们

@2020 AskGo
京ICP备20001863号