【轉】VS2015編譯TensorFlow C++程式完全攻略
原文地址:https://blog.csdn.net/jacke121/article/details/80473648
本文參考和綜合了多篇網路部落格文章,加以自己的實踐,最終終於在windows環境下,編譯出可以用於C++程式呼叫tensorflow API的程式,並執行成功
考慮到網路上關於這方面的資料還較少,特總結全過程如下,希望能幫助到有需要的碼農朋友,文中有部分文字步驟是借鑑他人文章,引用路徑在最後列出。
一、環境準備:
- 安裝visual stduio2015
- 安裝Swigwin-3.0.12,注意其下載解壓以後即可使用,本人放置路徑在D:/lib/swigwin-3.0.12,可執行檔案地址為 D:/swigwin-3.0.12/swig.exe
- 安裝python3.6,安裝時注意選擇將路徑新增到環境變數。
- 安裝CMake-3.8.0 ,安裝時注意選擇將路徑新增到環境變數。
- 安裝Git,用於在編譯過程中從GitHub上下載依賴項。
- 將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設定各項編譯引數
- 開啟下載tensorflow原始檔的根目錄,本文路徑是E:TF Code/TensorFlow,在路徑下進入../tensorflow\contrib\cmake, 新建資料夾\build。
- 開啟已安裝的CMAKE-GUI工具,進行各項編譯選項的配置,本文配置介面如下:
- 點選configue,下方提示Configuring done後,點選Generate,等待Generating done後完成編譯設定。如果中間有報錯,請檢測各路徑設定是否正確。
三、編譯生成tensorflow庫檔案:
- 開啟visual studio2015,開啟E:\TF Code\tensorflow\tensorflow\contrib\cmake\build下的ALL_BUILD專案。我們在此只以release版本為例,所以檢查編譯平臺是
- 點選生成解決方案,編譯的時間很長,我的膝上型電腦編譯一次大概3到4個小時,編譯到最後一般都會報錯
fatal error C1060: compiler is out of heap space 沒關係,等待整個工程全部編譯完成(據說記憶體特別大的電腦不會報)。
-
找到tf_core_kernels專案,右鍵單獨編譯,操作如下圖。
4. tf_core_kernels專案編譯成功後,再同樣對tensorflow_static作單獨編譯,最後再對tensorflow作單獨編譯。.
這樣tensorflow.lib和tensorflow.dll檔案就可以編譯出來了,生成的庫檔案路徑在
..\tensorflow\tensorflow\contrib\cmake\build\Release下。
四、使用tensorflow庫檔案編寫C++程式
- 在vs2015中建立一個新的Win32控制檯工程TestTensorFlow,注意也必須把編譯平臺設定成。
- 新建一個TestTensorFlow.h,在其中輸入
1
2
3
4
#pragma once
#define COMPILER_MSVC
#define NOMINMAX
- 對應的TestTensorFlow.CPP檔案中輸入如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// 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
();
}
- 設定要包含的tensorflow標頭檔案路徑,右鍵專案屬性——C/C++——附加包含目錄
- D:\soft\tensorflow-r1.6\tensorflow\contrib\cmake\build\Release
D:\soft\tensorflow-r1.6\tensorflow\contrib\cmake\build\external\nsync\public
D:\soft\tensorflow-r1.6\tensorflow\contrib\cmake\build\protobuf\src\protobuf\src
D:\soft\tensorflow-r1.6\tensorflow\contrib\cmake\build
D:\soft\tensorflow-r1.6
lib目錄:
D:\soft\tensorflow-r1.6\tensorflow\contrib\cmake\build\Release
PLATFORM_WINDOWS
報錯1:
嚴重性 程式碼 說明 專案 檔案 行 禁止顯示狀態
錯誤 C3872 “0x3000”: 此字元不允許在識別符號中使用 tf_test01 e:\project\tf_test01\tf_test01\TestTensorFlow.h 5
原因:有中文空格
報錯2:
嚴重性 程式碼 說明 專案 檔案 行 禁止顯示狀態
錯誤 C1014 包含檔案太多: 深度 = 1024 tf_test01 D:\soft\tensorflow-r1.6\third_party\eigen3\unsupported\Eigen\CXX11\Tensor 1
標頭檔案引用重複:unsupported:
D:\soft\tensorflow-r1.6\tensorflow\contrib\cmake\build\external\eigen_archive
D:\soft\tensorflow-r1.6\third_party\eigen3
刪掉標頭檔案引用:
D:\soft\tensorflow-r1.6\third_party\eigen3 - 引入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功能有不匹配,但是不影響執行結果,有知道如何解決的朋友可以留言給我,謝謝。
參考:https://www.cnblogs.com/steven_oyj/p/8259205.html