使用 ncnn 将 pytorch 模型部署到安卓手机

  1. 在编译 NCNN 时开启图形卡支持。Vulkan 用于 GPU,设置 -DNCNN_VULKAN=ON
  2. MobileNetV3

在编译到 MT 时开启 CMAKE 0091 特性

cmake_minimum_required(VERSION 3.20.0)
cmake_policy(SET CMP0091 NEW)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
project("client-project")

训练 YOLO

\Envs\torch\Scripts\activate.ps1
python train.py --batch 6 --workers 2 --imgsz 960 --epochs 300 --data "\Core\yaml\data.yaml" --cfg "\Core\yaml\cfg.yaml" --weights \ Core\weights\best.pt --device 0

模型转换

from torch import nn
import torch.utils.model_zoo as model_zoo
import torch.onnx
from libs import define
from libs.net import Net
from libs.dataset import ImageDataset
import os

test_data = ImageDataset(define.testPath,False)
test_loader = torch.utils.data.DataLoader( test_data, batch_size=1, shuffle=True)

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = Net(out_dim=19).to(device)
model.load_state_dict(torch.load( "./widget/last.pt" ))
model.eval()

def saveOnnx():
    for data, target in test_loader:
        data, target = data.to(device), target.to(device)
        label = target.long()
        y = model(data)
        # 导出模型
        torch.onnx.export(model, # 正在运行的模型
                        data, # 模型输入(或多个输入的元组)
                        "./widget/best.onnx", # 保存模型的位置(可以是文件或文件对象)
                        export_params=True, # 将训练好的参数权重存储在模型文件中
                        opset_version=10, # 导出模型的 ONNX 版本
                        do_constant_folding=True, # 是否执行常量折叠以进行优化
                        input_names = ['input'], # 模型的输入名称
                        output_names = ['output'], # 模型的输出名称
                        dynamic_axes={'input': {0:'batch_size'}, # 可变长度轴
                                        'output': {0:'batch_size'}})

        traced_script_module = torch.jit.trace(model, data)
        return

saveOnnx()
# 转换
os.system("python -m onnxsim ./widget/best.onnx ./widgetbest-sim.onnx")
os.system("./bin/onnx2ncnn.exe ./widget/best-sim.onnx ./widget/best.param ./widget/best.bin")
os.system("./bin/ncnnoptimize.exe ./widget/best.param ./widget/best.bin ./widget/best-opt.param ./widget/best-opt.bin 65536")

python .\export.py --weights weights/best.pt --img 960 --batch 1 --train
python -m onnxsim best.onnx best-sim.onnx
.\onnx2ncnn.exe best-sim.onnx best.param best.bin
ncnnoptimize best.param best.bin best-opt.param best-opt.bin 65536

Git 克隆 ncnn 仓库及子模块

$ git clone https://github.com/Tencent/ncnn.git
$ cd ncnn
$ git submodule update --init

为 Linux 构建

安装所需的构建依赖项:

  • git
  • g++
  • cmake
  • protocol buffer (protobuf) 头文件和 protobuf 编译器
  • vulkan 头文件和加载器库
  • glslang
  • (可选) opencv # 用于构建示例

一般来说,如果你拥有过去 10 年的 Intel、AMD 或 Nvidia GPU,Vulkan 就可以轻松使用。

在某些系统上,目前(2020 年 10 月)可能没有易于获得的 Vulkan 驱动,因此你可能需要禁用 Vulkan 的使用。这适用于 Raspberry Pi 3(但正在开发中有一个实验性的开源 Vulkan 驱动,尚未准备好)。Nvidia Tegra 系列设备(如 Nvidia Jetson)应该支持 Vulkan。确保安装了最新的软件以获得最佳体验。

在 Debian、Ubuntu 或 Raspberry Pi OS 上,你可以使用以下命令安装所有必需的依赖项:

sudo apt install build-essential git cmake libprotobuf-dev protobuf-compiler libvulkan-dev vulkan-utils libopencv-dev

