我怎样才能在 TensorFlow 中解决 'ran out of gpu memory'

How can I solve 'ran out of gpu memory' in TensorFlow

我 运行 TensorFlow 中的 MNIST 演示有 2 个卷积层和一个全连接层,我收到一条消息 'ran out of memeory trying to allocate 2.59GiB',但它显示总内存为 4.69GiB,并且是免费的内存是 3.22GiB,怎么会停在 2.59GiB 呢?有了更大的网络,我该如何管理 gpu 内存?我只关心如何充分利用 gpu 内存并想知道它是如何发生的,而不是如何预分配内存

不是那个。首先,您可以通过监视您的 gpu 来查看它在运行时获得了多少内存。例如,如果你有一个 nvidia gpu,你可以用 watch -n 1 nvidia-smi 命令检查它。 但在大多数情况下,如果您没有设置 gpu 内存的最大部分,它会分配几乎整个空闲内存。您的问题是您的 gpu 内存不足。 cnn 网络非常繁重。当你试图为你的网络提供数据时,不要用你的全部数据来做。以小批量执行此喂食程序。

我在 GTX 970 上训练小型 CNN 时遇到内存不足错误。我有点侥幸地发现告诉 TensorFlow 根据需要在 GPU 上分配内存(而不是预先)解决了我所有的问题问题。这可以使用以下 Python 代码完成:

    config = tf.ConfigProto()
    config.gpu_options.allow_growth = True
    sess = tf.Session(config=config)

以前,TensorFlow 会预分配大约 90% 的 GPU 内存。由于某些未知原因,即使模型 可以 完全适合 GPU 内存,这稍后也会导致内存不足错误。通过使用上面的代码,我不再有 OOM 错误。

注意:如果模型太大无法放入 GPU 内存,这可能无济于事!

默认情况下,TensorFlow 将所有 GPU 的几乎所有 GPU 内存(受 CUDA_VISIBLE_DEVICES 约束)映射到进程可见。这样做是为了通过减少内存碎片更有效地使用设备上相对宝贵的 GPU 内存资源。

TensorFlow 在 Session 上提供了两个配置选项来控制它。

第一个是 allow_growth 选项,它尝试根据运行时分配仅分配尽可能多的 GPU 内存:

config = tf.ConfigProto()
config.gpu_options.allow_growth = True
session = tf.Session(config=config)

第二种方法是 per_process_gpu_memory_fraction 选项,它确定应分配给每个可见 GPU 的内存总量的比例。例如,您可以通过以下方式告诉 TensorFlow 只分配每个 GPU 总内存的 40%:

config = tf.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = 0.4
session = tf.Session(config=config)

对于 Tensorflow 2:

config = tf.compat.v1.ConfigProto()
config.gpu_options.allow_growth = True
session = tf.compat.v1.Session(config=config)

来自TensorFlow guide

gpus = tf.config.experimental.list_physical_devices('GPU')
if gpus:
    # Restrict TensorFlow to only allocate 1GB of memory on the first GPU
    try:
        tf.config.experimental.set_virtual_device_configuration(gpus[0],
       [tf.config.experimental.VirtualDeviceConfiguration(memory_limit=1024)])
        logical_gpus = tf.config.experimental.list_logical_devices('GPU')
        print(len(gpus), "Physical GPUs,", len(logical_gpus), "Logical GPUs")
    except RuntimeError as e:
        # Virtual devices must be set before GPUs have been initialized
        print(e)

memory_limit=*value* 调整为适合您的 GPU 的值。 例如从 Nvidia docker 容器和远程屏幕会话访问 1070ti,这是 memory_limit=7168,没有进一步的错误。只需要确保偶尔清除 GPU 上的会话(例如 Jupyter 内核重启)。

张量流 2

由于我们不再有会话,因此解决方案不再可行。

默认情况下,TensorFlow 映射进程可见的所有 GPU 的几乎所有 GPU 内存(受 CUDA_VISIBLE_DEVICES 约束)。
在某些情况下,希望进程只分配可用内存的一个子集,或者只根据进程的需要增加内存使用量。 TensorFlow 提供了两种方法来控制它。其中之一是使用 set_memory_growth tf.config.experimental.set_memory_growth

为了全面了解,我推荐这个link:Limiting GPU memory growth

在深入研究上述其他可能的解释之前,请检查没有挂起的进程保留 GPU 内存。我刚刚遇到我的 Tensorflow 脚本因某些错误而挂起,但我没有注意到它,因为我用 nvidia-smi 监视了 运行 个进程。现在挂起的脚本没有出现在 nvidia-smi 的输出中,但仍在保留 GPU 内存。杀死挂起的脚本(Tensorflow 通常会产生与系统中 GPU 一样多的脚本)完全解决了类似的问题(在用尽所有 TF 魔法之后)。

对于 Tensorflow 2 或 Keras:

from tensorflow.python.framework.config import set_memory_growth
tf.compat.v1.disable_v2_behavior()
gpus = tf.config.experimental.list_physical_devices('GPU')
if gpus:
    try:
        for gpu in gpus:
            set_memory_growth(gpu, True)
    except RuntimeError as e:
        print(e)

TensorFlow 数据集对象。这是一个高性能选项,更适合内存中无法容纳的数据集以及从磁盘或分布式文件系统流式传输的数据集。

如果您有大型数据集并且正在 GPU 上进行训练,请考虑使用 Dataset 对象,因为它们会处理性能关键的细节,例如:

在您的 GPU 繁忙时在 CPU 上异步预处理您的数据,并将其缓冲到队列中。 在 GPU 内存上预取数据,以便在 GPU 完成前一批处理后立即可用,这样您就可以充分利用 GPU。

  • tf.keras.preprocessing.image_dataset_from_directory 将分类到 class 特定文件夹中的图像文件转换为图像张量的标记数据集。

资源:https://keras.io/getting_started/intro_to_keras_for_engineers/