CentOS6源码编译安装TensorFlow
文章目录
文章首发于微信公众号:链家产品技术团队,欢迎搜索关注~
公司前一阵搞了两台GPU服务器,终于有“玩具”可以玩了~用的卡是最新的P100(好吧,真正最新的是V100,不过还没铺货)。本着爱折腾的精神,自然就开始了折腾它们的征程(结果是我被折腾了。。。)
以前自己也搭建过TensorFlow的开发环境(见链接),所以一开始以为这次也不会难,结果。。。咳咳,还是要正视自己的水平的。因为服务器上装的是系统是CentOS,以前自己捣鼓的时候用的是Ubuntu,差别还是不少的,所以特此记录自己踩过的坑,也给其他人一些经验帮助。
这次折腾总共分为两个阶段:最初打算直接通过pip下载TensorFlow安装包安装,结果完全失败,不过在此期间摸清了许多限制条件,也为第二个阶段——通过编译的方式安装TensorFlow打下了基础。
系统版本:CentOS release 6.8 (Final) 64位
追根溯源
首先,目标是安装TensorFlow,所以查阅TensorFlow官网的源码安装教程
发现需要使用Bazel来进行编译TensorFlow源码,进而生成pip安装包,通过pip来安装
那下一步就是安装Bazel。去Bazel官网查看,发现主要提供了Ubuntu、MacOS、Windows的安装方式,对于其他平台来说,需要通过源码编译的方式来安装。所需要的环境条件主要是JDK8、Python、跟C相关的编译工具等
CentOS 6.8自带的gcc版本为4.4.7,不支持C++11,而TensorFlow和Bazel的编译需要C++11的支持,所以要将gcc升级为支持C++11的版本,经过网上查找,gcc版本跨度不是很大的情况下,可以使用低版本的来编译安装高版本的gcc。gcc4.9.4可以通过4.4.7编译安装
CentOS 6.8自带的Python版本为2.6.6,而TensorFlow和Bazel的编译所需要的Python版本最低为2.7
因为要使用GPU,所以关于TensorFlow部分还需要一些额外的条件,在编译之前需要具备显卡驱动、Cuda Toolkit以及cuDNN
所以整个安装流程如下:
Java8、gcc4.9.4、Python2.7、pip、Bazel、NVIDIA Driver、CUDA、cuDNN、TensorFlow
所有环境变量添加在/etc/profile.d/path.sh
文件中
安装过程
1、Java-8
去Oracle官网下载最新的Java8版本即可(8u144)
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
下载.tar.gz格式的压缩包后,解压缩,将bin目录所在的路径添加到PATH当中即可
2、gcc-4.9.4
2.1 准备工作
先检查系统中是否安装了g++,如果没有的话在编译安装gcc时会报错
make[1]: *** [stage1-bubble] Error 2
使用yum安装g++
yum install gcc-c++
2.2 下载gcc源码
http://ftp.gnu.org/gnu/gcc/gcc-4.9.4/gcc-4.9.4.tar.bz2
解压
tar -jxvf gcc-4.9.4.tar.bz2
进入目录,接下来的操作都在这个目录下进行
cd gcc-4.9.4
2.3 下载所需要的依赖库
正常只需要执行
./contrib/download_prerequisites
但是因为服务器无法访问外网(后来就算可以访问了,但是连接依旧有限,比如这步自动下载一些依赖包的操作,就无法正常进行),所以我们采用先把所需要的依赖包下载下来后,放到所需要的目录(后来发现是ftp服务器无法请求= =)
查看下载操作的脚本
vim contrib/download_prerequisites
可以发现脚本通过wget下载了五个依赖包,分别是
也可以去 ftp://gcc.gnu.org/pub/gcc/infrastructure/ 下载
下载完成后将它们放到gcc-4.9.4目录下即可,然后把脚本中的下载命令注释掉后再执行
./contrib/download_prerequisites
2.4 配置编译安装
官方建议新建一个目录用于编译,所以
mkdir build
cd build
配置
../../gcc-4.9.4/configure --prefix=/opt/gcc-4.9.4/ --enable-checking=release --enable-languages=c,c++ --disable-multilib
关于具体的参数设置可以参照 https://gcc.gnu.org/install/configure.html
编译
make -j4
-j4指的是使用四个线程,服务器的CPU大约使用了不到20分钟。不过有人不建议使用多线程编译,说是可能会失败。
安装
make install
打开/etc/profile.d/path.sh
添加如下内容
1 | export PATH=/opt/gcc-4.9.4/bin:$PATH |
一般添加第一行就可以,但是在Bazel的编译过程中会出现一些错误,加上后面的部分可以解决这些错误
最后再退出重新登录一下即可
通过 gcc -v
和 g++ -v
可以看到版本已经变成了4.9.4:gcc version 4.9.4 (GCC)
3、Python-2.7
Python也需要通过编译源码的方式安装,使用刚才升级过的gcc来编译。之所以这样做是因为可以在后续操作中避免一些错误
3.1 准备工作
安装一些系统依赖
1 | yum groupinstall -y 'development tools' |
3.2 下载Python2.7源码
https://www.python.org/ftp/python/2.7.14/Python-2.7.14.tar.xz
解压
xz -d Python-2.7.14.tar.xz
tar -xvf Python-2.7.14.tar
进入目录,接下来的操作都在这个目录下进行
cd Python-2.7.14
3.3 配置编译安装
配置
./configure --prefix=/usr/local
编译,用时几分钟
make
安装
make install
3.4 使新版本生效
两种方式:加入PATH、软连接
加入PATH
export PATH=/usr/local/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
软连接
mv /usr/bin/python /usr/bin/python2.6
ln -s /usr/local/bin/python2.7 /usr/bin/python
此时通过 python -V
可以查看Python版本已经为2.7
3.5 解决yum失效问题
因为yum依赖的是原来Python2.6版本,所以做以下修改
vim /usr/bin/yum
将第一行 #!/usr/bin/python
改为 #!/usr/bin/python2.6
3.6 更新setuptools和pip
分别下载 setuptools 和 pip 的安装包
解压后进到相应的目录,执行
python setup.py install
此时通过 pip -V
可以查看pip的版本,已经是对应于Python2.7的了
顺手更新pip源(全局),毕竟还是国内的快
vim /etc/pip.conf
然后写入如下内容并保存
1 | [global] |
4、Bazel-0.5.3
接下来是编译安装Bazel,主要参照 官方教程 即可
4.1 下载Bazel源码
去GitHub上下载 bazel-\<VERSION>-dist.zip 格式的源码,下载最新版或者特定版本均可。此处下载的是0.5.3版本(最新的为0.5.4)
https://github.com/bazelbuild/bazel/releases/download/0.5.3/bazel-0.5.3-dist.zip
解压,最好指定目录,因为Bazel所有文件都放在根目录
unzip bazel-0.5.3-dist.zip -d bazel-0.5.3
进入目录,接下来的操作都在这个目录下进行
cd bazel-0.5.3
4.2 编译
运行
./compile.sh
编译出的结果放在 output/bazel
当中,将其复制到PATH路径下即可
cp output/bazel /usr/local/bin
或者
cp output/bazel /usr/bin
可以执行 bazel
验证是否安装成功
4.3 一些错误
- 第一个
1 | ERROR: /root/gg/bazel/third_party/BUILD:106:1: Extracting interface //third_party:apache_commons_collections failed (Exit 1): ijar failed: error executing command |
参照这个 issue 解决:
升级gcc后,需要添加CXX, CC, LDFLAGS and CXXFLAGS等环境变量
- 第二个
1 | Executing genrule //src:embedded_tools failed (Exit 1): bash failed: error executing command |
mkdir /root/tmp
export TMPDIR=/root/tmp
- 第三个
1 | AttributeError: ZipFile instance has no attribute '__exit__' |
当初升级gcc后直接编译Bazel报的错误,经查找是Python版本的问题(当时Python还是2.6),使用gcc4.9.4编译安装Python2.7后问题解决
5、NVIDIA Driver
5.1 准备工作
安装一些系统依赖
yum install kernel
5.2 下载驱动程序
去 http://www.nvidia.cn/Download/index.aspx 这里寻找对应的显卡驱动即可,这里选择:
- Product Type: Tesla
- Product Series: P-Series
- Product: Tesla P100
- Operating System: Linux 64-bit
- CUDA Toolkit: 8.0
- Language: English(US)
这里下载的文件名是:NVIDIA-Linux-x86_64-384.66.run
5.3 安装
添加可执行权限,安装
chmod +x NVIDIA-Linux-x86_64-384.66.run
./NVIDIA-Linux-x86_64-384.66.run
进入安装界面后一路同意就可以,是否安装32位的库,我选择的同意。对于最后出现的warning我选择了忽略
安装完成后需要重启服务器,驱动才会生效
reboot
5.4 验证
执行
nvidia-smi
后可以看到一些显卡信息,包括驱动版本、风扇转速、温度、显卡型号、已用功率/总功率、已用显存/总显存、GPU计算力利用率等
5.5 一些错误
- 第一个
1 | ERROR: Unable to find the kernel source tree for the currently running kernel. Please make sure you have installed the kernel source files for your kernel and that they are properly configured; on Red Hat Linux systems, for example, be sure you have the 'kernel-source' or 'kernel-devel' RPM installed. If you know the correct kernel source files are installed, you may specify the kernel source path with the '--kernel-source-path' command line option. |
如果没做最一开始的准备工作,可能会出现这个错误
- 第二个
1 | WARNING: nvidia-installer was forced to guess the X library path '/usr/lib64' and X module path '/usr/lib64/xorg/modules'; these paths were not queryable from the system. If X fails to find the NVIDIA X driver module, please install the `pkg-config` utility and the X.Org SDK/development package for your distribution and reinstall the driver. |
安装完成后的warning,目前没发现有什么问题
6、CUDA-8.0
CUDA是英伟达开发的一款针对于使用GPU来加速计算的工具包,所以机器学习或者深度学习想要使用GPU来加速计算的话,就必须使用CUDA
6.1 下载
去 https://developer.nvidia.com/cuda-downloads 这里寻找对应平台的文件下载即可。这里有一份详尽官方的 说明文档
目前CUDA已经出了9.0,但是TenforFlow官方推荐的是8.0,所以我们安装的还是8.0版本
这里一些选项的选择为:
- Operating System: Linux
- Architecture: x86_64
- Distribution: CentOS
- Version: 6
- Installer Type: runfile(local)
下面会显示两个安装文件,一个 Base Installer ,一个Patch。安装完Base后再安装Patch即可
6.2 安装
添加可执行权限,安装
chmod +x cuda_8.0.61_375.26_linux.run
./cuda_8.0.61_375.26_linux.run
接下来会有一系列提示需要确认,其中在询问是否要安装显卡驱动时选 n ,因为我们之前已经安装了最新版本的驱动。其他的一路同意即可
安装完成后会出现以下内容:
1 | Installing the CUDA Toolkit in /usr/local/cuda-8.0 ... |
根据以上提示内容发现,缺少了一些推荐的库,但是这些库可能是跟运行它提供的samples有关,所以现在并没有安装。日后如果有问题,可以依照这些提示去安装一下
并且samples也可以选择不安装,因为在cuda的目录下有一份samples
最后再打一下补丁即可
chmod +x cuda_8.0.61.2_linux.run
./cuda_8.0.61.2_linux.run
6.3 测试
进入samples目录,选择第一个例子进行测试
cd /usr/local/cuda/samples/1_Utilities/deviceQuery
make
编译完成后执行
./deviceQuery
会看到一系列显卡参数信息,只要最后显示 Result = PASS
即说明CUDA安装成功
7、cuDNN-6.0
在CUDA之外,还有个库叫做cuDNN(CUDA Deep Neural Network library),是专门给深度神经网络针对GPU调优的,也是TensorFlow官方要求必须安装的
7.1 下载
去 https://developer.nvidia.com/rdp/cudnn-download 选择对应的版本下载即可。不过需要先注册开发者账号后才可以下载
目前cuDNN最新版本是7.0,因为担心兼容性问题所以没有选择最新版本。因为之前安装的CUDA是8.0,所以我们选择
Download cuDNN v6.0 (April 27, 2017), for CUDA 8.0
cuDNN v6.0 Library for Linux
7.2 安装
执行解压操作
tar -zxvf cudnn-8.0-linux-x64-v6.0-tgz
解压后的文件夹是cuda。执行以下操作把文件复制到相应的位置
1 | cp cuda/include/cudnn.h /usr/local/cuda/include/ |
8、TensorFlow-1.3.0
终于到最后一步了,整个过程主要参照 官方教程
8.1 准备工作
安装一些系统依赖
yum install python-devel
pip install numpy wheel
8.2 下载TensorFlow源码
最一开始是直接通过pip下载官方编译好的安装包进行安装,但因为CentOS的原因,并不能通过这种方式安装(在网上找到的CentOS安装TensorFlow大部分都是通过编译源码来安装的)。所以这也是导致这次安装如此繁琐的原因
目前TensorFlow的最新版本为1.3.0,源码可以通过git clone下来,也可以直接去releases界面下载
- git clone
git clone https://github.com/tensorflow/tensorflow
git checkout r1.3
- releases界面
8.3 配置
进入TensorFlow源码根目录后,执行
./configure
接下来会有一系列提示需要确认,其中
Do you wish to use jemalloc as the malloc implementation? [Y/n] 选择 n,因为选择y后编译不通过
Do you wish to build TensorFlow with CUDA support? [y/N] 选择 y,因为我们要使用GPU
其他的默认就可以(大写字母是默认选择)
以下是具体的配置选项
1 | ......... |
8.4 编译打包安装
接下来进行编译操作
bazel build --config=opt --config=cuda//tensorflow/tools/pip_package:build_pip_package
如果顺利的话就不会出现什么ERROR提示,整个编译过程大约十分钟。如果出现错误可以加入 --verbose_failures
参数,会提供更丰富的出错信息
编译完成后,接下来就是打包成 .whl 文件供pip安装使用,文件会放到/tmp/tensorflow_pkg目录下
bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg
安装
pip install /tmp/tensorflow_pkg/tensorflow-1.3.0-py2-none-any.whl
安装过程会自动联网下载一些依赖的包,如果无法连外网的话,那就需要自己下载所需要的包,然后上传到服务器后用pip离线安装
可以使用 官方pip源 或者 阿里pip源 来搜索安装,推荐后者,国内快
依赖的包有(可能不全):
- backports.weakref-1.0
- bleach-1.5.0
- funcsigs-1.0.2
- html5lib-0.9999999
- Markdown-2.6.9
- mock-2.0.0
- numpy-1.13.1
- pbr-3.1.1
- protobuf-3.4.0
- six-1.11.0
- tensorflow_tensorboard-0.1.6
- webencodings-0.5.1
- Werkzeug-0.12.2
- wheel-0.30.0
8.5 验证
进入python,进行 import tensorflow
,没有错误那就代表大功告成了!
8.6 一些错误
整个编译过程还是比较坎坷的
1、第一个错误
1 | ERROR: /root/gg/tensorflow/tensorflow/tensorflow/tools/pip_package/BUILD:100:1: no such package '@boringssl//': Traceback (most recent call last): |
这个错误出现的时候@boringssl和@protobuf是交替出现,no such package '@boringssl
。一开始以为是这两个包没有下载成功,因为在info信息中有连接下载链接失败的提示,并且错误信息中是说没有找到对应的包,所以去 tensorflow/workspace.bzl
中查找对应的下载链接,下载到具体的包后在服务器上做了个微型本地服务器,将workspace.bzl中的下载链接改成本地的下载链接。然而这个错误继续出现,后来经过白银指点,发现是 Cannot run program "patch"
这里的问题,遂去 yum install patch
后该错误不再出现。原来的思路一直局限在下载不成功上,没有仔细观察后面的错误信息
2、第二个错误
1 | C++ compilation of rule '@nanopb_git//: nanopb' failed: crosstool_wrapper_driver_is_not_gcc failed: error executing command |
后续内容还有一堆,其中@nanopb_git会变成其他包的名字,所以查找的重点就放在了后面 crosstool_wrapper_driver_is_not_gcc failed: error executing command
3、经过了一顿google,查阅了无数github上的issus,都没有发现类似的问题(有这部分相同的报错,但是后续错误内容不同),问题没有解决,我决定先编译TensorFlow提供的example,看看小范围编译是否存在问题
bazel build --config=opt --config=cuda //tensorflow/cc:tutorials_example_trainer
此时报错:
error: ‘MADV_NOHUGEPAGE’ undeclared
参照这个 issus 解决:
在进行configure配置时,将 Do you wish to use jemalloc as the malloc implementation? [Y/n] 选择 n
4、在对example编译成功后,又继续回来尝试编译源码,但是依旧出问题。不过,有时候命运就是捉弄人,尝到了‘踏破铁鞋无觅处,得来全不费功夫’的滋味
看到白银在看 这篇文章,突然发现在文章的前部有这样一句话:
“CentOS 6 上glibc最多到2.12,强行使用高版本的glibc会导致程序意外崩溃”
这篇文章之前看过,但是注意力从来没有留意这句话。突然想到会不会真的是glibc的问题。因为在之前的尝试过程中因为某些报错需要安装glibc2.14版本,而系统里自带的版本只到2.12,所以就去下载编译了glibc2.14版本,并且加入LD_LIBRARY_PATH中
那么在 .bashrc 中将glibc添加到LD_LIBRARY_PATH中这一行注释掉,结果竟然顺利编译成功!真是惊喜啊
感谢白银同学,最后两个关键问题都是在他的帮助下解决的~
Reference
- 官方安装指南
https://www.tensorflow.org/install/install_sources
https://docs.bazel.build/versions/master/install-compile-source.html
https://gcc.gnu.org/install/configure.html
http://docs.nvidia.com/cuda/cuda-installation-guide-linux/
- gcc安装
http://caosiyang.github.io/2016/05/04/installing-gcc/
http://www.cjjjs.com/paper/czxt/2017222114137150.html
- Python以及pip安装
http://farwmarth.com/%E5%8D%87%E7%BA%A7centos%E4%B8%8A%E7%9A%84python/
http://blog.csdn.net/tiantuanzi/article/details/50475718
http://www.itdadao.com/articles/c15a1317443p0.html
- 显卡驱动及CUDA相关(文章里关于禁用nouveau、重新建立initramfs image文件的操作在本服务器上不操作也可以正常安装显卡驱动)
http://www.gpusever.com/show.php?cid=33&id=27
http://www.centoscn.com/image-text/install/2015/0921/6199.html
- TensorFlow安装
http://www.jianshu.com/p/fdb7b54b616e
http://ju.outofmemory.cn/entry/311727
https://blog.abysm.org/2016/06/building-tensorflow-centos-6/
http://blog.csdn.net/may0324/article/details/53413024
http://www.alfrednanwu.com/machine-learning/-gtx-1080ubuntu1604cuda8cudnn51tensorflow