1. 程式人生 > >小米開源AI框架mace編譯構建

小米開源AI框架mace編譯構建

目錄

簡介

環境要求

簡介

MACE是一種針對移動異構計算平臺優化的深度學習推理框架。

編譯系統:虛擬機器 ubuntu 16.04 LTS

環境要求

MACE需要以下依賴項:

Software Installation command Tested version
Python 2.7
CMake apt-get install cmake >= 3.11.3
Jinja2 pip install -I jinja2==2.10 2.10
PyYaml pip install -I pyyaml==3.12 3.12.0
sh pip install -I sh==1.12.14 1.12.14
Numpy pip install -I numpy==1.14.0 Required by model validation
six pip install -I six==1.11.0 Required for Python 2 and 3 compatibility (TODO)
Software Installation command Remark
Android NDK Required by Android build, r15b, r15c, r16b, r17b
ADB apt-get install android-tools-adb Required by Android run, >= 1.0.32
TensorFlow pip install -I tensorflow==1.6.0 Required by TensorFlow model
Docker Required by docker mode for Caffe model
Scipy pip install -I scipy==1.0.0 Required by model validation
FileLock pip install -I filelock==3.0.0 Required by run on Android

注:如果在使用pip來進行安裝操作時碰到這樣的問題:pip Import Error:cannot import name main

解決方案:

sudo gedit /usr/bin/pip

將原來的:

from pip import main
if __name__ == '__main__':
    sys.exit(main())

改成:

from pip import __main__
if __name__ == '__main__':
    sys.exit(__main__._main())

1 安裝 Bazel

推薦尺寸大於bazel 0.13.0

使用以下方法之一在Ubuntu上安裝Bazel

  • 使用二進位制安裝程式(推薦)
  • 使用Bazel自定義APT儲存庫

方法一:使用二進位制安裝程式(推薦)

第1步:安裝所需的包
首先,安裝先決條件:pkg-config,zip,g++,zlib1g-dev,unzip,和python。

sudo apt-get install pkg-config zip g++ zlib1g-dev unzip python

第2步:下載Bazel
export BAZEL_VERSION=0.13.1
mkdir /bazel
cd /bazel
wget https://github.com/bazelbuild/bazel/releases/download/$BAZEL_VERSION/bazel-$BAZEL_VERSION-installer-linux-x86_64.sh

第3步:執行安裝程式
chmod +x bazel-*.sh
./bazel-$BAZEL_VERSION-installer-linux-x86_64.sh --user

第4步:刪除安裝包
cd /
rm -f /bazel/bazel-$BAZEL_VERSION-installer-linux-x86_64.sh

第5步:設定環境
該--user標誌將Bazel安裝到$HOME/bin系統上的目錄並設定.bazelrc路徑$HOME/.bazelrc。使用該--help命令可以檢視其他安裝選項。

如果您使用--user上面的標誌執行Bazel安裝程式,則Bazel可執行檔案將安裝在您的$HOME/bin目錄中。將此目錄新增到預設路徑,如下所示:

export PATH="$PATH:$HOME/bin"

也可以將此命令新增到~/.bashrc檔案中。

注:試過通過離線下載好的包進行安裝出現錯誤,後改成用wget線上下載進行安裝成功

如果安裝成功後輸入命令bazel 正常,使用sudo bazel卻提示找不到命令的話,解決方案如下:

以root使用者身份來編輯檔案/etc/sudoers
sudo vim /etc/sudoers

找到Defaults env_reset, 將其改為
Defaults        !env_reset  這裡加了這個感嘆號表示不重置環境變數

然後,編輯使用者根目錄下的配置檔案~/.bashrc
vim .bashrc

在檔案內最後追加
alias sudo='sudo env PATH=$PATH'

最後, 使配置檔案生效
source ~/.bashrc

方法二:使用Bazel自定義APT儲存庫

第1步:安裝JDK
安裝JDK 8:
sudo apt-get install openjdk-8-jdk

在Ubuntu 14.04 LTS上,必須使用PPA:
sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update && sudo apt-get install oracle-java8-installer

第2步:新增Bazel分發URI作為包源
注意:這是一次性設定步驟。

echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list
curl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -

如果要安裝Bazel的測試版,請替換stable為testing。

第3步:安裝和更新Bazel
sudo apt-get update && sudo apt-get install bazel

