TensorFlow学习系列之七:TensorFlow的源码编译

原文:https://blog.csdn.net/yhily2008/article/details/79967118

为了编译TensorFlow的源代码,除了要有gcc(版本不低于4.8)支持之外,还需要安装Google自产的编译工具Bazel。

1.安装Bazel

安装Bazel,需要Java JDK 8或更高版本的支持,所以接下来我们要的第一件工作,就是要确定Java 8/9是否已经安装(可用“java -version”来查询)。如果没有安装,则可以通过如下流程安装。 

(1)利用Ubuntu的PPA(Personal Package Archives个人软件包仓库(PPA),)安装Java 8。

sudo add-apt-repository ppa:webupd8team/java                #添加PPA

sudo apt-get update && sudo apt-get install oracle-java8-installer  #安装Java8
【error fixed】E: Package 'oracle-java8-installer' has no installation candidate:

sudo add-apt-repository ppa:ts.sch.gr/ppa
sudo apt-get update
sudo apt-get install oracle-java8-installer
 

在安装过程中,需要选择同意Oracle公司的许可协议(用TAB键选择<YES>,并按回车确认)。待上述流程安装完毕后,输入如下命令检查Java 8是否成功安装。 

yhilly@ubuntu:~$ java -version
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)

从提示信息中,可以看出Java 8已成功安装。需要注意的是,虽然Java 9已经面世,但和Java 9相关的软件生态还没有形成,盲目“追新”会让很多软件运行不了。比如说,Bazel暂时还没有“与时俱进”发布与jdk 1.9相匹配的版本,所以,我们选择让“Java 9飞一会儿”,暂时还使用稳定版本jdk 1.8。

(2)将Bazel发布版的URI设置为软件包源

输入如下两条指令可设置软件源: 

echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list
curl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -

(3)安装并更新Bazel

使用下面的指令更新并安装Bazel(下面的指令实际上是两条,用“&&”连接一下,可让多条命令同处一行)。

sudo apt-get update && sudo apt-get install bazel

在命令行输入“bazel version”,如果有正常的反馈信息输出,则表明Bazel安装完毕。 

Extracting Bazel installation...
Build label: 0.9.0
Build target: bazel-out/k8-fastbuild/bin/src/main/java/com/google/devtools/build/lib/bazel/BazelServer_deploy.jar
Build time: Tue Dec 19 09:31:58 2017 (1513675918)
Build timestamp: 1513675918
Build timestamp as int: 1513675918

2 .下载TensorFlow的源码

在编译工具准备好之后,下面我们要做的工作就是下载TensorFlow的源代码。为了获取在GitHub上的TensorFlow源码,比较方便的方式就是使用git工具(一款免费开源的分布式版本控制系统),Ubuntu中并没有预装这个工具,需要我们利用下面的命令安装: 

sudo apt install git

在输入root密码后,apt就会自动安装git工具。这里稍微说明一点的是,对于较新版本的Ubuntu而言,通常可使用简化版的“apt”命令来代替“apt-get”,事实上,为了兼容性,老版本指令的“apt-get”在新版本Ubuntu中依然有效,不过是新命令更加简单好记罢了。 

接下来,我们利用git命令把远程的TensorFlow代码“克隆”(复制)到本地,如图11-15所示。

图11-15 远程克隆TensorFlow源代码

然后进入家目录下的TensorFlow下载路径。

cd  ~/tensorflow

然后可利用“ls”命令查看一下TensorFlow的相关文件,如图11-16所示

图11-16 TensorFlow的源码文件夹

接下来,我们进入tensorflow源码文件夹,利用“git  checkout”(检出)TensorFlow版本1.6。

yhilly@ubuntu:~/tensorflow$ git  checkout  r1.6
Branch r1.6 set up to track remote branch r1.6 from origin.
Switched to a new branch 'r1.6'

3 配置编译文件

在用Bazel编译源代码之前,我们还需要在TensorFlow源代码路径下,运行configure文件,做一些必要的配置:

./configure

接下来,配置系统会给出各种询问,以确认编译时的配置参数,下面挑选比较重要的几个参数解释如下:

yhilly@ubuntu:~/tensorflow$ ./configure 
You have bazel 0.9.0 installed.
Please specify the location of python. [Default is /home/yhilly/anaconda3/envs/tensorflow/bin/python]:

上面的提示是Bazel让我们选择Python的安装路径,只要确保是Anaconda的Python路径即可,直接按一系列的回车键(Enter)表示使用默认值。 

Do you wish to build TensorFlow with jemalloc as malloc support? [Y/n]: 
jemalloc as malloc support will be enabled for TensorFlow.

