这段时间一直用python代码import tensorflow和keras的库,来搭建CNN框架进行图像的训练和预测,现在想用tensorflow的c++版来改写实现。故想自己编译一份tensroflow的lib和dll文件,创建工程调用其来实现相同的功能。本博客主要讲编译过程和一个简单的sample例子。
一.编译详细过程:
1.下载tensorflow源码,链接:点击打开链接,选择1.3.0版本。
2.准备工具:
一台配置了英伟达显卡的x64位win7系统电脑
(1)CMake 3.10.1点击打开链接
(2)swigwin-3.0.12点击打开链接
(3) VS2015
(4) cuda8.0+cudnnv5.1(如何安装配置验证参考我的之前博文“win7下cuda8.0安装跑gpu版tensorflow”
(5) 无网状态下需要下载部分文件。下面会介绍。
3.Cmake-gui编译tensorflow
(1)打开cmake-gui, 在tensorflow所在本机位置的tensorflow-1.3.0\tensorflow-1.3.0\tensorflow\contrib\cmake
路径下新建build文件夹2
(2)Browse Source和Browse Build按照此下选择(cmake文件夹下如果没有build文件夹,自己新建一个)
(3)点击cmake-gui左下角的Config按钮,会跳出来对话框,按照下图选择2015 Win64,然后点击Finish按钮
(4)会出现如下图的报错信息
(5)cmake-gui需要做如下配置,SWIG_EXECUTABLE路径设置到上面swigwin-3.0.12中swig.exe所在的位置
(6)再次点击configure按钮,出现下图,表示config成功
(7)展开tensorflow,按如下打勾的勾选上,然后点Generate
(8)出现Generating done表明生成成功
(9)然后点击Open Project按钮,打开工程
(10)点击菜单栏里的工具(T),选择选项按钮,在项目和解决方案下选择生成并运行项
做如下配置:设置最大并行项目生成数为1
(11)生成ALL_BUILD项目。
(12)中间不会很顺利,会报一些错误,如下所示:
分析无非这两大报错原因:a.由于网速慢或者资源原因,一些编译过程中需要下载的库download不下来。
b. re2工程编译不过去
(13)re2工程编译失败处理("re2/re2.h": No such file or directory)
转到到你的tensorflow文件里tensorflow-1.3.0\tensorflow\contrib\cmake\build\re2\src\re2目录下。
删除该目录下的非文件夹的文件,除了CmakeList.txt保留。
打开cmake-gui,如下图所示配置,单独重新配置re2工程。
记得Ungrouped Entries下的RE2_BUILD_TESTING取消勾选
BUILD下的BUILD_TESTING取消勾选
之后点击Config、Generate按钮重新生成Re2工程。不需要点open project按钮
重新仅生成Re2工程,成功。
(14)解决由于网速或者离线模式下相关文件不能下载而导致的失败问题
比如报downloading "htpps://storage.gooleapis.com/libpng-public-archive/libpng-1.2.53.tar.gz' failed
可以在有网的环境下事先下载好这份文件,拷贝到
tensorflow-1.3.0\tensorflow\contrib\cmake\build\downloads文件夹下。
然后转到tensorflow-1.3.0\tensorflow\contrib\cmake\build\png\src\png-stamp文件夹下,
把download-png.cmake里的东西清空,如下图所示:
对png工程重新仅生成该工程,编译成功。
解决该问题的方法也可以给离线模式编译带来参考,可以事先先准备好这些编译过程中需要下载的文件,所有文件均在
tensorflow-1.3.0\tensorflow\contrib\cmake\build\downloads文件夹里
下图是我编译成功该版tensorflow需要依赖的库
(15)重新生成ALL Build一般就能成功了(我按照此逻辑装过三次),如果不行可以留言!
生成成功后会在tensorflow-1.3.0\tensorflow\contrib\cmake\build\Release文件夹下看到tensorlow.lib和dll文件
到这边就编译结束啦!后面就可以写一些程序来调用这个dll。
该dll是x64 release版dll
下面是应用tensorflow.dll的一个简单会话例子。
用VS2015新建一个控制台程序。
sample1.cpp中代码如下:
// sample1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <Eigen\\Dense>
#include "tensorflow/core/public/session.h"
#include "tensorflow/cc/ops/standard_ops.h"
using namespace tensorflow;
GraphDef CreateGraphDef()
{
Scope root = Scope::NewRootScope();
auto X = ops::Placeholder(root.WithOpName("x"), DT_FLOAT,
ops::Placeholder::Shape({ -1, 2 }));
auto A = ops::Const(root, { { 3.f, 2.f },{ -1.f, 0.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()
{
std::cout << "me" << std::endl;
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 = { 1, 2, 3, 4 };
auto mapped_X_ = Eigen::TensorMap<Eigen::Tensor<float, 2, Eigen::RowMajor>>
(&data[0], 2, 2);
auto eigen_X_ = Eigen::Tensor<float, 2, Eigen::RowMajor>(mapped_X_);
Tensor X_(DT_FLOAT, TensorShape({ 2, 2 }));
X_.tensor<float, 2>() = 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[0];
std::cout << Y_.tensor<float, 2>() << std::endl;
session->Close();
getchar();
return 0;
}
同时在头文件stdafx.h文件中添加如下语句:
#include <tchar.h>
#define COMPILER_MSVC
#define NOMINMAX
完了之后对该工程进行路径及dll的配置:(我这边配的是绝对路径,最好用相对路径)
配置完后运行该sample工程,结果如下图: