• 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: f中,编辑文件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,在路径下进入../tensorflowcontribcmake, 新建文件夹uild。
    2. 打开已安装的CMAKE-GUI工具,进行各项编译选项的配置,本文配置界面如下:
    3.             
    4. 点击configue,下方提示Configuring done后,点击Generate,等待Generating done后完成编译设置。如果中间有报错,请检测各路径设置是否正确。

    三、编译生成tensorflow库文件

    1.  打开visual studio2015,打开E:TF Code ensorflow ensorflowcontribcmakeuild下的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文件就可以编译出来了,生成的库文件路径在.. ensorflow ensorflowcontribcmakeuildRelease下。

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

    1. 在vs2015中创建一个新的Win32控制台工程TestTensorFlow,注意也必须把编译平台设置成
    2. 新建一个TestTensorFlow.h,在其中输入
      #pragma once
      
      #define COMPILER_MSVC
      #define NOMINMAX  
    3. 对应的TestTensorFlow.CPP文件中输入如下:
      // TestTensorFlow.cpp : 定义控制台应用程序的入口点。
      //
      #include "stdafx.h"
      
      #include <vector>
      #include <eigen/Dense>
      
      #include "TestTensorFlow.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();
      } 
    4.  设置要包含的tensorflow头文件路径,右键项目属性——C/C++——附加包含目录
      E:TF Code	ensorflow	ensorflowcontribcmakeuildDebug
      E:TF Code	ensorflow	ensorflowcontribcmakeuildexternal
      syncpublic
      E:TF Code	ensorflow	ensorflowcontribcmakeuildprotobufsrcprotobufsrc
      E:TF Code	ensorflow	ensorflowcontribcmakeuildexternaleigen_archive
      E:TF Code	ensorflow	ensorflowcontribcmakeuild
      E:TF Code	ensorflow
      E:TF Code	ensorflow	hird_partyeigen3
    5.  引入tensorflow.lib文件,右键项目——添加——现有项,找到.. ensorflow ensorflowcontribcmakeuildRelease下的tensorflow.lib 

                 

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

                

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

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

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

         

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

           参考:

    1. https://www.cnblogs.com/jliangqiu2016/p/7642471.html
    2. http://www.qingpingshan.com/m/view.php?aid=322808
  • 相关阅读:
    交叉编译OpenCV的教程——基于aarch64-linux-gnu的交叉编译器
    Day01:我的Python学习之路
    将中文库导入到ARM板子中以解决中文显示乱码的教程
    Linux环境下挂载SD卡的教程
    Ubuntu下压缩与解压各种文件的命令
    Ubuntu14.04环境下Qt5.5以上版本无法输入中文的解决教程
    编程之美:队列中的最大最小值
    leetcode:Compare Version Numbers
    leetcode:Search for a Range
    csapp:无符号数可能造成的程序bug
  • 原文地址:https://www.cnblogs.com/steven_oyj/p/8259205.html
Copyright © 2020-2023  润新知