如果這一步出錯:
由於沒有公鑰,無法驗證下列簽名: NO_PUBKEY 7EA0A9C3F273FCD8
W: 倉庫 “http://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial InRelease” 沒有數字簽名。
N: 無法認證來自該源的資料,所以使用它會帶
解決辦法:(紅色字串是PUBKEY的後八位)
  sudo apt-key adv --recv-keys --keyserver keyserver.Ubuntu.com F273FCD8

安裝後,可以使用以下命令升級到較新版本的Bazel:
sudo apt-get upgrade bazel

注:安裝bazel最新版本0.17.1出現無法正常編譯mace

2 安裝Android NDK 

推薦的Android NDK版本包括r15b,r15c和r16b

# Download NDK r15c
cd /opt/
wget https://dl.google.com/android/repository/android-ndk-r15c-linux-x86_64.zip 
unzip android-ndk-r15c-linux-x86_64.zip 
rm -f android-ndk-r15c-linux-x86_64.zip


配置NDK系統環境變數

sudo vim /etc/profile

在檔案內最後追加

export ANDROID_NDK_VERSION=r15c
export ANDROID_NDK=/opt/android-ndk-${ANDROID_NDK_VERSION}
export ANDROID_NDK_HOME=${ANDROID_NDK}

# add to PATH
export PATH=${PATH}:${ANDROID_NDK_HOME}

檢視是否安裝成功
ndk-build

3 在Ubuntu16.04下安裝Docker(17.09)

1 安裝docker:sudo apt-get install docker.io
2 檢查版本: docker version 當出現client和service表面安裝成功
3 啟動docker:systemctl start docker.service
4 更新docker 
    4.1 需要使用apt-get來升級,藉助阿里的docker-ce源
    sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
  4.2 sudo apt-get update
  4.3 搜尋源 apt-cache madison docker-ce
 
  會出現版本,選擇一個
  4.4 sudo apt-get -y install docker-ce=17.09.0~ce-0~ubuntu --allow-unauthenticated
  4.5 檢視是否更新
    sudo docker version

構建並執行示例模型

首先,確保已經正確設定了環境

1 拉取MACE專案

git clone https://github.com/XiaoMi/mace.git
cd mace/
git fetch --all --tags --prune

# Checkout the latest tag (i.e. release version)
tag_name=`git describe --abbrev=0 --tags`
git checkout tags/${tag_name}
git clone https://github.com/XiaoMi/mace-models.git

3 構建通用MACE庫

cd path/to/mace
# Build library
# output lib path: builds/lib
bash tools/build-standalone-lib.sh

注:編譯時如果NDK沒有設定環境變數會提示未找到NDK則需要配置NDK路徑

在mace原始碼根目錄下有一個WORKSPACE檔案,請把你的NDK 路徑配置在android_ndk_repository下

NDK路徑是相對於mace原始碼的根目錄

# Set up Android NDK
android_ndk_repository(
    name = "androidndk",
    # Android 5.0
    api_level = 21,
    path="../../Android/Sdk/ndk-bundle",
)

4 將預先訓練的mobilenet-v2模型轉換為MACE格式模型

cd path/to/mace
# Build library
python tools/converter.py convert --config=/path/to/mace-models/mobilenet-v2/mobilenet-v2.yml

注: 在轉換模型過程中,如果mobilenet-v2.yml格式為code時,不知為何只要Android Studio開啟Demo工程就無法轉換成功,關閉後就可以,但是格式為file時就不存在此問題

編譯執行DEMO

位置:mace/examples/android

使用以下方法之一可以生成APK

  • 執行build.sh編譯
  • 使用Android Studio編譯

執行build.sh編譯

android工程目錄下有一個build.sh的配置檔案,執行就可以編譯,但是該配置使用的模型是mobilenet,該模型只有arm64-v8a平臺,而現在手機大部分是armeabi-v7a平臺,所以改成使用模型mobilenet-v2

第一步,修改build.sh檔案

開啟build.sh檔案

TARGET_ABI=arm64-v8a
修改成
TARGET_ABI=armeabi-v7a

