Mac 下 TensorFlow C++ API 的編譯與測試
在前篇博客介紹了從源碼編譯 TensorFlow 的 .whl 文件, 以便用 pip 進行安裝. 本文介紹 TensorFlow C++ API 的編譯與測試, 爲後續用 C++ 玩耍 TF 打下基礎 😂😂😂.
準備工作
- Python 環境準備
我採用的是 Anaconda3-4.2.0
發行版, Python 的版本爲 3.5.2
.
- 下載 TensorFlow 源碼, 此處我仍然是編譯 TensorFlow r1.10 版本, 因此下載完源代碼後, 使用 git 進行分支切換
git clone --recursive https://github.com/tensorflow/tensorflow ## 下載 TensorFlow
cd tensorflow/ ## 最好備份一份源代碼
git checkout -b r1.10 ## 切換到 r1.10 版本
- 安裝 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 ~/.bashrc
或 exec $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
看是否能得到輸出結果.
- 安裝
automake
, 後續編譯會用上, 比如 autoconf.
brew install automake
開始編譯
- 首先要進行設定一些安裝選項. 進入
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
- 使用 Bazel 進行源碼編譯
bazel build //tensorflow:libtensorflow_cc.so
等待近一個小時, 編譯即可完成. 中間如果報錯, Google 吧~. 我到這步沒有出現啥問題.
- 完成編譯之後, 會在當前目錄下生成多個目錄:
├── bazel-bin
├── bazel-genfiles
├── bazel-out
├── bazel-tensorflow
├── bazel-testlogs
可以在 bazel-bin/tensorflow
目錄下看到編譯好後的 libtensorflow_cc.so
文件以及 libtensorflow_framework.1.dylib
文件.
- 編譯其他依賴, 比如 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 愉快的玩耍了~ (淚流滿面) 🥺🥺🥺
參考資料
- Linux環境下編譯TensorFlow C++ API和測試方法總結(完美版) 這不是標題黨, 而是貨真價實的詳細資料, 如果遇到問題, 推薦參考. 比如要編譯 GPU 版本可以去翻翻. 👍👍👍
- Tensorflow c++ 實踐及各種坑 還未細看, 以後應該用得着, 先 Mark 一波
- tensorflow C++ api 可以參考
- tensorflow c++ API的編譯和調用 先存着, 也許以後用得着, 裏面的參考資料也不錯 (雖然還沒看, 從標題可以感覺到)