张新栋 · 2020年03月05日

被低估的ArmNN(一)如何编译

ArmNN是一个性能十分强劲的inference框架,本文主要分享下对ArmNN的编译。
首发:https://zhuanlan.zhihu.com/p/71369040
作者:张新栋

ArmNN是Arm机构开源的基于arm嵌入式设备的inference框架,在Arm Cortex-A CPUs、Arm Mali GPUs、Arm Machine Learning processor都可以达到很高的加速效果。不过可惜的是,由于缺乏文档及教程,该框架在国内推广的程度不高,目前Github上star仅有359个。相对于其他竞品inference框架如NCNN、Tengine、Mace、MNN等等,ArmNN的知名度显得很小。不过笔者在项目的多次使用中,发现ArmNN是一个被低估的框架(在arm设备上的性能几乎都优于目前的前传框架),不亏是ARM家精心调教的SDK,对自家核心的性能调教到了极致。

ArmNN基于Arm的另外一个开源计算引擎ComputeLibrary做后端的核心计算,前端支持多种离线训练框架,如TensorFlow、TFLITE、CAFFE以及ONNX。从功能上来说,几乎实现了与市面上所有离线训练框架无缝对接。而且ArmNN在FP32、FP16及INT8上的加速非常可观,笔者在RK3399上做300x300的Mobilenet-SSD(depth\_multiplier=1.0),效率可达90ms/ 帧,其余的框架大多在160ms左右徘徊。

笔者后续会在本专栏开源基于ArmNN的Mobilenet-SSD的部署流程及项目代码。接下来,我们将先跟大家讨论如何编译ArmNN。由于目标平台是RK3399-Android-8.1,我们将基于android-arm64-v8a进行编译。下面我们开始:

  • 下载NDK

笔者使用的版本为NDK-r17c,由于ArmNN使用了一些C++14的新特性,所以老一些的NDK版本在编译的时候会出很多莫名其妙的错误。出于稳妥考虑,建议大家用r17c以上的版本,准备完毕以后,需要配置NDK路径:

export NDK=~/armnn-devenv/toolchains/android-ndk-r17c

接下来制作自己的toolchain编译工具链,

$NDK/build/tools/make_standalone_toolchain.py \
    --arch arm64 \
    --api 26 \
    --stl=libc++ \
    --install-dir=$HOME/armnn-devenv/toolchains/aarch64-android-r17b
export PATH=$HOME/armnn-devenv/toolchains/aarch64-android-r17b/bin:$PATH

如果你想持久化以上环境变量到系统中,你可以写进.bashrc文件中(或macOS的.bash\_profile文件)。

  • 编译Boost

先下载对应版本的Boost库,

mkdir ~/armnn-devenv/boost
cd ~/armnn-devenv/boost
wget https://dl.bintray.com/boostorg/release/1.64.0/source/boost_1_64_0.tar.bz2
tar xvf boost_1_64_0.tar.bz2

进行编译,

 echo "using gcc : arm : aarch64-linux-android-clang++ ;" > $HOME/armnn-devenv/boost/user-config.jam
 cd ~/armnn-devenv/boost/boost_1_64_0
 ./bootstrap.sh --prefix=$HOME/armnn-devenv/boost/install
 ./b2 install --user-config=$HOME/armnn-devenv/boost/user-config.jam \
  toolset=gcc-arm link=static cxxflags=-fPIC --with-filesystem \
  --with-test --with-log --with-program_options -j16
  • 编译ComputeLibrary

先下载对应版本的ComputeLibrary,

 cd ~/armnn-devenv
 git clone https://github.com/ARM-software/ComputeLibrary.git

安装scons后(sudo apt-get install scons),进行编译

 cd ComputeLibrary
 scons arch=arm64-v8a neon=1 opencl=1 embed_kernels=1 extra_cxx_flags="-fPIC" \
  benchmark_tests=0 validation_tests=0 os=android -j16
  • 编译谷歌的ProtoBuf

首先仍是下载对应的源码,并切换至对应版本,

mkdir ~/armnn-devenv/google
 cd ~/armnn-devenv/google
 git clone https://github.com/google/protobuf.git
 cd protobuf
 git checkout -b v3.5.2 v3.5.2

需要注意的是,这里需要编译对应PC(笔者为x86)和目标平台(arm64-v8a)的两个版本。编译过程中依赖cUrl、autoconf、 llibtool等,可以通过如下命令安装 sudo apt-get install curl autoconf libtool build-essential g++。下面先编译x86版本的,

 ./autogen.sh
 mkdir x86_build
 cd x86_build
 ../configure --prefix=$HOME/armnn-devenv/google/x86_pb_install
 make install -j16
 cd ..

