Mac 下 TensorFlow C++ API 的編譯與測試

Mac 下 TensorFlow C++ API 的編譯與測試

前篇博客介紹了從源碼編譯 TensorFlow 的 .whl 文件, 以便用 pip 進行安裝. 本文介紹 TensorFlow C++ API 的編譯與測試, 爲後續用 C++ 玩耍 TF 打下基礎 😂😂😂.

準備工作

  1. Python 環境準備

我採用的是 Anaconda3-4.2.0 發行版, Python 的版本爲 3.5.2.

  1. 下載 TensorFlow 源碼, 此處我仍然是編譯 TensorFlow r1.10 版本, 因此下載完源代碼後, 使用 git 進行分支切換
git clone --recursive https://github.com/tensorflow/tensorflow   ## 下載 TensorFlow
cd tensorflow/  ## 最好備份一份源代碼
git checkout -b r1.10  ## 切換到 r1.10 版本
  1. 安裝 Bazel. 需要注意 Bazel 的版本有較爲嚴格的要求, 雖然在前篇博客介紹了某版本的 Bazel, 但這裏更新下思路, 應查看 tensorflow/configure.py, 搜索 Bazel 關鍵字, 查詢到:
_TF_MIN_BAZEL_VERSION = '0.24.1'
_TF_MAX_BAZEL_VERSION = '0.26.1'

清楚地指明瞭合適的 Bazel 版本, 這裏我選擇了 0.26.1, 於是到 https://github.com/bazelbuild/bazel/releases/tag/0.26.1 下載 Mac 版本:

mkdir ~/Programs
cd ~/Programs
wget https://github.com/bazelbuild/bazel/releases/download/0.26.1/bazel-0.26.1-darwin-x86_64

在當前目錄下得到 bazel-0.26.1-darwin-x86_64, 重命名並增加執行權限:

mv bazel-0.26.1-darwin-x86_64 bazel
chmod +x bazel

爲了隨時能訪問 bazel, 需要將其路徑加入到環境變量中, 修改 ~/.zshrc 或者 ~/.bashrc 文件, 增加:

export PATH=$PATH:~/Programs

執行 source ~/.zshrc 或者 source ~/.bashrcexec $SHELL 後, 再執行:

bazel version

## 輸出結果
Build label: 0.26.1
Build target: bazel-out/darwin-opt/bin/src/main/java/com/google/devtools/build/lib/bazel/BazelServer_deploy.jar
Build time: Thu Jun 6 11:08:11 2019 (1559819291)
Build timestamp: 1559819291
Build timestamp as int: 1559819291

看是否能得到輸出結果.

  1. 安裝 automake , 後續編譯會用上, 比如 autoconf.
brew install automake

開始編譯

  1. 首先要進行設定一些安裝選項. 進入 tensorflow/ 源碼目錄下, 並執行 ./configure 文件, 會要求進行一些配置, 一律選擇 N, 少給自己添堵~ 😂😂😂
cd tensorflow/
./configure

WARNING: Running Bazel server needs to be killed, because the startup options are different.
WARNING: --batch mode is deprecated. Please instead explicitly shut down your Bazel server using the command "bazel shutdown".
You have bazel 0.26.1 installed.
Please specify the location of python. [Default is anaconda3-4.2.0/bin/python]: ## 默認的話則按 Enter 進行確認, 否則添加新的路徑

Found possible Python library paths:
  anaconda3-4.2.0/lib/python3.5/site-packages
Please input the desired Python library path to use.  Default is [anaconda3-4.2.0/lib/python3.5/site-packages] ## 默認則按 Enter

Do you wish to build TensorFlow with XLA JIT support? [Y/n]: ## n
No XLA JIT support will be enabled for TensorFlow.

Do you wish to build TensorFlow with OpenCL SYCL support? [y/N]: ## n
No OpenCL SYCL support will be enabled for TensorFlow.

Do you wish to build TensorFlow with ROCm support? [y/N]: ## n
No ROCm support will be enabled for TensorFlow.

Do you wish to build TensorFlow with CUDA support? [y/N]: ## n
No CUDA support will be enabled for TensorFlow.

Do you wish to download a fresh release of clang? (Experimental) [y/N]: ## n
Clang will not be downloaded.

Please specify optimization flags to use during compilation when bazel option "--config=opt" is specified [Default is -march=native -Wno-sign-compare]: ## n


Would you like to interactively configure ./WORKSPACE for Android builds? [y/N]: ## n
Not configuring the WORKSPACE for Android builds.

Do you wish to build TensorFlow with iOS support? [y/N]: ## n
No iOS support will be enabled for TensorFlow.

## ...
Configuration finished
  1. 使用 Bazel 進行源碼編譯
bazel build //tensorflow:libtensorflow_cc.so

等待近一個小時, 編譯即可完成. 中間如果報錯, Google 吧~. 我到這步沒有出現啥問題.

  1. 完成編譯之後, 會在當前目錄下生成多個目錄:
