在实际项目部署过程中,会需要tensorflow c或者c++版本, 网上一通查,说自己编译会各种坑,投机取巧。。在拿到别人编译好的c和c++版本调用报错后,开始痛定思痛,躲不过的坑 自己来趟好了。。
先说下电脑环境:
-
linux18.04
-
cuda 10.0
-
cudnn 7.6.5
-
make 4.1
-
protobuf 3.7
############环境安装#############
怕tensorflow版本高 容易出错,保守选择 tensroflow 1.13.1版本, 并选择bazel的版本为0.19.2 为啥选择这个版本 是因为之前看过一个博客是这样对应的 ,
link
1 安装bazel
1.安装bazel需要的安装包:pkg-config,zip,g++,zlib1g-dev, unzip,python
$ sudo apt install unzip
$ sudo apt install make
$ sudo apt install g++
$ sudo apt install gcc
$ sudo apt install cmake
sudo apt-get install autoconf
sudo apt-get install automake
sudo apt-get install libtool
sudo apt install curl(used to download gmock)
sudo apt-get install zlib1g-dev
sudo apt-get install liblzma-dev
sudo apt-get install pkg-config zip g++ zlib1g-dev unzip python
如果安装不成功
2. git 上下载指定版本的bazel:可以在 bazel发布页上找对应版本
https://github.com/bazelbuild/bazel/releases
下面链接是我所对应的0.19.2的版本:
Release 0.19.2 · bazelbuild/bazel
3.运行安装程序
切换到bazel下载到的文件中,如果担心权限不够 可以先运行
chmod +x bazel-<version>-installer-linux-x86_64.sh
再运行:
./bazel-<version>-installer-linux-x86_64.sh --user
该--user
标志将Bazel
安装到$HOME/bin
系统上的目录并设置.bazelrc
路径$HOME/.bazelrc
。
2 安装protobuf
因为之前安装过protocbuf 3.7版本 现在重新安装3.6.1.2版本,存在两个版本共存问题,需要软连接:
- 下载protobuf 3.6.1.2版本:https://link.zhihu.com/?target=https%3A//codeload.github.com/protocolbuffers/protobuf/tar.gz/v3.6.1.2
- 解压并移动到相应文件夹中:
tar -zxvf protobuf-3。6.1.2.tar.gz
sudo cp -rf protobuf-3.6.1.2 /usr/local
cd /usr/local
sudo chmod -R 0777 protobuf-3.6.1.2 # 更改文件夹权限
- 安装protobuf-3.61.2:
$cd protobuf-3.6.1.2
$ ./autogen.sh
$ ./configure --prefix=/usr/protobuf # 为了与之前安装的protobuf版本分开来,设定配置目录
$ make
$ make check
$ sudo make install
- 创建软链接:
sudo ln -s /usr/protobuf/bin/protoc /usr/local/bin/protoc3.6
- 查看版本并验证安装是否成功:
protoc3.6 --version
- 查看系统默认protobuf
which protoc
- 将protocbuf3.6.1.2作为系统默认版本
vim ~/.profile 加入 export LD_LIBRARY_PATH=/usr/local/lib
- 激活profile
source ~/.profile
替换默认的probuf,,根据which protoc找到默认protoc版本地址,先删除掉该地址,再替换,我的默认地址在/usr/bin/protoc,新安装的protoc地址在 /usr/local/bin/protoc3.6,软连接替代掉:(!!!一定要替换掉,找到对应的protobuf版本,不然后期tensorflow即使编译出来了,调用会出现很多未知错误。)
rm /usr/bin/protoc
ln -s /usr/local/bin/protoc3.6 /usr/bin/protoc
至此,环境安装完毕。
3.安装tensorflow
重中之重的来liao…
- 下载tensorflow 我下载的是1.13.1版本 可以去官网上找各种其他版本:
https://link.zhihu.com/?target=https%3A//codeload.github.com/tensorflow/tensorflow/tar.gz/v1.13.1
下载完成后,解压:
tar -zxvf tensorflow-1.13.1.tar.gz
- 进入config配置
解压后进入tensorflow-1.13.1文件夹中:
开始配置:
./configure
开始出现一系列选项:
个人认为,如果要调用cuda时,最主要的是要知道自己的cuda和cudnn版本号:
cuda版本号查询:nvcc -V
cudnn版本号查询:cat /usr/local/cuda/include/cudnn.h | grep CUDNN_MAJOR -A 2
我的版本号是7.6.5
在配置时,如果需要用cuda,需要填上:
配置完就可以编译了。
3. bazel build编译:
不调用cuda:
bazel build --config=opt //tensorflow:libtensorflow_cc.so
调用cuda:
bazel build --config=opt --config=cuda //tensorflow:libtensorflow_cc.so
然后一直编译过程。。。要等30分钟。。。。。。最后出现:
过程中 踩坑无数, 下面开始踩坑之路:
【error】:
ERROR: …/tensorflow-1.13.1/tensorflow/core/kernels/BUILD:4680:1: no such package '@icu//xception: Error downloading [https://mirror.bazel.build/github.com/unicode-org/icu/archive/release-62-1.//github.com/unicode-org/icu/archive/release-62-1.tar.gz] to …/.cache/bazel/_bazel_zhang56dc5e19b594a565bd2f1d372/external/icu/release-62-1.tar.gz: Tried to reconnect at offset 9,642,752 but support it and referenced by ‘//tensorflow/core/kernels:string_util’
ERROR: Analysis of target ‘//tensorflow:libtensorflow_cc.so’ failed; build aborted: no such package '@icIOException: Error downloading [https://mirror.bazel.build/github.com/unicode-org/icu/archive/release-62ps://github.com/unicode-org/icu/archive/release-62-1.tar.gz] to …/.cache/bazel/_bazel_zh82456dc5e19b594a565bd2f1d372/external/icu/release-62-1.tar.gz: Tried to reconnect at offset 9,642,752 but support it
【分析】
icu_release-62-1.tar.gz下载不下来,所以可以自己手动下载下来,然后通过服务传上去,所以需要几步操作:1/搭建本地http服务;2/手动下载 icu_release-62-1.tar.gz;3/将下载tar.gz放到本地服务中。
搭建本地http服务有以下几步:
在linux终端输入:
sudo apt-get install httpd
再安装apache2:sudo apt-get install apache2
再安装apache2-dev sudo apt-get install apache2-dev
安装完成后 查看是否安装成功:sudo systemctl status apache2
后面在浏览器中粘贴localhost看是否有apache的界面出现 出现则安装成功;同时在根目录下可以看到/var/www/html文件夹,这个文件夹后面要用到。
2. 手动下载 icu_release-62-1.tar.gz:
https://link.zhihu.com/?target=https%3A//codeload.github.com/unicode-org/icu/tar.gz/release-62-1
(注:虽然直接从浏览器下载容易很多,但是也会经常断,这里推荐一个炒鸡好用的github加速网站,不用注册,GitHub 加速下载 - 在线工具)
3. 第三步将手动下载的文件上传至本地服务:
将icu_release-62-1.tar.gz 文件名改成release-62-1.tar.gz, 并将改后的文件放到/var/www/html文件夹下;
修改tensorflow/third_party/icu/workspace.bzl文件,在url=[…]中添加一条
"http://localhost/release-62-1.tar.gz"
清理 再重新编译:
bazel clean
bazel build --config=opt --config=cuda //tensorflow:libtensorflow_cc.so
【error】
ERROR: …/tensorflow-1.13.1/tensorflow/core/kernels/BUILD:4680:1: no such package ‘@icu//’: java.io.IOException: Error downloading [http://localhost/release-62-1.tar.gz, https 😕/mirror.bazel.build/github.com/unicode-org/icu/archive/release-62-1.tar.gz, https://github.com/unicode-org/icu/archive/release-62-1.tar.gz] to /home/zhangqinwei/.cache/bazel/bazel/81b182456dc5e19b594a565bd2f1d372/external/icu/release-62-1.tar.gz: Checksum was 86b85fbf1b 251d7a658de86ce5a0c8f34151027cc60b01e1b76f167379acf181 but wanted e15ffd84606323cbad5515bf9ecdf8061cc3bf80fb883b9e6aa162e485aa9761 and referenced by ‘//tensorflow/core/kernels:string_util’
ERROR: Analysis of target ‘//tensorflow:libtensorflow_cc.so’ failed; build aborted: no such package ‘@icu//’: java.io.IOException: Error downloading [http://localhost/release-62-1.tar.gz, https://mirror.bazel.build/github.com/ unicode-org/icu/archive/release-62-1.tar.gz, https://github.com/unicode-org/icu/archive/release-62-1.tar.gz ] to /home/zhangqinwei/.cache/bazel/_bazel_zhan gqinwei/81b182456dc5e19b594a565bd2f1d372/external/icu/release-62-1.tar.gz: Checksum was 86b85fbf1b251d7a658de86ce5a0c8f34151027cc60b01e1b76f167379acf181 but wanted e15ffd84606323cbad5515bf9e cdf8061cc3bf80fb883b9e6aa162e485aa9761
【分析】
release-62-1.tar.gz 的Checksum是86b85…但是得到的却是e15ff… 所以修改垓下tensorflow/third_party/icu/workspacd.bzl:
将sha256 由e15ff改成86b85…
sha256 = “86b85fbf1b251d7a658de86ce5a0c8f34151027cc60b01e1b76f167379acf181”,
清理 再重新编译:
bazel clean
bazel build --config=opt --config=cuda //tensorflow:libtensorflow_cc.so
【error】
ERROR: tensorflow-1.13.1/tensorflow/BUILD:393:1: no such package ‘@grpc//’: java.io.IOException: Error downloading [https://mirror.bazel.build/github.com/grpc/grpc/archive/69b6c047bc767b4d80e7af4d00ccb7c45b683dae.tar.gz, https://github.com/grpc/grpc/archive/69b6c047bc767b4d80e7af4d00ccb7c45b683dae.tar.gz] to /.cache/bazel/_bazel_zhangqinwei/81b182456dc5e19b594a565bd2f1d372/external/grpc/69b6c047bc767b4d80e7af4d00ccb7c45b683dae.tar.gz: Checksum was cde4cc00d517cd8a40cf61dfcf86902ccff792224ea4d08ac46cae7bcc70b914 but wanted 1aa84387232dda273ea8fdfe722622084f72c16f7b84bfc519ac7759b71cdc91 and referenced by ‘//tensorflow:grpc++’
ERROR: Analysis of target ‘//tensorflow:libtensorflow_cc.so’ failed; build aborted: Analysis failed
【分析】
乍一看以为是与上面的icu_release 一样是某个sha256需要改成对应的值,最后没找到这个sha256, 后来想是不是也是grcp这个模块下载不下来,开始处理:
重复上面第一个错误:(这里本地服务已经建好,只需要手动下载后,再上传上去好了):
1 手动下载 69b6c047bc767b4d80e7af4d00ccb7c45b683dae.tar.gz
https://codeload.github.com/grpc/grpc/tar.gz/69b6c047bc767b4d80e7af4d00ccb7c45b683dae
2.将下载下来的 69b6c047bc767b4d80e7af4d00ccb7c45b683dae.tar.gz 放到var/www/html文件夹下;
3.修改tensorflow/tensorflow/workspace.bzl文件:在urls = […]中加一条:
"http://localhost/grpc-69b6c047bc767b4d80e7af4d00ccb7c45b683dae.tar.gz",
如下:
清理 再重新编译:
bazel clean
bazel build --config=opt --config=cuda //tensorflow:libtensorflow_cc.so
4. 安装其他依赖库
安装完tensorflow后,将tensorflow中生成的bazel-genfiles 等文件和include文件 拷贝到根目录下面:
sudo mkdir /usr/local/include/tf
sudo cp -r bazel-genfiles/ /usr/local/include/tf/
sudo mkdir /usr/local/include/tf/tensorflow
sudo cp -r tensorflow/* /usr/local/include/tf/tensorflow/
sudo cp -r third_party /usr/local/include/tf/
sudo cp -r bazel-bin/tensorflow/*.so /usr/local/lib/
5. 测试
创建一个demo文件夹,demo文件夹下具体内容目录如下:
demo–|
|---- /build
|---- /include
|----/lib
|---- /src
|----CMakeLists.txt
随便编写一段脚,如:
#include <tensorflow/core/platform/env.h>
#include <tensorflow/core/public/session.h>
#include <iostream>
using namespace std;
using namespace tensorflow;
int main()
{
Session* session;
Status status = NewSession(SessionOptions(), &session);
if (!status.ok()) {
cout << status.ToString() << "\n";
return 1;
}
cout << "Session successfully created.\n";
}
保存为test.cpp,放到src文件夹下;
将libtensorflow_cc.so文件复制到lib文件夹下,如果不知道libtensorflow_cc.so文件在哪儿,可以用whereis libtensorflow_cc.so
查找文件所在位置,将其copy到lib文件夹下。
打开CMakeLists.txt文件,写cmake文件:
cmake_minimum_required (VERSION 2.8.8)
project (tf_example)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -std=c++11 -W")
aux_source_directory(./src DIR_SRCS)
link_directories(./lib)
include_directories(
path_to_tensorflow/tensorflow
path_to_tensorflow/tensorflow/bazel-genfiles
path_to_tensorflow/tensorflow/contrib/makefile/gen/protobuf/include
) add_executable(tf_test ${DIR_SRCS}) target_link_libraries(tf_example tensorflow_cc)
进入build文件夹下:
cd build
cmake ..
make
会生成tf_test可执行文件,执行无误即大功告成。
如果make不成功,中间有各种报错,比如这种:
error: #error This file was generated by a newer version of protoc which is~~~
看意思是说编译的protobuf版本不对,重新安装的protobuf,往前翻目录2的安装教程,再bazel clean 后重新编译tensorflow,再走一遍。。