如何构建和使用Google TensorFlow C ++ API

How to build and use Google TensorFlow C++ api

我真的很想在C++中开始使用谷歌的新的TysFooFLoad库。网站和文档在如何构建项目的C++ API方面真的不太清楚,我不知道从哪里开始。

有经验的人可以通过发现和共享使用TysFROW的C++ API来帮助吗?


要开始,您应该按照下面的说明从github下载源代码(您需要bazel和最新版本的gcc)。

C++ API(和系统的后端)在EDCOX1中0。目前,只支持C++会话接口和C API。您可以使用其中任何一个来执行使用python API构建并序列化到GraphDef协议缓冲区的tensorflow图。还有一个用于在C++中构建图形的实验特性,但是目前这一点还不如Python API(如目前没有支持自动微分)那么全面。您可以在这里看到一个示例程序,它在C++中构建一个小的图形。

C++ API的第二部分是用于添加一个新的EDCOX1×2的API,它是包含CPU和GPU的数值内核实现的类。关于如何在EDCOX1 3中创建这些示例,以及在C++中添加新的OP的教程有很多例子。


为了添加到@ MRY的文章中,我编写了一个教程,讲解如何用C++ API加载TySoFrase图。这是非常小的,应该能帮助你理解所有的部分是如何组合在一起的。这是它的肉:

要求:

  • Bazel安装
  • 克隆tensorflow repo

