当使用tf.device('/cpu:0')时,Tensorflow如何分配GPU内存。

12

系统信息:1.1.0,GPU,Windows,Python 3.5,在ipython控制台中运行代码。

我正试图运行两个不同的Tensorflow会话,一个在GPU上(执行一些批处理工作),另一个在CPU上用于快速测试。

问题在于,当我生成第二个会话时,使用with tf.device('/cpu:0')指定后,该会话尝试分配GPU内存并导致我的另一个会话崩溃。

我的代码:

import os
os.environ["CUDA_VISIBLE_DEVICES"] = ""
import time

import tensorflow as tf

with tf.device('/cpu:0'):
  with tf.Session() as sess:
    # Here 6 GBs of GPU RAM are allocated.
    time.sleep(5)

如何强制Tensorflow忽略GPU?

更新:

根据@Nicolas的评论建议,我查看了此答案并运行了

import os
os.environ["CUDA_VISIBLE_DEVICES"] = ""
import tensorflow as tf

from tensorflow.python.client import device_lib
print(device_lib.list_local_devices())

输出:

[name: "/cpu:0"
device_type: "CPU"
memory_limit: 268435456
locality {
}
incarnation: 2215045474989189346
, name: "/gpu:0"
device_type: "GPU"
memory_limit: 6787871540
locality {
  bus_id: 1
}
incarnation: 13663872143510826785
physical_device_desc: "device: 0, name: GeForce GTX 1080, pci bus id: 0000:02:00.0"
]

我觉得即使我明确告诉脚本忽略任何CUDA设备,它仍然会发现并使用它们。这可能是TF 1.1的一个错误吗?

2个回答

12

设置CUDA_VISIBLE_DEVICES为空字符串不能掩盖对脚本可见的CUDA设备。

根据CUDA_VISIBLE_DEVICES的文档(由我强调):

仅在序列中存在索引的设备对CUDA应用程序可见,并按照该序列的顺序枚举它们。 如果其中一个索引无效,则只有其前面的索引对CUDA应用程序可见。例如,将CUDA_VISIBLE_DEVICES设置为2,1会导致设备0不可见,并在设备1之前枚举设备2。 将CUDA_VISIBLE_DEVICES设置为0,2,-1,1会使设备0和2可见,而设备1不可见。

看起来空字符串曾被处理为“不存在有效设备”,但是其含义已更改,因为文档中没有提到它。

将代码更改为os.environ["CUDA_VISIBLE_DEVICES"] = "-1"可以解决该问题。运行

import os
os.environ["CUDA_VISIBLE_DEVICES"]="-1"    
import tensorflow as tf

from tensorflow.python.client import device_lib
print(device_lib.list_local_devices())

现在打印

[name: "/cpu:0"
device_type: "CPU"
memory_limit: 268435456
locality {
}
incarnation: 14097726166554667970
]

现在实例化一个tf.Session不会再占用GPU内存了。


1
我为一些文档示例聚合了各种答案(包括您的答案),详情请参阅stackoverflow.com/documentation/tensorflow/10621。希望您不介意。随意编辑它。 - pfm

2

您介意尝试这些配置选项之一吗?

config = tf.ConfigProto()
config.gpu_options.allow_growth = True
# or config.gpu_options.per_process_gpu_memory_fraction = 0.0
with tf.Session(config=config) as sess:
    ...

根据文档,它应该可以帮助您管理特定会话的GPU内存,因此您的第二个会话应该能够在GPU上运行。根据答案,您还应尝试这样做:
import os
os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID"   # see issue #152
os.environ["CUDA_VISIBLE_DEVICES"]="-1"

config.gpu_options.allow_growth = True 这个选项似乎可以解决问题,尽管我认为这相当令人困惑。 allow_growth 只是关闭了 GPU 内存的预分配,但是当我禁用脚本的 CUDA 设备时,为什么还要预分配内存呢? - GPhilo
当你说“session”时,你是指tf.Session吗?因为我在一个Python进程中创建了两个tf.Session:一个用于GPU部分,另一个用于CPU部分。 - pfm
我在问题中更新了一些额外的信息,这些信息来自你在(已删除?)评论中提供的链接。 - GPhilo
我删除了评论并将其直接放在答案的编辑部分。另外,如果您添加 os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID" 会怎样? - pfm
1
好的,我找到了问题,我会在这条回答下面发布它。 - GPhilo
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接