天天看点

TensorFlow 的 c ++ 实践及各种坑!

Tensorflow当前官网仅包含python、C、Java、Go的发布包,并无C++ release包,并且tensorflow官网也注明了并不保证除python以外库的稳定性,在功能方面python也是最完善的。众所周知,python在开发效率、易用性上有着巨大的优势,但作为一个解释性语言,在性能方面还是存在比较大的缺陷,在各类AI服务化过程中,采用python作为模型快速构建工具,使用高级语言(如C++,java)作为服务化程序实现是大势所趋。本文重点介绍tensorflow C++服务化过程中实现方式及遇到的各种问题。

对于tensorflow c++库的使用,有两种方法:

(1) 最佳方式当然是直接用C++构建graph,但是当前c++tensorflow库并不像python api那样full-featured。可参照builds a small graph in c++ here, C++ tensorflow api中还包含cpu和gpu的数字内核实现的类,可用以添加新的op。可参照https://www.tensorflow.org/extend/adding_an_op

(2) 常用的方式,c++调用python生成好的graph。本文主要介绍该方案。

(1) 编译tensorflow源码C++ so

(2) 模型训练输出结果

(3) 模型固化

(4) 模型加载及运行

(5) 运行问题

环境要求: 公司tlinux2.2版本, GCC版本 >= 4.8.5

安装组件: protobuf 3.3.0 bazel 0.5.0 python 2.7 java8

机器要求: 4GB内存

a. 安装java8

yum install java

b. 安装protobuf 3.3.0

下载 下载https://github.com/google/protobuf/archive/v3.3.0.zip

./configure && make && make install

c. 安装bazel

download https://github.com/bazelbuild/bazel/releases

sh bazel-0.5.0-installer-linux-x86_64.sh

d. 编译源码

最好采用最新release版本:https://github.com/tensorflow/tensorflow/releases

bazel build //tensorflow:libtensorflow_cc.so

编译过程中可能遇到的问题:

问题一: fatal error: unsupported/Eigen/CXX11/Tensor: No such file or directory

安装Eigen3.3或以上版本

问题二: java.io.IOException: Cannot run program "patch"

yum install patch

问题三: 内存不够

TensorFlow 的 c ++ 实践及各种坑!

模型训练输出可参照改用例去实践https://blog.metaflow.fr/tensorflow-saving-restoring-and-mixing-multiple-models-c4c94d5d7125 , google上也很多,模型训练保存好得到下面文件:

TensorFlow 的 c ++ 实践及各种坑!

模型固化方式有三种:

a. freeze_graph 工具

b. 利用freeze_graph.py工具

c. 利用tensorflow python

import os, argparseimport tensorflow as tffrom tensorflow.python.framework import graph_util

在具体实际项目,用方式一与方式二将生成的模型利用tensorflow c++ api加载,报以上错误,采用tensorflow python加载模型报同样错:

TensorFlow 的 c ++ 实践及各种坑!

原因是模型中用到了BatchNorm,修复方式如上面c中给出的方案

构建输入输出

模型输入输出主要就是构造输入输出矩阵,相比python的numpy库,tensorflow提供的Tensor和Eigen::Tensor还是非常难用的,特别是动态矩阵创建,如果你的编译器支持C++14,可以用xTensor库,和numpy一样强大,并且用法机器类似。如果是C++11版本就好好看看eigen库和tensorflow::Tensor文档吧。例举集中简单的用法:

矩阵赋值:

SOFTMAX:

模型加载及session初始化:

运行:

0.10以上的tensorflow库是线程安全的,因此可多线程调用predict

问题一:运行告警

是因为在编译tensorflow so库的时候没有把这些CPU加速指令编译进去,因此可以在编译的时候加入加速指令,在没有GPU条件下,加入这些库实测可以将CPU计算提高10%左右。

需要注意的是并不是所有CPU都支持这些指令,一定要实机测试,以免abort。

问题二: C++ libtensorflow和python tensorflow混用

为验证C++加载模型调用的准确性,利用swig将c++ api封装成了python库供python调用,在同时import tensorflow as tf和import封装好的python swig接口时,core dump

TensorFlow 的 c ++ 实践及各种坑!

该问题tensorflow官方并不打算解决

本文来自 全球人工智能 微信公众号