上面的选项表示是否使用jemalloc代替传统的malloc来管理内存?Jemalloc是杰森·埃文斯(Jason Evans)于2006年开发的用以取代传统低性能的malloc内存管理模块而开发的一款内存管理模块[4]。埃文斯并非等闲之辈,他是FreeBSD项目(一种类UNIX操作系统)的重要维护者之一。 
Jemalloc先被Firefox浏览器采用,后来又被Facebook在其自己的各类应用上广泛使用,一战成名。好技术当然要用!直接按回车,确认默认值Y(默认值通常就是被大写的选项)。 

Do you wish to build TensorFlow with Google Cloud Platform support? [Y/n]: n
No Google Cloud Platform support will be enabled for TensorFlow.

这个选项是询问是否采用Google云平台来支持TensorFlow。这个云平台国内通常无法访问,建议输入“n”。有条件的读者,可直接按回车确认使用。 

Do you wish to build TensorFlow with Hadoop File System support? [Y/n]: n
No Hadoop File System support will be enabled for TensorFlow.

这个选项是询问是否使用Hadoop 文件系统(HDFS)来支持TensorFlow。如果搭建了Hadoop集群,有读取HDFS数据需求的用户,可以回车确认。如果没有需求,手动输入“n”。 

Do you wish to build TensorFlow with Amazon S3 File System support? [Y/n]: n
No Amazon S3 File System support will be enabled for TensorFlow.

类似的,这个选项是询问TensorFlow是否支持亚马逊的S3文件系统。读者根据自己的需要来确定“Y”或“n”。如果用不着,建议选择“n”。 

Do you wish to build TensorFlow with Apache Kafka Platform support? [y/N]: 
No Apache Kafka Platform support will be enabled for TensorFlow.

Kafka是由Apache软件基金会开发的一个开源流处理平台,是一种高吞吐量的分布式发布订阅消息系统。如果没有这个需要,建议选择默认值“N”。 

Do you wish to build TensorFlow with XLA JIT support? [y/N]: n
No XLA JIT support will be enabled for TensorFlow.

这个选项是询问是否开启XLA JIT编译支持。XLA(Accelerated Linear Algebra/加速线性代数)目前还是TensorFlow的实验项目,XLA 使用 JIT(Just in Time,即时编译)技术来分析用户在运行时(runtime)创建的 TensorFlow 图,专门用于实际运行时的维度和类型。作为新技术,这项编译技术还不成熟,爱折腾的“极客”读者可以选“y”,否则选择默认值“N”。 

Do you wish to build TensorFlow with CUDA support? [y/N]: 
No CUDA support will be enabled for TensorFlow.

这个选项是询问是否使用CUDA。CUDA是一种由NVIDIA推出的通用并行计算架构,该架构使GPU能够解决复杂的计算问题。如果用户配备有NVIDIA的GPU,可以选择“y”,如果仅使用TensorFlow的CPU版本,回车确认“N”。 

Do you wish to build TensorFlow with MPI support? [y/N]: 
No MPI support will be enabled for TensorFlow.

这个选项是询问是否使用MPI。MPI(Message-Passing-Interface 消息传递接口)是实现进程级别的并行程序的通信协议,它通过在进程之间进行消息传递。如果不是基于TensorFlow做并行程序开发,建议回车确认选择默认值“N”。 

Please specify optimization flags to use during compilation when bazel option "--config=opt" is specified [Default is -march=native]: 

这个选项是指定CPU编译优化选项。默认值就是“-march=native”。这里“m”表示“machine(机器)”,“arch”就是“architecture”简写。“march”合在一起表示机器的结构,如果选择“-march=native”,则表示选择本地(native)CPU,如果本地CPU比较高级,就可以支持SSE4.2、AVX等选项。这里建议选择默认值。 

Would you like to interactively configure ./WORKSPACE for Android builds? [y/N]:

这个选项是问是否进入Android的工作空间配置,如果不用手机版的TensorFlow开发,则选择默认值“N”。 

之后,当显示“Configuration finished”(配置完成)字样,则表示配置顺利完成。

4 编译源文件

在配置完毕Bazel的编译选项之后,接下来就可以使用如下指令编译TensorFlow的源代码: 

bazel build --config=opt //tensorflow/tools/pip_package:build_pip_package

如果想获得GPU支持,则需要加入编译选项“--config=cuda”。上述指令将在“/tensorflow/tools/pip_package”路径下,构建一个pip包文件。 
倘若上述命令导致编译失败,一个可能的失败原因是,Bazel作为并行编译器,会耗费非常多的系统资源,特别是对利用虚拟机安装Ubuntu的用户,一旦系统资源耗尽,编译自然难成。 

下面的编译指令是对线程数、内存等资源做了限制,且一旦编译失败,让Bazel给出详细的错误信息。

bazel build -c opt --jobs 1 --local_resources 2048,0.5,1.0 --verbose_failures //tensorflow/tools/pip_package:build_pip_package

