由于最近比较忙,一直到假期才有空,因此将自己学到的知识进行分享。如果有不对的地方,请指出,谢谢!目前深度学习越来越火,学习、使用tensorflow的相关工作者也越来越多。最近在研究tensorflow线下采用 python 脚本训练出模型, 利用freeze_graph工具输出.pb图文件,之后再线上生产环境windows平台上用C++代码直接调用预先训练好的模型完成预测的工作。因为目前tensorflow提供的C++的API比较少,所以参考了以上几篇已有的日志,做个总结。这里编译出TensorFlow C++ library,遇到的坑进行填埋。之后的调用C++library相对比较简单,可以参考链接部分。

Step1:Windows 10必备环境准备

1.1安装VS2015

1.2安装Swigwin-3.0.12,其可执行文件地址为 D:/lib/swigwin-3.0.12/swig.exe

1.4安装python3.5,安装时注意选择将路径添加到环境变量。

1.5安装CMake-3.8.0 ,安装时注意选择将路径添加到环境变量。

1.6安装Git,用于在编译过程中从GitHub上下载依赖项。

1.7 将GitHub上TensorFlow的master分支 下载并解压到文件夹D:\tf中,编辑文件tensorflow/tensorflow/contrib/cmake/CMakeLists.txt,将第87行至93行修改如下:

if (tensorflow_OPTIMIZE_FOR_NATIVE_ARCH)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_OPT_ARCH_NATIVE_SUPPORTED)
if (COMPILER_OPT_ARCH_NATIVE_SUPPORTED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
else()
CHECK_CXX_COMPILER_FLAG("/arch:AVX" COMPILER_OPT_ARCH_AVX_SUPPORTED)
if(COMPILER_OPT_ARCH_AVX_SUPPORTED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:AVX")
endif()
endif()
endif()

总结下这一部分的三个重要地址:

Python可执行文件地址为:D:/lib/Python35/python.exe;
Python库文件地址为:D:/lib/Python35/libs/python35.lib(release版本), D:/lib/Python35/libs/python35_d.lib(Debug版本);
Swigwin可执行文件地址:D:/lib/swigwin-3.0./swig.exe。

Step2:编译 TensorFlow shared lib

2.1 打开文件夹 D:\tf\tensorflow-master\tensorflow\contrib\cmake, 新建文件夹\build。以管理员身份运行 开始 \ 所有程序 \ Visual Studio 2015\Visual Studio Tools\ Developer Command Prompt for VS 2015,输入powershell,使用命令切换到新建的build文件夹下。使用指令1用于build编译项目。可以看到,使用的就是上一部分保存的三个路径。当命令行中出现Generating done,说明build成功。

# 指令1(release)
cmake .. -A x64 -DCMAKE_BUILD_TYPE=Release -DSWIG_EXECUTABLE=D:/lib/swigwin-3.0.12/swig.exe-DPYTHON_EXECUTABLE=D:/lib/Python35/python.exe -DPYTHON_LIBRARIES=D:/lib/Python35/libs/python35.lib -Dtensorflow_BUILD_SHARED_LIB=ON # 指令1(debug)
cmake .. -A x64 -DCMAKE_BUILD_TYPE=Debug -DSWIG_EXECUTABLE=D:/lib/swigwin-3.0.12/swig.exe-DPYTHON_EXECUTABLE=D:/lib/Python35/python.exe -DPYTHON_LIBRARIES=D:/lib/Python35/libs/python35_d.lib-Dtensorflow_BUILD_SHARED_LIB=ON

或者,这里我用cmake-gui界面进行cmake编译出release和debug版本,如下图所示:

2.2 命令行中输入指令2开始编译,在编译过程中保持网络畅通,有15个依赖库需要下载。编译过程中可能出现一些警告,不用担心,只要没有错误编译就可以通过。

# 指令2(release)
MSBuild /p:Configuration=Release ALL_BUILD.vcxproj
# 指令2(debug)
MSBuild /p:Configuration=Debug ALL_BUILD.vcxproj

2.3 但是,我在自己的电脑上编译失败,并出现了90个错误,这些错误都指向了两文件:

D:\tf\tensorflow-master\tensorflow\contrib\cmake\build\re2\src\re2\re2\testing\re2_test.cc
D:\tf\tensorflow-master\tensorflow\contrib\cmake\build\re2\src\re2\re2\testing\search_test.cc

re2包提供了正则表达式的功能,文件夹testing中是测试文件,在TensorFlow运行过程中其实不需要这些测试功能,所以可以通过禁止编译re2的测试部分来移除这些错误。

Step3:排除错误

3.1对出错的工程文件夹下,修改文件D:\tf\tensorflow-master\tensorflow\contrib\cmake\build\re2\src\re2\CMakeLists.txt(一定要翻墙下载到),将第16行修改为:

option(RE2_BUILD_TESTING “enable testing for RE2” OFF)

,并保存。

3.2 重新进行编译(步骤2.2)。在编译过程中,会出现错误:

C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.\V140\Microsoft.CppCommon.targets(,): error MSB6006: “cmd.exe”已退
出,代码为 。 [D:\tensorflow-master\tensorflow\contrib\cmake\build\grpc.vcxproj]

这个应该是没有成功下载grpc,这个应该是个bug,给的链接不对(多次编译都编不过去),百度了下grpc对我现在的应用暂时用不多(不了解可以百度gprc)因此,暂时不需要grpc,也就不下载,编辑文件tensorflow/tensorflow/contrib/cmake/CMakeLists.txt,将第23行修改如下:

option(tensorflow_ENABLE_GRPC_SUPPORT "Enable gRPC support" OFF)

3.3重新cmake 和Build编译项目,并重新进行编译,重复步骤2.1,2.2和3.1。可能会出现错误:

fatal error C1060: compiler is out of heap space

这应该是跟自己的硬件相关,我自己的电脑配置不太好。出现这个错误,首先等待编译过程的完成,然后重复运行指令2。大概重复运行两三次这个问题就没有了。每次重复运行前,需等待整个编译过程完成。

也可能会出现这样的错误(Debug编译出现这样的错误):

这可能在实际中编译采用的是x86,并没有真正采用x64的环境进行编译,因此打开命令窗口Developer Command Prompt for VS 2015,输入powershell,使用命令切换到新建的build文件夹下,输入指令3,然后在输入指令2。

# 指令3
set PreferredToolArchitecture=x64

3.4 编译到最后会出现错误(debug版本比较严格)符号重载的错误,如下图所示:

error C2678: binary '<': no operator found which takes a left-hand operand of type IndicesRowIterator

修改对应的文件夹下的文件,我这里是D:\tf\tensorflow-master-ngrpc\tensorflow\contrib\boosted_trees\lib\utils\sparse_column_iterable.cc,增加到文件中,增加的内容如下所示:

bool operator<( const IndicesRowIterator& other ) const {
QCHECK_LT( iter_, other.iter_ );
return ( row_idx_ < other.row_idx_ );
}

最终编译成功。出现需要的相应的release和debug版本的lib和动态链接库

Step4:在Windows上编译和运行一个简单的TensorFlow C++ 程序

4.1在vs2015中创建一个新的工程solution,并在对应的文件中输入如下:

#include <vector>
#include <eigen/Dense> #include "matmul.h"
#include "tensorflow/core/public/session.h"
#include "tensorflow/cc/ops/standard_ops.h" using namespace tensorflow; // Build a computation graph that takes a tensor of shape [?, 2] and
// multiplies it by a hard-coded matrix.
GraphDef CreateGraphDef()
{
Scope root = Scope::NewRootScope(); auto X = ops::Placeholder(root.WithOpName("x"), DT_FLOAT,
ops::Placeholder::Shape({ -, }));
auto A = ops::Const(root, { { .f, .f },{ -.f, .f } }); auto Y = ops::MatMul(root.WithOpName("y"), A, X,
ops::MatMul::TransposeB(true)); GraphDef def;
TF_CHECK_OK(root.ToGraphDef(&def)); return def;
} int main()
{
GraphDef graph_def = CreateGraphDef(); // Start up the session
SessionOptions options;
std::unique_ptr<Session> session(NewSession(options));
TF_CHECK_OK(session->Create(graph_def)); // Define some data. This needs to be converted to an Eigen Tensor to be
// fed into the placeholder. Note that this will be broken up into two
// separate vectors of length 2: [1, 2] and [3, 4], which will separately
// be multiplied by the matrix.
std::vector<float> data = { , , , };
auto mapped_X_ = Eigen::TensorMap<Eigen::Tensor<float, , Eigen::RowMajor>>
(&data[], , );
auto eigen_X_ = Eigen::Tensor<float, , Eigen::RowMajor>(mapped_X_); Tensor X_(DT_FLOAT, TensorShape({ , }));
X_.tensor<float, >() = eigen_X_; std::vector<Tensor> outputs;
TF_CHECK_OK(session->Run({ { "x", X_ } }, { "y" }, {}, &outputs)); // Get the result and print it out
Tensor Y_ = outputs[];
std::cout << Y_.tensor<float, >() << std::endl; session->Close();
getchar();
}

4.2在对应的头文件中输入如下:

#pragma once

#define COMPILER_MSVC
#define NOMINMAX

4.3在vs2015中,属性配置界面中,include Directories:

D:\tf\tensorflow-master-ngrpc\tensorflow\contrib\cmake\build\Debug
D:\tf\tensorflow-master-ngrpc\tensorflow\contrib\cmake\build\external\nsync\public
D:\tf\tensorflow-master-ngrpc\tensorflow\contrib\cmake\build\protobuf\src\protobuf\src
D:\tf\tensorflow-master-ngrpc\tensorflow\contrib\cmake\build\external\eigen_archive
D:\tf\tensorflow-master-ngrpc\tensorflow\contrib\cmake\build
D:\tf\tensorflow-master-ngrpc
D:\tf\tensorflow-master-ngrpc\third_party\eigen3

4.4在vs2015中,属性配置界面中,Additional Library Directories(release版本):

D:\tf\tensorflow-master-ngrpc\tensorflow\contrib\cmake\build\Release

4.5在vs2015中,属性配置界面中,Linker Settings(release版本):

tensorflow.lib

4.6编译和运行程序,运行结果如下所示:

- -

参考:

https://joe-antognini.github.io/machine-learning/build-windows-tf

http://quqixun.com/?p=785

http://blog.csdn.net/longji/article/details/72760409

http://blog.csdn.net/rockingdingo/article/details/75452711

https://github.com/tensorflow/tensorflow/issues

https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/cmake

https://stackoverflow.com/questions/42603407/how-to-compile-tensor-flow-with-sse-and-and-avx-instructions-on-windows

Windows下编译TensorFlow1.3 C++ library及创建一个简单的TensorFlow C++程序的更多相关文章

  1. Windows下编译objective-C

    Windows下编译objective-C 2011-08-31 14:32 630人阅读 评论(0) 收藏 举报 windowscocoa工具objective clibraryxcode   目录 ...

  2. 在Windows下编译ffmpeg完全手册

    本文的内容几乎全部来自于FFmpeg on Windows,但是由于国内的网络封锁,很难访问这个域名下的内容,因此我一方面按照我自己的理解和实践做了翻译,另一方面也是为了能提供一个方便的参考方法. 注 ...

  3. 在Windows下编译OpenSSL(VS2005和VC6)

    需要说明的是请一定安装openssl-0.9.8a .  openssl-1.0.0我没有编译成功. 如何在Windows下编译OpenSSL (Vs2005使用Vc8的cl编译器)1.安装Activ ...

  4. 在Windows下编译WebRTC

    前言 这篇文章的目的在于为你节省生命中宝贵的10小时(甚至更多),或者浪费你10分钟.作为Google更新频繁的大型跨平台基础库,WebRTC的编译一直被人称为噩梦.如果恰巧你偏要在Windows下编 ...

  5. [转] Windows下编译OpenSSL

    简述 OpenSSL是一个开源的第三方库,它实现了SSL(Secure SocketLayer)和TLS(Transport Layer Security)协议,被广泛企业应用所采用.对于一般的开发人 ...

  6. 在Windows下编译FFmpeg详细说明

    MinGW:一个可自由使用和自由发布的Windows特定头文件和使用GNC工具集导入库的集合,允许你生成本地的Windows程序而不需要第三方C运行时 MinGW,即 Minimalist GNU F ...

  7. 如何在WINDOWS下编译BOOST C++库 .

    如何在WINDOWS下编译BOOST C++库 cheungmine 2008-6-25   写出来,怕自己以后忘记了,也为初学者参考.使用VC8.0和boost1.35.0.   1)下载boost ...

  8. windows下编译java源文件的编码错误

    import java.util.Arrays;public class ArrayAsAReference{ public static void main(String[] args) { int ...

  9. Windows下编译SDL

    Windows下编译SDL的理由我就不多说了,无论用VS来编译或调试SDL库都是很方便的.而且SDL源代码中也包含了VC工程,你所要做的只是解压VC工程,进行适当的配置,然后编译.调试. 编译SDL大 ...

随机推荐

  1. Hibernate第一天——入门和基本操作

    第一个接触的框架就是这个Hibernate框架了,Hibernate本意是 冬眠 ,这里有必要引用CSDN上某位网友某个帖子的评论先引出框架的概念: 框架:一个软件半成品,帮你做了一些基础工作,你就可 ...

  2. HBase数据访问的一些常用方式

    类型 特点 场合 优缺点分析 Native Java API 最常规和高效的访问方式 适合MapReduce作业并行批处理HBase表数据 Hbase Shell HBase的命令行工具,最简单的访问 ...

  3. Kubernetes学习之路(十四)之服务发现Service

    一.Service的概念 运行在Pod中的应用是向客户端提供服务的守护进程,比如,nginx.tomcat.etcd等等,它们都是受控于控制器的资源对象,存在生命周期,我们知道Pod资源对象在自愿或非 ...

  4. Kubernetes学习之路(十七)之statefulset控制器

    目录 一.statefulset简介 二.为什么要有headless?? 三.为什么要 有volumeClainTemplate?? 四.statefulSet使用演示 (1)查看statefulse ...

  5. jzoj5377 开拓

    哇好火的dp啊. 开始根本想不出 这里如果顺着dp肯定是不行的,没办法记录钻头能力值 显然能力值的变化会影响后面收入 而具体影响就是:全部乘了1-0.01k或1+0.01c. 可以倒着dp(orz) ...

  6. [TJOI2015]概率论[卡特兰数]

    题意 \(n\) 个节点二叉树的叶子节点的期望个数. \(n\leq 10^9\) . 分析 实际询问可以转化为 \(n\) 个点的不同形态的二叉树的叶子节点总数. 定义 \(f_n\) 表示 \(n ...

  7. 关于big-endian和little-endian

    详解大端模式和小端模式 一.大端模式和小端模式的起源 关于大端小端名词的由来,有一个有趣的故事,来自于Jonathan Swift的<格利佛游记>:Lilliput和Blefuscu这两个 ...

  8. Fortran的数组与指针

    个人理解,欢迎指正 指针就是记录数据的内存地址的变量.指针可以指向单个变量,也可以指向数组. 数组是一个概念,是若干个类型相同的元素的有序集合.在Fortran语言中,数组中存放的元素,可以是整数,实 ...

  9. 求二维数组最大子数组的和。郭林林&胡潇丹

    求二维数组子数组的最大值,开始思路不太清晰.先从最简单的开始. 以2*2的简单数组为例找规律, 假设最大数为a[0][0],则summax=a[0][0],比较a[0][0]+a[0][1].a[0] ...

  10. CF100015C

    主要找到环上任意一条边,有比较dis(u,v),dis(u,a)+w+dis(b,v),dis(u,b)+w+dis(a,u) 然后,然后没了 lca求dis(u,v):dis(u,v)=dis[u] ...