一、搭建MNN基础编译环境
1.基础依赖库安装
这些依赖是无关编译选项的基础编译依赖
- cmake(3.10 以上)
- protobuf (3.0 以上)
- 指protobuf库以及protobuf编译器。版本号使用 protoc --version 打印出来。
- 在某些Linux发行版上这两个包是分开发布的,需要手动安装
- Ubuntu需要分别安装 libprotobuf-dev 以及 protobuf-compiler 两个包
- Mac OS 上使用 brew install protobuf 进行安装
- C++编译器
- GCC或Clang皆可 (macOS无需另外安装,Xcode自带)
- GCC推荐版本4.9以上
- 在某些发行版上GCC (GNU C编译器)和G++(GNU C++编译器是分开安装的)。
- 同样以Ubuntu为例,需要分别安装 gcc 和 g++
- GCC推荐版本4.9以上
- GCC或Clang皆可 (macOS无需另外安装,Xcode自带)
PS:如果使用Clang,推荐版本3.9以上
- zlib
- MacOS在指定MNN_BUILD_SHARED_LIBS=OFF时编MNNConvert需要zlib静态库,MacOS上默认的zlib只有动态库,所以需要
brew install zlib
# 自行安装的zlib库如果想被pkg-config工具找到,需要设置PKG_CONFIG_PATH环境变量
# 可以在当前shell内临时修改PKG_CONFIG_PATH
export PKG_CONFIG_PATH="/usr/local/Cellar/zlib/{version}/lib/pkgconfig:$PKG_CONFIG_PATH"
# 或者修改~/.bash_profile使得其他shell也生效
echo "export PKG_CONFIG_PATH=/usr/local/Cellar/zlib/{version}/lib/pkgconfig:\$PKG_CONFIG_PATH" >> ~/.bash_profile
编译选项说明:
- OpenCL
- macOS下CMake会自动检测,但Apple已经在10.15 Catalina中彻底移除OpenCL支持
- Linux下你需要ocl-icd-opencl-dev以及特定厂商的ICD包(不同显卡选择不同)
- Nvidia: nvidia-opencl-dev
- AMD: amd-opencl-dev
- Vulkan
- libvulkan-dev
- OpenGL
- Linux下不支持
2.编译MNN模型转换工具(cmake的参数见附录1)
cd MNN/ ./schema/generate.shmkdir build cd build cmake .. -DMNN_BUILD_CONVERTER=true && make -j4
编译产物包含模型转换工具'MNNConvert'和模型输出工具'MNNDump2Json.out'
2.使用编译好的模型转换工具将 ONNX 模型文件转成 MNN 模型
./MNNConvert -f ONNX --modelFile XXX.onnx --MNNModel XXX.mnn --bizCode biz
二、推理框架编译
步骤如下:
- 在https://developer.android.com/ndk/downloads/下载安装NDK,建议使用最新稳定版本(使用MNN模型转换工具相同的环境)
-
#在 .bashrc 或者 .bash_profile 中设置 NDK 环境变量,例如: export ANDROID_NDK=/Users/username/path/to/android-ndk-r14b #进入MNN目录 cd /path/to/MNN #执行生成脚本 ./schema/generate.sh #(可选,模型仅demo工程需要)。注意get_model.sh需要事先编译好模型转换工具,参见上述一。 ./tools/script/get_model.sh cd project/android
- 编译armv7动态库:
-
mkdir build_32 && cd build_32 && ../build_32.sh
- 编译armv8动态库:
-
mkdir build_64 && cd build_64 && ../build_64.sh
编译后会生成对应的*.so(libMNN.so/libMNN_CL.so/libMNN_GL.so/libMNN_Vulkan.so等,由cmake参数决定)动态库文件,根据需求使用。
附:
使用cmake编译时,可以修改CMakeLists.txt中的选项:
- MNN_DEBUG
默认关闭,关闭时,不保留符号,开启优化。
- MNN_USE_THREAD_POOL
默认开启,使用 MNN 内部的无锁线程池实现多线程优化。关闭后,视MNN_OPENMP开关选择OpenMP或关闭多线程优化。
注:MNN 的无锁线程池最多允许两个实例同时使用,即最多供两个模型同时推理使用。参考代码 source/backend/cpu/ThreadPool.cpp 中 MNN_THREAD_POOL_MAX_TASKS 宏的定义。
- MNN_OPENMP
默认开启,在 MNN_USE_THREAD_POOL 关闭时生效,依赖OpenMP实现多线程优化。关闭后,禁用OpenMP。
- MNN_OPENCL
默认关闭,开启后,编译OpenCL部分,可以通过指定MNN_FORWARD_OPENCL利用GPU进行推理。
- MNN_OPENGL
默认关闭,开启后,编译OpenGL部分,可以通过指定MNN_FORWARD_OPENGL利用GPU进行推理。
*需要android-21及以上,亦即脚本中指定 -DANDROID_NATIVE_API_LEVEL=android-21*
- MNN_VULKAN
默认关闭,开启后,编译Vulkan部分,可以通过指定MNN_FORWARD_VULKAN利用GPU进行推理。
- MNN_ARM82
默认关闭,开启后,编译Arm8.2部分,用Arm8.2+扩展指令集实现半精度浮点计算(fp16)和int8(sdot)加速
使用Arm82+扩展指令的方法如下:
// 创建session需要的配置
MNN::ScheduleConfig config;
// 选择
Backendconfig.type = MNN_FORWARD_CPU;
// 线程数
config.numThread = 2;
// 配置相应的
BackendBackendConfig backendConfig;
// 选择低精度
backendConfig.precision = BackendConfig::Precision_Low;
config.backendConfig = &backendConfig;
附录1:CMake参数总览
以下参数用于控制编译的阶段的各个细节,请按照实际需求选择
默认值 | 作用 | |
MNN_VULKAN | OFF | 编译 GPU 优化库:MNN-VULKAN |
MNN_ARM82 | OFF | 编译 MNN-ARM82 (新架构的CPU 优化 Backend) |
MNN_OPENCL | OFF | 编译 GPU 优化库: MNN-OpenCL |
MNN_OPENGL | OFF | 编译 GPU 优化库:MNN-OpenGL |
MNN_USE_SYSTEM_LIB | OFF | 编译 OpenCL / Vulkan 时,依赖系统的OpenCL / Vulkan 库或者。OFF 表示在运行时寻找系统驱动 |
MNN_BUILD_HARD | OFF | ARM平台下控制-mfloat-abi参数为hard或softfp |
MNN_BUILD_SHARED_LIBS | ON | 控制MNN相关库是否编译为动态库而非静态库 |
MNN_FORBID_MULTI_THREAD | OFF | 禁用多线程 |
MNN_BUILD_TOOLS | ON | 编译测试工具 |
MNN_BUILD_DEMO | OFF | 编译Demo |
MNN_BUILD_TRAIN | OFF | 编译训练相关 |
MNN_BUILD_QUANTOOLS | OFF | 编译量化工具 |
MNN_BUILD_CONVERTER | OFF | 编译模型转换器 |
MNN_EVALUATION | OFF | 编译评估工具 |
MNN_DEBUG_MEMORY | OFF | 调试内存 |
MNN_DEBUG_TENSOR_SIZE | OFF | 调试Tensor大小 |
MNN_SUPPORT_TFLITE_QUAN | OFF | 支持TFLite的量化Op |
MNN_PORTABLE_BUILD | OFF | 静态链接第三方依赖来创建不依赖特定路径的可执行文件 |
MNN_SEP_BUILD | ON | 分开编译MNN的各个后端以及表达式.只在MNN_BUILD_SHARED_LIBS=ON时有效 |
MNN_AAPL_FMWK | OFF | 在Apple平台下将MNN作为Framework而非静态/动态库编译并打包metallib |