我的理解是,在尝试创建 tensorflow 会话时,如果可用 GPU 内存量不足以满足程序的要求,则程序应该引发错误并退出。但似乎不是这种情况,这种行为非常烦人且难以察觉,尤其是在使用 Jupyter Notebook 时。
代码
我试图运行以下程序(据说是 debug.py)
import tensorflow as tf
a1 = tf.constant([0.0,0.0])
b1 = tf.constant([2.0,2.0])
mse1, update1 = tf.metrics.mean_squared_error(a1,b1)
mse2 = tf.losses.mean_squared_error(a1,b1)
with tf.Session() as sess:
sess.run(tf.local_variables_initializer())
update1.eval()
print(mse1.eval())
print(mse2.eval())
该程序仅计算两个向量 a1 和 b1 之间的 mean_squared_error (MSE),正确的输出(来自两个 print() 行)应该是 4.0 和 4.0。如果没有其他 python 程序正在使用我的 GPU,这确实是输出。
意外行为
如果另一个程序正在使用 GPU(例如,另一个 jupyter notebook 使用 tensorflow 运行某些东西,而不限制其 GPU 使用量gpu_options.per_process_gpu_memory_fraction),那么上面的代码将输出不同的东西。第一个打印行 ( mse1) 会输出一些随机数,例如“0.0”(最常见)、“3e-45”、“nan”等,这显然是错误的。第二个打印行 ( mse2) 始终打印正确答案:4.0。
有时运行此代码python debug.py会生成错误消息
E tensorflow/stream_executor/cuda/cuda_driver.cc:924] 未能从设备分配 176.44M(185008128 字节):CUDA_ERROR_OUT_OF_MEMORY
但是程序没有退出,并且仍然打印结果,尽管不正确。
python debug.py 在其他情况下,通过生成另一条错误消息来运行此代码
E tensorflow/core/common_runtime/direct_session.cc:170] 内部:为 CUDA 设备序号 0 初始化 StreamExecutor 失败:内部:对 cuDevicePrimaryCtxRetain 的调用失败:CUDA_ERROR_OUT_OF_MEMORY;报告的总内存:8502771712
并且程序退出而不打印任何输出。
最烦人的是,在 Jupyte Notebook 中运行相同的代码总是不会产生错误或警告消息,尽管输出不正确。这就是为什么我一直以为我误解了如何在tf.metrics.mean_squared_error没有意识到可能存在内存错误的情况下调用。
系统
我分别使用 CUDA 8、Ubuntu 16.04 和 Nvidia GPU(1080 和 770M)验证了我的两台计算机分别运行 Tensorflow 1.3 和 1.4 的问题。
我的问题
(0) 我的代码有什么问题吗?
(1) 如果你还使用了 Jupyter Notebook 的 Tensorflow,那么在运行上述代码时,你是否曾经得到错误的输出(打印 4.0、4.0 以外的任何内容)?如果是这样,Jupyter 是否会提醒您任何错误?
(2) 这个退错问题的本质是什么mse1?是 GPU 内存泄漏吗?
(3)为什么问题发生时会出现这种不一致的行为?具体来说,为什么debug.py有时退出,有时不退出?为什么 Jupyter Notebook 永远不会退出或引发错误?
(4) 为什么mse2出错时永远不会mse1出错?我的理解是这tf.metrics.mean_squared_error是一个流式操作,因此需要将一些变量存储在不同的地方。
