1. 程式人生 > >TensorFlow-1.11.0 原始碼編譯&C++ API使用

TensorFlow-1.11.0 原始碼編譯&C++ API使用

『寫在前面』 關於tf,一種常見的使用方式是:線上下使用TensorFlow的Python Binding搭建和訓練模型,然後利用freeze_graph工具等工具輸出*.pb檔案(或使用tf.train.Saver儲存成*.meta檔案和checkpoint檔案),最後在線上使用C++呼叫預訓練好的模型進行inference。之前趟過一遍TF1.3.1,坑很多,有點後悔當時沒有記錄,主要還是在依賴包版本和系統相容性上,當時是在CentOS 7下編譯成功,MacOS下一直沒弄成。最近又需要整理一版使用,果斷選擇了當前最新的1.11版來試驗(貌似1.12也出了。。),果然坑少了很多,我首先在Mac下嘗試了一下,具體細節記錄如下,如有失誤歡迎指正。

版本說明

工具包安裝

  1. Protobuf
./autogen.sh
./configure --prefix=/usr/local
make -j4
sudo make install

\qquad安裝完畢,通過protoc --version驗證。

  1. Eigen 免安裝 直接引用原始檔即可

  2. bazel

  • MacOs下可以直接brew install bazel
  • 離線安裝建議使用shell指令碼,裡面各種依賴都已配好,指定一個安裝路徑,直接安裝即可。
sh bazel-0.5.4-installer-darwin-x86_64.sh --prefix=/some/path

編譯TensorFlow

有網環境下

  1. 首先執行./configure,根據自己實際情況進行選擇,我是一路N下來的?
  2. 使用bazel編譯Tensorflow原始碼,生成動態連結庫檔案,在原始碼包根目錄執行以下命令:
bazel build -c opt --copt=-msse3 --copt=-msse4.1 --copt=-msse4.2 --copt=-mavx --copt=-mavx2 --copt=-mfma tensorflow:libtensorflow_cc.so

無網環境下

\qquad如果伺服器無法連線外網,則會因為無法下載所需的依賴包而導致build失敗。 \qquad解決方法是將所需依賴項依次下載到本地,然後修改rootdir/WORKSPACE檔案和rootdir/tensorflow/workspace.bzl檔案。同樣在根目錄執行上述編譯指令,此時會自動從本地載入已經下載好的依賴包。

修改bzl檔案等的方法,將urls一項修改為本地路徑即可。例:

http_archive(
    name = "io_bazel_rules_closure",
    sha256 = "bc41b80486413aaa551860fc37471dbc0666e1dbb5236fb6177cb83b0c105846",
    strip_prefix = "rules_closure-dec425a4ff3faf09a56c85d082e4eed05d8ce38f",
    urls = [
        "file://///home/xxx/tf_deps/dec425a4ff3faf09a56c85d082e4eed05d8ce38f.tar.gz",
    ],
)

小結

\qquad編譯完成後,根目錄結構如下: 編譯結果 \qquad依次執行以下指令將所需標頭檔案和庫檔案安裝到系統目錄或其他目錄下:

mkdir /usr/local/include/google
cp -r tensorflow /usr/local/include/google
cp -r third_party /usr/local/include/google
cp -r bazel-genfiles /usr/local/include/google
cp -r bazel-bin/tensorflow/libtensorflow_cc.so /usr/local/lib/

\qquad其實第一個cp其實只需要將tensorflow資料夾中的標頭檔案拷走即可,命令列玩的不6所以就不獻醜了。。以上是大多數blog中都會提及的檔案,我在使用過程中發現新版本TF有一個小坑?會去找一個bazel輸出目錄下的標頭檔案\qquad/private/var/tmp/路徑下有一個名字叫_bazel_username的資料夾,在這個目錄下找到和先前TF根目錄bazel-bin連結的實際路徑對應的那一長串(MD5?)的資料夾,將該資料夾下的???/external/com_google_absl/absl統統拷走,同樣拷到/usr/local/include/google下就好了。

使用方法

CMakeLists.txt編寫

注意不但需要設定TF的include路徑,還需要設定protobuf和eigen的路徑。

set(Pjt_name cpp_tf)
cmake_minimum_required(VERSION 3.6)

set(CMAKE_CXX_STANDARD 11)

set(SOURCE_FILES main.cpp)

set(TF_DIR /usr/local/include/google/)
set(Eigen_DIR <指到Eigen原始碼包一級>)
set(Protobuf_DIR ***/protobuf-3.6.0/src)
include_directories(${TF_DIR} ${Eigen_DIR} ${Protobuf_DIR})

link_directories(/usr/local/lib)

add_executable(${Pjt_name} ${SOURCE_FILES})
target_link_libraries(${Pjt_name} tensorflow_cc)

Demo

#include <tensorflow/core/platform/env.h>
#include <tensorflow/core/public/session.h>

#include <iostream>

using namespace std;
using namespace tensorflow;

int main()
{
    Session* session;
    Status status = NewSession(SessionOptions(), &session);
    if (!status.ok()) {
        cout << status.ToString() << "\n";
        return 1;
    }
    cout << "Session successfully created.\n";
    return 0;
}

關於預訓練模型呼叫及其他TF C++ API的使用,後續有時間我會再整理補充,個人認為主要分為以下幾步:載入模型及網路引數,構建輸入Tensor,Run Session,處理輸出