Tensorflow源代码编译踩坑若干

Tensorflow源代码编译踩坑若干

已知:GPU Cluster服务器,非root账户,python 3.6 + CUDA 9.2 + cuDNN 7.6.5

欲:装Tensorflow r2.2(装B)

主要指引:Tensorflow官方的指引:从源代码构建

不得不说pytorch就是好用,只要在conda里面指定py版本cuda版本cudnn版本就能傻瓜式地装好,我爱pytorch,但是人家写的某些源码仍然使用tensorflow写的。所以说还是有必要把tensorflow也安排上。

官方提供的pip包(通过pip install tensorflow安装)只有CPU版本(tf.test.is_gpu_available() -> False),而且GPU版本(通过pip install tensorflow-gpu安装)的官方版一般也只有9.0或者10.0版本的pip包[1]。看了别人有说解决方案可以是直接用别人编译好的.whl包,但是找了一个试了一下好像8太彳亍。还有建议装CUDA其他版本的,我也没去试了。思前想后,最后还是决定根据官方指引,直接从源代码编译。

首先安装bazel。我直接在bazel的Github仓库中下载了bazel-2.2.0-installer-linux-x86_64.sh(可以用wget下载但是没必要,直接先开本地加速下载再用scp更加快嘻嘻)然后直接运行就行,这个没啥好说的,对当前用户安装就行。

然后就是clone tensorflow源码,这个也没啥好说的有手就行,耐心一下就是,毕竟带项目。clone完源码之后记得切分支。我就切了r2.2。

然后就开始踩坑辣。


坑1:./configure提示bazel版本出问题

直接魔改configure.py,把_TF_MAX_BAZEL_VERSION = '2.0.0' 手动改成_TF_MAX_BAZEL_VERSION = '2.2.0'就行。还有根目录下有个.bazelversion的它原来写的也是2.0.0,这个我们也换成2.2.0。

然后运行./configure,直接抄官方指引的答案就行了。基本上除了CUDA那一栏是y,其他都是n(一路回车)。值得注意的是,貌似它会直接检测到CUDA和cuDNN目录,所以也不用我们手动输入CUDA和cuDNN版本了。然后还有个Cuda compute capability的东西。这个好像它也是直接检测并帮我们填好了默认值,直接回车就完事了。如果不放心的可以去wikipedia搜这个东西,下面画了一个表,罗列了所有显卡对应的数字。

然后开始构建pip软件包。由于我是用的r2.2,所以直接抄它的第一个命令bazel build //tensorflow/tools/pip_package:build_pip_package

坑2:执行bazel build开始会下一堆东西,有的时候直接ERROR,报错connect time out

解决方法就是最土味的↑+回车,再次执行一遍命令。下好了的包会缓存

坑3:执行bazel build报错@org_python_license不能load,原因为checksum对不上

我们打开tensorflow目录(tensorflow这个repo下面有个叫tensorflow的目录)下的workspace.bzl文件,搜索这个org_python_license 看一看,在465行发现url的居然是docs.python.org/2.7/xxxxx,出问题。这个库具体是干啥的不是很清楚,但是下的都是些license TXT。为了保险起见,改成3.6,再次执行bazel build,checksum还是对不上,把get XXX wanted YYY的XXX复制到sha256_urls前面的那串字符串,再次执行bazel build,可以了。下完这些包之后又是漫长的等待,可以先暂时挂挂机。

封好这个pip软件包之后,再抄官方指引的下一条命令

./bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg

完事之后cd进/tmp/tensorflow_pkg/之后ls一下,发现打好的包,然后pip install就行

坑4:pip install完之后迫不及待地想玩一下tensorflow结果报错

这个别人也会提到:一定要切换到tensorflow源码以外的目录,不然会报错!

之后就可以tf.test.is_gpu_available()看到日志里面罗列出所有的显卡信息。

2020-03-31 15:24:50.608297: I tensorflow/compiler/xla/service/service.cc:176]   StreamExecutor device (0): Tesla P100-SXM2-16GB, Compute Capability 6.0
2020-03-31 15:24:50.608304: I tensorflow/compiler/xla/service/service.cc:176]   StreamExecutor device (1): Tesla P100-SXM2-16GB, Compute Capability 6.0
2020-03-31 15:24:50.608309: I tensorflow/compiler/xla/service/service.cc:176]   StreamExecutor device (2): Tesla P100-SXM2-16GB, Compute Capability 6.0
2020-03-31 15:24:50.608314: I tensorflow/compiler/xla/service/service.cc:176]   StreamExecutor device (3): Tesla P100-SXM2-16GB, Compute Capability 6.0

并且在最后返回了True。于是我们来跑一个TF程序试一试,看看能不能正常使用GPU资源来计算。

注意一下,在tensorflow 2.x里面如果还想使用tensorflow 1.x的api的话,把import tensorflow as tf改成import tensorflow.compat.v1 as tf就行了,耶✌

坑5:session.run时会提到编译用cuDNN和运行的cuDNN版本不匹配的问题

完整报错如下:

E tensorflow/stream_executor/cuda/cuda_dnn.cc:343] Loaded runtime CuDNN library: 7.0.5 but source was compiled with: 7.6.5. CuDNN library major and minor version needs to match or have higher minor version in case of CuDNN 7.0 or later version. If using a binary install, upgrade your CuDNN library. If building from sources, make sure the library loaded at runtime is compatible with the version specified during compile configuration.

搜了一下,有人提到是软链接的问题。但是当我检查cuDNN软链接的时候发现并没有其他的cuDNN版本:ls /usr/local/cuda/lib64发现只有libcudnn.so.7和libcudnn.so.7.6.5。后来发现是环境变量的问题:需要在~/.bashrc中设置

export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH

然后source ~/.bashrc一下,再运行就OK辣~

大家笑一笑就好

参考

  1. ^见Github issue https://github.com/tensorflow/tensorflow/issues/28022#issuecomment-485357906
编辑于 03-31