随后安装arm64-v8a版本的,

mkdir arm64_build
 cd arm64_build
 CC=aarch64-linux-android-clang \
   CXX=aarch64-linux-android-clang++ \
   CFLAGS="-fPIE -fPIC" LDFLAGS="-pie -llog" \
    ../configure --host=aarch64-linux-android \
    --prefix=$HOME/armnn-devenv/google/arm64_pb_install \
    --with-protoc=$HOME/armnn-devenv/google/x86_pb_install/bin/protoc
 make install -j16
 cd ..
  • 编译ArmNN

我们这里采用的frontend为tensorflow,所以我们需要先下载对应的tensorflow源码,

 cd ~/armnn-devenv/google/
 git clone https://github.com/tensorflow/tensorflow.git

随后下载ArmNN源码,

cd ~/armnn-devenv/
git clone https://github.com/ARM-software/armnn.git

在PC中生成解析tensorflow的protobuf定义(使用x86平台中编译好的protoc),

 cd ~/armnn-devenv/google/tensorflow
 ~/armnn-devenv/armnn/scripts/generate_tensorflow_protobuf.sh \
  $HOME/armnn-devenv/google/tf_pb $HOME/armnn-devenv/google/x86_pb_install

随后编译ArmNN,

mkdir ~/armnn-devenv/armnn/build
cd ~/armnn-devenv/armnn/build
CXX=aarch64-linux-android-clang++                                                        \
CC=aarch64-linux-android-clang                                                           \
CXX_FLAGS="-fPIE -fPIC"                                                                  \
cmake ..                                                                                 \
 -DCMAKE_SYSTEM_NAME=Android                                                              \
 -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a                                                       \
 -DCMAKE_ANDROID_STANDALONE_TOOLCHAIN=$HOME/armnn-devenv/toolchains/aarch64-android-r17c/ \
 -DCMAKE_EXE_LINKER_FLAGS="-pie -llog"                                                    \
 -DARMCOMPUTE_ROOT=$HOME/armnn-devenv/ComputeLibrary/                                     \
 -DARMCOMPUTE_BUILD_DIR=$HOME/armnn-devenv/ComputeLibrary/build                           \
 -DBOOST_ROOT=$HOME/armnn-devenv/boost_1_64_0/install/                                    \
 -DARMCOMPUTENEON=1 -DARMCOMPUTECL=1                                                      \
 -DTF_GENERATED_SOURCES=$HOME/armnn-devenv/google/tf_pb/                                  \
 -DBUILD_TF_PARSER=1                                                                      \
 -DPROTOBUF_ROOT=$HOME/armnn-devenv/google/arm64_pb_install/                              \
 -DBUILD_TESTS=1                                                                          \
 -DTHIRD_PARTY_INCLUDE_DIRS=$HOME/armnn-devenv/armnn/third-party/stb                      \
 -DCMAKE_BUILD_TYPE=Release -DBUILD_ARMNN_QUANTIZER=1 -DBUILD_ARMNN_SERIALIZER=1
make -j16

编译完以后,你可以将库和测试用例推到目标平台中进行测试,

 adb push libarmnnTfParser.so /data/local/tmp/
 adb push libarmnn.so /data/local/tmp/
 adb push UnitTests /data/local/tmp/
 adb push $NDK/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so /data/local/tmp/
 adb push $HOME/armnn-devenv/google/arm64_pb_install/lib/libprotobuf.so /data/local/tmp/libprotobuf.so.15.0.1
 adb shell 'ln -s libprotobuf.so.15.0.1 /data/local/tmp/libprotobuf.so.15'
 adb shell 'ln -s libprotobuf.so.15.0.1 /data/local/tmp/libprotobuf.so'

执行测试用例,

 adb shell 'LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/UnitTests'
  • 最后

至此,我们完成了ArmNN的编译。ArmNN是一个性能十分强劲的inference框架,我们在后续的专栏中,会持续给大家更新ArmNN的使用方法及教程,欢迎大家留言讨论、关注专栏。谢谢大家!

专注嵌入式端的AI算法实现,欢迎关注作者微信公众号和知乎嵌入式AI算法实现专栏

WX20200305-192544.png

更多嵌入式AI相关的技术文章请关注极术嵌入式AI专栏

推荐阅读
关注数
18838
内容数
1371
嵌入式端AI,包括AI算法在推理框架Tengine,MNN,NCNN,PaddlePaddle及相关芯片上的实现。欢迎加入微信交流群,微信号:aijishu20(备注:嵌入式)
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息