tensorflow的conv2d函数执行失败问题

问题描述

运行tensorflow的时候执行卷积出现下面的告警信息,困扰了我很长一段时间。
UnknownError: 2 root error(s) found.
(0) Unknown: Failed to get convolution algorithm. This is probably because cuDNN failed to initialize, so try looking to see if a warning log message was printed above.
[[{{node conv0/convolution}}]]
(1) Unknown: Failed to get convolution algorithm. This is probably because cuDNN failed to initialize, so try looking to see if a warning log message was printed above.
[[{{node conv0/convolution}}]]
百度结果中有多种解决方案,最坑的就是tensorflow和cuda的版本问题。翻过来覆过去安装多少遍,最后还是继续出现。

config = tf.ConfigProto(gpu_options=tf.GPUOptions(allow_growth=True))
config.gpu_options.per_process_gpu_memory_fraction = 0.99
with tf.Session(config=config) as sess:

这是一个有效的办法。但是这一次我使用的是keras, tensorflow只是后端,没办法设置session(我对keras不熟悉),于是这个问题又出现了。
仔细研究后,发现出现这个错误的根本原因在于:tensorflow默认攫取所有显存,据说这样可以有效避免内存碎片的产生。而当显存已经被图形界面等占用了一部分的时候,就会出现这样的错误。

~$ nvidia-smi
Mon Sep 28 20:07:12 2020       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 440.82       Driver Version: 440.82       CUDA Version: 10.2     |
|-------------------------------+----------------------+----------------------+
| 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 1050    Off  | 00000000:01:00.0  On |                  N/A |
| 45%   31C    P8    N/A /  75W |    249MiB /  1992MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|    0      1225      G   /usr/lib/xorg/Xorg                           131MiB |
|    0      1632      G   /usr/bin/gnome-shell                         114MiB |
+-----------------------------------------------------------------------------+

这是运行tensorflow之前的显存情况,被图形界面占用了249M/1992M。

nvidia-smi
Mon Sep 28 20:20:59 2020       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 440.82       Driver Version: 440.82       CUDA Version: 10.2     |
|-------------------------------+----------------------+----------------------+
| 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 1050    Off  | 00000000:01:00.0  On |                  N/A |
| 45%   32C    P8    N/A /  75W |   1979MiB /  1992MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|    0      1225      G   /usr/lib/xorg/Xorg                           120MiB |
|    0      1632      G   /usr/bin/gnome-shell                         114MiB |
|    0      2547      G   /usr/lib/firefox/firefox                       1MiB |
|    0      2898      C   ...e/zhangyl/anaconda3/envs/tf1/bin/python  1729MiB |
+-----------------------------------------------------------------------------+

这是出现错误之后的,python占用了1729M。
那么应该怎么避免这种情况呢?让我读原著,学原文,看tensorflow的文档是怎么说的。

限制GPU显存的增长

在缺省的情况下,tensorflow会把所有GPU(根据CUDA_VISIBLE_DEVICES)的几乎所有显存提供给进程。这样做是为了更有效的利用相对宝贵的GPU显存资源,因为可以减少内存的碎片。如果要限制tensorflow只使用特定的一组GPU,我们可以使用tf.config.experimental.set_visible_devices 方法。

gpus = tf.config.experimental.list_physical_devices('GPU')
if gpus:
  # Restrict TensorFlow to only use the first GPU
  try:
    tf.config.experimental.set_visible_devices(gpus[0], 'GPU')
    logical_gpus = tf.config.experimental.list_logical_devices('GPU')
    print(len(gpus), "Physical GPUs,", len(logical_gpus), "Logical GPU")
  except RuntimeError as e:
    # Visible devices must be set before GPUs have been initialized
    print(e)

有些情况下我们希望进程只使用一部分显存,或者只根据进程的需要增加显存需求。tensorflow提供了两个方法来解决这个问题。

第一个方法是打开显存增长开关,调用tf.config.experimental.set_memory_growth,这样进程只会使用需要用到的显存:它会先申请很少的显存,随着程序的运行需要更多的显存,我们才会想tensorflow进程提供更多的GPU显存区域。注意我们不会释放显存,因为那会导致显存碎片。要在制定的GPU上打开显存增长开关,需要在分配任何张量或运行任何计算前使用下面的代码。

gpus = tf.config.experimental.list_physical_devices('GPU')
if gpus:
  try:
    # Currently, memory growth needs to be the same across GPUs
    for gpu in gpus:
      tf.config.experimental.set_memory_growth(gpu, True)
    logical_gpus = tf.config.experimental.list_logical_devices('GPU')
    print(len(gpus), "Physical GPUs,", len(logical_gpus), "Logical GPUs")
  except RuntimeError as e:
    # Memory growth must be set before GPUs have been initialized

打开这个开关的另一个方法是设置环境变量TF_FORCE_GPU_ALLOW_GROWTH为True。这个配置是对整个平台有效的。

第二个方法是设置虚拟GPU设备,使用tf.config.experimental.set_virtual_device_configuration,给在这个GPU上能使用的显存设一个上限。

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:

注意:虚拟设备被初始化后就不能被修改了。

如果你真的想要限制tensorflow进程所能使用的显存,这就是个很有效的方法。这种需求对于开发者来说很常见,因为还用其它的应用,例如GUI工作站。

翻译的不好,大体就是这样了。讲得很清楚了。和tf.ConfigProto的定义非常类似,那应该就是上面内容的一个封装。我用上面的第二个方法有效解决了前面说的错误。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值