骁龙神经处理引擎SDK参考指南(27)

281 篇文章 28 订阅
17 篇文章 7 订阅

骁龙神经处理引擎SDK参考指南(27)


6.5.8 使用 D32 数据格式的 UDO 教程

概述
本教程介绍了在 DSP 上运行具有 D32 数据格式的 UDO 并使用该包执行 Alexnet 模型所需的步骤。本教程选择卷积运算来演示 UDO 的实现。D32 是 Depth-32 的缩写,是一种内部创建的矢量友好数据格式,用于高效的 DSP 操作。

SNPE SDK 在以下位置提供了此示例的资源

  • $SNPE_ROOT/examples/NativeCpp/UdoExample/Conv2D/src/DSP/Conv2DInt8D32Impl

有关 UDO 的一般信息可在UDO 概述中找到。

有关在不使用 UDO 的情况下运行 Alexnet 网络的信息,请参阅Alexnet 教程。

有关创建 UDO 包和使用该包执行模型的信息,请参阅UDO 教程。

先决条件

以下教程假设已遵循常规SNPE 设置来支持 SDK 环境、Caffe 环境和所需的平台依赖项。此外,我们需要一个提取的 QNN-SDK(不需要 QNN-SDK 设置)来生成骨架代码和构建库。有关 QNN-SDK 的详细信息,请参阅第 1 页的 QNN 文档 Q N N S D K R O O T / d o c s / i n d e x . h t m l ,其中 Q N N S D K R O O T 是 Q N N − S D K 安装的位置。将设为 QNN_SDK_ROOT/docs/index.html,其中QNN_SDK_ROOT是 QNN-SDK 安装的位置。将 设为 QNNSDKROOT/docs/index.html,其中QNNSDKROOTQNNSDK安装的位置。将设为QNN_SDK_ROOT解压后的 QNN-SDK 位置。有关获取 Alexnet 模型的详细信息,请访问教程设置。此外,对于本教程所需的 CPU 相关资源,建议遵循UDO 权重教程上提供的教程。

介绍

以下是开发和运行 UDO 的步骤

  • 1.)包生成

  • 2.)框架模型转换为 DLC

  • 3.)包实施

  • 4.)包编译

  • 5.)模型执行

步骤 1-4 在 x86 主机上脱机运行,并且是步骤 5 中执行所必需的。步骤 5 提供有关使用 SNPE 命令行可执行文件snpe-net-run执行的信息。

第 1 步:生成包

生成 Conv2DPackage 需要snpe-udo-package-generator工具和提供的 UDO 插件: Conv2DQuant.json 。Conv2DQuant.json 为您提供 DSP(uint8) 实现的框架代码。插件位于 $SNPE_ROOT/examples/NativeCpp/UdoExample/Conv2D/config 下。有关创建 UDO 插件的更多信息可以在此处找到。

使用以下命令生成 Conv2DPackage UDO 包:

export SNPE_UDO_ROOT=$SNPE_ROOT/share/SnpeUdo
mkdir $SNPE_ROOT/models/alexnet/ConvD32UdoDsp
snpe-udo-package-generator -p $SNPE_ROOT/examples/NativeCpp/UdoExample/Conv2D/config/Conv2DQuant.json -o $SNPE_ROOT/models/alexnet/ConvD32UdoDsp

此命令在 $SNPE_ROOT/models/alexnet/ConvD32UdoDsp/Conv2DPackage 中创建基于卷积的包。

有关 snpe-udo-package-generator 工具的更多信息,请访问此处

步骤 2:框架模型转换为 DLC

将 Caffe Alexnet 模型转换为 DLC 需要snpe-caffe-to-dlc工具。snpe-caffe-to-dlc 工具通过 --udo 命令行选项使用与包生成中使用的相同的 Conv2D.json。如果您遵循教程设置,批量维​​度为 1 的 alexnet 将位于 $SNPE_ROOT/models/alexnet/caffe 中。

使用以下命令转换 Alexnet:

snpe-caffe-to-dlc --input_network $SNPE_ROOT/models/alexnet/caffe/deploy_batch_1.prototxt --caffe_bin $SNPE_ROOT/models/alexnet/caffe/bvlc_alexnet.caffemodel --output_path $SNPE_ROOT/models/alexnet/dlc/alexnet_udo.dlc --udo $SNPE_ROOT/examples/NativeCpp/UdoExample/Conv2D/config/Conv2D.json

这将生成一个名为 alexnet_udo.dlc 的 DLC,其中包含位于 $SNPE_ROOT/models/alexnet/dlc 的 UDO 卷积。

第 3 步:包实施

生成的包创建操作实现的骨架,用户必须填充该骨架才能创建功能性 UDO。与 SNPE 兼容的其余代码支架由snpe-udo-package-generator提供。

本教程的 UDO 实现在 $SNPE_ROOT/examples/NativeCpp/UdoExample/Conv2D/src 下提供。

DSP 实现 (Android)

软件包中需要实现DSP的文件有

  • ConvD32UdoDsp/Conv2DPackage/jni/src/DSP/ConvolutionImplLibDsp.c
  • ConvD32UdoDsp/Conv2DPackage/include/ConvolutionImplLibDsp.h

提供的示例实现位于以下位置

  • SNPE_ROOT/examples/NativeCpp/UdoExample/Conv2D/src/DSP/Conv2DInt8D32Impl/ConvolutionImplLibDsp.c
  • SNPE_ROOT/examples/NativeCpp/UdoExample/Conv2D/src/DSP/Conv2DInt8D32Impl/ConvolutionImplLibDsp.h

将提供的实现复制到包中:

cp -f $SNPE_ROOT/examples/NativeCpp/UdoExample/Conv2D/src/DSP/Conv2DInt8D32Impl/ConvolutionImplLibDsp.c $SNPE_ROOT/models/alexnet/ConvD32UdoDsp/Conv2DPackage/jni/src/DSP/
cp -f $SNPE_ROOT/examples/NativeCpp/UdoExample/Conv2D/src/DSP/Conv2DInt8D32Impl/ConvolutionImplLibDsp.h $SNPE_ROOT/models/alexnet/ConvD32UdoDsp/Conv2DPackage/include/

或者,用户可以在包中提供自己的实现。

第四步:包编译

Hexagon DSP 运行时编译

DSP 运行时的编译利用了 make 系统。为了构建 DSP 实现库,需要安装和设置 Hexagon-SDK。有关详细信息,请按照页面上的设置说明进行操作$HEXAGON_SDK_ROOT/docs/readme.html,该页面HEXAGON_SDK_ROOT是您的 Hexagon-SDK 安装位置。有关编译适用于 DSP 的 UDO 的信息可在编译适用于 DSP 的 UDO中找到。

注意:对于DSP,PLATFORM只会确定注册库的ABI。

模型执行

使用 snpe-net-run 执行

使用 UDO 执行 AlexNet 与在不使用 UDO 的情况下使用snpe-net-run基本相同。

SNPE SDK 提供 Linux 和 Android下snpe-net-run的二进制文件

  • $SNPE_ROOT/bin/x86_64-linux-clang
  • $SNPE_ROOT/bin/arm-android-clang8.0
  • $SNPE_ROOT/bin/aarch64-android-clang8.0
  • $SNPE_ROOT/bin/aarch64-oe-linux-gcc8.2
  • $SNPE_ROOT/bin/aarch64-oe-linux-gcc9.3
  • $SNPE_ROOT/bin/aarch64-ubuntu-gcc7.5

对于 UDO,snpe-net-run 通过 --udo_package_path 选项使用注册库。LD_LIBRARY_PATH 还必须更新以包含从包编译生成的运行时特定工件。

Android 目标执行

在 Android 目标上执行的教程将使用 arm64-v8a 架构。本教程的这一部分对于所有运行时 DSP 或 CPU 都是通用的。

# architecture: arm64-v8a - compiler: clang - STL: libc++
export SNPE_TARGET_ARCH=aarch64-android-clang8.0
export SNPE_TARGET_STL=libc++_shared.so

然后,将 SNPE 二进制文件和库推送到目标设备:

adb shell "mkdir -p /data/local/tmp/snpeexample/$SNPE_TARGET_ARCH/bin"
adb shell "mkdir -p /data/local/tmp/snpeexample/$SNPE_TARGET_ARCH/lib"

adb push $SNPE_ROOT/lib/$SNPE_TARGET_ARCH/$SNPE_TARGET_STL \
      /data/local/tmp/snpeexample/$SNPE_TARGET_ARCH/lib