要使用 Vulkan 后端,你需要安装 Vulkan 头文件、一个 Vulkan 驱动加载器、GLSL 到 SPIR-V 编译器和 vulkaninfo 工具。最好从你的发行版仓库中获取。或者,从 https://vulkan.lunarg.com/sdk/home 下载并安装完整的 Vulkan SDK(大小约为 200MB;它包含所有头文件、文档和预构建加载器,以及一些额外的工具和所有内容的源代码)。

wget https://sdk.lunarg.com/sdk/download/1.2.189.0/linux/vulkansdk-linux-x86_64-1.2.189.0.tar.gz?Human=true -O vulkansdk-linux-x86_64-1.2.189.0.tar.gz
tar -xf vulkansdk-linux-x86_64-1.2.189.0.tar.gz
export VULKAN_SDK=$(pwd)/1.2.189.0/x86_64

在稍后构建 ncnn 时使用 Vulkan,你还需要为你的 GPU 拥有 Vulkan 驱动。对于 AMD 和 Intel GPU,这些可以在 Mesa 图形驱动中找到,通常在所有发行版中默认安装(例如,在 Debian/Ubuntu 上使用 sudo apt install mesa-vulkan-drivers)。对于 Nvidia GPU,必须下载并安装专有 Nvidia 驱动(某些发行版会以更简单的方式允许安装)。安装 Vulkan 驱动后,使用 vulkaninfovulkaninfo | grep deviceType 确认 Vulkan 库和驱动是否正常工作,它应该列出 GPU 设备类型。如果安装了多个 GPU(包括集成 GPU 和独立 GPU 的情况,常见于笔记本电脑),你可能需要记下设备的顺序以便稍后使用。

Nvidia Jetson 设备中的 Vulkan 支持应包含在 Nvidia 提供的 SDK (Jetpack) 或预构建的操作系统镜像中。

Raspberry Pi 的 Vulkan 驱动是存在的,但尚未成熟。你可以根据自己的判断进行实验,并报告结果和性能。

cd ncnn
mkdir -p build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DNCNN_VULKAN=ON -DNCNN_SYSTEM_GLSLANG=ON -DNCNN_BUILD_EXAMPLES=ON ..
make -j$(nproc)

你可以向上面的 cmake 添加 -GNinja 来使用 Ninja 构建系统(使用 ninjacmake --build . 调用构建)。

对于 Nvidia Jetson 设备,向 cmake 添加 -DCMAKE_TOOLCHAIN_FILE=../toolchains/jetson.toolchain.cmake

对于 Rasberry Pi 3,向 cmake 添加 -DCMAKE_TOOLCHAIN_FILE=../toolchains/pi3.toolchain.cmake -DPI3=ON。你也可以考虑禁用 Vulkan 支持,因为 Raspberry Pi 的 Vulkan 驱动仍不成熟,但启用支持并未使用它也不会有坏处。

通过运行一些示例来验证构建:

cd ../examples
../build/examples/squeezenet ../images/256-ncnn.png
[0 AMD RADV FIJI (LLVM 10.0.1)] queueC=1[4] queueG=0[1] queueT=0[1]
[0 AMD RADV FIJI (LLVM 10.0.1)] bugsbn1=0 buglbia=0 bugcopc=0 bugihfa=0
[0 AMD RADV FIJI (LLVM 10.0.1)] fp16p=1 fp16s=1 fp16a=0 int8s=1 int8a=1
532 = 0.163452
920 = 0.093140
716 = 0.061584

你也可以运行基准测试(第 4 个参数是使用的 GPU 设备索引,参考 vulkaninfo,如果你有多个 GPU):

