PaddleLite使用瑞芯微NPU预测部署

Paddle Lite已支持Rockchip NPU的预测部署。 其接入原理是与之前华为Kirin NPU类似,即加载并分析Paddle模型,将Paddle算子转成Rockchip NPU组网API进行网络构建,在线生成并执行模型。

支持现状

已支持的芯片

  • RK1808/1806

  • RV1126/1109

注意:支持RK3399Pro需要瑞芯微进行底层代码的重构,其工作量巨大,因此,暂不支持该款芯片。

已支持的设备

  • RK1808/1806 EVB

  • TB-RK1808S0 AI计算棒

  • RV1126/1109 EVB

已支持的Paddle模型

模型

性能

  • 测试环境

    • 编译环境

      • Ubuntu 16.04,GCC 5.4 for ARMLinux armhf and aarch64
    • 硬件环境

      • RK1808EVB/TB-RK1808S0 AI计算棒

        • CPU:2 x Cortex-A35 1.6 GHz

        • NPU:3 TOPs for INT8 / 300 GOPs for INT16 / 100 GFLOPs for FP16

      • RV1109EVB

        • CPU:2 x Cortex-A7 1.2 GHz

        • NPU:1.2Tops,support INT8/ INT16

  • 测试方法

    • warmup=10, repeats=30,统计平均时间,单位是ms

    • 线程数为1,DeviceInfo::Global().SetRunMode设置LITE_POWER_HIGH

    • 分类模型的输入图像维度是{1, 3, 224, 224}

  • 测试结果

模型RK1808EVBTB-RK1808S0 AI计算棒RV1109EVB
CPU(ms)NPU(ms)CPU(ms)NPU(ms)CPU(ms)NPU(ms)
MobileNetV1-int8266.6235056.139359.0079969.4335335.039936.6995
ResNet50-int81488.34699918.198991983.60150123.59351960.2725229.8895

已支持(或部分支持)的Paddle算子

  • relu

  • conv2d

  • depthwise_conv2d

  • pool2d

  • fc

  • softmax

  • batch_norm

  • concat

  • elementwise_add

  • elementwise_sub

  • elementwise_mul

  • elementwise_div

  • transpose2

  • reshape2

  • sigmoid

  • scale

  • flatten

  • flatten2

  • pad2d

可以通过访问https://github.com/PaddlePaddle/Paddle-Lite/blob/develop/lite/kernels/rknpu/bridges/paddle_use_bridges.h获得最新的算子支持列表。

参考示例演示

测试设备

  • RK1808 EVB

    rk1808_evb_front

    rk1808_evb_back

  • TB-RK1808S0 AI计算棒

    tb-rk1808s0

  • RV1126 EVB

    rk1126_evb

准备设备环境

  • RK1808 EVB

    • 需要依赖特定版本的firmware,请参照rknpu_ddk的说明对设备进行firmware的更新;

    • 由于RK1808 EVB在刷firmware后,只是一个纯净的Linux系统,无法像Ubuntu那样使用apt-get命令方便的安装软件,因此,示例程序和PaddleLite库的编译均采用交叉编译方式;

    • 将MicroUSB线插入到设备的MicroUSB OTG口,就可以使用Android的adb命令进行设备的交互,再也不用配置网络使用ssh或者通过串口的方式访问设备了,这个设计非常赞!

    • 将rknpu_ddk的lib64目录下除librknpu_ddk.so之外的动态库都拷贝到设备的/usr/lib目录下,更新Rockchip NPU的系统库。

  • TB-RK1808S0 AI计算棒

    • 参考TB-RK1808S0 wiki教程的将计算棒配置为主动模式,完成网络设置和firmware的升级,具体步骤如下:

      • 将计算棒插入Window7/10主机,参考主动模式开发配主机的虚拟网卡IP地址,通过ssh toybrick@192.168.180.8验证是否能登录计算棒;

      • 参考Window7/10系统配置计算棒网络共享,SSH登录计算棒后通过wget www.baidu.com验证是否能够访问外网;

      • 参考固件在线升级,建议通过ssh登录计算棒,在shell下执行sudo dnf update -y命令快速升级到最新版本系统(要求系统版本>=1.4.1-2),可通过rpm -qa | grep toybrick-server查询系统版本:

      1. $ rpm -qa | grep toybrick-server
      2. toybrick-server-1.4.1-2.rk1808.fc28.aarch64
      • 将rknpu_ddk的lib64目录下除librknpu_ddk.so之外的动态库都拷贝到设备的/usr/lib目录下,更新Rockchip NPU的系统库。
  • RV1126 EVB

    • 需要升级1.51的firmware(下载和烧录方法请联系RK相关同学),可通过以下命令确认librknn_runtime.so的版本:
    1. # strings /usr/lib/librknn_runtime.so | grep build |grep version
    2. librknn_runtime version 1.5.1 (161f53f build: 2020-11-05 15:12:30 base: 1126)
    • 示例程序和PaddleLite库的编译需要采用交叉编译方式,通过adb进行设备的交互和示例程序的运行。

    • 将rknpu_ddk的lib目录下除librknpu_ddk.so之外的动态库都拷贝到设备的/usr/lib目录下,更新Rockchip NPU的系统库。

