windows环境VS2015编译TensorFlow C++程序完全攻略

steven_oyj 2018-01-10 原文

windows环境VS2015编译TensorFlow C++程序完全攻略

本文参考和综合了多篇网络博客文章,加以自己的实践,最终终于在windows环境下,编译出可以用于C++程序调用tensorflow API的程序,并执行成功。

考虑到网络上关于这方面的资料还较少,特总结全过程如下,希望能帮助到有需要的码农朋友,文中有部分文字步骤是借鉴他人文章,引用路径在最后列出。

一、环境准备:

  1. 操作系统:windows8.1
  2. 安装visual stduio2015
  3. 安装Swigwin-3.0.12,注意其下载解压以后即可使用,本人放置路径在D:/lib/swigwin-3.0.12,可执行文件地址为 D:/swigwin-3.0.12/swig.exe
  4. 安装python3.5,安装时注意选择将路径添加到环境变量。
  5. 安装CMake-3.8.0 ,安装时注意选择将路径添加到环境变量。
  6. 安装Git,用于在编译过程中从GitHub上下载依赖项。
  7. 将GitHub上TensorFlow的master分支 下载并解压到文件夹D:\tf中,编辑文件tensorflow/tensorflow/contrib/cmake/CMakeLists.txt,将第87行至93行修改如下:
 1 if (tensorflow_OPTIMIZE_FOR_NATIVE_ARCH)
 2   include(CheckCXXCompilerFlag)
 3   CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_OPT_ARCH_NATIVE_SUPPORTED)
 4   if (COMPILER_OPT_ARCH_NATIVE_SUPPORTED)
 5     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
 6   else()
 7     CHECK_CXX_COMPILER_FLAG("/arch:AVX" COMPILER_OPT_ARCH_AVX_SUPPORTED)
 8     if(COMPILER_OPT_ARCH_AVX_SUPPORTED)
 9       set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:AVX")
10     endif()
11   endif()
12 endif()

 二、使用CMAKE设置各项编译参数

  1. 打开下载tensorflow源文件的根目录,本文路径是E:TF Code/TensorFlow,在路径下进入../tensorflow\contrib\cmake, 新建文件夹\build。
  2. 打开已安装的CMAKE-GUI工具,进行各项编译选项的配置,本文配置界面如下:
  3.             
  4. 点击configue,下方提示Configuring done后,点击Generate,等待Generating done后完成编译设置。如果中间有报错,请检测各路径设置是否正确。

三、编译生成tensorflow库文件

  1.  打开visual studio2015,打开E:\TF Code\tensorflow\tensorflow\contrib\cmake\build下的ALL_BUILD项目。我们在此只以release版本为例,所以检查编译平台是
  2. 点击生成解决方案,编译的时间很长,我的笔记本电脑编译一次大概3到4个小时,编译到最后一般都会报错
    fatal error C1060: compiler is out of heap space 没关系,等待整个工程全部编译完成(据说内存特别大的电脑不会报)。
  3. 找到tf_core_kernels项目,右键单独编译,操作如下图。

    

  4. tf_core_kernels项目编译成功后,再同样对tensorflow_static作单独编译,最后再对tensorflow作单独编译。.

   这样tensorflow.lib和tensorflow.dll文件就可以编译出来了,生成的库文件路径在..\tensorflow\tensorflow\contrib\cmake\build\Release下。

