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

281 篇文章 30 订阅

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


创建 UDO 配置

用户应该旨在填写上面配置中描述的字段,以充分描述 UDO。在某些情况下,此配置中所需的信息可以很容易地从有关该操作的框架文档中获得。然而,可能会有细微的警告,因此鼓励用户确保正确分类和描述输入、输出和参数。一个潜在的警告是,如果仅根据文档编写配置,输入可能会被错误分类为参数,反之亦然。在这种情况下,一个有用的技巧是使用 Netron(可在此处找到:https: //github.com/lutzroeder/netron )等开源工具可视化模型,以协助正确制作 UDO 配置。

一旦创建了充分描述的配置,就可以将其用作框架转换器的参数,如使用UDO 准备模型中所述。

笔记:

  1. 一个配置文件中可以定义多个 UDO 包。用户应注意,此处指定的包名称必须与创建相应包时使用的包名称相匹配。
  2. 每个输入、输出和张量参数都被归类为同一类型的张量对象,这意味着所有字段都是共享的。输入和输出的名称不是必需的,因为配置是操作的一般描述。
  3. 对于参数,名称字段始终是必需的。
  4. 张量布局是指示张量内数据排列的约定。因此, NHWC的张量布局意味着数据以 组织(batch x height x width x channel),其中通道是变化最快的维度。请注意,这是 SNPE 的默认排列,如果选择了其他张量布局,这可能会对包含 UDO 的模型产生影响。值得注意的是,如果NCHW的张量布局被选中,则可能需要将数据和/或张量参数重塑为 SNPE 默认值以保持维度理解。如果用户遇到这种情况,他们可能会注意到在 UDO 层之前引入了中间置换层,这最终将提供所讨论的张量。这些警告应该作为转换器警告、调试消息或通过工具中描述的可视化工具的输出显示出来。有关张量布局的更多详细信息,用户可以参阅文档的 输入图像格式部分。
  5. 对于 CPU、GPU 和 DSP 核心类型,每个 UDO 包可以定义任意数量的运算符。然而,所提供的框架代码被定制为在一个包中只定义一个操作。一个微妙的区别是生成的 DSP V65 或 DSP V66 实现源代码期望每个实现库执行一个操作。而在 CPU、GPU 和 DSP V68 或更高版本的情况下,库中可能有任意数量的操作。
  6. 张量的数据类型决定了张量中包含的数据将如何存储在 DLC 中,以及 SNPE 在运行时执行期间移交的内存类型。虽然张量以 UDO 定义指定的确切数据类型存储在 DLC 中,但根据所选的核心类型,用户可能期望接收的内存类型可能存在运行时限制。用户应访问以下部分:编译 UDO 包以获取更多详细信息。

4.4.3定义 UDO 包

一个 UDO 包主要由一个注册库和一个或多个实现库组成。主要思想是注册库包含有关操作性质的信息,而实现包含执行操作所需的内核(有关更多详细信息,请参阅UDO 概述)。UDO 包可以通过 UDO 配置来定义,它包含操作和路径的文本规范,最终将帮助定义将代表 UDO 包的目录结构。本节将讨论 UDO 包的定义,而定义包后的创建将推迟到创建UDO 包的部分。

UDO 包配置说明

在UDO 配置字段描述中找到的所有字段都被复制用于 UDO 包配置规范。因此,上述 UDO 配置文件的细分是该部分中的描述与添加的两个包特定字段的组合。下面包含一个通用配置,并解释了特定于包的字段。用户应该查看UDO 配置字段描述以获取对复制字段的更详细描述,并查看相关注释。

{
    “UdoPackage_0”:
    {
        “运营商”:[
            {
                “类型”: ””,
                “输入”:[
                    {“名称”:“”,“数据类型”:“FLOAT_32”,“静态”:真,
                        “tensor_layout”:“NHWC”}],
                “输出”:[
                    {“名称”:“”,“data_type”:“FLOAT_32”}
                ],
                “标量参数”:[
                    {“名称”:“scalar_param_1”,“data_type”:“INT_32”}
                ],
                “张量参数”:[
                    {“名称”:“tensor_param_1”,“data_type”:“FLOAT_32”,
                    “tensor_layout”:“NHWC”}],
                “核心类型”:[“CPU”,“GPU”,“DSP”],
                “dsp_arch_types”:[“v66”,“v68”]
            }
        ],
        "UDO_PACKAGE_NAME": "MyCustomUdoPackage",
        "UDO_PACKAGE_PATH": "",
        “SNPE_UDO_ROOT”:“”
    }
}

其他字段解释如下:

  • UDO_PACKAGE_NAME:包含 UDO 的包的名称。
  • UDO_PACKAGE_PATH:保存 UDO 包的路径。如果未提供,将使用当前目录。
  • SNPE_UDO_ROOT:这是一个可选变量,让工具知道 SnpeUdo API 目录在用户环境中的位置。这可以在此处设置或作为环境变量设置。

笔记

  1. 配置中指定的信息用于实例化信息数据结构,这些结构对于 SNPE 如何执行包含 UDO 的模型至关重要。这意味着 UDO 包和包含 UDO 的模型之间的协同作用,因此,推荐的策略是使用相同的配置来定义 UDO 及其对应的包。
  2. 包名称的定义将确定在生成的包中找到的源文件和实现库的名称。
  3. 操作类型将确定生成的包中包含的方法、类和源文件的名称。
  4. 包 core-types 是包中每个运算符提到的所有核心类型的集合。

4.4.4创建 UDO 包

本节描述使用snpe-udo-package-generator从用户定义操作的简单文本规范创建 UDO 包的过程。从 SNPE API 的角度来看,一个 UDO 包由一个注册库和一个或多个实现库组成。因此,虽然用户可以独立于此规定创建 UDO 包,但本节描述了创建部分定义的 UDO 包的过程,该包可以轻松实现和编译以生成相关库。

生成 UDO 骨架代码

要使用 SNPE 工具生成包,必须创建描述操作和包详细信息的 UDO 配置。有关详细信息,请参阅定义 UDO 包。一旦指定配置以充分表示所需的 UDO,就可以将其作为参数提供给 snpe-udo -package-generator中描述的 SNPE UDO 包生成器工具。该工具的目的是生成部分骨架代码以帮助快速制作原型。本节介绍包生成器工具的用法及其生成的工件。

为了运行snpe-udo-package-generator,用户应该按照SNPE Setup中的设置说明进行操作。该工具还依赖于 Mako 模板库,可在此处找到:https: //www.makotemplates.org/download.html。此外,我们需要一个提取的 QNN-SDK(不需要 QNN-SDK 设置)来生成骨架代码。有关 QNN-SDK 的详细信息,请参阅页面上的 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 位置。设置完成后,可以使用以下命令生成包:

snpe-udo-package-generator -p <my_config.json> -o <my-dir>

上述命令将创建一个 UDO 包,该包将是一个由框架代码和构建文件组成的目录,可用于将包内容编译成独立的共享库。UDO 教程中引用的配置文件已用于生成以下 udo 包内容:

|-- 生成文件
|-- 通用.mk
|-- 配置
| `-- softmax.json
|-- 包括
| |-- SoftmaxUdoPackageCpuImplValidationFunctions.hpp
| |-- SoftmaxUdoPackageDspImplValidationFunctions.hpp
| |-- SoftmaxUdoPackageGpuImplValidationFunctions.hpp
| `-- 工具
| |-- IUdoOpDefinition.hpp
| |-- UdoDspShared.h
| |-- UdoMacros.hpp
| |-- UdoOperation.hpp
| `-- UdoUtil.hpp
`-- jni
    |-- 安卓.mk
    |-- 应用.mk
    `-- 源代码
        |-- 中央处理器
        | |-- 生成文件
        | |-- 生成文件
        | | |-- 安卓.mk
        | | |-- 应用.mk
        | | `-- Makefile.linux-x86_64
        | `-- 源代码
        | |-- SoftmaxUdoPackageInterface.cpp
        | |-- 操作
        | | `-- Softmax.cpp
        | `-- 工具
        | |-- BackendUtils.hpp
        | |-- 中央处理器
        | | |-- CpuBackendUtils.cpp
        | | `-- CpuBackendUtils.hpp
        | `-- CustomOpUtils.hpp
        |-- 数字信号处理器
        | |-- 生成文件
        | |-- 包括
        | | `-- DspOps.hpp
        | `-- 源代码
        | |-- SoftmaxUdoPackageInterface.cpp
        | `-- 行动
        | `-- Softmax.cpp
        |-- DSP_V68
        | |-- 生成文件
        | |-- SoftmaxImplLibDsp.cpp
        | `-- SoftmaxUdoPackageImplLibDsp.cpp
        |-- 显卡
        | |-- 生成文件
        | |-- 包括
        | | |-- GpuCustomOpPackage.hpp
        | | `-- 操作.hpp
        | |-- 生成文件
        | | |-- 安卓.mk
        | | `-- 应用程序.mk
        | `-- 源代码
        | |-- GpuCustomOpPackage.cpp
        | |-- SoftmaxUdoPackageInterface.cpp
        | `-- 行动
        | `-- Softmax.cpp
        |-- 注册
        | |-- 生成文件
        | |-- SoftmaxUdoPackageCpuImplValidationFunctions.cpp
        | |-- SoftmaxUdoPackageDspImplValidationFunctions.cpp
        | |-- SoftmaxUdoPackageGpuImplValidationFunctions.cpp
        | `-- SoftmaxUdoPackageRegLib.cpp
        `-- 工具
            `-- UdoUtil.cpp

UDO 包的内容

  • 可以使用 Linux 主机的 make 构建系统或 Android 设备的 Android-NDK 构建系统编译该包。简而言之,make 系统使用顶级 Makefile、common.mk和每个运行时目录中的各个 makefile 进行配置。android-build 系统使用jni/Android.mk和jni/Application.mk配置。有关更多编译详细信息,请参阅编译 UDO 包。
  • config 目录包含用于创建包的 JSON 配置。
  • include 目录包含三种文件:来自 SNPE UDO API 的标头、特定于 UDO 包及其操作的标头文件,以及一个包含 SNPE UDO API 调用的 C++ 帮助器实用程序目录。用户应该注意,包含 utils API 只是为了方便创建实现源代码。实用程序的使用不是构建或执行 UDO 包的先决条件。
  • 包的相关源文件组织在jni/src目录下。配置中指定的每个核心类型都会有一个子目录。注册 (reg) 目录包含创建注册库所需的文件,注册库通常是 SNPE API 的入口点。还有来自前面提到的 C++ helper utils 的源代码。通常,用户只需要编辑特定于运行时或注册目录中的代码。

生成的源代码

本节和以下子节介绍了使用生成 UDO 骨架代码中显示的包内容在包中生成的源代码。当最终确定时,一个 UDO 包应该包含一个注册库和一个或多个实现库。为了生成注册库,编译了jni/src/reg中的源代码。实现库是使用来自每个核心类型特定目录的源代码编译的。回想一下,该工具创建的包仍然需要实施。以下小节将介绍需要实施的文件。所有生成的源代码都将带有自动生成的标签在标题中。源代码在生成阶段被认为是部分完整的,用户有责任根据需要实施某些文件,以确保与 SNPE API 的适当兼容性和功能。所有要实现的代码都会在body中有add code here的标签,表示需要实现。请注意,所有库都链接到 C++ 实用程序源代码。

完成注册骨架代码

如前所述,注册库是从jni/src/reg中的源代码创建的。该目录包含一个用于编译包的 Makefile、每个运行时分开的一个或多个验证文件以及包特定文件:SoftMaxUdoPackageRegLib.cpp其中包含打开库时由 SNPE UDO API 解析的函数符号。注册库文件包含 API 调用,这些调用为 SNPE UDO API 提供有关模型中操作性质的信息,以及它们所属的实现库。用户只需要编辑验证文件,这些文件旨在包含用户希望为库中包含的操作实施的任何可选验证。用户应注意,是否实施验证由他们自行决定。上面 Softmax 示例中使用的验证文件的示例片段如下所示:

SnpeUdo_ErrorType_t
SoftmaxCpuValidationFunction::validateOperation(SnpeUdo_OpDefinition_t* def) {
    /**
     * 在这里添加代码
     */
    返回 SNPE_UDO_NO_ERROR;
}

完成实施骨架代码

实现库是根据核心类型创建的,源代码位于jni/src中的核心类型特定目录下。以CPU运行时为例,jni/src/CPU目录包含一个构建CPU实现库的Makefile,一个包特定的源文件:SoftmaxUdoPackageInterface.cpp,用于库中包含的所有操作,以及一个per operation source文件:Softmax.cpp应该包含运行时实现。与注册情况一样,在一般情况下不应编辑包特定的源文件。类似地,此文件包含返回有关实现库中包含的操作的信息的方法,以及充当最终在每个操作文件中执行的代码之上的间接层的方法。在 CPU 的情况下, Softmax.cpp中的三个方法即:finalize、execute和free用户有责任编辑。请注意,这些方法分别创建操作、执行其实现和释放操作。因此,这些完全由用户决定。下面包含一个示例生成的实施库版本:

Qnn_ErrorHandle_t 执行(CustomOp* 操作){

  /**
   * 在这里添加代码
   **/

  返回 QNN_SUCCESS;
}

Qnn_ErrorHandle_t finalize(const CustomOp* 操作){
  QNN_CUSTOM_BE_ENSURE_EQ(操作->numInput(),1,QNN_OP_PACKAGE_ERROR_VALIDATION_FAILURE)
  QNN_CUSTOM_BE_ENSURE_EQ(操作->numOutput(),1,QNN_OP_PACKAGE_ERROR_VALIDATION_FAILURE)

  /**
   * 在这里添加代码
   **/

  返回 QNN_SUCCESS;
}

Qnn_ErrorHandle_t free(CustomOp& operation) {

    /**
    * 在这里添加代码
    **/

    返回 QNN_SUCCESS;
}

笔记

  • 在一般情况下,包应该只需要能够正确执行的功能编辑。初始未实现的包保证可以编译。
  • 一个微妙的区别是生成的 DSP V65 或 DSP V66 实现源代码期望每个实现库执行一个操作。而在 CPU、GPU 和 DSP V68 或更高版本的情况下,库中可能有任意数量的操作。
  • 每个运行时的实现源文件之间存在差异。在 GPU 的情况下,执行工作流已经实现,用户只需要实现Operation和setKernelInfo方法。与 CPU 和 GPU 相比,DSP 使用的 API 不依赖于生成的源代码部分中讨论的 C++ 辅助工具。这意味着某些辅助方法和构造函数在 DSP 案例中可能不可用。对于 DSP 情况,用户需要实现softmaxImpl方法。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值