linux 下 tensorflow C++ CPU編譯過程記錄,已編譯CPU庫直接下載(測試ubuntu18.04、ubuntu20、debian10測試未發現依賴問題)
背景(跳過,並沒有什麼用)
最近專案中要做一個NSFW檢測,在網上找到一個別人訓練好的tensorflow 的PB模型,但是程式碼是Python, 想用C++ 去呼叫這個模型,預測。
因為我覺得C++ 首先客戶部署簡單(和客戶確定好libc基礎下),只需要整理好相關.so檔案,不像python,除了搭建環境外,還需要通過pip安裝很多依賴。客戶操作步驟越多,就越容易部署過程中出問題。
之所以寫這篇隨筆,主要因為在百度搜索tensorflow編譯時,大部分都在說直接系統下編譯,這樣很可能會出現問題,因為每個linux發行版的glic、gcc預設安裝版本會有區別,比如我本機使用debian 10,在apt-get install gcc時,會裝gcc 11,如果是ubuntu 18 apt-get install gcc時, 會裝gcc7。
我一開始也是在本機中使用gcc11編譯,喜提gcc編譯錯誤。
這一點在官網中有宣告:https://tensorflow.google.cn/install/source?hl=zh_cn
也就是說,最好使用gcc7版本進行編譯。
如果你當前是ubuntu,可以嘗試在本機編譯,如果其他發行版,強烈建議docker 內下載ubuntu 編譯,編譯完成後,取出so庫到生產環境。
經測試, debian10、ubuntu 18.04、ubuntu 20.04,在docker ubuntu 18.04環境下編譯出來的tensorflow庫,可以直接使用。
首先,建議使用隨筆最下方提供的連結,下載已編譯好的SO庫,和整理好的標頭檔案,嘗試直接呼叫。
整體步驟
強烈建議docker 內下載ubuntu 編譯
0. 真機擴大記憶體,可以動態生成swap檔案: swapon swap檔案路徑新增swap記憶體,具體百度
1. 安裝docker、下載ubuntu 18.04
2. 進入虛擬環境,搭建安裝編譯所需要的bazel、gcc、g++、python3、python3-dev、git...
3. git 拉取指定版本tensorflow
4. 執行tensorflow 中的configure程式,生成構建檔案。
5. bazle 編譯
6. 使用docker cp,把docker內ubuntu中編譯好的so庫提取到生產環境。
編譯環境
因為是在docker中構建的,所以就不過多介紹真機環境
tensorflow: 1.15.4
bazel: 3.1.0
bazel 下載慢,可以使用華為雲映象:https://mirrors.huaweicloud.com/bazel/
docker: ubuntu 18.04
記憶體: 8G, 交換空間(磁碟空間當記憶體): 8G
主要注意一下記憶體,必須10G以上,因為bazel編譯時,會時不時佔用很大記憶體,如果記憶體不夠用電腦就會因為記憶體不夠卡死。
在tensorflow官網中介紹構建時使用 --local_ram_resources=2048 引數限制記憶體在2G左右,但我嘗試了一下並沒有效果。
gcc: 7.5.0
初始化環境
使用docker 進入ubuntu 容器,執行:
apt-get update apt-get install git python3 python3-dev vi wget unzip python3-pip # 編譯時會涉及到python指令碼執行,用到了numpy pip3 install numpy # 建立python3軟連線,python 指令碼執行,預設使用python命令 ln -s /usr/bin/python3 /usr/bin/python
拉取專案:
git clone -b v1.15.4 https://gitee.com/mirrors/tensorflow.git
下載bazel:
我使用的是tensorflow 1.15.4, bazel版本是:3.1.0。
如果不清楚該使用什麼版本bazel,可以先隨意下載一個版本,執行./configure,如果版本不對,會告訴當前bazel版本不對,應使用那個版本。
通過wget 下載以上兩個檔案中其中一個,一個是安裝sh指令碼,一個是可執行二進位制檔案:
wget https://mirrors.huaweicloud.com/bazel/3.1.0/bazel-3.1.0-installer-linux-x86_64.sh chmod +x bazel-3.1.0-installer-linux-x86_64.sh ./bazel-3.1.0-installer-linux-x86_64.sh
ps: 使用指令碼安裝,要保證本機已安裝unzip,上方搭建環境中已把unzip加入到其中
生成編譯檔案
# 進入tensorflow 專案目錄下,執行
./configure
一路回車,主要是選擇Python路徑、GPU選項等等
開始編譯
1. 編譯前,要確保記憶體(實體記憶體+交換空間swap)在10G以上,最好16G,不然會編譯時耗盡記憶體卡死,最後被系統殺死
2. 編譯過程中,會去github倉庫下載專案,由於國內github不穩定,這個過程是很容易出錯的,出錯內容不僅僅是timeout,有可能是no search xxx,當出錯後,反覆多嘗試幾次
建議白天編譯,晚上早上好像github會很慢。如果有條件,da梯子編譯最好。
3. 當你到達這一步的時候,那麼恭喜你,編譯過程最困難的地方已經結束了,到這裡基本不會有其他問題了(保證是GCC7)。
4. 建議在機器效能好的環境下編譯,不然編譯會很慢
bazel build --config=opt //tensorflow:libtensorflow_cc.so
ps: 注意,//tensorflow:libtensorflow_cc.so 不是註釋,這也是bazel引數一部分!!一定要複製全了,不能光是bazel build --config=opt
提出庫檔案
編譯成功後,進入bazel-bin/tensorflow目錄下,正常情況會有so庫檔案:
把庫打包,通過docker cp 複製到宿主機環境:
tar -zcvf lib.tar *.so*
宿主機下:
docker cp {docker 容器ID}:/{bazel編譯路徑}/lib.tar /{宿主機目錄}
已編譯庫連結
連結: https://quqi.avyeld.com/s/6273754/oBIsB31RssXZ5s4D
加壓後執行build.sh,通過g++ 構建hello world程式,需要把libtensorflow_cc.so.2.5.0和libtensorflow_framework.so.2.5.0放到系統庫目錄下。
g++11,使用此庫構建成功。