TensorFlow非Root权限源码编译安装

来源:互联网 发布:sql双引号转义字符 编辑:程序博客网 时间:2024/06/05 02:45

Google的分布式深度学习框架TensorFlow出来也有一段时间了。笔者在TensorFlow最初放出时就跟进,不过当时其显存管理优化不到位,最后放弃(改用mxnet了,是一个相当不错的深度学习框架)。
最近,TensorFlow 0.8.0放出,同时开放了分布式学习能力。为此,笔者重新编译安装TensroFlow,打算对其性能做一些测试。
笔者的生产环境控制比较严格,开发人员不具有root权限。另一方面,生产环境比较老了,编译器的版本不够。在这种情况下编译安装TensorFlow还是比较繁琐的。尤其是bazel,总是不能对环境变量的变化做出匹配,导致安装过程受阻。
经过一番折腾,摸索出一套编译安装方法,记录在案。

1. 环境准备

笔者的系统环境:

Linux version 2.6.32-279.el6.x86_64 (mockbuild@x86-008.build.bos.redhat.com) (gcc version 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC) )

首先搭建目录结构。

mkdir usr

使用如下的环境变量配置,注意这里包含了cuda和cudnn的路径,不过这次安装并没有编译安装gpu版本。gpu版本的安装还有一些麻烦事要做,留待下次再记录吧。

export HOME=...#home文件夹的位置export HOME_USR=$HOME/usrexport CUDA_HOME=$HOME/cudaexport CUDNN_HOME=$HOME/cudnnexport JAVA_HOME=$HOME/jdk1.8.0_65export PATH=$HOME/bazel_bin:$HOME_USR/bin:$CUDA_HOME/bin:$PATHexport CPATH=$HOME_USR/include:$CUDA_HOME/include:$CUDNN_HOMEexport C_INCLUDE_PATH=$CPATHexport CPLUS_INCLUDE_PATH=$CPATHexport LIBRARY_PATH=$HOME_USR/lib:$HOME_USR/lib64:$CUDA_HOME/lib64:$CUDA_HOME/lib64:$CUDNN_HOMEexport LD_LIBRARY_PATH=$LIBRARY_PATHexport LD_RUN_PATH=$LIBRARY_PATHexport COMPILER_PATH=$PATHexport CC=gccexport CXX=g++export PKG_CONFIG_PATH=$HOME_USR/lib/pkgconfig:$PKG_CONFIG_PATH

目前gcc的版本太低,先编译安装gcc 4.8.4。
首先准备好以下源文件包。

gmp-4.3.2.tar.bz2mpfr-2.4.2.tar.bz2mpc-0.8.1.tar.gzlibffi-3.2.1.tar.gzgcc-4.8.4.tar.bz2

上述版本不一定必须一致,但安装过程应该是大同小异。
整个安装脚本如下:

echo "gmp first"tar xvf ./gmp-4.3.2.tar.bz2cd ./gmp-4.3.2./configure --prefix=$HOME_USRmake -j 20make installmake check #### IMPORTANTcd -echo "mpfr second"tar xvf ./mpfr-2.4.2.tar.bz2cd ./mpfr-2.4.2./configure --prefix=$HOME_USRmake -j 20make installcd -echo "mpc third"tar xvf ./mpc-0.8.1.tar.gzcd ./mpc-0.8.1./configure --prefix=$HOME_USRmake -j 20make installcd -echo "libffi fourth"tar xvf ./libffi-3.2.1.tar.gzcd ./libffi-3.2.1./configure --prefix=$HOME_USRmake -j 20make installcd -echo "gcc"tar xvf ./gcc-4.8.4.tar.bz2cd ./gcc-4.8.4mkdir buildcd build../configure --prefix=$HOME_USR --mandir=$HOME_USR/share/man --infodir=$HOME_USR/share/info -enable-checking -enable-languages=c,c++,fortran -disable-multilib --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,fortran --disable-dssi --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linuxmake -j 20make install

然后是python 2.7.9,顺便把pip也安装上,方便python库的安装。准备好下面的源文件包:

Python-2.7.9.tgzpip-7.1.0.tar.gzsetuptools-18.1.tar.gzwheel-0.26.0.tar.gz

整个安装脚本如下:

echo "python"tar xvf ./Python-2.7.9.tgzcd ./Python-2.7.9/./configure --prefix=$HOME_USR --enable-sharedmake -j 20make installcd -echo "setuptools"tar xvf ./setuptools-18.1.tar.gzcd ./setuptools-18.1python setup.py buildpython setup.py installcd -echo "pip"tar xvf ./pip-7.1.0.tar.gzcd ./pip-7.1.0python setup.py buildpython setup.py installcd -echo "wheel"tar xvf ./wheel-0.26.0.tar.gzcd wheel-0.26.0python setup.py buildpython setup.py installcd -

安装一下OpenBLAS。获取OpenBLAS源码。然后:

make -j 20make PREFIX=$HOME_USR install

下面是numpy。为了方便还安装了ipython,这个不是必须的。在OpenBLAS之后再安装numpy,否则numpy就无法利用OpenBLAS的加速能力。

pip install numpypip install ipython

可以选择安装一个VirtualEnv。直接用pip就行了。这里就不安装了。
Bazel还需要一个jdk 1.8.0,直接去官网下载即可。注意到上面已经再环境变量中设置了JAVA_HOME的路径。

2.Bazel

没有root权限要编译安装bazel,有一些麻烦。笔者使用了下面这种比较hack的方法。不知道有没有更好的方法可以解决此问题。
首先要做如下准备:

mkdir $HOME/bazel_bin

注意到之前已经把bazel_bin写入环境变量了。在上述文件夹中添加以下几个文件。

cpp_bazelgcc_bazelgcov_bazelpython_bazel

其内容分别如下。

# cpp_bazelexport HOME=...#home文件夹的位置 ;export HOME_USR=$HOME/usr ;export CUDA_HOME=$HOME/cuda ;export CUDNN_HOME=$HOME/cudnn ;export JAVA_HOME=$HOME/jdk1.8.0_65 ;export PATH=$HOME/bazel_bin:$HOME_USR/bin:$CUDA_HOME/bin:$PATH ;export CPATH=$HOME_USR/include:$CUDA_HOME/include:$CUDNN_HOME ;export C_INCLUDE_PATH=$CPATH ;export CPLUS_INCLUDE_PATH=$CPATH ;export LIBRARY_PATH=$HOME_USR/lib:$HOME_USR/lib64:$CUDA_HOME/lib64:$CUDA_HOME/lib64:$CUDNN_HOME ;export LD_LIBRARY_PATH=$LIBRARY_PATH ;export LD_RUN_PATH=$LIBRARY_PATH ;export COMPILER_PATH=$PATH ;export CC=gcc ;export CXX=g++ ;export PKG_CONFIG_PATH=$HOME_USR/lib/pkgconfig:$PKG_CONFIG_PATH ;$HOME_USR/bin/cpp $@
# gcc_bazelexport HOME=...#home文件夹的位置 ;export HOME_USR=$HOME/usr ;export CUDA_HOME=$HOME/cuda ;export CUDNN_HOME=$HOME/cudnn ;export JAVA_HOME=$HOME/jdk1.8.0_65 ;export PATH=$HOME/bazel_bin:$HOME_USR/bin:$CUDA_HOME/bin:$PATH ;export CPATH=$HOME_USR/include:$CUDA_HOME/include:$CUDNN_HOME ;export C_INCLUDE_PATH=$CPATH ;export CPLUS_INCLUDE_PATH=$CPATH ;export LIBRARY_PATH=$HOME_USR/lib:$HOME_USR/lib64:$CUDA_HOME/lib64:$CUDA_HOME/lib64:$CUDNN_HOME ;export LD_LIBRARY_PATH=$LIBRARY_PATH ;export LD_RUN_PATH=$LIBRARY_PATH ;export COMPILER_PATH=$PATH ;export CC=gcc ;export CXX=g++ ;export PKG_CONFIG_PATH=$HOME_USR/lib/pkgconfig:$PKG_CONFIG_PATH ;$HOME_USR/bin/gcc $@
# gcov_bazelexport HOME=...#home文件夹的位置 ;export HOME_USR=$HOME/usr ;export CUDA_HOME=$HOME/cuda ;export CUDNN_HOME=$HOME/cudnn ;export JAVA_HOME=$HOME/jdk1.8.0_65 ;export PATH=$HOME/bazel_bin:$HOME_USR/bin:$CUDA_HOME/bin:$PATH ;export CPATH=$HOME_USR/include:$CUDA_HOME/include:$CUDNN_HOME ;export C_INCLUDE_PATH=$CPATH ;export CPLUS_INCLUDE_PATH=$CPATH ;export LIBRARY_PATH=$HOME_USR/lib:$HOME_USR/lib64:$CUDA_HOME/lib64:$CUDA_HOME/lib64:$CUDNN_HOME ;export LD_LIBRARY_PATH=$LIBRARY_PATH ;export LD_RUN_PATH=$LIBRARY_PATH ;export COMPILER_PATH=$PATH ;export CC=gcc ;export CXX=g++ ;export PKG_CONFIG_PATH=$HOME_USR/lib/pkgconfig:$PKG_CONFIG_PATH ;$HOME_USR/bin/gcov $@
# python_bazelexport HOME=...#home文件夹的位置 ;export HOME=/data/rd/tensor_flow_portable ;export HOME_USR=$HOME/usr ;export CUDA_HOME=$HOME/cuda ;export CUDNN_HOME=$HOME/cudnn ;export JAVA_HOME=$HOME/jdk1.8.0_65 ;export PATH=$HOME/bazel_bin:$HOME_USR/bin:$CUDA_HOME/bin:$PATH ;export CPATH=$HOME_USR/include:$CUDA_HOME/include:$CUDNN_HOME ;export C_INCLUDE_PATH=$CPATH ;export CPLUS_INCLUDE_PATH=$CPATH ;export LIBRARY_PATH=$HOME_USR/lib:$HOME_USR/lib64:$CUDA_HOME/lib64:$CUDA_HOME/lib64:$CUDNN_HOME ;export LD_LIBRARY_PATH=$LIBRARY_PATH ;export LD_RUN_PATH=$LIBRARY_PATH ;export COMPILER_PATH=$PATH ;export CC=gcc ;export CXX=g++ ;export PKG_CONFIG_PATH=$HOME_USR/lib/pkgconfig:$PKG_CONFIG_PATH ;$HOME_USR/bin/python2 $@