cd ../benchmark
../build/benchmark/benchncnn 10 $(nproc) 0 0
[0 AMD RADV FIJI (LLVM 10.0.1)] queueC=1[4] queueG=0[1] queueT=0[1]
[0 AMD RADV FIJI (LLVM 10.0.1)] bugsbn1=0 buglbia=0 bugcopc=0 bugihfa=0
[0 AMD RADV FIJI (LLVM 10.0.1)] fp16p=1 fp16s=1 fp16a=0 int8s=1 int8a=1
num_threads = 4
powersave = 0
gpu_device = 0
cooling_down = 1
squeezenet min = 4.68 max = 4.99 avg = 4.85
squeezenet_int8 min = 38.52 max = 66.90 avg = 48.52

要在 CPU 上运行基准测试,将第 5 个参数设置为 -1


使用 Visual Studio Community 2017 为 Windows x64 构建

https://visualstudio.microsoft.com/vs/community/ 下载并安装 Visual Studio Community 2017。

启动命令提示符:Start → Programs → Visual Studio 2017 → Visual Studio Tools → x64 Native Tools Command Prompt for VS 2017

https://github.com/google/protobuf/archive/v3.4.0.zip 下载 protobuf-3.4.0。

构建 protobuf 库:

cd <protobuf-root-dir>
mkdir build
cd build
cmake -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=%cd%/install -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_MSVC_STATIC_RUNTIME=OFF ../cmake
nmake
nmake install

(可选) 从 https://vulkan.lunarg.com/sdk/home 下载并安装 Vulkan SDK。

构建 ncnn 库(将 protobuf-root-dir 替换为正确的路径):

cd <ncnn-root-dir>
mkdir -p build
cd build
cmake -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=%cd%/install -DProtobuf_INCLUDE_DIR=<protobuf-root-dir>/build/install/include -DProtobuf_LIBRARIES=<protobuf-root-dir>/build/install/lib/libprotobuf.lib -DProtobuf_PROTOC_EXECUTABLE=<protobuf-root-dir>/build/install/bin/protoc.exe -DNCNN_VULKAN=ON ..
nmake
nmake install

注意:为了加快多核机器上的编译过程,推荐使用 -G 标志配置 cmake 来使用 jomninja


为 macOS 构建

首先根据你的需求安装 Xcode 或 Xcode 命令行工具。

然后通过 homebrew 安装 protobuflibomp

brew install protobuf libomp

https://vulkan.lunarg.com/sdk/home 下载并安装 Vulkan SDK。

wget https://sdk.lunarg.com/sdk/download/1.2.189.0/mac/vulkansdk-macos-1.2.189.0.dmg?Human=true -O vulkansdk-macos-1.2.189.0.dmg
hdiutil attach vulkansdk-macos-1.2.189.0.dmg
sudo /Volumes/vulkansdk-macos-1.2.189.0/InstallVulkan.app/Contents/MacOS/InstallVulkan --root `pwd`/vulkansdk-macos-1.2.189.0 --accept-licenses --default-answer --confirm-command install
hdiutil detach /Volumes/vulkansdk-macos-1.2.189.0

# 设置环境变量

export VULKAN_SDK=`pwd`/vulkansdk-macos-1.2.189.0/macOS
cd <ncnn-root-dir>
mkdir -p build
cd build

cmake -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" \
 -DVulkan_INCLUDE_DIR=`pwd`/../vulkansdk-macos-1.2.189.0/MoltenVK/include \
 -DVulkan_LIBRARY=`pwd`/../vulkansdk-macos-1.2.189.0/MoltenVK/dylib/macOS/libMoltenVK.dylib \
 -DNCNN_VULKAN=ON -DNCNN_BUILD_EXAMPLES=ON ..

cmake --build . -j 4
cmake --build . --target install

注意:如果在安装过程中遇到与 libomp 相关的错误,你也可以查看我们的 GitHub Actions 此处 来安装和使用 openmp


使用交叉编译为 ARM Cortex-A 系列构建

https://developer.arm.com/open-source/gnu-toolchain/gnu-a/downloads 下载 ARM 工具链。

export PATH="<your-toolchain-compiler-path>:${PATH}"