adb push $SNPE_ROOT/lib/$SNPE_TARGET_ARCH/*.so \
      /data/local/tmp/snpeexample/$SNPE_TARGET_ARCH/lib
adb push $SNPE_ROOT/bin/$SNPE_TARGET_ARCH/snpe-net-run \
      /data/local/tmp/snpeexample/$SNPE_TARGET_ARCH/bin

接下来,更新目标设备上的环境变量以包含 SNPE 库和二进制文件:

adb shell
export SNPE_TARGET_ARCH=aarch64-android-clang8.0
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/data/local/tmp/snpeexample/$SNPE_TARGET_ARCH/lib
export PATH=$PATH:/data/local/tmp/snpeexample/$SNPE_TARGET_ARCH/bin

最后,将 Alexnet UDO 模型和输入数据推送到设备:

cd $SNPE_ROOT/models/alexnet
mkdir data/rawfiles && cp data/cropped/*.raw data/rawfiles/
adb shell "mkdir -p /data/local/tmp/alexnet_udo"
adb push data/rawfiles /data/local/tmp/alexnet_udo/cropped
adb push data/target_raw_list.txt /data/local/tmp/alexnet_udo
adb push dlc/alexnet_udo.dlc /data/local/tmp/alexnet_udo
rm -rf data/rawfiles

Hexagon DSP 执行

DSP在设备上的执行过程与CPU基本相同。然而,DSP 运行时需要量化的网络参数。虽然 DSP 允许未量化的 DLC,但通常建议量化 DLC 以提高性能。本教程将使用量化 DLC 作为说明性示例。量化 DLC 需要snpe-dlc-quantize工具。

要量化 DLC 以在 DSP 上使用:

cd $SNPE_ROOT/models/alexnet/
snpe-dlc-quantize --input_dlc dlc/alexnet_udo.dlc --input_list data/cropped/raw_list.txt --udo_package_path ConvUdoCpu/Conv2DPackage/libs/x86-64_linux_clang/libUdoConv2DPackageReg.so --output_dlc dlc/alexnet_udo_quantized.dlc

这里的 ConvUdoCpu 文件夹包含 Conv2D UDO 的 CPU 实现。有关此内容的更多详细信息,请参阅UDO 权重教程。

有关snpe-dlc-quantize的更多信息,请访问量化。有关 UDO 特定量化的信息,请访问使用 UDO 量化 DLC。有关 DSP 运行时的信息,请访问DSP 运行时。

现在将量化模型推送到设备:

adb push dlc/alexnet_udo_quantized.dlc /data/local/tmp/alexnet_udo

在 DSP 上执行之前,将 DSP 的 SNPE 库推送到设备:

adb shell "mkdir -p /data/local/tmp/snpeexample/dsp/lib"
adb push $SNPE_ROOT/lib/dsp/*.so /data/local/tmp/snpeexample/dsp/lib

现在将 DSP 特定的 UDO 库推送到设备。根据配置中指定的 DSP 架构,dsp_v68目录可以是dsp_v60或dsp(使用旧版 SNPE SDK)。

cd $SNPE_ROOT/models/alexnet/ConvD32UdoDsp
adb shell "mkdir -p /data/local/tmp/alexnet_udo/dsp"
adb push Conv2DPackage/libs/dsp_v60/*.so /data/local/tmp/alexnet_udo/dsp
adb push Conv2DPackage/libs/arm64-v8a/libUdoConv2DPackageReg.so /data/local/tmp/alexnet_udo/dsp # Pushes reg lib

然后设置所需的环境变量并在设备上运行 snpe-net-run:

adb shell
cd /data/local/tmp/alexnet_udo/
export LD_LIBRARY_PATH=/data/local/tmp/alexnet_udo/dsp/:$LD_LIBRARY_PATH
export ADSP_LIBRARY_PATH="/data/local/tmp/alexnet_udo/dsp/;/data/local/tmp/snpeexample/dsp/lib;/system/lib/rfsa/adsp;/system/vendor/lib/rfsa/adsp;/dsp"
snpe-net-run --container alexnet_udo_quantized.dlc --input_list target_raw_list.txt --udo_package_path dsp/libUdoConv2DPackageReg.so --use_dsp

要验证分类结果,请在您的 CPU 主机上运行以下命令。

cd $SNPE_ROOT/models/alexnet/
adb pull /data/local/tmp/alexnet_udo/output .
python3 $SNPE_ROOT/models/alexnet/scripts/show_alexnet_classifications.py -i data/cropped/raw_list.txt \
                                                                          -o output/ \
                                                                          -l data/ilsvrc_2012_labels.txt

输出应如下所示,显示所有图像的分类结果。

分类结果

Classification results
<input_files_dir>/trash_bin.raw     0.949348 412 ashcan, trash can, garbage can,
                                                 wastebin, ash bin, ash-bin, ashbin,
                                                 dustbin, trash barrel, trash bin

<input_files_dir>/plastic_cup.raw   0.749104 647 measuring cup
<input_files_dir>/chairs.raw        0.365685 831 studio couch, day bed
<input_files_dir>/notice_sign.raw   0.722708 458 brass, memorial tablet, plaque

6.5.9 DSP 运行时

ADSP_LIBRARY_PATH 环境 - 适用于 ADSP 和 CDSP

DSP 运行时是一个动态加载的模块,需要使用 AIP 和 DSP 运行时。该模块位于:

  • $SNPE_ROOT/lib/dsp/libsnpe_dsp_v65_domains_v2_skel(对于 v65 目标)
  • $SNPE_ROOT/lib/dsp/libsnpe_dsp_v66_domains_v2_skel(对于 v66 目标)

该模块在 ADSP 或 CDSP 上运行,具体取决于目标。请参阅概述部分中的 Snapdragon 设备支持矩阵表,以确定各种 Snapdragon 设备上 DSP 的 SNPE 支持。SNPE 自动检测适当的 DSP。

DSP加载器需要将环境变量ADSP_LIBRARY_PATH设置为存储共享库的目录。该环境变量用于 ADSP 和 CDSP。

对于命令行可执行文件

ADSP_LIBRARY_PATH的典型设置如下所示:

export ADSP_LIBRARY_PATH="<path_to_dsp_skel>;/system/lib/rfsa/adsp;/system/vendor/lib/rfsa/adsp;/dsp"

其中<path_to_dsp_skel>是 $SNPE_ROOT/lib/dsp/libsnpe_dsp_v65_domains_v2_skel.so 和/或其他 skel 文件 (libsnpe_dsp_*_skel.so) 已推送的路径。不要在路径中包含骨架的文件名。

例子:

假设适当的 dsp skel 已推送到 /data/local/tmp/snpeexample/dsp/lib,则将使用以下命令来设置 ADSP_LIBRARY_PATH。

export ADSP_LIBRARY_PATH="/data/local/tmp/snpeexample/dsp/lib;/system/lib/rfsa/adsp;/system/vendor/lib/rfsa/adsp;/dsp"

设置ADSP_LIBRARY_PATH时需要注意的要点:

与 LD_LIBRARY_PATH 不同,该路径必须包含在引号内。此外,与 LD_LIBRARY_PATH 不同的是,目录分隔符是分号,而不是冒号。

对于 Android 和大多数嵌入式 Linux 系统,下面的 3 个路径必须是 ADSP_LIBRARY_PATH 的一部分。如果缺少其中任何一个,DSP 运行时可能会失败。

  • /system/lib/rfsa/adsp
  • /system/vendor/lib/rfsa/adsp
  • /dsp

对于嵌入式Linux汽车系统,需要以下DSP路径。

  • /usr/lib/rfsa/adsp
  • /dsp

对于 Android APK

还必须为 Android APK 设置 ADSP_LIBRARY_PATH,并且不能使用“导出”命令来完成。它必须在 APK 中运行的代码内完成。

SNPE Android Java API 自动设置 ADSP_LIBRARY_PATH。提供的 SNPE Java AAR 库会自动为您的 Android 应用程序设置 DSP 环境。

不使用 SNPE Java AAR 的 Android 应用程序必须在本机代码中显式设置 ADSP_LIBRARY_PATH。下面提供了一个示例。

bool SetAdspLibraryPath(std::string nativeLibPath) {
    std::stringstream path;
    path << nativeLibPath << ";/system/lib/rfsa/adsp;/system/vendor/lib/rfsa/adsp;/dsp";
    return setenv("ADSP_LIBRARY_PATH", path.str().c_str(), 1 /*override*/) == 0;
}

假设 DSP 可加载模块(libsnpe_dsp_v65_domains_v2_skel.so 和/或 libsnpe_dsp_v66_domains_v2_skel.so)放置在与 Android 应用程序中的 libSNPE.so 相同的位置,则传递给上述方法的“nativeLibPath”输入应该是由以下 Android API:

application.getApplicationInfo().nativeLibraryDir
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值