python tools/converter.py convert --config=mace/examples/android/mobilenet.yml --target_abis=$TARGET_ABI
cp -rf builds/mobilenet/include/mace/public/*.h $INCLUDE_DIR
cp -rf builds/mobilenet/model $LIBRARY_DIR

重新指定模型路徑
mobilenet-v2模型路徑:mace-models/mobilenet-v2/mobilenet-v2.yml替換mobilenet模型路徑:mace/examples/android/mobilenet.yml

模型轉換成功後會builds下生成mobilenet-v2目錄
將mobilenet-v2替換mobilenet

修改完成如下所示
python tools/converter.py convert --config=mace-models/mobilenet-v2/mobilenet-v2.yml  --target_abis=$TARGET_ABI
cp -rf builds/mobilenet-v2/include/mace/public/*.h $INCLUDE_DIR
cp -rf builds/mobilenet-v2/model $LIBRARY_DIR

第二步,修改CMake配置檔案 

開啟macelibrary Module下CMakeLists.txt檔案

set(mace_lib ${CMAKE_SOURCE_DIR}/src/main/cpp/lib/arm64-v8a/libmace.a)
set(mobilenet_lib ${CMAKE_SOURCE_DIR}/src/main/cpp/model/arm64-v8a/mobilenet.a)

將arm64-v8a平臺換成armeabi-v7a
將mobilenet.a 修改成 mobilenet-v2.a

修改完成如下所示
set(mace_lib ${CMAKE_SOURCE_DIR}/src/main/cpp/lib/armeabi-v7a/libmace.a)
set(mobilenet_lib ${CMAKE_SOURCE_DIR}/src/main/cpp/model/armeabi-v7a/mobilenet-v2.a)

第三步,修改build.gradle

開啟macelibrary Module工程下的build.gradle

abiFilters "arm64-v8a"
修改成
abiFilters "armeabi-v7a"

第四步,修改模型轉換格式

file:檔案格式,tensorflow的模型將轉換成 .pb格式檔案

code:c++程式碼格式,模型加密與保護

模型轉換成C++程式碼,防止反編譯有效保護模型

model_graph_format: file
model_data_format: file

將模型圖形格式和模型資料格式都轉換為程式碼

model_graph_format: code
model_data_format: code

具體操作將mace-models/mobilenet-v2 目錄下的mobilenet-v2.yml和mobilenet-v2-host.yml都修改為code,修改完成如下所示
library_name: mobilenet-v2
target_abis: [armeabi-v7a, arm64-v8a]
model_graph_format: code
model_data_format: code

第五步,設定sdk和ndk路徑

在專案根目錄下local.properties檔案設定SDK和NDK

sdk.dir=E\:\\AndroidStudio\\SDK
ndk.dir=E\:\\AndroidStudio\\android-ndk-r16b

第六步,編譯Demo

在專案根目錄下執行
./build.sh

注:因為編譯時有進行模型轉換,如上所注,在編譯的時候Android Studio不能開啟該Demo工程,否則編譯將出現錯誤。編譯完成後可能會因為沒有連線裝置而提示錯誤,但是可以在app/build/outputs下看是否有成功打包apk

2 使用Android Studio編譯

第一步,轉換模型資料

將mace-models/mobilenet-v2 目錄下的mobilenet-v2.yml和mobilenet-v2-host.yml都修改為code,修改完成如下所示
library_name: mobilenet-v2
target_abis: [armeabi-v7a, arm64-v8a]
model_graph_format: code
model_data_format: code

修改完後使用命令轉換
python tools/converter.py convert --config=/path/to/mace-models/mobilenet-v2/mobilenet-v2.yml

第二步,匯入Demo工程,設定sdk和ndk

注:ndk如果設定最新的版本將無法正常編譯,請選擇推薦的版本

第三步,將生成的庫放至macelibrary

在Demo專案中的macelibrary/src/main/cpp 目錄下

    1 新建include/mace/public資料夾

           1.1 將builds/include/mace/public/ 下的mace.h 和 mace_runtime.h複製到該資料夾下

           1.2 將builds/mobilenet-v2/include/mace/public/ 下的mace_engine_factory.h 、mobilenet_v2.h複製到該資料夾下

    2 新建lib資料夾

           2.1 將builds/lib下的arm64-v8a、armeabi-v7a和linux-x86-64複製到該資料夾下

           2.2 將cpu_gpu/下的libmace.a、libmace.so檔案複製到與此同級別目錄後刪除cpu_gpu資料夾

    3 新建model資料夾

           3.1 將builds/mobilenet-v2/model 下的 arm64-v8a/mobilenet-v2.a、armeabi-v7a/mobilenet-v2.a複製到該資料夾下

           3.2 將mobilenet-v2.a 重新命名為 mobilenet.a  或 修改CMakeLists.txt檔案  將mobilenet.a 改為 mobilenet-v2.a  如下

                 set(mobilenet_lib ${CMAKE_SOURCE_DIR}/src/main/cpp/model/arm64-v8a/mobilenet-v2.a)

第四步,點選執行

修改以下程式碼,載入使用模型mobilenet_v2後點擊執行