或者安装发行版提供的交叉编译器(例如,在 Debian / Ubuntu 上,你可以执行 sudo apt install g++-arm-linux-gnueabi g++-arm-linux-gnueabihf g++-aarch64-linux-gnu)。

根据你的需求,构建以下一个或多个目标。

AArch32 软浮点目标 (arm-linux-gnueabi)

cd <ncnn-root-dir>
mkdir -p build-arm-linux-gnueabi
cd build-arm-linux-gnueabi
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/arm-linux-gnueabi.toolchain.cmake ..
make -j$(nproc)

AArch32 硬浮点目标 (arm-linux-gnueabihf)

cd <ncnn-root-dir>
mkdir -p build-arm-linux-gnueabihf
cd build-arm-linux-gnueabihf
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/arm-linux-gnueabihf.toolchain.cmake ..
make -j$(nproc)

AArch64 GNU/Linux 目标 (aarch64-linux-gnu)

cd <ncnn-root-dir>
mkdir -p build-aarch64-linux-gnu
cd build-aarch64-linux-gnu
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/aarch64-linux-gnu.toolchain.cmake ..
make -j$(nproc)

使用交叉编译为 Hisilicon 平台构建

下载并安装 Hisilicon SDK。工具链应位于 /opt/hisi-linux/x86-arm

cd <ncnn-root-dir>
mkdir -p build
cd build

# 选择一个 cmake 工具链文件,取决于你的目标平台

cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/hisiv300.toolchain.cmake ..
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/hisiv500.toolchain.cmake ..
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/himix100.toolchain.cmake ..
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/himix200.toolchain.cmake ..

make -j$(nproc)
make install

为 Android 构建

你可以使用来自 https://github.com/Tencent/ncnn/releases 的预构建 ncnn-android-lib.zip。

http://developer.android.com/ndk/downloads/index.html 下载 Android NDK 并安装它,例如:

unzip android-ndk-r21d-linux-x86_64.zip
export ANDROID_NDK=<your-ndk-root-path>

(可选) 移除 Android NDK 中的硬编码调试标志 android-ndk issue

# 打开 $ANDROID_NDK/build/cmake/android.toolchain.cmake

# 删除 "-g" 行

