使用bazel从源代码编译tensorflow踩坑记录

文章目录

0.写在前面的话

0.1配置信息

基本配置 版本
CPU Intel® Xeon® CPU E5645 @2.40GHz
GPU GeForce GTX 650 Ti (compute capability 3.0)
操作系统 Ubuntu18.04
openjdk 11.0.3
python 3.6.8
bazel 0.25.2

0.2废话和吐槽

实验室的电脑,由于CPU型号比较老,不支持AVX指令集,所以用tensorflow官方发布的包只能支持到tensorflow1.5。
同时,GPU型号也比较老,compute capacity只有3.0,所以跑网络的时候官方的包也不支持,只能用CPU硬跑。
最后,由于最近需要用tensorflow lite,而tensorflow1.7以下版本的Lite有bug,所以只能考虑从源代码编译一下,顺带给个优化。

1.理想流程

1.1安装bazel

1.1.1安装java的JDK

JDK我之前就安装过了,此处略去。可以参考[2]中的步骤安装。

1.1.2安装bazel包

安装时提示bazel版本不能高于0.25.2,所以安装了bazel0.25.2。
首先下载bazel安装包。网上教程下载.sh文件比较多,我比较懒,直接下载了deb包。用.sh文件法可以参考[1]下载完成后进入文件所在目录(我一般放在~/Downloads

cd ~/Downloads

然后用dpkg安装bazel包

sudo dpkg -i bazel_0.25.2-linux-x86_64.deb

一般这个时候会报错,显示依赖没有安装,所以用apt修复依赖

sudo apt-get -f install

然后继续安装

sudo dpkg -i bazel_0.25.2-linux-x86_64.deb

安装完毕,查看一下有没有安装好

bazel --version

1.2下载tensorflow源代码并选择版本

1.2.1下载安装git

sudo apt-get install git

有条件的可以配置ssh,反正迟早都需要一个github账号的。

1.2.2下载源代码

千万不要用网页上的Download Zip下载的那个zip包,那个没法选择安装的版本。
进入目录,输入

sudo git clone https://github.com/tensorflow/tensorflow

会在当前路径下新建一个名为tensorflow的文件夹,里面是源代码文件。
要是有ssh,可以用

sudo git clone github@github.com:tensorflow/tensorflow.git

1.2.3选择版本

选择想要编译的版本,例如tensorflow1.14

sudo git checkout r1.14

可能是bazel版本的问题,我选择1.12版本的时候,编译有我无法排除的报错,其他版本没尝试,欢迎有知道原因的大佬补充。

1.3用bazel编译源代码并生成.whl文件

1.3.1配置编译文件

先进入下载的源文件的文件夹

cd ~/Downloads/tensorflow

配置编译文件

sudo ./configure

里面有很多选项需要配置,我不太懂,一般都是默认。

1.3.2开始编译

这一步有很多坑,详见踩坑记录。理想中的过程如下:

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

等待一段时间(可能几十分钟,甚至几个小时)后编译完毕。在“bazel-bin”文件夹下,有我们需要的打包工具build_pip_package。

1.3.3生成.whl文件

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

打包完成后生成的文件在~/tensorflow_pkg文件夹下。

1.3.4用pip安装编译完成的tensorflow

先进入.whl文件所在的文件夹

cd ~/tensorflow_pkg

之后用pip安装

sudo pip3 install 

2.踩坑记录

2.1编译过程中文件无法下载

Tensorflow依赖的包很多,所以编译的时候还要下载一些依赖包。在源代码里面已经给出了依赖包的下载地址,bazel会自动下载。
但是有时候网络不好,或者部分资源下载速度慢(甚至无法下载),这时候只能自己想办法下载到本地,再安装。这类报错的特点是xxx failed downloading,或者带有下载地址。解决办法如下:

2.1.1找到记录下载地址的源文件

源文件地址一般可以在报错中找到,打开源文件(当前在tensorflow目录下),例如aws模块在:

sudo gedit ./third_party/aws/workspace.bzl 

grpc模块在:

sudo gedit ./tensorflow/workspace.bzl

以grpc模块为例,打开文件找到如下代码

tf_http_archive(
        name = "grpc",
        sha256 = "67a6c26db56f345f7cee846e681db2c23f919eba46dd639b09462d1b6203d28c",
        strip_prefix = "grpc-4566c2a29ebec0835643b972eb99f4306c4234a3",
        system_build_file = clean_dep("//third_party/systemlibs:grpc.BUILD"),
        urls = [
            "http://mirror.tensorflow.org/github.com/grpc/grpc/archive/4566c2a29ebec0835643b972eb99f4306c4234a3.tar.gz",
            "https://github.com/grpc/grpc/archive/4566c2a29ebec0835643b972eb99f4306c4234a3.tar.gz",
        ],
    )

urls = []里面就是下载地址,手动想办法下载下来。

2.1.2搭建本地服务器

因为就是临时使用一下,所以装个小服务器就行:

sudo apt-get install nginx-light
sudo service nginx start

之后打开浏览器输入http://127.0.0.1看到Welcome to nginx!之类的内容就说明安装成功了。

2.1.3在源文件中添加路径

把手动下载下来的文件放到/var/www/html/路径下。假设手动下载的文件是ABCD.tar.gz:

cp ABCD.tar.gz /var/www/html/

并在步骤2.1.1中打开的文件中添加新的url:

tf_http_archive(
        name = "grpc",
        sha256 = "67a6c26db56f345f7cee846e681db2c23f919eba46dd639b09462d1b6203d28c",
        strip_prefix = "grpc-4566c2a29ebec0835643b972eb99f4306c4234a3",
        system_build_file = clean_dep("//third_party/systemlibs:grpc.BUILD"),
        urls = [
			"http://127.0.0.1/ABCD.tar.gz",
            "http://mirror.tensorflow.org/github.com/grpc/grpc/archive/4566c2a29ebec0835643b972eb99f4306c4234a3.tar.gz",
            "https://github.com/grpc/grpc/archive/4566c2a29ebec0835643b972eb99f4306c4234a3.tar.gz",
        ],
    )

每个模块的文件都需要单独更改url。

更改完毕后直接编译就可以不用联网下载了。

2.2编译过程中内存不足

Tensorflow源代码编译过程中占用内存很严重,编译过程中出错很多都是因为内存被用光了。我的电脑有12个核心,8G内存下编译崩溃error了好几次。之后尝试过

bazel build --config=opt --local_resources=4096,6,10 --verbose_failures //tensorflow/tools/pip_package:build_pip_package

其中--local_resources=4096,6,10是限制占用内存最多为4096 M,最多占用6个CPU,最多10个IO线程。-verbose_failures用于打印报错信息。但是占用内存依旧很多,仍然会报错。
由于不是使用虚拟机,所以之后一直用的下面的代码编译,限制了jobs的数量。

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

最后真正解决问题的方法是扩大了swap分区的大小。系统默认是2.0 GB的swap,一般采用1~1.5倍的内存大小作为swap大小,我的内存8 GB,在这里我稍微再扩大一点,采用16 GB的swap。设置方法如下:
首先查看系统本身的swap,此处是16 GB,是我设置之后的,对应的文件是/swapfile

$ swapon -s
Filename		Type		Size		Used		Priority
/swapfile      	file    	16777212	3612052		-2

以下参考[3]设置:

# 如果第一步存在swapfile则需要先禁用
sudo swapoff /swapfile
# 修改swap 空间的大小为2G
sudo dd if=/dev/zero of=/swapfile bs=1G count=16
# 设置文件为“swap file”类型
sudo mkswap /swapfile
# 启用swapfile
sudo swapon /swapfile

2.3ModuleNotFoundError

配置bazel编译选项的时候没细看,python路径选错了,应该手动输入

# python 路径
/usr/bin/python3.6
# python 模块路径
/usr/local/lib/python3.6/dist-packages

而不是用默认的

/usr/lib/python3/dist-packages

参考

[1] TensorFlow学习系列之七:TensorFlow的源码编译
[2] Ubuntu18.04下jdk安装与配置
[3] Ubuntu 18.04 swap空间的修改

上一篇:Android关于RecycleView中的Adapter详解


下一篇:java – 在不同的机器上运行bazel远程执行程序测试