高通AI Engine SDK(QNN)使用教程(环境配置、模型转换、量化、推理、分析)

火鸡大师傅 2024-09-04 10:31:07 阅读 82

在这里插入图片描述

1. Introduction

1.1 什么是QNN

QNN是高通发布的神经网络推理引擎,是SNPE的升级版,其主要功能是:

完成从Pytorch/TensorFlow/Keras/Onnx等神经网络框架到高通计算平台的模型转换;完成模型的低比特量化(int8),使其能够运行在高通神经网络芯片上;提供测试工具(qnn-net-run),可以运行网络并保存输出;提供测试工具(qnn-profile-viewer),可以进行FLOPS、参数量、每一层运行时间等分析;

1.2 QNN与SNPE的变化

SNPE模型使用容器(DL container)格式保存,QNN模型使用cpp,json和bin文件保存;SNPE模型在运行前无需编译,可以直接在不同平台下运行,QNN的模型需要先编译到对应平台,才可以运行;SNPE模型转化(snpe-xxx-to-dlc)和模型量化(snpe-dlc-quantize)在QNN中被合并到一个步骤(qnn-xxx-converter)

2. Linux端

QNN的Linux端提供这些功能:

qnn-accuracy-debugger

qnn-netron

qnn-platform-validator

qnn-tensorflow-converter

qnn-accuracy-evaluator

qnn-net-run

qnn-profile-viewer

qnn-tflite-converter

qnn-context-binary-generator

qnn-onnx-converter

qnn-pytorch-converter

qnn-throughput-net-run

qnn-model-lib-generator

qnn-op-package-generator

qnn-quantization-checker

模型转化、模型量化、模型分析等操作需要在Linux下完成。

2.1 环境配置

2.1.1 拷贝文件

以qnn-2.13.2.230822为例,将QNN的SDK解压到服务器端,然后配置环境变量(仅在当前终端生效,新开终端需要再次配置):

<code>export QNN_SDK_ROOT=/path/to/your/qnn-2.13.2.230822

执行初始化操作:

source ${QNN_SDK_ROOT}/bin/envsetup.sh

输出:

[INFO] AISW SDK environment set

[INFO] QNN_SDK_ROOT: /xxx/xxx/qnn-2.13.2.230822

2.1.2 配置Python环境

新建Conda环境(推荐):

conda create -n qnn python==3.8

conda activate qnn

自动安装依赖:

${QNN_SDK_ROOT}/bin/check-python-dependency

如果遇到Permission denied,需要把 ${QNN_SDK_ROOT}/bin路径下的文件赋予可执行权限:

chomd 777 ${QNN_SDK_ROOT}/bin/*

2.1.3 安装Linux依赖

执行:

bash ${QNN_SDK_ROOT}/bin/check-linux-dependency.sh

2.1.4 测试

执行

qnn-net-run --version

输出:

qnn-net-run pid:1947023

QNN SDK v2.13.2.230822171732_60416

配置成功

2.2 模型转化

onnx是通用的神经网络输出格式,以onnx模型格式的转换为例:

qnn-onnx-converter -i model.onnx -o model.cpp

会生成 model.cppmodel.binmodel_net.json 三个文件。

2.3 模型量化

在QNN中,模型量化和模型转化被合并到一个操作,如果需要进行模型量化,只需要用 --input_list 参数指定一批量化数据。

需要注意的是,要进行模型量化,只需要指定--input_list即可,此时就算不指定其他量化参数,也会进行量化操作(见官方文档)

The only required option to enable quantization along with conversion is the –input_list option, which provides the quantizer with the required input data for the given model.

qnn-onnx-converter -i model.onnx -o qnn/model_q.cpp --input_list /path/to/your/input.txt

其中input.txt的文件格式与SNPE相同。

2.4 量化参数

量化参数主要通过运行qnn-onnx-converter时指定这些参数来指定:

quantization_overrides:指定量化的参数param_quantizer:指定参数量化的方法。default:tf(即minmax量化),还有enhanced/adjusted/symmetric可选act_quantizer:指定激活函数量化的方法(同上)algorithms:详见官方文档:

“cle” - Cross layer equalization includes a number of methods for equalizing weights and biases across layers in order to rectify imbalances that cause quantization errors. “bc” - Bias correction adjusts biases to offset activation quantization errors. Typically used in conjunction with “cle” to improve quantization accuracy.

其他量化参数详见官方文档,不在此赘述。

2.5 模型编译

如果需要运行QNN的模型,需要先对模型转化中生成的model.cppmodel.bin进行编译,编译时使用-t指定编译平台(默认编译aarch64-androidx86_64-linux-clang平台):

# for linux

qnn-model-lib-generator -c model.cpp -b model.bin -o bin -t x86_64-linux-clang

需要注意的是,如果需要编译安卓运行的库(aarch64-android),需要先配置NDK环境。

2.6 NDK配置

将NDK文件上传到Linux服务器,并且解压(NDK使用android-ndk-r25c-linux版本),然后执行:

export ANDROID_NDK_ROOT=/path/to/your/ndk/android-ndk-r25c

PATH=$PATH:$ANDROID_NDK_ROOT

NDK配置完成后,执行:

# for android

qnn-model-lib-generator -c model.cpp -b model.bin -o bin -t "aarch64-android"

2.7 模型推理

使用qnn-net-run工具来进行模型推理,推理时需要用--backend参数指定推理后端的库,有如下参数可选:

CPU - libQnnCpu.soHTP (Hexagon v68) - libQnnHtp.soSaver - libQnnSaver.so

以使用HTP(模拟)为例,运行:

qnn-net-run --model bin/x86_64-linux-clang/libmodel.so --input_list /path/to/your/input.txt --backend "${QNN_SDK_ROOT}/lib/x86_64-linux-clang/libQnnHtp.so"

模型输出会默认保存到output文件夹。

3. Android端

QNN安卓端提供如下工具:

qnn-context-binary-generator

qnn-net-run

qnn-platform-validator

qnn-profile-viewer

qnn-throughput-net-run

基本只能进行模型推理和计算平台的验证。

3.1 环境配置

3.1.1 拷贝文件

将文件push到安卓设备上:

adb shell mkdir -p /data/local/tmp/qnn2/arm64/lib

adb shell mkdir -p /data/local/tmp/qnn2/arm64/bin

adb push D:\Program\qnn-2.13.2.230822\lib\aarch64-android\. /data/local/tmp/qnn2/arm64/lib

adb push D:\Program\qnn-2.13.2.230822\bin\aarch64-android\. /data/local/tmp/qnn2/arm64/bin

3.1.2 设置环境变量

每次重启终端都需要设置

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/data/local/tmp/qnn2/arm64/lib

export PATH=$PATH:/data/local/tmp/qnn2/arm64/bin

3.1.3 测试

qnn-net-run --version

输出

qnn-net-run pid:12495

QNN SDK v2.13.2.230822171732_60416

如果报错

/system/bin/sh: qnn-net-run: can’t execute: Permission denied

需要先赋予可执行权限

chmod 777 /data/local/tmp/qnn2/arm64/bin/qnn-net-run

3.2 CPU/GPU推理

首先将模型和数据Push到设备上,然后执行:

# cpu

qnn-net-run --model models/qnn/libmodel.so --input_list /path/to/your/input.txt --backend /data/local/tmp/qnn2/arm64/lib/libQnnCpu.so --output_dir outputs/qnn

# gpu

qnn-net-run --model models/qnn/libmodel.so --input_list /path/to/your/input.txt --backend /data/local/tmp/qnn2/arm64/lib/libQnnGpu.so --output_dir outputs/qnn

其中--backend参数可以指定的值如下:

CPU - libQnnCpu.soGPU - libQnnGpu.soHTA - libQnnHta.soDSP (Hexagon v65) - libQnnDspV65Stub.soDSP (Hexagon v66) - libQnnDspV66Stub.soDSP - libQnnDsp.soHTP (Hexagon v68) - libQnnHtp.so[Deprecated] HTP Alternate Prepare (Hexagon v68) - libQnnHtpAltPrepStub.soSaver - libQnnSaver.so

如果需要使用HTP或者DSP推理,需要Push额外的lib文件。

3.3 DSP推理

高通对不同芯片,支持DSP的库版本不同:SM7325使用hexagon-v68,SM8475使用hexagon-v69。

# v68

adb push D:\Program\qnn-2.13.2.230822\lib\hexagon-v68\unsigned\. /data/local/tmp/qnn2/dsp/lib

# v69

adb push D:\Program\qnn-2.13.2.230822\lib\hexagon-v69\unsigned\. /data/local/tmp/qnn2/dsp/lib

设置环境变量:

export ADSP_LIBRARY_PATH="/data/local/tmp/qnn2/dsp/lib;/system/vendor/lib/rfsa/adsp"code>

执行模型推理:

qnn-net-run --model models/qnn/libmodel.so --input_list /path/to/your/input.txt --backend /data/local/tmp/qnn2/arm64/lib/libQnnHtp.so --output_dir outputs/qnn

对于推理后端的支持,查看examples/QNN/NetRun/android/android-qnn-net-run.sh文件可以发现,v68、v69和v73使用的是libQnnHtp.so,v66使用的是libQnnDspV66Stub.so,v65使用的是libQnnDspV65Stub.so,使用时需要Push相应的库。

4. 结果分析

在运行qnn-net-run时指定--profiling_level参数:

qnn-net-run --model models/qnn/libmodel.so --input_list /path/to/your/input.txt --backend /data/local/tmp/qnn2/arm64/lib/libQnnHtp.so --output_dir outputs/qnn ----profiling_level basic

basic: captures execution and init time.detailed: in addition to basic, captures per Op timing for execution, if a backend supports it.client: captures only the performance metrics measured by qnn-net-run.

会在output文件夹下生成profile文件,在Linux下,可以使用qnn-profile-viewer对profile文件进行分析:

qnn-profile-viewer --input_log qnn-profiling-data_0.log

生成分析的结果:

Qnn Init/Prepare/Finalize/De-Init/Execute/Lib-Load Statistics:

--- Init Stats:

---

NetRun: 331158 us

Compose Graphs Stats:

---

NetRun: 74748 us

Finalize Stats:

--- Graph 0 (model):

NetRun: 256372 us

Backend (RPC (finalize) time): 4922 us

Backend (QNN accelerator (finalize) time): 4504 us

Backend (Accelerator (finalize) time): 4421 us

Backend (QNN (finalize) time): 256364 us

De-Init Stats:

---

NetRun: 15810 us

Backend (RPC (deinit) time): 1224 us

Backend (QNN Accelerator (deinit) time): 966 us

Backend (Accelerator (deinit) time): 934 us

Backend (QNN (deinit) time): 15801 us

Execute Stats (Average):

--- Total Inference Time:

--- Graph 0 (model):

NetRun: 2952 us

Backend (Number of HVX threads used): 4 count

Backend (RPC (execute) time): 2920 us

Backend (QNN accelerator (execute) time): 2600 us

Backend (Accelerator (execute) time): 2492 us

Backend (QNN (execute) time): 2949 us

Execute Stats (Overall):

---

NetRun IPS: 214.8888 inf/sec

对算法来说,关心的是推理时间,此处的推理时间是平均后的,为2.952ms

对CPU推理的profile进行分析,平均推理时间为148.259ms,量化后的模型加速效果显著。



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。