文件夹结构:

  • tensorflow/tensorflow/|project name|/
  • tensorflow/tensorflow/|project name|/|project name|.cc (e.g. https://gist.github.com/jimfleming/4202e529042c401b17b7)
  • tensorflow/tensorflow/|project name|/BUILD

建造:

1
2
3
4
5
6
7
cc_binary(
    name ="<project name>",
    srcs = ["<project name>.cc"],
    deps = [
       "//tensorflow/core:tensorflow",
    ]
)

可能有两个解决办法:

  • 现在,需要在TensorFlow repo中进行构建。
  • 编译后的二进制文件很大(103MB)。

https://medium.com/@jimfleming/loading-a-tensorflow-graph-with-the-c-api-4caaff88463f


如果您希望避免使用BAZEL来构建项目并生成大二进制,那么我已经组装了一个存储库,用CMake来指导TysFraseC++库的使用。你可以在这里找到它。总体思路如下:

  • 克隆TensorFlow存储库。
  • 将生成规则添加到EDCOX1(8)中(所提供的不包括所有C++功能)。
  • 构建TensorFlow共享库。
  • 安装特定版本的eigen和protobuf,或者将它们作为外部依赖项添加。
  • 配置CMAKE项目以使用TensorFlow库。

首先,在安装了protobufeigen之后,您需要构建tensorflow:

1
2
./configure
bazel build //tensorflow:libtensorflow_cc.so

然后将以下内容包括头部和动态共享库复制到/usr/local/lib/usr/local/include中:

1
2
3
4
5
mkdir /usr/local/include/tf
cp -r bazel-genfiles/ /usr/local/include/tf/
cp -r tensorflow /usr/local/include/tf/
cp -r third_party /usr/local/include/tf/
cp -r bazel-bin/libtensorflow_cc.so /usr/local/lib/

最后,使用示例编译:

1
2
3
4
5
6
g++ -std=c++11 -o tf_example \
-I/usr/local/include/tf \
-I/usr/local/include/eigen3 \
-g -Wall -D_DEBUG -Wshadow -Wno-sign-compare -w  \
-L/usr/local/lib/libtensorflow_cc \
`pkg-config --cflags --libs protobuf` -ltensorflow_cc tf_example.cpp


如果您正在考虑在一个独立的包上使用TysFraceC++API,那么您可能需要TysFraceU.C.C..(因此也有一个C API版本TunSoRoS.SO)来构建C++版本,您可以使用:

1
bazel build -c opt //tensorflow:libtensorflow_cc.so

注1:如果要添加intrinsics支持,可以将此标志添加为:--copt=-msse4.2 --copt=-mavx

注2:如果您也在考虑在项目中使用opencv,那么在同时使用两个libs时会出现问题(tensorflow问题),您应该使用--config=monolithic

在构建库之后,您需要将它添加到项目中。为此,您可以包括以下路径:

1
2
3
4
tensorflow
tensorflow/bazel-tensorflow/external/eigen_archive
tensorflow/bazel-tensorflow/external/protobuf_archive/src
tensorflow/bazel-genfiles

并将库链接到您的项目:

1
2
tensorflow/bazel-bin/tensorflow/libtensorflow_framework.so (unused if you build with --config=monolithic)
tensorflow/bazel-bin/tensorflow/libtensorflow_cc.so

当您正在构建项目时,还应该指定编译器使用C++ 11标准。

旁注:与TensorFlow 1.5版相关的路径(您可能需要检查您的版本中是否有任何更改)。

这个链接也帮助我找到了所有这些信息:链接


您可以使用此shellscript安装(大部分)它的依赖项,克隆、构建、编译并将所有必要的文件获取到../src/includes文件夹中:

https://github.com/node-tensorflow/node-tensorflow/blob/master/tools/install.sh


如果您不想自己构建张力流,而操作系统是Debian或Ubuntu,则可以使用TysFraceC/C++库下载预构建的包。此分布可用于CPU的C/C++推理,不包括GPU支持:

https://github.com/kecsap/tensorflow_cpp_包装/发布

编写了如何在TysFooSt流(TFEXLY)中冻结检查点的指令,并用C/C++ API加载该模型进行推理:

https://github.com/kecsap/tensorflow_cpp_packaging/blob/master/readme.md

小心:我是这个Github项目的开发人员。


如果您不介意使用CMake,也有TysFraceYOCC项目,它为您构建和安装TF C++API,以及方便链接的CMAKE目标。项目自述文件包含一个示例和Dockerfiles,您可以很容易地遵循。


我使用黑客/解决方法来避免自己构建整个tf库(这样既节省了时间(3分钟内设置)、磁盘空间、安装dev依赖项,又节省了生成的二进制文件的大小)。这是官方不支持的,但如果你只是想快速跳入,效果很好。

通过PIP(pip install tensorflowpip install tensorflow-gpu安装TF。然后找到它的库_pywrap_tensorflow.so(tf 0.-1.0)或_pywrap_tensorflow_internal.so(tf 1.1+)。在我的情况下(Ubuntu),它位于/usr/local/lib/python2.7/dist-packages/tensorflow/python/_pywrap_tensorflow.so。然后在构建系统找到的地方(例如,/usr/lib/local)创建一个名为lib_pywrap_tensorflow.so的库的符号链接。前缀lib很重要!您还可以给它另一个lib*.so名称—如果您称它为libtensorflow.so的话,您可以更好地与编写用于tf的其他程序兼容。

然后创建一个C++项目,如您所使用的(Cube、Spand、Bazel,不管您喜欢什么)。

然后,您就可以直接链接到这个库,让tf可用于您的项目(您还必须链接到python2.7库)!在cmake中,您只需添加target_link_libraries(target _pywrap_tensorflow python2.7)

C++头文件位于这个库的周围,例如在EDCOX1×21中。

再一次:这种方式是官方不支持的,您可能会遇到各种问题。库似乎与protobuf等静态链接,因此您可能会遇到奇怪的链接时间或运行时问题。但我能够加载一个存储的图表,恢复权重和运行推理,这是IMO最需要的功能在C++中。


TunSoFrices本身只提供了关于C++ API的非常基本的例子。这里有一个很好的资源,其中包括数据集、RNN、LSTM、CNN等示例
TySoFraseC++实例


上面的答案足以说明如何构建库,但是如何收集头仍然很棘手。在这里,我分享了我用来复制必要标题的小脚本。

SOURCE是第一个参数,它是张量流源(构建)方向;DST是第二个参数,它是include directory保存收集的头文件。(例如,在cmake,include_directories(./collected_headers_here)中)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#!/bin/bash

SOURCE=$1
DST=$2
echo"-- target dir is $DST"
echo"-- source dir is $SOURCE"

if [[ -e $DST ]];then
    echo"clean $DST"
    rm -rf $DST
    mkdir $DST
fi


# 1. copy the source code c++ api needs
mkdir -p $DST/tensorflow
cp -r $SOURCE/tensorflow/core $DST/tensorflow
cp -r $SOURCE/tensorflow/cc $DST/tensorflow
cp -r $SOURCE/tensorflow/c $DST/tensorflow

# 2. copy the generated code, put them back to
# the right directories along side the source code
if [[ -e $SOURCE/bazel-genfiles/tensorflow ]];then
    prefix="$SOURCE/bazel-genfiles/tensorflow"
    from=$(expr $(echo -n $prefix | wc -m) + 1)

    # eg. compiled protobuf files
    find $SOURCE/bazel-genfiles/tensorflow -type f | while read line;do
        #echo"procese file --> $line"
        line_len=$(echo -n $line | wc -m)
        filename=$(echo $line | rev | cut -d'/' -f1 | rev )
        filename_len=$(echo -n $filename | wc -m)
        to=$(expr $line_len - $filename_len)

        target_dir=$(echo $line | cut -c$from-$to)
        #echo"[$filename] copy $line $DST/tensorflow/$target_dir"
        cp $line $DST/tensorflow/$target_dir
    done
fi


# 3. copy third party files. Why?
# In the tf source code, you can see #include"third_party/...", so you need it
cp -r $SOURCE/third_party $DST

# 4. these headers are enough for me now.
# if your compiler complains missing headers, maybe you can find it in bazel-tensorflow/external
cp -RLf $SOURCE/bazel-tensorflow/external/eigen_archive/Eigen $DST
cp -RLf $SOURCE/bazel-tensorflow/external/eigen_archive/unsupported $DST
cp -RLf $SOURCE/bazel-tensorflow/external/protobuf_archive/src/google $DST
cp -RLf $SOURCE/bazel-tensorflow/external/com_google_absl/absl $DST