准备交叉编译环境

  • 为了保证编译环境一致,建议参考编译环境准备中的Docker开发环境进行配置;

  • 由于有些设备只提供网络访问方式(例如:TB-RK1808S0 AI计算棒),需要通过scp和ssh命令将交叉编译生成的PaddleLite库和示例程序传输到设备上执行,因此,在进入Docker容器后还需要安装如下软件:

    1. # apt-get install openssh-client sshpass

运行图像分类示例程序

  • 下载示例程序PaddleLite-linux-demo.tar.gz,解压后清单如下:

    1. - PaddleLite-linux-demo
    2. - image_classification_demo
    3. - assets
    4. - images
    5. - tabby_cat.jpg # 测试图片
    6. - tabby_cat.raw # 已处理成raw数据的测试图片
    7. - labels
    8. - synset_words.txt # 1000分类label文件
    9. - models
    10. - mobilenet_v1_int8_224_for_cpu_fluid # Paddle fluid non-combined格式的、适用于ARM CPU的MobileNetV1-int8量化模型
    11. - mobilenet_v1_int8_224_for_rockchip_npu_fluid # Paddle fluid non-combined格式的、适用于Rockchip NPU的MobileNetV1-int8全量化模型
    12. - mobilenet_v1_int8_224_for_cpu
    13. - model.nb # 已通过opt转好的、适合ARM CPU的obileNetV1-int8量化模型
    14. - mobilenet_v1_int8_224_for_rockchip_npu
    15. - model.nb # 已通过opt转好的、适合Rockchip NPU的MobileNetV1-int8全量化模型
    16. - resnet50_int8_224_for_cpu_fluid # Paddle fluid non-combined格式的、适用于ARM CPU的ResNet50-int8量化模型
    17. - resnet50_int8_224_for_rockchip_npu_fluid # Paddle fluid non-combined格式的、适用于Rockchip NPU的ResNet50-int8全量化模型
    18. - resnet50_int8_224_for_cpu
    19. - model.nb # 已通过opt转好的、适合ARM CPU的ResNet50-int8量化模型
    20. - resnet50_int8_224_for_rockchip_npu
    21. - model.nb # 已通过opt转好的、适合Rockchip NPU的ResNet50-int8全量化模型
    22. - shell
    23. - CMakeLists.txt # 示例程序CMake脚本
    24. - build
    25. - image_classification_demo # 已编译好的示例程序
    26. - image_classification_demo.cc # 示例程序源码
    27. - convert_to_raw_image.py # 将测试图片保存为raw数据的python脚本
    28. - build.sh # 示例程序编译脚本
    29. - run_with_adb.sh # RK1808/RK1806/RV1126/RV1109 EVB的示例程序运行脚本
    30. - run_with_ssh.sh # TB-RK1808S0 AI计算棒的示例程序运行脚本
    31. - libs
    32. - PaddleLite
    33. - arm64 # 适用于RK1808 EVB和TB-RK1808S0 AI计算棒的PaddleLite预编译库
    34. - include # PaddleLite头文件
    35. - lib
    36. - librknpu_ddk.so # RK DDK库
    37. - libgomp.so.1 # gnuomp库
    38. - libpaddle_light_api_shared.so # 预编译PaddleLite库
    39. - armhf # 适用于RK1806/RV1126/RV1109 EVB的PaddleLite预编译库
  • 按照以下命令分别运行转换后的ARM CPU模型和Rockchip NPU模型,比较它们的性能和结果;

    1. 注意:
    2. 1run_with_adb.sh不能在docker环境执行,否则可能无法找到设备,也不能在设备上运行;
    3. 2run_with_ssh.sh不能在设备上运行,且执行前需要配置目标设备的IP地址、SSH账号和密码;
    4. 2build.sh需要在docker环境中执行,如果需要测试armhf库,可将build.shTARGET_ARCH_ABI修改成armhf后重新生成image_classification_demo
    5. 运行适用于ARM CPUmobilenetv1全量化模型
    6. $ cd PaddleLite-linux-demo/image_classification_demo/assets/models
    7. $ cp mobilenet_v1_int8_224_for_cpu/model.nb mobilenet_v1_int8_224_for_cpu_fluid.nb
    8. $ cd ../../shell
    9. $ vim ./run_with_adb.sh vim ./run_with_ssh.sh
    10. MODEL_NAME设置为mobilenet_v1_int8_224_for_cpu_fluid
    11. For RK1808 EVB
    12. $ ./run_with_adb.sh arm64
    13. (RK1808 EVB)
    14. warmup: 5 repeat: 10, average: 266.276001 ms, max: 266.576996 ms, min: 266.158997 ms
    15. results: 3
    16. Top0 tabby, tabby cat - 0.522023
    17. Top1 Egyptian cat - 0.395266
    18. Top2 tiger cat - 0.073605
    19. Preprocess time: 2.684000 ms
    20. Prediction time: 266.276001 ms
    21. Postprocess time: 0.456000 ms
    22. For RK1806/RV1126/RV1109 EVB
    23. $ ./build.sh armhf
    24. $ ./run_with_adb.sh armhf
    25. (RV1126 EVB)
    26. warmup: 5 repeat: 10, average: 338.019904 ms, max: 371.528992 ms, min: 331.010010 ms
    27. results: 3
    28. Top0 tabby, tabby cat - 0.522023
    29. Top1 Egyptian cat - 0.395266
    30. Top2 tiger cat - 0.073605
    31. Preprocess time: 3.443000 ms
    32. Prediction time: 338.019904 ms
    33. Postprocess time: 0.600000 ms
    34. (RV1109 EVB)
    35. warmup: 5 repeat: 10, average: 335.438400 ms, max: 346.362000 ms, min: 331.894012 ms
    36. results: 3
    37. Top0 tabby, tabby cat - 0.522023
    38. Top1 Egyptian cat - 0.395266
    39. Top2 tiger cat - 0.073605
    40. Preprocess time: 3.420000 ms
    41. Prediction time: 335.438400 ms
    42. Postprocess time: 0.582000 ms
    43. For TB-RK1808S0 AI计算棒
    44. $ ./run_with_ssh.sh arm64
    45. (TB-RK1808S0 AI计算棒)
    46. warmup: 5 repeat: 10, average: 358.836304 ms, max: 361.001007 ms, min: 358.035004 ms
    47. results: 3
    48. Top0 tabby, tabby cat - 0.522023
    49. Top1 Egyptian cat - 0.395266
    50. Top2 tiger cat - 0.073605
    51. Preprocess time: 3.670000 ms
    52. Prediction time: 358.836304 ms
    53. Postprocess time: 0.542000 ms
    54. 运行适用于Rockchip NPUmobilenetv1全量化模型
    55. $ cd PaddleLite-linux-demo/image_classification_demo/assets/models
    56. $ cp mobilenet_v1_int8_224_for_rockchip_npu/model.nb mobilenet_v1_int8_224_for_rockchip_npu_fluid.nb
    57. $ cd ../../shell
    58. $ vim ./run_with_adb.sh vim ./run_with_ssh.sh
    59. MODEL_NAME设置为mobilenet_v1_int8_224_for_rockchip_npu_fluid
    60. For RK1808 EVB
    61. $ ./run_with_adb.sh arm64
    62. (RK1808 EVB)
    63. warmup: 5 repeat: 10, average: 6.663300 ms, max: 6.705000 ms, min: 6.590000 ms
    64. results: 3
    65. Top0 Egyptian cat - 0.514779
    66. Top1 tabby, tabby cat - 0.421183
    67. Top2 tiger cat - 0.052648
    68. Preprocess time: 2.391000 ms
    69. Prediction time: 6.663300 ms
    70. Postprocess time: 0.470000 ms
    71. For RK1806/RV1126/RV1109 EVB
    72. $ ./build.sh armhf
    73. $ ./run_with_adb.sh armhf
    74. (RV1126 EVB)
    75. warmup: 5 repeat: 10, average: 5.956600 ms, max: 6.083000 ms, min: 5.860000 ms
    76. results: 3
    77. Top0 Egyptian cat - 0.497230
    78. Top1 tabby, tabby cat - 0.409483
    79. Top2 tiger cat - 0.081897
    80. Preprocess time: 3.514000 ms
    81. Prediction time: 5.956600 ms
    82. Postprocess time: 0.539000 ms
    83. (RV1109 EVB)
    84. warmup: 5 repeat: 10, average: 7.163200 ms, max: 7.459000 ms, min: 7.055000 ms
    85. results: 3
    86. Top0 Egyptian cat - 0.497230
    87. Top1 tabby, tabby cat - 0.409483
    88. Top2 tiger cat - 0.081897
    89. Preprocess time: 3.465000 ms
    90. Prediction time: 7.163200 ms
    91. Postprocess time: 0.595000 ms
    92. For TB-RK1808S0 AI计算棒
    93. $ ./run_with_ssh.sh arm64
    94. (TB-RK1808S0 AI计算棒)
    95. warmup: 5 repeat: 10, average: 9.819400 ms, max: 9.970000 ms, min: 9.776000 ms
    96. results: 3
    97. Top0 Egyptian cat - 0.514779
    98. Top1 tabby, tabby cat - 0.421183
    99. Top2 tiger cat - 0.052648
    100. Preprocess time: 4.277000 ms
    101. Prediction time: 9.819400 ms
    102. Postprocess time: 5.776000 ms
  • 如果需要更改测试图片,可通过convert_to_raw_image.py工具生成;

  • 如果需要重新编译示例程序,直接运行./build.sh即可,注意:build.sh的执行必须在docker环境中,否则可能编译出错。

更新模型

  • 通过Paddle训练或X2Paddle转换得到MobileNetv1 foat32模型mobilenet_v1_fp32_224_fluid

  • 通过Paddle+PaddleSlim后量化方式,生成MobileNetV1-int8全量化模型

    • 下载PaddleSlim-quant-demo.tar.gz,解压后清单如下:

      1. - PaddleSlim-quant-demo
      2. - image_classification_demo
      3. - quant_post # 后量化
      4. - quant_post_rockchip_npu.sh # Rockchip NPU 一键量化脚本
      5. - README.md # 环境配置说明,涉及PaddlePaddle、PaddleSlim的版本选择、编译和安装步骤
      6. - datasets # 量化所需要的校准数据集合
      7. - ILSVRC2012_val_100 # 从ImageNet2012验证集挑选的100张图片
      8. - inputs # 待量化的fp32模型
      9. - mobilenet_v1
      10. - resnet50
      11. - outputs # 产出的全量化模型
      12. - scripts # 后量化内置脚本
    • 查看README.md完成PaddlePaddle和PaddleSlim的安装

    • 直接执行./quant_post_rockchip_npu.sh即可在outputs目录下生成MobileNetV1-int8全量化模型

      1. $ cd PaddleSlim-quant-demo/image_classification_demo/quant_post
      2. $ ./quant_post_rockchip_npu.sh
      3. ...
      4. 2021-01-20 14:02:45,671-INFO: Preparation stage ...
      5. 2021-01-20 14:02:47,205-INFO: Run batch: 0
      6. 2021-01-20 14:02:52,124-INFO: Run batch: 5
      7. 2021-01-20 14:02:56,072-INFO: Finish preparation stage, all batch:10
      8. 2021-01-20 14:02:56,079-INFO: Sampling stage ...
      9. 2021-01-20 14:03:08,759-INFO: Run batch: 0
      10. 2021-01-20 14:04:11,117-INFO: Run batch: 5
      11. 2021-01-20 14:05:00,945-INFO: Finish sampling stage, all batch: 10
      12. 2021-01-20 14:05:00,946-INFO: Calculate KL threshold ...
      13. 2021-01-20 14:05:33,664-INFO: Update the program ...
      14. 2021-01-20 14:05:34,400-INFO: The quantized model is saved in ../outputs/mobilenet_v1
      15. post training quantization finish, and it takes 169.63866925239563.
      16. --------start eval int8 model: mobilenet_v1-------------
      17. grep: warning: GREP_OPTIONS is deprecated; please use an alias or script
      18. ----------- Configuration Arguments -----------
      19. batch_size: 20
      20. class_dim: 1000
      21. data_dir: ../dataset/ILSVRC2012_val_100
      22. image_shape: 3,224,224
      23. inference_model: ../outputs/mobilenet_v1
      24. input_img_save_path: ./img_txt
      25. save_input_img: False
      26. test_samples: -1
      27. use_gpu: 0
      28. ------------------------------------------------
      29. Testbatch 0, acc1 0.75, acc5 1.0, time 1.38 sec
      30. End test: test_acc1 0.76, test_acc5 0.93
      31. --------finish eval int8 model: mobilenet_v1-------------
  • 参考模型转化方法,利用opt工具转换生成Rockchip NPU模型,仅需要将valid_targets设置为rknpu,arm即可。

    1. $ ./opt --model_dir=mobilenet_v1_int8_224_for_rockchip_npu_fluid \
    2. --optimize_out_type=naive_buffer \
    3. --optimize_out=opt_model \
    4. --valid_targets=rknpu,arm
    5. 替换自带的Rockchip NPU模型
    6. $ cp opt_model.nb mobilenet_v1_int8_224_for_rockchip_npu/model.nb
  • 注意:opt生成的模型只是标记了Rockchip NPU支持的Paddle算子,并没有真正生成Rockchip NPU模型,只有在执行时才会将标记的Paddle算子转成Rockchip NPU组网API,最终生成并执行模型。

更新支持Rockchip NPU的Paddle Lite库

  • 下载PaddleLite源码和Rockchip NPU DDK

    1. $ git clone https://github.com/PaddlePaddle/Paddle-Lite.git
    2. $ cd Paddle-Lite
    3. $ git checkout <release-version-tag>
    4. $ git clone https://github.com/airockchip/rknpu_ddk.git
  • 编译并生成PaddleLite+RockchipNPU for armv8 and armv7的部署库

    • For RK1808 EVB and TB-RK1808S0 AI计算棒

      • tiny_publish编译方式

        1. $ ./lite/tools/build_linux.sh --with_extra=ON --with_log=ON --with_rockchip_npu=ON --rockchip_npu_sdk_root=./rknpu_ddk
        2. tiny_publish模式下编译生成的build.lite.linux.armv8.gcc/inference_lite_lib.armlinux.armv8.rknpu/cxx/lib/libpaddle_light_api_shared.so替换PaddleLite-linux-demo/libs/PaddleLite/arm64/lib/libpaddle_light_api_shared.so文件;
      • full_publish编译方式

        1. $ ./lite/tools/build_linux.sh --with_extra=ON --with_log=ON --with_rockchip_npu=ON --rockchip_npu_sdk_root=./rknpu_ddk full_publish
        2. full_publish模式下编译生成的build.lite.linux.armv8.gcc/inference_lite_lib.armlinux.armv8.rknpu/cxx/lib/libpaddle_full_api_shared.so替换PaddleLite-linux-demo/libs/PaddleLite/arm64/lib/libpaddle_full_api_shared.so文件;

      将编译生成的build.lite.linux.armv8.gcc/inference_lite_lib.armlinux.armv8.rknpu/cxx/include替换PaddleLite-linux-demo/libs/PaddleLite/arm64/include目录;

    • For RK1806/RV1126/RV1109 EVB

      • tiny_publish编译方式

        1. $ ./lite/tools/build_linux.sh --arch=armv7hf --with_extra=ON --with_log=ON --with_rockchip_npu=ON --rockchip_npu_sdk_root=./rknpu_ddk
        2. tiny_publish模式下编译生成的build.lite.linux.armv7hf.gcc/inference_lite_lib.armlinux.armv7hf.rknpu/cxx/lib/libpaddle_light_api_shared.so替换PaddleLite-linux-demo/libs/PaddleLite/armhf/lib/libpaddle_light_api_shared.so文件;
      • full_publish编译方式

        1. $ ./lite/tools/build_linux.sh --arch=armv7hf --with_extra=ON --with_log=ON --with_rockchip_npu=ON --rockchip_npu_sdk_root=./rknpu_ddk full_publish
        2. full_publish模式下编译生成的build.lite.linux.armv7hf.gcc/inference_lite_lib.armlinux.armv7hf.rknpu/cxx/lib/libpaddle_full_api_shared.so替换PaddleLite-linux-demo/libs/PaddleLite/armhf/lib/libpaddle_full_api_shared.so文件。

      将编译生成的build.lite.linux.armv7hf.gcc/inference_lite_lib.armlinux.armv7hf.rknpu/cxx/include替换PaddleLite-linux-demo/libs/PaddleLite/armhf/include目录;

  • 替换头文件后需要重新编译示例程序

其它说明

  • RK研发同学正在持续增加用于适配Paddle算子bridge/converter,以便适配更多Paddle模型。