四、使用tensorflow库文件编写C++程序

  1. 在vs2015中创建一个新的Win32控制台工程TestTensorFlow,并新建一个TestTensorFlow.h,在其中输入
    #pragma once
    
    #define COMPILER_MSVC
    #define NOMINMAX  
  2. 对应的TestTensorFlow.CPP文件中输入如下:
    // TestTF1.cpp : 定义控制台应用程序的入口点。
    //
    #include "stdafx.h"
    
    #include <vector>
    #include <eigen/Dense>
    
    #include "TestTF1.h"
    #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()
    {
    	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();
    } 
  3.  设置要包含的tensorflow头文件路径,右键项目属性——C/C++——附加包含目录
    E:\TF Code\tensorflow\tensorflow\contrib\cmake\build\Debug
    E:\TF Code\tensorflow\tensorflow\contrib\cmake\build\external\nsync\public
    E:\TF Code\tensorflow\tensorflow\contrib\cmake\build\protobuf\src\protobuf\src
    E:\TF Code\tensorflow\tensorflow\contrib\cmake\build\external\eigen_archive
    E:\TF Code\tensorflow\tensorflow\contrib\cmake\build
    E:\TF Code\tensorflow
    E:\TF Code\tensorflow\third_party\eigen3
  4.  引入tensorflow.lib文件,右键项目——添加——现有项,找到..\tensorflow\tensorflow\contrib\cmake\build\Release下的tensorflow.lib 

            

  5.  设置预编译选项,右键属性——C/C++——预处理器,预处理器定义中加入PLATFORM_WINDOWS

            

  6. 编译TestTensorFlow项目,就可以成功生成TestTensorFlow.exe了。

  7.直接运行程序,会报错

  8,把..\tensorflow\tensorflow\contrib\cmake\build\Release下的tensorflow.dll拷贝到TestTensorFlow.exe同文件夹下,再运行即可成功得到输出结果如下:

     

     输出结果有一句警告,好像是我编译参数还是跟CPU功能有不匹配,但是不影响执行结果,有知道如何解决的朋友可以留言给我,谢谢。

 

       参考:

  1. https://www.cnblogs.com/jliangqiu2016/p/7642471.html
  2. http://www.qingpingshan.com/m/view.php?aid=322808

 

发表于 2018-01-10 16:12 红脸书生 阅读() 评论() 编辑 收藏

 

版权声明:本文为steven_oyj原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/steven_oyj/p/8259205.html

windows环境VS2015编译TensorFlow C++程序完全攻略的更多相关文章

  1. [C#]基于命名管道的一对多进程间通讯

    在工作中碰到了一个进程间通讯的问题,大概是这样的: 项目本身是.net Core做的,但是有部分功能Core中 […]...

  2. Entity Framework (EF) Core工具创建一对多和多对多的关系

     一、 EntirtyFramework(EF)简介        EntirtyFramework框架是一个 […]...

  3. WebAPI的AuthorizeAttribute扩展类中获取POST提交的数据

    在WEBAPI中,AuthorizeAttribute类重写时,如何获取post数据是个难题,网上找资料也不好 […]...

  4. C++ 中的虚函数表及虚函数执行原理

    为了实现虚函数,C++ 使用了虚函数表来达到延迟绑定的目的。虚函数表在动态/延迟绑定行为中用于查询调用的函数。 […]...

  5. 高性能 C++ HTTP 客户端原理与实现

    Http协议,是全互联网共同的语言,而Http Client,可以说是我们需要从互联网世界获取数据的最基本方法 […]...

  6. Vulkan移植GpuImage(一)高斯模糊与自适应阈值

    自适应阈值效果图 demo 这几天抽空看了下GpuImage的filter,移植了高斯模糊与自适应阈值的vul […]...

  7. C# vb .NET生成QR二维码

      二维码比条形码具有更多优势,有些场合使用二维码比较多,比如支付。通过将某些数据生成二维码,就可以实现一码走 […]...

  8. ibatis.net 入门demo 实现基本增删改查

    1、项目架构体系  DAO(数据访问层)   Domain(实体层)  Text(表示层) 2、比较重要的是需 […]...

随机推荐

  1. 《Java 8 in Action》Chapter 1:为什么要关心Java 8

    自1998年 JDK 1.0(Java 1.0) 发布以来,Java 已经受到了学生、项目经理和程序员等一大批 […]...

  2. 【深入理解Java虚拟机】垃圾回收

    引用计数算法 给对象加一个计数器,引用一次+1,引用时效就-1,当计数器=0时对象就不能再被使用; 实现简单, […]...

  3. RTOS,什么是硬实时和软实时

    RTOS,什么是硬实时和软实时 RTOS is real time operating system. It […]...

  4. 再度分(tu)析(cao)Egret这个年轻人

    再度分析Egret的种种种种 写在最前 笔者用Egret来开发游戏已经有2年多之久了,从它出现到如今的3.2. […]...

  5. 拜拜了,GOPATH君!新版本Golang的包管理入门教程

    Go 1.11和1.12实现了对包管理的初步支持,Go的新依赖管理系统使依赖版本信息明确且易于管理。Using […]...

  6. 准备数据集用于flink学习

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有 […]...

  7. Jmeter全局变量设置

    背景:因为BeanShell PreProcessor制造的参数是一些随机参数,每个HTTP取样器包括其他取样 […]...

  8. 调用腾讯QQ天气预报的JS代码

    一直在用腾讯的天气预报,原本都挺好的。可是腾讯视乎发现了有外链情况。又是对其IP地址库(http://fw.q […]...

展开目录

目录导航