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

281 篇文章 30 订阅

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


4.4.5编译 UDO 包

介绍

本节提供有关为 SNPE 中所有支持的运行时编译 UDO 包的信息。

如UDO 概述中所述,一组注册和实现库统称为 UDO 包。用户可以使用兼容的工具链完全控制为他们所需的运行时构建这些库。或者,SNPE SDK 提供工具和实用程序来轻松创建和编译 UDO。有关用于创建 UDO 包的工具的更多信息,请参阅创建 UDO 包。本节介绍基于包生成器提供的目录结构的 UDO 包编译。

实现用户定义的操作

从根本上说,需要使用位于 $SNPE_ROOT/share/SnpeUdo/include 的头文件中定义的 API 集来开发 UDO。每个运行时可能会施加额外的要求,并提供用于自定义实现以适应运行时的选项。UDO API 的详细信息可以在C++ API的 API 文档中找到。
本节假定 UDO 包是使用创建 UDO 包中描述的 UDO包生成器工具生成的,该工具根据用户配置的 UDO 规范生成部分实现框架。

为包编译制定目标

UDO 包生成器工具创建一个 makefile 来编译特定运行时和目标平台组合的包。makefile 旨在提供一个简单的接口来为本机使用 make 或需要 ndk-build 的平台进行编译。使用提供的 makefile 还允许针对各种目标进行每个库的编译。

每个 make 目标的一般形式是 _。只有 形式的目标包括所有可能的目标。例如,运行

make cpu

将为 x86 和 Android 平台编译 CPU。此外,对于适用的平台,PLATFORM make 变量可用于选择特定平台 ABI,类似于 ndk-build 中的 APP_ABI。默认情况下,PLATFORM 设置为 arm64-v8a 和 armeabi-v7a。下面列出了可用目标的综合表。

注意:生成文件的使用是可选的,生成库不是必需的。

注意:对于以下所有示例,显示的工件适用于 arm64-v8a 目标。

为 CPU 实现 UDO

需要基于核心 UDO API 的 CPU UDO 实现库才能在 CPU 运行时运行 UDO 包。UDO 包生成器工具将创建一个包含所需格式的空白构造的骨架,但创建和执行操作的核心逻辑需要由用户填写。这可以通过在UDO 包生成器工具生成的.cpp文件中完成finalize()、execute()和free()函数的实现来完成。

注意:要考虑的一个重要概念是 SNPE 提供与 UDO 的所有输入和输出相对应的张量数据,这些数据不是直接在内部tensorData定义的SnpeUdo_TensorParam_t,而是作为不透明指针。UDO 实现有望使用 SNPE 在执行时发布的 CustomOp 操作对象中的方法来获取原始张量指针的句柄。有关数据结构的更多详细信息,请参阅SnpeUdo_CpuInfrastructure_t。CPU 运行时仅使用浮点激活张量进行操作。因此,CPU UDO 实现应实现为仅接收和产生浮点张量,并将配置文件中的字段 data_type 设置为 FLOAT_32。所有其他数据类型将被忽略。有关详细信息,请参阅定义 UDO 。

SNPE 模型量化工具需要在主机上编译和运行 UDO 包,snpe-dlc-quantize. 有必要使用 snpe-dlc-quantize 对模型进行量化,以运行在 DSP 上至少具有一个非浮点输入的 UDO 层。

在主机上为 CPU 编译 UDO

在主机 x86 平台上编译 CPU UDO 实现库的步骤如下:

  1. 设置环境变量$SNPE_UDO_ROOT。
export SNPE_UDO_ROOT=<absolute_path_to_SnpeUdo_headers_directory>

  1. 运行下面的 make 指令来编译 UDO 包:
make cpu_x86

为主机 CPU 编译后的预期工件是

  • UDO CPU实现库:/libs/x86-64_linux_clang/libUdoImplCpu.so
  • UDO包注册库:/libs/x86-64_linux_clang/libUdoReg.so

注意:该命令必须从包根目录运行。

为设备上的 CPU 编译 UDO

在Android平台编译CPU UDO实现库的步骤如下:

  1. 设置环境变量$SNPE_UDO_ROOT。
export SNPE_UDO_ROOT=<absolute_path_to_SnpeUdo_headers_directory>
  1. $NDK_BUILD必须为 Android NDK 构建工具链设置。
export NDK_BUILD=<absolute_path_to_android_ndk_directory>
  1. 运行下面的 make 指令来编译 UDO 包:
make cpu_android

NDK 构建运行需要共享 C++ 标准库。确保设备上存在 libc++_shared.so LD_LIBRARY_PATH。

为 Android CPU 编译后的预期工件是

  • UDO CPU实现库:/libs/arm64-v8a/libUdoImplCpu.so
  • UDO包注册库:/libs/arm64-v8a/libUdoReg.so
  • 共享标准 C++ 库的副本:/libs/arm64-v8a/libc++_shared.so

为 GPU 实现 UDO

与 CPU runtime 类似,需要基于核心 UDO API 的 GPU UDO 实现库才能在 GPU runtime 上运行 UDO 包。UDO 包生成器工具将创建一个包含所需格式的空白构造的骨架,但创建和执行操作的核心逻辑需要由用户填写。这可以通过完成setKernelInfo()和功能的实现,并在UDO 包生成器工具生成的.cppOperation()文件中添加 GPU 内核实现来完成。

SNPE GPU UDO 支持网络中的 16 位浮点激活。用户应该期望来自 SNPE GPU UDO 的输入/输出 OpenCL 缓冲存储器采用 16 位浮点(或 OpenCL 半)数据格式作为存储类型。为了提高精度,用户可以选择使用 32 位浮点数据实现内核的内部数学运算,并在从 UDO 内核读取输入缓冲区或写入输出缓冲区时转换为半精度。

SNPE GPU 允许用户选择缓存与相似类型的多个 GPU UDO 实例关联的 OpenCL 程序。它提供 API 以通过SnpeUdo_GpuInfrastructure_t. 在网络中的后续调用期间,缓存改进了 OpenCL 程序的 JIT 编译时间。

注意: SNPE 提供与 UDO 的所有输入和输出相对应的张量数据,不是直接在内部,tensorData而是作为不透明指针。UDO 实现预计将其转换为SnpeUdo_GpuTensorData_t并保存张量的 OpenCL 内存指针。SnpeUdo_GpuTensorData_t有关详细信息,请参阅。SNPE 在创建 UDO op 工厂时发布的 Per-op factory 基础设施对象将为用户提供 OpenCL 上下文和 OpenCL 命令队列。SnpeUdo_GpuOpFactoryInfrastructure_t有关数据结构的更多详细信息,请参阅。

在设备上为 GPU 编译 UDO

在Android平台编译GPU UDO实现库的步骤如下:

  1. 设置环境变量$SNPE_UDO_ROOT。
export SNPE_UDO_ROOT=<absolute_path_to_SnpeUdo_headers_directory>
  1. $NDK_BUILD必须为 Andorid NDK 构建工具链设置。
export NDK_BUILD=<absolute_path_to_android_ndk_directory>
  1. $CL_LIBRARY_PATH必须为 libOpenCL.so 库位置设置。
export CL_LIBRARY_PATH=<absolute_path_to_OpenCL_library>

OpenCL 共享库不作为 SNPE SDK 的一部分分发。

  1. 运行下面的 make 指令来编译 UDO 包:
make gpu_android

注意:共享的 OpenCL 库是特定于目标的。它应该在CL_LIBRARY_PATH.
为 Android GPU 编译后的预期工件是:

  • UDO GPU实现库:/libs/arm64-v8a/libUdoImplGpu.so
  • UDO包注册库:/libs/arm64-v8a/libUdoReg.so
  • 共享标准 C++ 库的副本:/libs/arm64-v8a/libc++_shared.so
  • 共享 OpenCL 库的副本:/libs/arm64-v8a/libOpenCL.so
    为 DSP V65 和 V66 实现 UDO

SNPE 利用 QNN 在 DSP 上运行 UDO 层。因此,需要基于 QNN SDK API 的 DSP 实现库才能在 DSP 运行时运行 UDO 包。UDO 包生成器工具将创建模板文件.cpp,用户需要在_executeOp()模板文件的函数中实现执行逻辑。

SNPE UDO 使用工作线程、六角向量扩展 (HVX) 代码和 VTCM 支持为操作的多线程提供支持。

DSP 运行时仅在网络层之间传播无符号的 8 位激活张量。但如果需要,它可以将数据反量化为浮点数。因此,开发 DSP 内核的用户可以期望 UINT_8 或 FLOAT_32 激活张量进出操作,因此可以将配置文件中的字段 data_type 设置为这两个设置之一。有关详细信息,请参阅定义 UDO 。

在设备上为 DSP V65 和 V66 编译 UDO

此 SNPE 版本支持使用 Hexagon-SDK 3.5.x 构建 UDO DSP 实现库。

  1. 设置环境变量$SNPE_UDO_ROOT
export SNPE_UDO_ROOT=<absolute_path_to_SnpeUdo_headers_directory>
  1. 需要安装和设置 Hexagon-SDK。有关详细信息,请按照页面上的设置说明进行操作 H E X A G O N S D K R O O T / d o c s / r e a d m e . h t m l ,其中 H E X A G O N S D K R O O T 是 H e x a g o n − S D K 安装位置。确保 HEXAGON_SDK_ROOT/docs/readme.html,其中HEXAGON_SDK_ROOT是 Hexagon-SDK 安装位置。确保 HEXAGONSDKROOT/docs/readme.html,其中HEXAGONSDKROOTHexagonSDK安装位置。确保HEXAGON_SDK_ROOT设置为使用 Hexagon-SDK 构建工具链。还设置$HEXAGON_TOOLS_ROOT和SDK_SETUP_ENV
export HEXAGON_SDK_ROOT=<hexagon sdk 安装路径> 
export HEXAGON_TOOLS_ROOT=$HEXAGON_SDK_ROOT/tools/HEXAGON_Tools/8.3.07 
export ANDROID_NDK_ROOT=<Android NDK 安装路径> 
export SDK_SETUP_ENV=Done
  1. $NDK_BUILD必须为 Andorid NDK 构建工具链设置。
export  NDK_BUILD=<absolute_path_to_android_ndk_directory>
  1. 编译包时也可以指定目标体系结构。如果没有提供目标体系结构,则 arm64-v8a 和 armeabi-v7a 都是目标。
export UDO_APP_ABI=<target_architecture>
  1. 运行下面的 make 指令来编译 UDO DSP 实现库:
make dsp PLATFORM=$UDO_APP_ABI

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

为 DSP 编译后的预期工件是

  • UDO DSP实现库:/libs/dsp_<dsp_arch_type>/libUdoImplDsp.so
  • UDO包注册库:/libs/$UDO_APP_ABI/libUdoReg.so

注意:该命令必须从包根目录运行。

为 DSP V68 或更高版本实现 UDO
SNPE 利用 QNN 在 DSP v68 或更高版本上运行 UDO 层。因此,需要基于 QNN SDK API 的 DSP 实现库才能在 DSP 运行时运行 UDO 包。UDO 包生成器工具将创建模板文件ImplLibDsp.cpp,用户需要在Impl()模板文件中的函数中实现执行逻辑。

SNPE UDO 提供对六边形矢量扩展 (HVX) 代码和基于成本的调度的支持。

DSP 运行时在网络层之间传播无符号 8 位或无符号 16 位激活张量。但如果需要,它可以将数据反量化为浮点数。因此,开发 DSP 内核的用户可以期望 UINT_8、UINT_16 或 FLOAT_32 激活张量进出操作,因此可以将配置文件中的字段 data_type 设置为这三个设置之一。有关详细信息,请参阅 QNN SDK。

在设备上为 DSP_V68 或更高版本编译 UDO
此 SNPE 版本支持使用 Hexagon-SDK 4.x 和 QNN SDK 构建 UDO DSP 实现库。

  1. 设置环境变量$SNPE_UDO_ROOT
export SNPE_UDO_ROOT=<absolute_path_to_SnpeUdo_headers_directory>
  1. 需要安装和设置 Hexagon-SDK 4.0+。 H E X A G O N S D K 4 R O O T / d o c s / r e a d m e . h t m l 有关 H e x a g o n − S D K 的详细信息,请按照页面上的设置说明进行操作,其中 H E X A G O N S D K 4 R O O T 是 H e x a g o n − S D K 安装的位置。确保 HEXAGON_SDK4_ROOT/docs/readme.html有关 Hexagon-SDK 的详细信息,请按照页面上的设置说明进行操作,其中HEXAGON_SDK4_ROOT是 Hexagon-SDK 安装的位置。确保 HEXAGONSDK4ROOT/docs/readme.html有关HexagonSDK的详细信息,请按照页面上的设置说明进行操作,其中HEXAGONSDK4ROOTHexagonSDK安装的位置。确保HEXAGON_SDK4_ROOT设置为使用 Hexagon-SDK 构建工具链。另外,设置 H E X A G O N T O O L S R O O T 和 S D K S E T U P E N V 。此外,我们需要一个提取的 Q N N − S D K (不需要 Q N N − S D K 设置)来构建库。有关 Q N N − S D K 的详细信息,请参阅页面上的 Q N N 文档 HEXAGON_TOOLS_ROOT和SDK_SETUP_ENV。此外,我们需要一个提取的 QNN-SDK(不需要 QNN-SDK 设置)来构建库。有关 QNN-SDK 的详细信息,请参阅页面上的 QNN 文档 HEXAGONTOOLSROOTSDKSETUPENV。此外,我们需要一个提取的QNNSDK(不需要QNNSDK设置)来构建库。有关QNNSDK的详细信息,请参阅页面上的QNN文档QNN_SDK_ROOT/docs/index.html,其中QNN_SDK_ROOT是 QNN-SDK 安装的位置。将 设置$QNN_SDK_ROOT为解压缩的 QNN-SDK 位置。
export HEXAGON_SDK_ROOT=<hexagon sdk 安装路径> 
export HEXAGON_SDK4_ROOT=<hexagon sdk 4.x 安装路径> 
export HEXAGON_TOOLS_ROOT=$HEXAGON_SDK_ROOT/tools/HEXAGON_Tools/8.3.07/ 
export QNN_SDK_ROOT=<QNN sdk 安装路径> 
export ANDROID_ND K_ROOT= <Android NDK 安装路径> 
export SDK_SETUP_ENV=Done
  1. $NDK_BUILD必须为 Andorid NDK 构建工具链设置。
export NDK_BUILD=<absolute_path_to_android_ndk_directory>
  1. 编译包时也可以指定目标体系结构。如果没有提供目标体系结构,则 arm64-v8a 和 armeabi-v7a 都是目标。
export UDO_APP_ABI=<target_architecture>
  1. 运行下面的 make 指令来编译 UDO DSP 实现库:
制作 dsp 平台=$UDO_APP_ABI
  1. 运行下面的 make 指令来生成用于离线缓存生成的库:
make dsp_x86 X86_CXX=<path_to_x86_64_clang>
  1. 运行下面的 make 指令生成一个可以在 Android ARM 架构上使用的库:
make dsp_aarch64

为 DSP 编译后的预期工件是

  • UDO DSP实现库:/libs/dsp_v68/libUdoImplDsp.so

  • UDO包注册库:/libs/$UDO_APP_ABI/libUdoReg.so
    为离线缓存生成编译后的预期工件是

  • UDO DSP实现库:/libs/x86-64_linux_clang/libUdoImplDsp.so
    针对 Android ARM 架构编译后的预期工件是

  • UDO DSP实现库:/libs/$UDO_APP_ABI/libUdoImplDsp_AltPrep.so
    注意:该命令必须从包根目录运行。

制作目标表

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值