Windows下編譯TensorFlow1.3 C++ library及建立一個簡單的TensorFlow C++程式
由於最近比較忙,一直到假期才有空,因此將自己學到的知識進行分享。如果有不對的地方,請指出,謝謝!目前深度學習越來越火,學習、使用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行修改如下:
1 2 3 4 5 6 7 8 9 10 11 12 |
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.12/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 2 3 4 5 |
# 指令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.0\V140\Microsoft.CppCommon.targets(171,5): error MSB6006: “cmd.exe”已退 出,程式碼為 1。 [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上編譯和執行一個簡單的TensorFlowC++ 程式
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({ -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.2在對應的標頭檔案中輸入如下:
#pragma once #define COMPILER_MSVC #define NOMINMAX
4.3在vs2015中,屬性配置介面中,includeDirectories:
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編譯和執行程式,執行結果如下所示:
7 17 -1 -3
參考:
https://joe-antognini.github.io/machine-learning/build-windows-tf
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