不过,一旦对编译资源做了限制,编译速度将会非常缓慢,可能耗时若干小时!当显示“INFO: Build completed successfully, 2173 total actions”字样时,表示编译成功。之后,在TensorFlow文件夹下,多了若干个与Bazel相关的文件夹。到此,工作还没有完毕,我们还需要构造一个Python的安装包(pip)。 

图11-17  编译成功后的TensorFlow文件夹

在“bazel-bin”文件夹下,有我们需要的打包工具build_pip_package。假设我们把这个打包的位置定位为当前路径(TensorFlow的源文件)的“/temp”文件夹下,则使用如下指令: 

bazel-bin/tensorflow/tools/pip_package/build_pip_package  ~/tensorflow_pkg

当然,上述指令后面的打包生成路径(“~/tensorflow_pkg”,这里的“~”表示笔者的家目录“/home/yhilly/”),实际上是可以任意指定的。比如说,如果是直接放到系统根目录下的临时文件夹(/tmp/tensorflow_pkg)。当然,如果放在根目录下,则需要加sudo权限,否则可能会因为权限不足而导致创建文件夹失败。 

在打包完毕后,下面我们可以在打包生成路径(如“~/tensorflow_pkg”),查看到我们的劳动成果(用“ls”命令查看),其中“tensorflow-1.6.0rc1-cp36-cp36m -linux_x86_64.whl”就是我们折腾半天的回报。它就是支持本地CPU优化适配的Python 3.6编译版本。

5 .测试编译结果

在编译完毕之后,我们还得安装上述“轮文件”(wheel file,以.whl为扩展名)。这里稍微简单介绍一下这个所谓的“轮文件”。“轮文件”是Python用以取代“蛋文件(egg file)”的一类新式安装包,支持pip 1.4或setuptools 0.8以上版本。 

之所以Python不再扯“蛋”,自然是因为“轮文件”能带来更多便利。最直观的便利是,对于纯Python文件或C扩展文件(比如Objective-C)的编译“作品”,它的安装速度更快。它还能创建一个“.pyc”的文件,集成到安装文件中,用以确保与Python解释器更加匹配,并能在跨平台、跨机器的安装中保证软件的一致性。“wheel”本身还有“方向盘”的含义,或许之所以取这样的名字,可能因为它的存在,能给用户更大的“掌控感”吧。

图11-18 Python的“盘文件”示意图

下面我们要做的工作就是,利用pip来安装我们亲手编译的TensorFlow二进制文件:
 
pip  install  ~/tensorflow_pkg/tensorflow-1.6.0-cp36-cp36m-linux_x86_64.whl 
当出现下面的字样,则表明安装成功。
Installing collected packages: tensorflow
Successfully installed tensorflow-1.6.0
一旦TensorFlow安装成功之后,接下来我们要做的就是,重新进入Python的交互式环境,测试运行一下前文提到的“Hello World”版本的TensorFlow程序,看有没有警告信息。这里需要介绍一下一个经验之谈,不要在TensorFlow的源文件目录下进入Python,否则,Python可能会因为误以为当前目录中的Tensorflow就是要导入的模块,从而导致装载失败。换一个目录进入Python,就可以解决此类问题。
  1.  
    yhilly@ubuntu:~$ python
  2.  
    ython 3.6.2 |Continuum Analytics, Inc.| (default, Jul 20 2017, 13:51:32)
  3.  
    [GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux
  4.  
    Type "help", "copyright", "credits" or "license" for more information.
  5.  
    >>> import tensorflow as tf
  6.  
    >>> hello = tf.constant("Hello, TensorFlow!")
  7.  
    >>> sess = tf.Session()
  8.  
    >>> print(sess.run(hello))
  9.  
    b'Hello World, TensorFlow!'
我们还可以通过下面的指令查询TensorFlow的安装版本和路径:
 
  1.  
    >>> tf.__version__ #单词version左右各两个下划线,下同。
  2.  
    '1.6.0'

6.卸载TensorFlow

如果我们不想再使用TensorFlow,或者想更新一个新的运行环境,可以利用pip3(或pip)命令卸载掉之前的TensorFlow,具体指令如下所示: 

pip3  uninstall  tensorflow        #卸载TensorFlow

至此,我们把TensorFlow的“生(安装)”和“死(卸载)”都介绍了一遍。之所以还大费周章地把TensorFlow源代码的编译流程讲解一遍,其实就是想借助这个案例,把Linux生态下的源码下载(使用git指令)、Bazel编译与打包、Python的安装与卸载,都顺便讲解了一番,这些流程在其他环境下也可能用到,所以还是值得折腾的。

节选自 张玉宏《深度学习之美》部分章节,电子工业出版社,博文视点,2018年

To be continued~~~

作者:柒月
Q群 :2122210(嵌入式/机器学习)
原文地址:https://www.cnblogs.com/Ph-one/p/13859271.html