├── bazel-bin
├── bazel-genfiles
├── bazel-out
├── bazel-tensorflow
├── bazel-testlogs

可以在 bazel-bin/tensorflow 目錄下看到編譯好後的 libtensorflow_cc.so 文件以及 libtensorflow_framework.1.dylib 文件.

  1. 編譯其他依賴, 比如 Eigen3, Protobuf, Nsync 等庫:
cd tensorflow/  ## 先進入到 tensorflow 的源碼目錄
cd tensorflow/contrib/makefile
./build_all_linux.sh ## 執行該腳本, 對依賴項進行編譯

等待數十分鐘, 完成依賴項的編譯. 此時將在 tensorflow/contrib/makefile/downloads 目錄下看到各個編譯好的依賴項, 包含頭文件以及靜態庫等. 期間曾報錯 autoconf not found, 是因爲前面 brew install automake 中的 automake 忘了安裝.

測試用例

完成 TF 的編譯之後, 就要寫點 C++ 代碼來測試下有沒有效果了. 這裏參考 Linux環境下編譯TensorFlow C++ API和測試方法總結(完美版) 中的測試用例一, 並對 CMakeLists.txt 文件進行了修改, 以符合我的需要.

首先創建一個目錄, 用於存放自己寫的測試代碼 test.cpp:

mkdir local
cd local
vim test.cpp
vim CMakeLists.txt

其中 test.cpp 中的內容爲:

#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";
}

CMakeLists.txt 中的內容爲:

#指定 cmake 的最小版本
cmake_minimum_required(VERSION 2.8.8)
#項目名稱/工程名
project(demo)
#設置c++編譯器
# Set C++14 as standard for the whole project
set(CMAKE_CXX_STANDARD 14)
#設置TENSORFLOW_DIR變量,變量內容爲安裝的tensorflow文件夾路徑
set(TENSORFLOW_DIR /Users/xxx/Codes/Python/BuildTF/tensorflow) ## 注意這裏是我的 TensorFlow 源碼目錄
# 將源碼目錄保存到變量中
aux_source_directory(. DIR_SRCS)  # 搜索當前目錄下的所有.cpp文件  
#add_library(demo ${SRC_LIST})   #明確指定包含哪些源文件                 
#設置包含的目錄,項目中的include路徑,換成自己的路徑即可, 注意包含了 TensorFlow 本身以及第三方依賴庫的路徑
include_directories( 
    ${CMAKE_CURRENT_SOURCE_DIR}

    ${TENSORFLOW_DIR}
    ${TENSORFLOW_DIR}/bazel-genfiles
    ${TENSORFLOW_DIR}/bazel-bin/tensorflow
    ${TENSORFLOW_DIR}/tensorflow/contrib/makefile/downloads/nsync/public
    ${TENSORFLOW_DIR}/tensorflow/contrib/makefile/downloads/eigen
    ${TENSORFLOW_DIR}/tensorflow/contrib/makefile/downloads/absl
    ${TENSORFLOW_DIR}/tensorflow/contrib/makefile/downloads/protobuf
    ${TENSORFLOW_DIR}/tensorflow/contrib/makefile/downloads/protobuf/src
   ) 
#設置鏈接庫搜索目錄,項目中lib路徑
link_directories(${TENSORFLOW_DIR}/tensorflow/contrib/makefile/downloads/nsync/builds/default.macos.c++11)
link_directories(${TENSORFLOW_DIR}/bazel-bin/tensorflow)  #動態鏈接庫目錄
#添加要編譯的可執行文件
#add_executable(demo test.cpp)
add_executable(demo ${DIR_SRCS})    ## 生成可執行文件
#設置 target 需要鏈接的庫
#添加可執行文件所需要的庫,連接libtensorflow_cc.so和libtensorflow_framework庫,鏈接動態鏈接庫
#target_link_libraries(demo tensorflow_cc tensorflow_framework)
## 其中 ${TENSORFLOW_DIR}/bazel-bin/tensorflow/libtensorflow_framework.1.dylib 不添加也能成功編譯
target_link_libraries(demo ${TENSORFLOW_DIR}/bazel-bin/tensorflow/libtensorflow_cc.so ${TENSORFLOW_DIR}/bazel-bin/tensorflow/libtensorflow_framework.1.dylib)

完成以上步驟後, 在當前目錄下創建 build 目錄, 並執行如下命令對 test.cpp 進行編譯:

mkdir build   #創建build文件,是爲了將編譯程序放到build文件中
cd build
cmake ..   #使用cmake構建生成make文件
make       #使用make編譯
./demo    #運行可執行文件

得到如下結果:

2020-04-26 23:20:31.366661: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.2 AVX AVX2 FMA
Session successfully created.

說明代碼被成功編譯了!

以後可以和 TensorFlow C++ API 愉快的玩耍了~ (淚流滿面) 🥺🥺🥺

參考資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章