1. 程式人生 > >win10編譯tensorflow C++介面

win10編譯tensorflow C++介面

首先,我覺得這是一個比較DT的活,因為,tensorflow支援最好的程式語言應該是python(應該說大部分深度學習框架支援的最好的語言都是Python),tensorflow的底層說是C/C++編寫的,但是,感覺它對C/C++真的很不友好,有關Python的資料一查一大把,有關C/C++的一查寥寥無幾,能看到的還有很多直接就照搬官網的那點少到可憐的例子...由於我可能會比較多的用C/C++來開發,所以,有點希望用上C/C++的API,所以才有了這篇筆記。

好了,就不廢話了,在此先推薦一篇之前參考的文章,寫得比較清楚了,但是我覺得可能還有點不太準確,或者說我沒遇到的問題,或者說我不是這麼解決的。

OK,廢話不多說,直接上方法:

1、需要準備的東西

首先是軟體:CMake Gui,我這裡用的是CMake 3.11.0,基本上3.0以上的應該都OK;VS2015(社群版免費的,基本就可以了);CUDA9.0以及配套的cudnn7(深度學習必備精品,用CPU的那就不需要了);Anaconda,官網或者去清華映象下載(python大蟒蛇的絕佳工具,學習和使用深度學習技術應該還是有必要弄一個的吧);swigwin-3.0.12(這個我不太清楚是幹啥的,但是有用);梯子(梯子可以解決我參考的那篇部落格提到的某些問題,當然這些問題其實也可以用部落格的方法解決的);原始碼(我下載的是tensorflow1.8的,因為我電腦上裝的就是tensorflow1.8 Python版本的);Git(這很重要,編譯過程中要下載檔案的,就是通過Git);

2、Cmake原始碼

以上材料和開發環境我就預設是裝好的,Anaconda比較好辦,參考我之前的一篇筆記,有很簡單粗暴易行的方法,其他方法發也很簡單,基本能搜到N多教程。然後解壓下載下來的原始碼,用Cmake GUI開啟,並設定原始碼路徑和Cmake出來的工程路徑:

image.png

然後按左下角的image.png,配置工程,然後回報錯的:

image.png

這裡是由於沒有設定SWIG的路徑,SWIG再官網下載後解壓出來就可以了,然後新增到

image.png

中,然後再次點選Configure再配置一遍,然後就修改一些專案

image.png

image.png

image.png

image.png

image.png

tensorflow項裡面,有梯子的話就可以這樣做:

image.png

如果沒有梯子的話就這樣:

image.png

沒有GPU的話就把tensorflow_ENABLE_GPU也去掉吧。

然後再次點選Configure配置一邊工程,沒有報錯的話就點選generate生成工程。

3、VS2015編譯

用VS2015開啟vs14_project/tensorflow.sln工程,整個工程Cmake出來時包含274個專案在裡面:

image.png

首先修改配置屬性,改為x64下的Release(因為Anaconda的時Release的,沒有Debug,所以這裡最好編譯Release的,Debug可能會有錯誤,而且編譯一個就差不多9G+了,不想嘗試編譯Debug了),之後需要修改前面五個檔案的配置屬性:

image.png

配置好後修改一個檔案tensorflow\contrib\boosted_trees\lib\utils\sparse_column_iterable.cc,將第99~101行註釋掉,改為:

bool operator<( const IndicesRowIterator& other ) const {
    QCHECK_LT( iter_, other.iter_ );
    return ( row_idx_ < other.row_idx_ );
}

image.png

然後就右擊解決方案生成解決方案,這個過程會超級久,因為還要下載很多依賴項,甚至回有一點卡,我查了下工作管理員,主要時比較耗記憶體和CPU,CPU佔有幾乎快滿了。然後我是會出現一個問題,跟tf_core_gpu_kernel編譯不過有關的(看了下錯誤,感覺應該時跟訪問許可權有關,我的CUDA和VS都是裝在C盤的,應該就導致訪問許可權不足,目測是這個原因),這個時候就關閉VS,然後以管理員身份執行VS2015,然後再開啟tensorflow工程,然後點編譯解決方案(不要重新編譯,點編譯就可以,不然又得花很多時間),然後這一項會編譯很久,超級久的,以至於我都一度懷疑人生。然後還有一個DT的事情,tf_core_kernel編譯的時候是很容易出現“compiler is out of heap space”導致這一項編譯失敗,然後就會出現別的問題,這個時候就是再點編譯專案就可以了,再次編譯但是不是重新編譯,然後就可以了,因為在編譯這一項的時候是很佔CPU的,CPU幾乎就爆滿了,所以容易出現問題。

基本上這麼做之後就可以編譯通過了,但是我這邊會有一個錯誤,跟Python API有關的,tf_python_api這一項我沒有編譯過,還是報了“cmd.exe”的錯誤,可能是跟我已經裝了tensorflow的python版有關吧,具體沒有查,因為這不是我的目的,況且我電腦上已經有tensorflow的Python版,所以這個我就忽略了,也不是很需要這個。

接下來就是打包標頭檔案和lib檔案、dll檔案,在解決方案中找到INSTALL工程,右鍵單獨對其進行編譯,編譯完成之後就回把相關的標頭檔案、lib檔案、dll檔案和exe檔案(如果需要的話可以找我要打包出來的檔案,編譯這個還挺花時間的)。

編譯好之後做一下小的測試,試驗一下是不是可以用。

4、測試

首先,新建一個控制檯應用程式,然後在工程中新增打包出來的標頭檔案和lib檔案的路徑,程式碼如下:

#include "stdafx.h"
     
#define COMPILER_MSVC
#define NOMINMAX
     
#include <vector>
#include <Eigen/Dense>
    
#include "tensorflow/core/public/session.h"
#include "tensorflow/cc/ops/standard_ops.h"
#include "tensorflow/cc/ops/training_ops.h"
#include "tensorflow/core/framework/graph.pb.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();
     
    return 0;
}

程式的輸出資訊如下:

image.png

跟Python版一樣,也是會先顯示一段系統和硬體資訊,然後是輸出結果,關於程式碼中的變數和函式等都是什麼意思,或者怎麼樣些一個C++的tensorflow程式,後面我再研究研究吧,不過我Python版都不太會寫,所以就還是要花點時間。

原文地址:https://www.bearoom.xyz/2018/08/28/win10%e7%bc%96%e8%af%91tensorflow-c%e6%8e%a5%e5%8f%a3/