list(APPEND ANDROID_COMPILER_FLAGS
-g
-DANDROID

构建 armv7 库

cd <ncnn-root-dir>
mkdir -p build-android-armv7
cd build-android-armv7

cmake -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" \
 -DANDROID_ABI="armeabi-v7a" -DANDROID_ARM_NEON=ON \
 -DANDROID_PLATFORM=android-14 ..

# 如果你想启用 Vulkan,则需要平台 API 版本 >= android-24

cmake -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" \
 -DANDROID_ABI="armeabi-v7a" -DANDROID_ARM_NEON=ON \
 -DANDROID_PLATFORM=android-24 -DNCNN_VULKAN=ON ..

make -j$(nproc)
make install

选择 build-android-armv7/install 文件夹用于进一步的 JNI 使用。

构建 aarch64 库:

cd <ncnn-root-dir>
mkdir -p build-android-aarch64
cd build-android-aarch64

cmake -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake"\
 -DANDROID_ABI="arm64-v8a" \
 -DANDROID_PLATFORM=android-21 ..

# 如果你想启用 Vulkan,则需要平台 API 版本 >= android-24

cmake -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" \
 -DANDROID_ABI="arm64-v8a" \
 -DANDROID_PLATFORM=android-24 -DNCNN_VULKAN=ON ..

make -j$(nproc)
make install

选择 build-android-aarch64/install 文件夹用于进一步的 JNI 使用。


在 macOS 上使用 xcode 为 iOS 构建

你可以使用来自 https://github.com/Tencent/ncnn/releases 的预构建 ncnn.framework、glslang.framework 和 openmp.framework。

安装 xcode

如果你想构建启用 bitcode 的库,可以将以下 cmake 参数中的 -DENABLE_BITCODE=0 替换为 -DENABLE_BITCODE=1

下载并安装 openmp 以启用 iPhoneOS 上的多线程推理功能

wget https://github.com/llvm/llvm-project/releases/download/llvmorg-11.0.0/openmp-11.0.0.src.tar.xz
tar -xf openmp-11.0.0.src.tar.xz
cd openmp-11.0.0.src

# 应用一些编译修复

sed -i'' -e '/.size **kmp_unnamed_critical_addr/d' runtime/src/z_Linux_asm.S
sed -i'' -e 's/**kmp_unnamed_critical_addr/\_\_\_kmp_unnamed_critical_addr/g' runtime/src/z_Linux_asm.S

mkdir -p build-ios
cd build-ios

cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/ios.toolchain.cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=install \
 -DIOS_PLATFORM=OS -DENABLE_BITCODE=0 -DENABLE_ARC=0 -DENABLE_VISIBILITY=0 -DIOS_ARCH="armv7;arm64;arm64e" \
 -DPERL_EXECUTABLE=/usr/local/bin/perl \
 -DLIBOMP_ENABLE_SHARED=OFF -DLIBOMP_OMPT_SUPPORT=OFF -DLIBOMP_USE_HWLOC=OFF ..

cmake --build . -j 4
cmake --build . --target install

# 将 openmp 库和头文件复制到 xcode 工具链 sysroot

sudo cp install/include/\* /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include
sudo cp install/lib/libomp.a /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/lib

下载并安装 openmp 以启用 iPhoneSimulator 上的多线程推理功能

wget https://github.com/llvm/llvm-project/releases/download/llvmorg-11.0.0/openmp-11.0.0.src.tar.xz
tar -xf openmp-11.0.0.src.tar.xz
cd openmp-11.0.0.src

# 应用一些编译修复

sed -i'' -e '/.size **kmp_unnamed_critical_addr/d' runtime/src/z_Linux_asm.S
sed -i'' -e 's/**kmp_unnamed_critical_addr/\_\_\_kmp_unnamed_critical_addr/g' runtime/src/z_Linux_asm.S

mkdir -p build-ios-sim
cd build-ios-sim

cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/ios.toolchain.cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=install \
 -DIOS_PLATFORM=SIMULATOR -DENABLE_BITCODE=0 -DENABLE_ARC=0 -DENABLE_VISIBILITY=0 -DIOS_ARCH="i386;x86_64" \
 -DPERL_EXECUTABLE=/usr/local/bin/perl \
 -DLIBOMP_ENABLE_SHARED=OFF -DLIBOMP_OMPT_SUPPORT=OFF -DLIBOMP_USE_HWLOC=OFF ..

cmake --build . -j 4
cmake --build . --target install

# 将 openmp 库和头文件复制到 xcode 工具链 sysroot

sudo cp install/include/\* /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include
sudo cp install/lib/libomp.a /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/lib

打包 openmp 框架:

cd <openmp-root-dir>

mkdir -p openmp.framework/Versions/A/Headers
mkdir -p openmp.framework/Versions/A/Resources
ln -s A openmp.framework/Versions/Current
ln -s Versions/Current/Headers openmp.framework/Headers
ln -s Versions/Current/Resources openmp.framework/Resources
ln -s Versions/Current/openmp openmp.framework/openmp
lipo -create build-ios/install/lib/libomp.a build-ios-sim/install/lib/libomp.a -o openmp.framework/Versions/A/openmp
cp -r build-ios/install/include/\* openmp.framework/Versions/A/Headers/
sed -e 's/**NAME**/openmp/g' -e 's/**IDENTIFIER**/org.llvm.openmp/g' -e 's/**VERSION**/11.0/g' Info.plist > openmp.framework/Versions/A/Resources/Info.plist

下载并安装 Vulkan SDK。

wget https://sdk.lunarg.com/sdk/download/1.2.189.0/mac/vulkansdk-macos-1.2.189.0.dmg?Human=true -O vulkansdk-macos-1.2.189.0.dmg
hdiutil attach vulkansdk-macos-1.2.189.0.dmg
sudo /Volumes/vulkansdk-macos-1.2.189.0/InstallVulkan.app/Contents/MacOS/InstallVulkan --root `pwd`/vulkansdk-macos-1.2.189.0 --accept-licenses --default-answer --confirm-command install
hdiutil detach /Volumes/vulkansdk-macos-1.2.189.0

# 设置环境变量

export VULKAN_SDK=`pwd`/vulkansdk-macos-1.2.189.0/macOS

为 iPhoneOS 构建库:

cd <ncnn-root-dir>
mkdir -p build-ios
cd build-ios

cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/ios.toolchain.cmake -DIOS_PLATFORM=OS -DIOS_ARCH="armv7;arm64;arm64e" \
 -DENABLE_BITCODE=0 -DENABLE_ARC=0 -DENABLE_VISIBILITY=0 \
 -DOpenMP_C_FLAGS="-Xclang -fopenmp" -DOpenMP_CXX_FLAGS="-Xclang -fopenmp" \
 -DOpenMP_C_LIB_NAMES="libomp" -DOpenMP_CXX_LIB_NAMES="libomp" \
 -DOpenMP_libomp_LIBRARY="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/lib/libomp.a" \
 -DNCNN_BUILD_BENCHMARK=OFF ..

# Vulkan 仅在 arm64 设备上可用

cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/ios.toolchain.cmake -DIOS_PLATFORM=OS64 -DIOS_ARCH="arm64;arm64e" \
 -DENABLE_BITCODE=0 -DENABLE_ARC=0 -DENABLE_VISIBILITY=0 \
 -DOpenMP_C_FLAGS="-Xclang -fopenmp" -DOpenMP_CXX_FLAGS="-Xclang -fopenmp" \
 -DOpenMP_C_LIB_NAMES="libomp" -DOpenMP_CXX_LIB_NAMES="libomp" \
 -DOpenMP_libomp_LIBRARY="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/lib/libomp.a" \
 -DVulkan_INCLUDE_DIR=`pwd`/../vulkansdk-macos-1.2.189.0/MoltenVK/include \
 -DVulkan_LIBRARY=`pwd`/../vulkansdk-macos-1.2.189.0/MoltenVK/dylib/iOS/libMoltenVK.dylib \
 -DNCNN_VULKAN=ON -DNCNN_BUILD_BENCHMARK=OFF ..

cmake --build . -j 4
cmake --build . --target install

为 iPhoneSimulator 构建库:

cd <ncnn-root-dir>
mkdir -p build-ios-sim
cd build-ios-sim

cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/ios.toolchain.cmake -DIOS_PLATFORM=SIMULATOR -DIOS_ARCH="i386;x86_64" \
 -DENABLE_BITCODE=0 -DENABLE_ARC=0 -DENABLE_VISIBILITY=0 \
 -DOpenMP_C_FLAGS="-Xclang -fopenmp" -DOpenMP_CXX_FLAGS="-Xclang -fopenmp" \
 -DOpenMP_C_LIB_NAMES="libomp" -DOpenMP_CXX_LIB_NAMES="libomp" \
 -DOpenMP_libomp_LIBRARY="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/lib/libomp.a" \
 -DNCNN_BUILD_BENCHMARK=OFF ..

cmake --build . -j 4
cmake --build . --target install

打包 glslang 框架:

cd <ncnn-root-dir>

mkdir -p glslang.framework/Versions/A/Headers
mkdir -p glslang.framework/Versions/A/Resources
ln -s A glslang.framework/Versions/Current
ln -s Versions/Current/Headers glslang.framework/Headers
ln -s Versions/Current/Resources glslang.framework/Resources
ln -s Versions/Current/glslang glslang.framework/glslang
libtool -static build-ios/install/lib/libglslang.a build-ios/install/lib/libSPIRV.a build-ios/install/lib/libOGLCompiler.a build-ios/install/lib/libOSDependent.a -o build-ios/install/lib/libglslang_combined.a
libtool -static build-ios-sim/install/lib/libglslang.a build-ios-sim/install/lib/libSPIRV.a build-ios-sim/install/lib/libOGLCompiler.a build-ios-sim/install/lib/libOSDependent.a -o build-ios-sim/install/lib/libglslang_combined.a
lipo -create build-ios/install/lib/libglslang_combined.a build-ios-sim/install/lib/libglslang_combined.a -o glslang.framework/Versions/A/glslang
cp -r build/install/include/glslang glslang.framework/Versions/A/Headers/
sed -e 's/**NAME**/glslang/g' -e 's/**IDENTIFIER**/org.khronos.glslang/g' -e 's/**VERSION**/1.0/g' Info.plist > glslang.framework/Versions/A/Resources/Info.plist

打包 ncnn 框架:

cd <ncnn-root-dir>

mkdir -p ncnn.framework/Versions/A/Headers
mkdir -p ncnn.framework/Versions/A/Resources
ln -s A ncnn.framework/Versions/Current
ln -s Versions/Current/Headers ncnn.framework/Headers
ln -s Versions/Current/Resources ncnn.framework/Resources
ln -s Versions/Current/ncnn ncnn.framework/ncnn
lipo -create build-ios/install/lib/libncnn.a build-ios-sim/install/lib/libncnn.a -o ncnn.framework/Versions/A/ncnn
cp -r build-ios/install/include/\* ncnn.framework/Versions/A/Headers/
sed -e 's/**NAME**/ncnn/g' -e 's/**IDENTIFIER**/com.tencent.ncnn/g' -e 's/**VERSION**/1.0/g' Info.plist > ncnn.framework/Versions/A/Resources/Info.plist

选择 ncnn.frameworkglslang.frameworkopenmp.framework 文件夹进行应用开发。


为 WebAssembly 构建

安装 Emscripten

git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install 2.0.8
./emsdk activate 2.0.8

source emsdk/emsdk_env.sh

不带任何扩展名构建以实现通用兼容性:

mkdir -p build
cd build
cmake -DCMAKE_TOOLCHAIN_FILE=../emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
 -DNCNN_THREADS=OFF -DNCNN_OPENMP=OFF -DNCNN_SIMPLEOMP=OFF -DNCNN_RUNTIME_CPU=OFF -DNCNN_SSE2=OFF -DNCNN_AVX2=OFF -DNCNN_AVX=OFF \
 -DNCNN_BUILD_TOOLS=OFF -DNCNN_BUILD_EXAMPLES=OFF -DNCNN_BUILD_BENCHMARK=OFF ..
cmake --build . -j 4
cmake --build . --target install

带 WASM SIMD 扩展构建:

mkdir -p build-simd
cd build-simd
cmake -DCMAKE_TOOLCHAIN_FILE=../emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
 -DNCNN_THREADS=OFF -DNCNN_OPENMP=OFF -DNCNN_SIMPLEOMP=OFF -DNCNN_RUNTIME_CPU=OFF -DNCNN_SSE2=ON -DNCNN_AVX2=OFF -DNCNN_AVX=OFF \
 -DNCNN_BUILD_TOOLS=OFF -DNCNN_BUILD_EXAMPLES=OFF -DNCNN_BUILD_BENCHMARK=OFF ..
cmake --build . -j 4
cmake --build . --target install

带 WASM Thread 扩展构建:

mkdir -p build-threads
cd build-threads
cmake -DCMAKE_TOOLCHAIN_FILE=../emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
 -DNCNN_THREADS=ON -DNCNN_OPENMP=ON -DNCNN_SIMPLEOMP=ON -DNCNN_RUNTIME_CPU=OFF -DNCNN_SSE2=OFF -DNCNN_AVX2=OFF -DNCNN_AVX=OFF \
 -DNCNN_BUILD_TOOLS=OFF -DNCNN_BUILD_EXAMPLES=OFF -DNCNN_BUILD_BENCHMARK=OFF ..
cmake --build . -j 4
cmake --build . --target install

带 WASM SIMD 和 Thread 扩展构建:

mkdir -p build-simd-threads
cd build-simd-threads
cmake -DCMAKE_TOOLCHAIN_FILE=../emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
 -DNCNN_THREADS=ON -DNCNN_OPENMP=ON -DNCNN_SIMPLEOMP=ON -DNCNN_RUNTIME_CPU=OFF -DNCNN_SSE2=ON -DNCNN_AVX2=OFF -DNCNN_AVX=OFF \
 -DNCNN_BUILD_TOOLS=OFF -DNCNN_BUILD_EXAMPLES=OFF -DNCNN_BUILD_BENCHMARK=OFF ..
cmake --build . -j 4
cmake --build . --target install

选择 build-XYZ/install 文件夹用于进一步使用。


为 AllWinner D1 构建

https://occ.t-head.cn/community/download?id=3913221581316624384 下载 c906 工具链包。

tar -xf riscv64-linux-x86_64-20210512.tar.gz
export RISCV_ROOT_PATH=/home/nihui/osd/riscv64-linux-x86_64-20210512

启用 riscv-v 向量和 simpleocv 的 ncnn 构建:

mkdir -p build-c906
cd build-c906
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/c906.toolchain.cmake \
 -DCMAKE_BUILD_TYPE=relwithdebinfo -DNCNN_OPENMP=OFF -DNCNN_THREADS=OFF -DNCNN_RUNTIME_CPU=OFF -DNCNN_RVV=ON \
 -DNCNN_SIMPLEOCV=ON -DNCNN_BUILD_EXAMPLES=ON ..
cmake --build . -j 4
cmake --build . --target install

选择 build-c906/install 文件夹用于进一步使用。

你可以将二进制文件上传到 build-c906/examples 文件夹并在 D1 板上运行进行测试。


为 Loongson 2K1000 构建

对于 gcc 版本 <= 8.5,你需要修复 msa.h 头文件以解决 msa fmadd 错误。

打开 /usr/lib/gcc/mips64el-linux-gnuabi64/8/include/msa.h,找到 __msa_fmadd_w 并应用以下更改:

// #define **msa_fmadd_w **builtin_msa_fmadd_w
#define **msa_fmadd_w(a, b, c) **builtin_msa_fmadd_w(c, b, a)

启用 mips msa 和 simpleocv 的 ncnn 构建:

mkdir -p build
cd build
cmake -DNCNN_DISABLE_RTTI=ON -DNCNN_DISABLE_EXCEPTION=ON -DNCNN_RUNTIME_CPU=OFF -DNCNN_MSA=ON -DNCNN_MMI=ON -DNCNN_SIMPLEOCV=ON ..
cmake --build . -j 2
cmake --build . --target install

选择 build/install 文件夹用于进一步使用。

你可以运行 build/examples 文件夹中的二进制文件进行测试。


为 Android 上的 Termux 构建

在手机上安装 Termux 应用,并在 Termux 中安装 Ubuntu。

如果你想使用 ssh,只需在 Termux 中安装 openssh。

pkg install proot-distro
proot-distro install ubuntu

或者你可以使用 proot-distro list 查看可以安装的系统。

在成功安装 Ubuntu 后,使用 proot-distro login ubuntu 登录 Ubuntu。

然后构建 ncnn,无需安装任何其他依赖项。

git clone https://github.com/Tencent/ncnn.git
cd ncnn
git submodule update --init
mkdir -p build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DNCNN_BUILD_EXAMPLES=ON -DNCNN_PLATFORM_API=OFF -DNCNN_SIMPLEOCV=ON ..
make -j$(nproc)

然后你可以运行测试:

在我的 Pixel 3 XL 上使用 Qualcomm 845,无法加载 256-ncnn.png

cd ../examples
../build/examples/squeezenet ../images/128-ncnn.png