首先需要说明的是,这个问题我并没有找出原因来。记下来的目的是把过程记录下来,让自己或他人再遇到这个问题时少走弯路。
环境:ubuntu18.04 anaconda3 python3.7 cuda10.1 cudnn7.6.5 tensorflow-gpu1.15.0,显卡1050 驱动440.82
过程:我是在做吴恩达的深度学习作业的时候遇到这个问题的(第四部分第一周的Convolution model-Application-v1),在计算图中定义了卷积后,执行时出了错。错误没有拷贝,大体是说卷积遇到错误,cudnn的初始化遇到错误。
网上有解决这个问题的各种办法,我几乎都尝试了一遍。
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:
这个我加上了,但是不起作用。
然后怀疑是版本问题,开始了为期一天的换版本的尝试。首先降tensorflow-gpu的版本,最低降到1.13.1 因为我的cuda是之前好不容易装好的(版本10.2,runtime10.1,我也不知道为什么,反正能用),所以没重装cuda,tensorflow1.12.0及一下就不支持cuda10了。但是都不起作用。然后又把tensorflow-gpu升到1.15.0,还是不行。
接着试图修改cudnn。但支持这几个版本tensowflow的只有7.6.5,但是build不同。anaconda定义对应的cudnn是7.6.5build cuda10.0_0,。试着换build cuda10.1_0,结果发现cudnn换了后,tensorflow就找不到了,应该里面有定义。又重装tensorflow,结果发现重装后cudnn又自动降回去了.总之,换版本似乎不起作用。
期间用vscode写了个小程序,用于测试tensorflow-gpu的可用性。
import tensorflow as tf
from tensorflow.python.client import device_lib as dl
print('list_local-device: \n\n',dl.list_local_devices(),'\n\n')
print('tf.version= ',tf.__version__,'\n\n')
print("gpu : ",tf.test.is_gpu_available(),"###\n\n")
结果每次安装完后执行不成功,但是重启后再执行成功,但是jupyter那边执行conv2d依然出错。出错时的结果还不同,有时是gpu:False 有时则直接执行失败,提示显存不够。
于是把目光放在了显存上。按照百度来的方法,
from numba import cuda
cuda.select_device(0)
cuda.close()
试图用这个方法释放显存。结果也不成功。select_device直接就失败了。
然后就想到了用nvidia-smi观察显存的变化情况,从重启开始,一步步观察。奇迹的一幕出现了:问题解决了。conv2d的执行正常了,再重启重来一次,还是正常的。
也许这个问题就像双缝实验一样,只要观察,就会正常:)
也许合理的解释是nvidia-smi程序中有一些机制,使其趋于正常。
反复的测试表明,tensorflow在运行时显存的释放的确不及时。
好了,总结一下这一过程中获得的一些经验:
- 使用anaconda安装tensorflow是最好的方法。它会直接安装所有需要的组件。安装非常简单:
conda install tensorflow-gpu
.不过现在这样运行会直接安装tensorflow2.2 。所以要安装tensorflow-gpu1需要先conda search tensorflow-gpu
。然后选择版本号conda install tensorflow-gpu=1.15.0
.如果要加上build号就是conda install tensorflow-gpu=1.15.0=h0d30ee6_0
. - 显存的观察和释放。
nvidia-smi
命令不仅列出了显卡驱动、cuda版本等,还有显存的情况,更关键的是列出了其pid。所以可以观察到是哪个进程占用了显存,必要时kill
之,显存就能释放出来了。jupyter中断服务并不释放显存,重启时会。但有时显存似乎没有被有效释放。这应该是cuda cudnn和驱动之间配合上的问题。具体原因不知道,反正现在一切都正常了。 - tensorflow1和2的差别巨大,足以让你怀疑人生。