以上是第一个比较hack的地方。目前还没有找到更好的解决办法。
获取Bazel的源码。这里建议获取github上的release包而不是直接clone代码。

bazel_0.2.1.tar.gz

解压后需要更改CROSSBUILD,这里承接上面的hack工作。
修改下面的文件:

bazel-0.2.1/tools/cpp/CROSSTOOL

寻找以下代码块:

toolchain {  abi_version: "local"  ...  toolchain_identifier: "local_linux"  ...  }

以下用[HOME]代表$HOME路径,注意这里需要用绝对路径。

tool_path { name: "cpp" path: "/usr/bin/cpp" }

改为

tool_path { name: "cpp" path: "[HOME]/bazel_bin/cpp_bazel" }

tool_path { name: "gcc" path: "/usr/bin/gcc" }

改为

tool_path { name: "gcc" path: "[HOME]/bazel_bin/gcc_bazel" }

linker_flag: "-B/usr/bin/"

下面增加两行:

linker_flag: "-B[HOME]/usr/bin/"linker_flag: "-B[HOME]/bazel_bin/"

再往下把

cxx_builtin_include_directory: "/usr/lib/gcc/"

替换为

cxx_builtin_include_directory: "[HOME]/usr/lib/gcc/"cxx_builtin_include_directory: "[HOME]/usr/include"

最后把

tool_path { name: "gcov" path: "/usr/bin/gcov" }

替换为

tool_path { name: "gcov" path: "[HOME]/bazel_bin/gcov_bazel" }

如此修改完成后,开始编译

cd bazel-0.2.1./compile.sh

如果编译失败,最好每次都把/tmp/bazel.****删除再重新编译。
最后,建立一个软链接方便bazel的使用:

ln -s 源码所在目录绝对路径/bazel-0.2.1/output/bazel ~/bazel_bin/bazel

使用

bazel version

检查是否安装成功。

3. TensorFlow CPU

有了上面关于Bazel的hack之后,TensorFlow CPU的编译相对简单。不过TensorFlow GPU的编译还需要其他的hack,这个之后再记录。
建议去github上直接获取最新的源码:

git clone --recursive https://github.com/tensorflow/tensorflow.git

接下来需要改变文件

tensorflow/tensorflow.bzl

找到函数

tf_extension_linkopts

return []

改为

return ["-lrt"]

下面可以基本上按照官网的指示编译安装了。

./configure

注意,这里不能选择支持GPU。更改了默认的环境变量,要编译安装GPU支持的TensorFlow,还需要更多的hack。

bazel build -c opt //tensorflow/tools/pip_package:build_pip_packagebazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkgpip install /tmp/tensorflow_pkg/tensorflow-0.8.0-py2-none-any.whl

可以用运行一个mnist训练测试TensorFlow是否安装成功

cd tensorflow/models/image/mnistpython convolutional.py
1 0