TensorFlow C++动态库编译

在CentOS 7.2上编译TensorFlow 1.4版本的C++动态库,以及整理相应的头文件。完成后,只需要库文件以及头文件即可用C++ API调用TensorFlow. 这样的好处是自己的工程可以自由选择编译工具,而不需要依赖谷歌的构建工具Bazel.


  • 基本依赖
  • 编译libtensorflow_cc.so
  • 编译Protobuf和Eigen
  • 整理库文件和头文件
  • 测试示例
  • 后记
  • References

基本依赖

  • 安装Java
$ java -version
java version "1.8.0_144"
  • 编译安装Bazel

TensorFlow要用Bazel来进行构建,所以要先安装Bazel,后面我们编译好动态库后,就可以摆脱Bazel这个依赖了。Bazel的编译安装很简单,最终得到的是self-contained Bazel binary,按照官网教程即可。

$ bazel version
Build label: 0.7.0- (@non-git)
  • 安装其他依赖

TensorFlow官网,源码编译安装的教程中,提到要安装一些Python依赖。这里建议用virtualenv或者其他的Python运行环境管理工具来做隔离,专门为这个动态库的编译建一个新的Python运行环境,否则会把机器的Python环境搞得比较乱。

sudo yum install python-devel   # ubuntu是python-dev
pip install six
pip install numpy
pip instal wheel

编译libtensorflow_cc.so

git clone获取TensorFlow的源码。当然,也可以直接去TensorFlow Release的页面上找相应版本的源码:

git clone https://github.com/tensorflow/tensorflow
cd tensorflow
git checkout r1.4

编译之前,要进行一系列的配置,包括Python路径等等:

./configure

编译C++ API所需的库,期间Bazel需要联网下载许多依赖,时间有点长:

bazel build --config=opt //tensorflow:libtensorflow_cc.so

编译正常完成后,会在bazel-bin/tensorflow/文件夹下生产libtensorflow_cc.solibtensorflow_framework.so这两个动态库文件。


编译Protobuf和Eigen

# protobuf
mkdir /tmp/proto
./tensorflow/contrib/makefile/download_dependencies.sh
cd tensorflow/contrib/makefile/downloads/protobuf/
./autogen.sh
./configure --prefix=/tmp/proto/
make
make install

# eigen
mkdir /tmp/eigen
cd ../eigen
mkdir build_dir
cd build_dir
cmake -DCMAKE_INSTALL_PREFIX=/tmp/eigen/ ../
make install
cd ../../../../../..

整理库文件和头文件

把编译得到的库文件以及分散在各个地方的头文件整理集中起来。

  • 库文件
mkdir -p ../tf_test/lib
cp bazel-bin/tensorflow/libtensorflow_cc.so ../tf_test/lib/
cp bazel-bin/tensorflow/libtensorflow_framework.so ../tf_test/lib/  # 之前编译r0.12和r1.3版本的库,只需要libtensorflow_cc.so,1.4版本的似乎分成了两个so文件,即还需要libtensorflow_framework.so
cp /tmp/proto/lib/libprotobuf.a ../tf_test/lib/
  • 头文件
mkdir -p ../tf_test/include/tensorflow
cp -r bazel-genfiles/* ../tf_test/include/
cp -r tensorflow/cc ../tf_test/include/tensorflow
cp -r tensorflow/core ../tf_test/include/tensorflow
cp -r third_party ../tf_test/include
cp -r /tmp/proto/include/* ../tf_test/include
cp -r /tmp/eigen/include/eigen3/* ../tf_test/include

上面是从1.3版本的这个教程里提到的目录,但是对于1.4以后的版本,似乎还缺少nsync的头文件,这点在这个教程里有提到:

cp -r tensorflow/contrib/makefile/downloads/nsync/public ../tf_test/include/external/nsync/public

不需要的.cc文件可以删掉:

cd ../tf_test/
find . -name "*.cc" -type f -delete

测试示例

准备好库文件和相应的头文件后,可以编译测试示例:

示例代码tf_test/test.cc:

#include "tensorflow/cc/client/client_session.h"
#include "tensorflow/cc/ops/standard_ops.h"
#include "tensorflow/core/framework/tensor.h"

int main() {
  using namespace tensorflow;
  using namespace tensorflow::ops;
  Scope root = Scope::NewRootScope();
  // Matrix A = [3 2; -1 0]
  auto A = Const(root, { {3.f, 2.f}, {-1.f, 0.f}});
  // Vector b = [3 5]
  auto b = Const(root, { {3.f, 5.f}});
  // v = Ab^T
  auto v = MatMul(root.WithOpName("v"), A, b, MatMul::TransposeB(true));
  std::vector outputs;
  ClientSession session(root);
  // Run and fetch v
  TF_CHECK_OK(session.Run({v}, &outputs));
  // Expect outputs[0] == [19; -3]
  LOG(INFO) << outputs[0].matrix();
  return 0;
}
$ pwd
/some/where/tf_test
$ ls
include lib test.cc
$ g++ -std=c++11 -I./include -I./include/external/nsync/public -L./lib test.cc -ltensorflow_cc -ltensorflow_framework -o test
$ ./test

正确的情况下,应该会输出19 -3,还会输出类似Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX AVX2 FMA的信息,这涉及到CPU指令优化的问题,可以在编译动态库的时候进行指令优化,具体可以看TensorFlow官网的教程,这里就不展开了。


后记

TensorFlow的版本升级迭代比较频繁,网上各个版本的C++动态库编译及涉及到的头文件位置都不太一样。本人还看过一个教程,先基于源码编译TensorFlow的pip包,用pip安装TensorFlow之后,再去安装目录(/usr/lib/python2.7/site-packages/tensorflow/include)下找头文件。总之,遇到编译的问题,可以google问题的解法,比较各人的环境配置总会存在差异的地方。


References

  • Building TensorFlow 1.3.0 as a standalone project (Raspberry pi 3 included)
  • Creating Tensorflow C++ headers and libraries for macOS
  • Installing TensorFlow from Sources
  • Packaged TensorFlow C++ library for bazel-independent use
  • libtensorflow_cc.so依赖libtensorflow_framework.so的问题

你可能感兴趣的:(TensorFlow C++动态库编译)