FEATURED · 精选文章

Paddle Lite 联发科 MediaTek APU 部署实战:基于 NNAdapter 将 Paddle 模型在线编译到 MTK Neuron

发布时间 / 2026/9/16 18:26:11
来源 / 创域科博编辑部
栏目 / 资讯中心
Paddle Lite 联发科 MediaTek APU 部署实战:基于 NNAdapter 将 Paddle 模型在线编译到 MTK Neuron Paddle Lite 联发科 MediaTek APU 部署实战基于 NNAdapter 将 Paddle 模型在线编译到 MTK Neuron【免费下载链接】Paddle-LitePaddlePaddle High Performance Deep Learning Inference Engine for Mobile and Edge (飞桨高性能深度学习端侧推理引擎项目地址: https://gitcode.com/GitHub_Trending/pa/Paddle-LitePaddle Lite 已支持 MediaTek APU 的预测部署其接入方式与华为 Kirin NPU 类似加载并分析 Paddle 模型后将 Paddle 算子转换为 NNAdapter 中间表示再在线转成 MTK 的 Neuron adapter API类似 Android NNAPI进行组网在目标芯片上编译并执行模型。读完本篇指南你可以掌握从交叉编译 Paddle Lite 部署库、用 opt 工具标记 APU 子图到在 MT8168 设备上运行分类示例并对比 CPU/APU 性能的完整流程并能从源码层面理解 NNAdapter 驱动对 MTK APU 的调用链。一、接入原理Paddle 算子如何落到 MTK Neuron联发科 APU 并非直接读取 Paddle 模型而是走 Paddle Lite 统一的 NNAdapter 接入框架。从源码结构看整个链路可以拆成三段设备端 HAL 驱动注册。每个 NNAdapter 后端都导出一个设备入口结构体MediaTek APU 的入口在 driver.cc 末尾NNADAPTER_EXPORT nnadapter::driver::Device NNADAPTER_AS_SYM2(DEVICE_NAME) { .name NNADAPTER_AS_STR2(DEVICE_NAME), .vendor MediaTek, .type NNADAPTER_ACCELERATOR, .version 1, .open_device nnadapter::mediatek_apu::OpenDevice, .close_device nnadapter::mediatek_apu::CloseDevice, .create_context nnadapter::mediatek_apu::CreateContext, .destroy_context nnadapter::mediatek_apu::DestroyContext, .validate_program 0, .create_program nnadapter::mediatek_apu::CreateProgram, .destroy_program nnadapter::mediatek_apu::DestroyProgram, .execute_program nnadapter::mediatek_apu::ExecuteProgram, };运行时库libnnadapter.so通过 dlopen 加载 device HAL 库libmediatek_apu.so并定位该入口完成设备打开、上下文创建、程序构建与执行的回调分派。这与部署包中lib/mediatek_apu/目录下的两个.so一一对应。模型在线构建组网。Program::BuildFromModel是核心实现在 engine.cc。其内部流程为先跑一系列图优化 Pass常量折叠ConstantFoldOperations、Conv2DBatchNorm 融合、Conv2DAdd/激活融合、MatMulAdd 融合为 FullyConnected、5D 的 Reshape-Transpose-Reshape 折叠为 4D、对称量化转非对称量化ConvertQuantizationSymmToAsymm、输入输出量化参数约束RestrictInputOutputQuantParams、数据布局 NCHW 转 NHWCConvertDataLayoutNCHWToNHWC以及 APU 专属的算子限制求解ResolveOperationLiminations然后通过 converter 把 NNAdapter 算子逐个转换成 Neuron 算子NeuronModel_addOperation等调用NeuronModel_identifyInputsAndOutputs、NeuronModel_relaxComputationFloat32toFloat16、NeuronModel_finish完成模型定型再经NeuronCompilation_create/finish在设备上完成编译最终NeuronExecution_create建好可执行的 inference 对象。若开启缓存编译产物会经NeuronCompilation_storeCompiledNetwork序列化进 buffer下次命中缓存时走 BuildFromCache用NeuronModel_restoreFromCompiledNetwork直接从编译网络恢复跳过在线组网。这解释了文档中的一个重要结论opt 工具生成的模型只是把 MediaTek APU 支持的 Paddle 算子标记出来并没有真正生成 MTK APU 模型只有在程序执行时才会将标记的算子转成 MTK Neuron adapter API 调用完成组网最终生成并执行模型。DDK 动态加载。neuron_adapter_wrapper.h 用函数指针表Neuron_getVersion、NeuronModel_create、NeuronCompilation_finish、NeuronExecution_compute等 28 个接口在运行时加载 MTK APU DDK 提供的NeuronAdapter.h对应库并在Initialize()中做能力探测Supported()。这也是为什么编译前必须解压apu_ddk.tar.gz并指定 SDK 路径——dependencies.cmake 明确要求if(NOT NNADAPTER_MEDIATEK_APU_SDK_ROOT) message(FATAL_ERROR Must set NNADAPTER_MEDIATEK_APU_SDK_ROOT or env NNADAPTER_MEDIATEK_APU_SDK_ROOT when NNADAPTER_WITH_MEDIATEK_APUON) endif()并在${NNADAPTER_MEDIATEK_APU_SDK_ROOT}/include下查找NeuronAdapter.h。此外engine.cc 的 Execute 中可以看到推理前后的量化数据搬移对非对称 per-layer 量化UInt8Asymm张量会做 Symm/Asymm 转换后再交给NeuronExecution_compute输出端再反向转换。这也与MTK APU 只支持量化 OP的约束相呼应。二、支持现状已支持的芯片与设备芯片MT8168 / MT8175 及其他智能芯片设备MT8168-P2V1 Tablet4 × Cortex-A53 2.0 GHz CPU0.3 TOPs APU已支持的 Paddle 模型官方 demo 资源包提供以下预量化模型mobilenet_v1_int8_224_per_layermobilenet_v1_int8_224_per_channelresnet50_int8_224_per_layerssd_mobilenet_v1_relu_int8_300_per_layer性能数据官方文档测试结果编译环境Ubuntu 16.04NDK-r17c with GCC for Android armeabi-v7a测试方法warmup1repeats5统计平均时间单位 ms线程数为 1paddle::lite_api::PowerMode CPU_POWER_MODE设置为paddle::lite_api::PowerMode::LITE_POWER_HIGH分类模型输入维度 {1, 3, 224, 224}检测模型维度 {1, 3, 300, 300}MT8168 测试结果模型CPU (ms)NPU (ms)mobilenet_v1_int8_224_per_layer128.6426.29mobilenet_v1_int8_224_per_channel130.3726.62resnet50_int8_224_per_layer758.4377.93ssd_mobilenet_v1_relu_voc_int8_300_per_layer271.8553.31已支持的算子MediaTek APU 驱动当前注册的 NNAdapter 算子集合定义在 all.hREGISTER_CONVERTER(ADD, ConvertElementwise) REGISTER_CONVERTER(AVERAGE_POOL_2D, ConvertPool2D) REGISTER_CONVERTER(CHANNEL_SHUFFLE, ConvertChannelShuffle) REGISTER_CONVERTER(CONCAT, ConvertConcat) REGISTER_CONVERTER(CONV_2D, ConvertConv2D) REGISTER_CONVERTER(CONV_2D_TRANSPOSE, ConvertConv2DTranspose) REGISTER_CONVERTER(DIV, ConvertElementwise) REGISTER_CONVERTER(FLATTEN, ConvertFlatten) REGISTER_CONVERTER(FULLY_CONNECTED, ConvertFullyConnected) REGISTER_CONVERTER(HARD_SWISH, ConvertHardSwish) REGISTER_CONVERTER(MAX_POOL_2D, ConvertPool2D) REGISTER_CONVERTER(MUL, ConvertElementwise) REGISTER_CONVERTER(RELU, ConvertUnaryActivations) REGISTER_CONVERTER(RELU6, ConvertUnaryActivations) REGISTER_CONVERTER(RESHAPE, ConvertReshape) REGISTER_CONVERTER(RESIZE_LINEAR, ConvertResizeBilinear) REGISTER_CONVERTER(RESIZE_NEAREST, ConvertResizeNearest) REGISTER_CONVERTER(SIGMOID, ConvertUnaryActivations) REGISTER_CONVERTER(SOFTMAX, ConvertSoftmax) REGISTER_CONVERTER(SPLIT, ConvertSplit) REGISTER_CONVERTER(SUB, ConvertElementwise) REGISTER_CONVERTER(TANH, ConvertUnaryActivations) REGISTER_CONVERTER(TRANSPOSE, ConvertTranspose) REGISTER_CONVERTER(UNSQUEEZE, ConvertUnsqueeze)各算子在不同后端上的最新支持情况可对照仓库中各驱动的 converter 注册文件查看例如 android_nnapi 算子列表、cambricon_mlu 算子列表 等文档同时提示MTK 研发同学正在持续增加适配 Paddle 算子的 bridge/converter以覆盖更多模型。三、运行图像分类示例程序1. 准备设备环境由于需要依赖特定版本的 firmware需通过 MTK 官方渠道官网联系我们类别选择销售获取测试设备和 firmware。2. 准备交叉编译环境为保证编译环境一致建议参考 Docker 统一编译环境 搭建 Docker 开发环境。3. 下载通用示例程序从 PaddleLite 官方 demo 资源包下载PaddleLite-generic-demo.tar.gz官方资源地址见 原中文文档解压后目录结构如下PaddleLite-generic-demo ├── image_classification_demo │ ├── assets │ │ ├── configs │ │ │ ├── imagenet_224.txt # config 文件 │ │ │ └── synset_words.txt # 1000 分类 label 文件 │ │ ├── datasets │ │ │ └── test │ │ │ ├── inputs │ │ │ │ └── tabby_cat.jpg # 输入图片 │ │ │ ├── outputs │ │ │ │ └── tabby_cat.jpg # 输出图片 │ │ │ └── list.txt # 图片清单 │ │ └── models │ │ └── mobilenet_v1_int8_224_per_layer │ │ ├── __model__ # Paddle fluid 组网文件 │ │ ├── conv1_weights # 参数文件 │ │ ├── batch_norm_0.tmp_2.quant_dequant.scale # 量化参数文件 │ │ └── subgraph_partition_config_file.txt # 自定义子图分割配置文件 │ └── shell │ ├── CMakeLists.txt # 示例程序 CMake 脚本 │ ├── build.android.arm64-v8a/demo # 已编译的 arm64 示例程序 │ ├── build.android.armeabi-v7a/demo # 已编译的 armv7 示例程序 │ ├── demo.cc # 示例程序源码 │ ├── build.sh # 编译脚本 │ ├── run_with_adb.sh # adb 运行脚本 │ ├── run_with_ssh.sh # ssh 运行脚本 │ └── run.sh # 运行脚本 └── libs ├── PaddleLite │ └── android │ ├── armeabi-v7a │ │ ├── include │ │ └── lib │ │ ├── mediatek_apu # MTK APU Neuron Adapter 库、NNAdapter 运行时、device HAL 库 │ │ │ ├── libnnadapter.so # NNAdapter 运行时库 │ │ │ └── libmediatek_apu.so # NNAdapter device HAL 库 │ │ ├── libpaddle_full_api_shared.so │ │ └── libpaddle_light_api_shared.so │ └── ... └── OpenCV # OpenCV 预编译库4. 在 ARM CPU 与 MediaTek APU 上分别运行注意run_with_adb.sh不能在 Docker 环境执行否则可能找不到设备也不能在设备上运行run_with_ssh.sh不能在设备上运行且执行前需配置目标设备的 IP、SSH 账号和密码build.sh根据入参生成针对不同操作系统、体系结构的二进制程序需查阅注释信息配置正确参数run_with_adb.sh入参包括模型名称、操作系统、体系结构、目标设备、设备序列号等run_with_ssh.sh入参包括模型名称、操作系统、体系结构、目标设备、IP 地址、用户名、用户密码等。在 ARM CPU 上运行 mobilenetv1 全量化模型$ cd PaddleLite-generic-demo/image_classification_demo/shell $ ./run_with_adb.sh mobilenet_v1_int8_224_per_layer imagenet_224.txt test android armeabi-v7a cpu 0123456789ABCDEF Top1 Egyptian cat - 0.502124 Top2 tabby, tabby cat - 0.413927 Top3 tiger cat - 0.071703 Top4 lynx, catamount - 0.008436 Top5 cougar, puma, catamount, mountain lion, painter, panther, Felis concolor - 0.000563 Preprocess time: 18.868000 ms, avg 18.868000 ms, max 18.868000 ms, min 18.868000 ms Prediction time: 127.107000 ms, avg 127.107000 ms, max 127.107000 ms, min 127.107000 ms Postprocess time: 15.878000 ms, avg 15.878000 ms, max 15.878000 ms, min 15.878000 ms在 MediaTek APU 上运行同一模型仅设备参数从cpu换为mediatek_apu$ cd PaddleLite-generic-demo/image_classification_demo/shell $ ./run_with_adb.sh mobilenet_v1_int8_224_per_layer imagenet_224.txt test android armeabi-v7a mediatek_apu 0123456789ABCDEF Top1 Egyptian cat - 0.690272 Top2 tabby, tabby cat - 0.690272 Top3 tiger cat - 0.087746 Top4 lynx, catamount - 0.023399 Top5 great white shark, white shark, man-eater, man-eating shark, Carcharodon carcharias - 0.000000 Preprocess time: 18.846000 ms, avg 18.846000 ms, max 18.846000 ms, min 18.846000 ms Prediction time: 26.371000 ms, avg 26.371000 ms, max 26.371000 ms, min 26.371000 ms Postprocess time: 15.773000 ms, avg 15.773000 ms, max 15.773000 ms, min 15.773000 ms两次运行的预测结果一致Top1 均为 Egyptian cat推理耗时从 CPU 的 127.1 ms 降到 APU 的 26.4 ms约 4.8 倍加速与上表性能数据吻合。如果需要更改测试图片将图片拷贝到PaddleLite-generic-demo/image_classification_demo/assets/datasets/test/inputs目录并把文件名追加到assets/datasets/test/list.txt若替换了头文件或库还需在 Docker 环境中重新编译示例程序# For arm64-v8a $ ./build.sh android arm64-v8a # For armeabi-v7a $ ./build.sh android armeabi-v7a四、更新模型1. 量化通过 Paddle 训练或 X2Paddle 转换得到 MobileNetV1 float32 模型mobilenet_v1_fp32_224_fluid然后参考 模型量化指南 使用 PaddleSlim 对 float32 模型进行量化最终得到全量化 MobileNetV1 模型mobilenet_v1_int8_224_per_layer。注意由于 MTK APU 只支持量化 OP在启动量化脚本时请特别注意相关参数的设置保证模型全量化、量化参数满足 APU 约束。2. 用 opt 工具生成 APU 子图模型参考 模型转换方法利用 opt 工具转换生成 MTK APU 模型仅需要将valid_targets设置为mediatek_apu,arm即可# 注意PaddleLite-generic-demo 中已包含类似 opt 工具优化生成 nb 模型的功能 $ cd PaddleLite-generic-demo/image_classification_demo/assets/models $ ./opt --model_dirmobilenet_v1_int8_224_per_layer \ --optimize_out_typenaive_buffer \ --optimize_outopt_model \ --valid_targetsmediatek_apu,armvalid_targets的含义是这些 target 上能接住的算子划入 NPU 子图其余回落 CPU 执行。再次强调opt 生成的模型只是标记了 MediaTek APU 支持的 Paddle 算子真正的 Neuron 组网与编译发生在运行时对应前文Program::BuildFromModel的调用链。五、从源码编译 Paddle Lite MediaTek APU 部署库1. 下载源码与 DDK$ git clone https://gitcode.com/GitHub_Trending/pa/Paddle-Lite.git $ cd Paddle-Lite $ git checkout release-version-tag $ wget https://paddlelite-demo.bj.bcebos.com/devices/mediatek/apu_ddk.tar.gz $ tar -xvf apu_ddk.tar.gzDDK 目录中包含include/NeuronAdapter.h是 dependencies.cmake 的强制检查项。2. 编译 tiny_publish / full_publish 部署库以 build_android.sh 为入口关键参数是--with_nnadapterON开启 NNAdapter 框架、--nnadapter_with_mediatek_apuON编译 MTK APU 驱动和--nnadapter_mediatek_apu_sdk_root指向 DDK 根目录。For armv8arm64-v8a# tiny_publish 编译方式 $ ./lite/tools/build_android.sh --android_stlc_shared --with_extraON --with_logON --with_nnadapterON --nnadapter_with_mediatek_apuON --nnadapter_mediatek_apu_sdk_root$(pwd)/apu_ddk # full_publish 编译方式 $ ./lite/tools/build_android.sh --android_stlc_shared --with_extraON --with_logON --with_nnadapterON --nnadapter_with_mediatek_apuON --nnadapter_mediatek_apu_sdk_root$(pwd)/apu_ddk full_publishFor armv7armeabi-v7a# tiny_publish 编译方式 $ ./lite/tools/build_android.sh --archarmv7 --android_stlc_shared --with_extraON --with_logON --with_nnadapterON --nnadapter_with_mediatek_apuON --nnadapter_mediatek_apu_sdk_root$(pwd)/apu_ddk # full_publish 编译方式 $ ./lite/tools/build_android.sh --archarmv7 --android_stlc_shared --with_extraON --with_logON --with_nnadapterON --nnadapter_with_mediatek_apuON --nnadapter_mediatek_apu_sdk_root$(pwd)/apu_ddk full_publish3. 替换示例程序中的头文件和库For armv8产物位于build.lite.android.armv8.gcc/inference_lite_lib.android.armv8.nnadapter/cxx/# 替换 include 目录 $ cp -rf build.lite.android.armv8.gcc/inference_lite_lib.android.armv8.nnadapter/cxx/include/ PaddleLite-generic-demo/libs/PaddleLite/android/arm64-v8a/include/ # 替换 NNAdapter 运行时库 $ cp -rf build.lite.android.armv8.gcc/inference_lite_lib.android.armv8.nnadapter/cxx/lib/libnnadapter.so PaddleLite-generic-demo/libs/PaddleLite/android/arm64-v8a/lib/mediatek_apu/ # 替换 NNAdapter device HAL 库 $ cp -rf build.lite.android.armv8.gcc/inference_lite_lib.android.armv8.nnadapter/cxx/lib/libmediatek_apu.so PaddleLite-generic-demo/libs/PaddleLite/android/arm64-v8a/lib/mediatek_apu/ # 替换 libpaddle_light_api_shared.so $ cp -rf build.lite.android.armv8.gcc/inference_lite_lib.android.armv8.nnadapter/cxx/lib/libpaddle_light_api_shared.so PaddleLite-generic-demo/libs/PaddleLite/android/arm64-v8a/lib/ # 替换 libpaddle_full_api_shared.so仅 full_publish 编译方式下存在 $ cp -rf build.lite.android.armv8.gcc/inference_lite_lib.android.armv8.nnadapter/cxx/lib/libpaddle_full_api_shared.so PaddleLite-generic-demo/libs/PaddleLite/android/arm64-v8a/lib/For armv7产物位于build.lite.android.armv7.gcc/inference_lite_lib.android.armv7.nnadapter/cxx/# 替换 include 目录 $ cp -rf build.lite.android.armv7.gcc/inference_lite_lib.android.armv7.nnadapter/cxx/include/ PaddleLite-generic-demo/libs/PaddleLite/android/armeabi-v7a/include/ # 替换 NNAdapter 运行时库 $ cp -rf build.lite.android.armv7.gcc/inference_lite_lib.android.armv7.nnadapter/cxx/lib/libnnadapter.so PaddleLite-generic-demo/libs/PaddleLite/android/armeabi-v7a/lib/mediatek_apu/ # 替换 NNAdapter device HAL 库 $ cp -rf build.lite.android.armv7.gcc/inference_lite_lib.android.armv7.nnadapter/cxx/lib/libmediatek_apu.so PaddleLite-generic-demo/libs/PaddleLite/android/armeabi-v7a/lib/mediatek_apu/ # 替换 libpaddle_light_api_shared.so $ cp -rf build.lite.android.armv7.gcc/inference_lite_lib.android.armv7.nnadapter/cxx/lib/libpaddle_light_api_shared.so PaddleLite-generic-demo/libs/PaddleLite/android/armeabi-v7a/lib/ # 替换 libpaddle_full_api_shared.so仅 full_publish 编译方式下存在 $ cp -rf build.lite.android.armv7.gcc/inference_lite_lib.android.armv7.nnadapter/cxx/lib/libpaddle_full_api_shared.so PaddleLite-generic-demo/libs/PaddleLite/android/armeabi-v7a/lib/替换头文件后需要重新编译示例程序按前文build.sh说明操作。六、其它说明与延伸阅读由于涉及 License 问题官方无法直接提供用于测试的 firmware需通过 MTK 官方联系渠道官网联系我们类别选择销售获取测试设备和 firmwareMTK 研发同学正在持续增加用于适配 Paddle 算子的 bridge/converter以支持更多 Paddle 模型想深入理解 NNAdapter 通用框架与子图划分机制可继续阅读 NNAdapter 开发文档 以及 lite/backends/nnadapter/nnadapter/src/runtime 下的 Model/Context/Execution 实现相关文档Docker 编译环境、量化指南、opt 模型优化工具、华为 Kirin NPU 部署指南。【免费下载链接】Paddle-LitePaddlePaddle High Performance Deep Learning Inference Engine for Mobile and Edge (飞桨高性能深度学习端侧推理引擎项目地址: https://gitcode.com/GitHub_Trending/pa/Paddle-Lite创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