Skip to content

AidLite Python 接口文档 ​

使用 AutoModel ​

以下步骤适用于 Linux Python SDK。 AutoModel 已合入当前维护源码。 安装包需要包含配套的核心、Python 扩展和后端。 已发布的旧安装包不一定包含此接口。 AutoModel 为本地后端和 Android 推理服务提供统一入口。 枚举成员和模型格式识别不代表该后端可以运行。 安装匹配的后端插件和 SDK。 后端需要提供相应张量 API。 入口统一不代表每个模型都已通过设备兼容性验证。 AutoModel 和 InferenceSession 支持显式选择 LOCAL 或 REMOTE。 以下 REMOTE 用法需要包含此功能的配套源码构建。 旧发布包不一定包含此功能。 使用前,阅读 REMOTE 模式排查。

准备模型 ​

  1. 使用已转换的本地模型。
  2. 确认模型后端与设备上的 SDK 版本匹配。
  3. 按原模型的要求准备输入。

新版 AIMO 可在 .aidem 中保存输入输出元数据。 原生 QNN context 使用配套的 <模型文件名>.io.json。 保留模型与配套文件。 不要把所有输入统一转换为 FP32。 元数据需要配套的新版 AIMO 转换器和模型打包服务。 已有模型文件不会自动更新。

“原模型”指 AIMO 转换入口的 ONNX 模型。 元数据不能恢复此前导出器已经改变的接口。 图像归一化、分词和其他模型预处理仍由调用方完成。

调用单输入模型 ​

  1. 从文件读取原模型的输入数组。
  2. 加载模型。
  3. 调用模型。
python
import numpy as np
from aidlite import AutoModel

inputs = np.load("input.npy", allow_pickle=False)
with AutoModel.from_pretrained("model.aidem") as model:
    outputs = model(inputs)

输入数组保留原模型要求的类型和形状。 例如,FP16 输入使用 numpy.float16。 ID 和掩码也使用各自声明的数据类型。 单输出模型返回数组。 多输出模型按原模型顺序返回元组。 输出在模型关闭后仍然可用。

调用多输入模型 ​

将各输入数组保存到同一个 .npz 文件。 使用原模型的输入名称作为键。 保留每个数组自身的数据类型。

python
import numpy as np
from aidlite import AutoModel

with np.load("inputs.npz", allow_pickle=False) as archive:
    inputs = {name: archive[name] for name in archive.files}

with AutoModel.from_pretrained("model.aidem", return_dict=True) as model:
    outputs = model(inputs)

返回字典使用原模型的输出名称。 位置参数也按原模型输入顺序处理。 不要按转换后的张量顺序重排输入。

检查接口 ​

加载模型后,检查 model.inputs 和 model.outputs。 每个 TensorSpec 提供名称、形状和数据类型。 model_shape 和 runtime_dtype 描述适配后的运行时接口。

参数行为
interface="auto"优先使用可用的 AIMO 元数据;缺少或无法使用时回退到后端张量 API。
interface="original"要求模型包含可验证的原接口元数据。
interface="runtime"使用内部接口,由调用方管理转换。

新版 AIMO QNN 模型会自动匹配已验证的名称、顺序和维度排列。 包装层只执行普通 SDK 接口需要的类型转换。 后端已有的量化和反量化不会再执行一次。 恢复数据类型不能恢复量化时损失的数值精度。

整数或布尔值无法通过接口转换保留时,调用会报错。 严格原接口模式下,名称、形状或布局无法确认时,加载会报错。 自动模式会在元数据无法使用时发出 ModelMetadataWarning。 随后使用后端的名称、形状和数据类型。 加载后检查 model.metadata_source、model.metadata_warning、model.inputs 和 model.outputs。 需要原接口时,请修正模型元数据。 不要通过随意转换类型来绕过错误。

支持范围 ​

原接口适配当前支持单产物 QNN 模型的 graph 0。 需要版本为 1 的 aplux.model_io 元数据。 QNN context 仍使用转换后确定的形状。 元数据不会让固定形状模型自动支持动态输入。

没有元数据的 .bin 或旧 .aidem 可能需要显式指定 framework。 from_pretrained() 只读取已转换的本地模型。 它不下载模型,也不直接转换任意 Transformers 权重。

ONNX 输入类型 ​

安装配套的新版 ONNX 插件。 该插件可直接绑定 float32、float16、bool、int8、int16、int32、int64、uint8、uint16、uint32 和 uint64 输入。 按 model.inputs 中的数据类型准备数组。 例如,FP16 模型输入使用 numpy.float16。 不要先转换成 FP32。 float64、字符串和压缩位宽类型不在当前支持范围内。 类型不受支持时,修正模型或选择支持该类型的后端。

选择 LOCAL 或 REMOTE ​

默认使用 LOCAL。 设置 implementation="remote",通过进程间通信调用 Android 推理服务。 model(x) 的调用方式保持相同。 device 选择执行设备;implementation 选择执行位置。 例如,device="dsp" 与 implementation="remote" 可同时使用。

python
import numpy as np
from aidlite import AutoModel

with AutoModel.from_pretrained(
    "model.qnn240.ctx.bin", implementation="remote"
) as model:
    print(model.implementation)  # remote
    # 本例使用一个固定形状的输入。按原模型要求准备真实输入。
    x = np.zeros(model.inputs[0].shape, dtype=model.inputs[0].dtype)
    y = model(x)

多输入模型仍可按名字传入字典。 return_dict=True、输出选择和输出缓冲区复用也可使用。 有有效 AIMO 元数据时,AutoModel 继续适配原模型的 dtype 和布局。 没有该元数据时,使用服务返回的运行时接口。 检查 model.inputs 和 model.outputs。 不要假定所有模型都使用 FP32。

InferenceSession 提供相同的执行位置选项:

python
from aidlite import InferenceSession

with InferenceSession(
    "model.qnn240.ctx.bin", framework="qnn240", device="dsp",
    implementation="remote",
) as session:
    # x 必须符合运行时接口。InferenceSession 不执行原接口适配。
    y = session.run(x)

已有代码也可设置 config.implement_type = ImplementType.TYPE_REMOTE。 显式 implementation 覆盖配置副本中的值,不修改原 config。 None 使用配置中的值;TYPE_DEFAULT 按 LOCAL 执行。 会话的 implementation 属性显示所选位置。

请检查以下条件:

  1. 安装相互匹配的 Python 扩展、核心、REMOTE 插件和 Android 服务。
  2. 确认服务支持所选后端和模型版本。只更新客户端不会更新 QNN。
  3. 确认服务可在加载后返回实际张量信息。高层入口不要求手填模型形状。
  4. 用 close() 或 with 释放会话。输出视图的生命周期规则保持相同。

缺少服务或模型信息时,调用报告错误,不自动切换到 LOCAL。 旧 2.3.2 适配器不支持高层 REMOTE;使用配套的维护版构建。 当前动态 ONNX 输入能力限于 LOCAL CPU;此选项不会扩展服务的动态形状能力。 IPC 延迟取决于服务、模型和设备,不能保证与 LOCAL 相同。

QNN REMOTE 调用优化 ​

固定形状、单图的 QNN REMOTE 模型可使用完整调用路径。 AutoModel 自动选择此路径。继续使用 model(x)。 此路径将输入、执行和所选输出合并为一次底层调用。 配套服务支持时,它可减少 IPC 往返次数。 输入输出的名字、原始 dtype 和布局规则保持相同。 输出选择、预分配输出和 copy=False 也可使用。

安装配套的 Python 扩展、核心和 REMOTE 插件。 插件在执行前检查服务能力和控制消息长度。 旧服务或过长的控制消息使用原有的逐步调用路径。 执行失败或超时后,不自动重试推理。 按错误信息重新建立会话。

其他后端、动态图和多图模型继续使用原有高层调用路径。 InferenceSession.run() 保留逐步绑定输入的行为。 例如,可先绑定输入 B,再传入输入 X 并执行。

REMOTE 插件将各 QNN 版本标识转换为服务协议中的 QNN 后端标识。 此转换不安装或升级 Android 上的 QNN。 服务仍须支持模型所用的 QNN 版本。

默认输出为独立副本。 copy=False 返回只读视图,并保留 Python 会话所有者。 下一次执行或显式关闭会话后,不再使用旧视图。 用实际模型测量延迟。此优化不保证 REMOTE 与 LOCAL 具有相同延迟。

复用远程输入缓冲区 ​

配套服务在完整推理路径中复用输入长度头、校验标记和字节缓冲区。 model(x) 和 InferenceSession.run() 的调用方式相同。 每个输入保留独立的准备区和已提交数据区,最多使用两个字节数组。 准备下一次输入时,服务不会改写后端当前持有的数组。 输入载荷读取失败时,不会设置部分输入或执行推理。 后端调用或输出写入失败后,后续请求使用新的缓存存储。

缓存属于当前模型上下文。 输入字节数变化时,服务替换对应的存储。 模型所有者释放后,Java 可以回收缓存。 共享内存中的输入仍会复制到 Java 数组;JNI 和后端的数据传递接口保持相同。 原生输入的包装对象也会复用。 此优化主要减少临时对象分配。

在 QCS8550、Android 13 和配套 QNN 2.48 的限定测试中,原生 UINT8 路径的 ART 进程分配量下降约 29% 至 39%。 大输入的 P50 延迟下降约 12% 至 17%。 这些数据只适用于所测模型和环境。 小输入 FP32 默认路径的三轮 P50 变化为 +3.47%、+4.34% 和 +1.54%。 尾延迟也有波动;不能据此保证延迟相同。 每个字节输入最多保留两个载荷数组。 部署前,用实际模型检查内存占用和延迟。

构建和检查步骤见服务输入缓冲说明。

检查 QNN 原生接口的缓冲区 ​

配套 JNI 在模型加载后读取并缓存实际的输入和输出规格。 它使用 SDK 返回的元数据,不使用调用者声明的形状来放宽检查。 每次推理不再查询这些规格。 此接口使用默认图;它不提供图切换操作。

普通输入和输出继续使用 FP32 数据表示。 原生模式使用模型实际的数据表示。 FloatArray 在原生模式下要求模型张量为 FP32。 字节数组保存原生数据的完整字节表示,可包含 FP16 或更宽的类型。 原有字节入口名称和 JNI 方法签名保持相同。 这些底层入口不会推断字节内容的数值类型,也不会安装新的后端能力。

输入数组必须与实际张量所需的长度完全相同。 带 size 参数时,该值还必须等于数组的字节数。 空引用、错误长度、负索引或越界索引会产生 IllegalArgumentException。 JNI 在取得数组数据和调用 SDK 之前执行检查。 错误输入不会替换已提交的输入。 使用正确数据后,可继续使用当前已加载的会话。

模型元数据缺失、无效或尺寸溢出时,模型加载失败。 释放该模型所有者,然后修正模型或 SDK 配套关系。 后端输出为空或返回错误长度时,JNI 会在复制到 Java 数组前报错。 后端异常也会释放本次取得的输入数组。 调用者仍须按顺序使用同一模型所有者,并在使用后释放它。

Python 调用者继续使用 AutoModel 或 InferenceSession。 这些检查位于配套 Android QNN JNI,不增加新的 Python 参数。 AutoModel 继续按有效 AIMO 元数据适配原模型的 dtype 和布局。 构建和测试步骤见QNN JNI 缓冲区说明。

使用 QNN 2.48 远程服务 ​

QNN 2.48 模型需要配套的 Android 服务、Java 原生接口(JNI)库和 QNN 运行库。 AutoModel 和 InferenceSession 使用相同的 implementation="remote" 选项。 例如,加载为 QNN 2.48 转换的模型:

python
from aidlite import AutoModel

with AutoModel.from_pretrained(
    "model.qnn248.ctx.bin", implementation="remote"
) as model:
    outputs = model(inputs)

按原模型要求准备 inputs。 不要把所有输入转换为 FP32。 有有效 AIMO 元数据时,AutoModel 继续适配原始 dtype 和布局。 服务仍需支持模型版本和数据模式。 客户端中的 QNN 版本标识不会升级 Android 运行库。

如果你自行构建服务,使用同一次 SDK 构建导出的头文件和静态库。 维护版 SDK 会导出 sdk-package/Release/manifest.json。 这是 SDK 配套清单,与模型输入输出元数据不同。 新版 SDK 的参数结构和清理接口已改变,不能只替换静态库。 将整个 SDK 配套目录交给 JNI 构建,通过 QNN_JNI_SDK_MANIFEST 选择它。 构建会检查文件哈希、应用二进制接口(ABI)、Android API 等级和 C++ 运行库。 省略此选项时,继续使用原来的 SDK 配对。 步骤见 SDK 构建指南 和 JNI 构建指南。

排查自定义 Android 服务时,在 AidQNN.init() 成功后调用 getInferenceFrameworkVersion()。 该方法返回已加载后端的 QNN 核心 API 版本,并缓存结果。 旧 JNI 或旧 SDK 无法查询时,返回 unknown,不再返回写死的 2.36.0。 核心 API 版本与 QAIRT 发行版本不同。 本次验证中,QAIRT 2.40.0.251030 返回 2.30.0,2.48.0.260626 返回 2.37.0。 保留 SDK 构建清单和库文件哈希,以确认具体安装包。 此方法不增加每次推理的查询开销,也不会自动升级远程服务。

QCS8550 的隔离服务已验证匹配的 QNN 2.40 和 2.48 运行库。 检查包括双输入、三输出、命名输入、输出复用和只读视图。 两个不同数据模式的会话也通过了并发检查。 受控元数据检查了原始输入类型和布局适配。 这不代表新的 AIMO 转换、加密模型或所有平台均已验证。 源码更新也不代表已安装的服务包已经更新。

用实际模型测量延迟。 本次配对测试中,2.48 的六组 P50 变化约为 −4.96% 到 +3.18%。 FP32 默认输出的 P99 约增加 8.8%。 这些结果不证明尾延迟等价,也不证明 REMOTE 与原生推理具有相同延迟。

可选推理控制 ​

保留默认的 model(inputs) 用法。 需要选择输出或复用输出数组时,使用 predict()。

选择输出 ​

使用 model.output_names 中的输出名称。 返回结果按所选顺序排列。

python
import numpy as np
from aidlite import AutoModel

inputs = np.load("input.npy", allow_pickle=False)
with AutoModel.from_pretrained("model.aidem") as model:
    name = model.output_names[0]
    result = model.predict(inputs, outputs=[name])

框架只读取和适配所选输出。 这可以减少输出复制和转换。 这不承诺减少模型内部的计算。 使用 return_dict=True 时,返回字典以所选输出名称作为键。

复用输出数组 ​

分配可写、C 连续的 NumPy 数组。 使用输出声明的数据类型和确定形状。 动态输出需要先获取实际形状,再分配数组。

python
import numpy as np
from aidlite import AutoModel

inputs = np.load("input.npy", allow_pickle=False)
with AutoModel.from_pretrained("model.aidem") as model:
    name = model.output_names[0]
    first = model.predict(inputs, outputs=[name])
    buffer = np.empty_like(first)
    result = model.predict(inputs, outputs=[name], out=buffer)

返回数组就是传入的缓冲区。 复用缓冲区会覆盖上一次的结果。 多个输出使用 out={name: array},键必须与所选输出完全一致。 输出缓冲区不能与输入重叠,也不能彼此重叠。 输出缓冲区要求 return_tensors="np"。 后端到缓冲区仍可能复制数据。 必要的数据类型或布局转换仍可能分配临时数组。

选择原生输入和输出模式 ​

这些选项适用于已经管理后端张量格式的 QNN 和 SNPE 流程。 加载模型时,分别设置 native_input 和 native_output。 两者默认均为 False。

python
from aidlite import AutoModel

with AutoModel.from_pretrained(
    "model.qnn248.ctx.bin",
    native_input=True,
    native_output=False,
) as model:
    print(model.inputs, model.outputs)

开启任一选项时,整个模型使用内部接口。 按 model.inputs 和 model.outputs 准备每个张量。 原生一侧使用物理张量类型。 普通一侧使用后端普通接口。 调用方需要确认量化参数和张量含义。 包装层不会额外执行量化。 原生模式在模型生命周期内保持不变。 原生模式不能与 interface="original" 合用。

设置图优先级 ​

通过 config 传入后端配置。 框架在加载时复制配置,不修改调用方对象。

python
from aidlite import AutoModel, Config

config = Config.create_instance()
if config is None:
    raise RuntimeError("Cannot create AidLite config")
config.graph_priority = "high"
with AutoModel.from_pretrained("model.qnn248.ctx.bin", config=config) as model:
    print(model.inputs)

graph_priority 默认为空字符串,保留后端默认优先级。 QNN DSP 支持 low、normal_low、normal、normal_high、high、high_plus、critical 和 critical_plus。 QNN 2.40 只提供四档原生优先级。 该版本将 normal_low 映射为 low。 high_plus、critical 和 critical_plus 映射为 high。 QNN 2.48 使用对应的原生档位。 优先级是否生效取决于后端和设备支持。 加载后修改原 config 不会改变已加载的模型。

控制 Python 并发 ​

release_gil 默认为 False。 默认调用保留原来的 Python 调度行为。 在 AutoModel.from_pretrained() 或 InferenceSession() 中设置 release_gil=True,可在原生推理期间允许其他 Python 线程运行。 该选项需要配套的新版本原生扩展和拥有完整生命周期的会话。 旧版借用 Model/Context 的适配器不支持此选项。

每个工作线程使用独立会话。 同一个会话仍按顺序调用。 推理期间不要修改输入,不要切换图,也不要关闭会话。 AutoModel 会按顺序执行同一模型的调用。 InferenceSession 在原生推理期间拒绝同一会话的其他原生操作。

先测量实际工作负载,再启用此选项。 短 CPU 模型可能因线程竞争而变慢。 释放 GIL 不保证同一 NPU 上的请求可以并行执行。 按设备和工作负载设置 config.number_of_threads。 多个会话同时使用大量 CPU 线程可能增加延迟。

查看量化参数 ​

TensorSpec.dtype 是调用接口要求的数据类型。 TensorSpec.native_dtype 是后端报告的物理数据类型。 两者可以不同。 例如,普通 QNN 接口可使用浮点数组,而物理张量使用 uint8。

python
from aidlite import AutoModel

with AutoModel.from_pretrained("model.qnn248.ctx.bin") as model:
    for spec in model.inputs + model.outputs:
        print(spec.name, spec.dtype, spec.native_dtype)
        print(spec.quantization, spec.quantize_scale, spec.quantize_offset)

可用的 QNN 逐张量参数通过 spec.quantization 返回。 参数对象提供 scale、zero_point、dtype 和 offset。 offset 使用 QNN 约定:zero_point = -offset。 spec.quantize_scale 和 spec.quantize_offset 提供相同参数的快捷读取方式。 参数来自已加载模型的后端张量信息。 AIMO 元数据继续提供原接口映射和经核对的形状。 缺失、无效或已知不支持的量化编码返回 None。 不要将 None 当成缩放值 1 或零点 0。 当前标量参数对象不表示逐通道、分块或压缩低位宽编码。 旧后端 API 不能报告完整编码类型时,调用方仍需核对模型的量化方式。 其他后端的量化约定未确认时,也返回 None。

手动量化和反量化 ​

quantize() 和 dequantize() 是可选工具。 它们不会被 model(inputs) 自动调用。 默认原接口的数据类型规则不变。

以下示例要求一个输入、一个输出的逐张量量化 QNN 模型。 输入文件必须使用后端要求的维度排列。

python
import numpy as np
from aidlite import AutoModel, quantize, dequantize

inputs = np.load("input-runtime-layout.npy", allow_pickle=False)
with AutoModel.from_pretrained(
    "model.qnn248.ctx.bin", native_input=True, native_output=True,
) as model:
    input_params = model.inputs[0].quantization
    output_params = model.outputs[0].quantization
    if input_params is None or output_params is None:
        raise ValueError("This model needs explicit supported quantization parameters")
    quantized = quantize(inputs, input_params)
    result = model.predict(quantized, copy=False)
    restored = dequantize(result, output_params, dtype=inputs.dtype)

quantize() 计算 round_to_even(x / scale) + zero_point,然后截断到整数类型范围。 dequantize() 计算 (q - zero_point) * scale。 QNN offset 与 zero point 符号相反。 不要直接把 QNN offset 作为 zero_point 传入。 工具不重排维度,不推断量化参数,也不恢复量化损失的精度。 整数类型支持原生字节序的 int8、uint8、int16、uint16、int32 和 uint32。 缩放值必须为正且有限。 非有限输入、无效零点、参数冲突和不匹配的数据类型会报错。 反量化默认返回 float32;可显式选择 float16 或 float64。 这个默认值只属于工具函数,不改变原模型的接口类型。

已知参数时,也可以直接传入数值。

python
import numpy as np
from aidlite import QuantizationParams, quantize, dequantize

params = QuantizationParams(scale=0.5, zero_point=10, dtype=np.uint8)
quantized = quantize(np.array([1.0], dtype=np.float16), params)
restored = dequantize(quantized, params, dtype=np.float16)
assert quantized[0] == 12
assert restored[0] == 1.0

same = quantize([1.0], scale=0.5, zero_point=10, dtype=np.uint8)

使用参数对象时,不要同时传入 scale、zero_point 或量化目标 dtype。 多输入和多输出模型应分别使用每个张量自己的参数。 普通 QNN 或 SNPE 输入输出已由后端转换时,不要再手动量化或反量化。

借用后端输出视图 ​

默认 copy=True,输出独立于后续推理和模型关闭。 需要减少输出复制时,显式使用 predict(copy=False)。

python
import numpy as np
from aidlite import AutoModel

inputs = np.load("input-runtime-layout.npy", allow_pickle=False)
with AutoModel.from_pretrained("model.onnx", interface="runtime") as model:
    view = model.predict(inputs, copy=False)
    saved = view.copy()

借用结果是只读 NumPy 视图。 框架不会复制该输出的数据。 后端本身仍可能复制或转换数据。 布局置换可以返回不连续的视图。 需要转换输出数据类型时,copy=False 会在推理前报错。 此时使用默认复制,或显式选择满足所需数据类型的内部接口。 copy=False 不能与 out 或 return_tensors="pt" 合用。 输出选择和 return_dict=True 仍可使用。

保持模型存活,并在下一次调用或关闭模型前处理完视图。 下一次调用可能覆盖或重新分配后端输出内存。 关闭模型后,不要访问借用的数组。 其他线程也不能在视图使用期间调用或关闭同一个模型。 需要保留结果时,在有效期内调用 view.copy()。

使用 QNN 2.40 和 2.48 后端 ​

以下行为需要包含原生张量修复的 QNN 2.40 或 2.48 插件。 源码合并不代表安装包已经发布。 QNN 2.40 和 2.48 使用相同的高层调用方式。 示例使用 QNN 2.48 模型。 使用 QNN 2.40 时,选择为该版本转换的模型。 例如,加载 model.qnn240.ctx.bin。 模型必须与插件和运行库版本匹配。 升级时,请确认插件包含本节所述修复。

python
import numpy as np
from aidlite import AutoModel, Config

config = Config.create_instance()
if config is None:
    raise RuntimeError("Cannot create AidLite config")
config.qnn_shared_buffer = True

with AutoModel.from_pretrained(
    "model.qnn248.ctx.bin", device="npu", config=config,
) as model:
    inputs = np.load("input.npy", allow_pickle=False)
    result = model(inputs)

先确认模型输入要求,再准备 input.npy。 有效的 AIMO 元数据仍决定原模型的数据类型和布局。 本节不要求所有原模型都使用 FP32。

qnn_shared_buffer=True 使用插件持有的 RPC 共享缓冲区。 它不表示任意 NumPy 数组都能直接注册为 NPU 内存。 输入仍可能需要复制、量化或布局转换。 不要把共享缓冲区等同于端到端零复制。

使用 native_input=True 和 native_output=True,可以传递内部数据。 数据类型必须与 native_dtype 一致。 FP16、布尔、整数及定点数据按实际字节数传递。 原生输出直接借用后端缓冲区。 普通 FP32 输出的转换缓冲区按需分配,并在后续调用中复用。 标量量化转换要求有效的 scale/offset 参数。 其他编码应使用原生模式,并由调用方执行对应转换。

量化标量输入按一个元素处理。 转换失败时,调用会报告错误。 普通输入转换复用张量尺寸检查结果。 它不再为维度列表分配临时存储。 量化算法和舍入方式保持不变。

如果加载 .so 模型或 QNN 2.48 的 .dlc 模型失败,请查看后端日志。 QNN model buffer must contain data 表示模型数据为空。 Create QNN model 或 Write QNN model file 表示内部模型文件准备失败。 重试前,先检查消息中的系统错误。 模型对象拥有内部模型文件。 释放模型对象时,也会释放该文件;初始化失败后同样适用。

如需使用可选的后端扩展,请在加载模型前设置其 JSON 路径:

python
config.backend_extension_config = "/absolute/path/backend-config.json"

调用 AutoModel.from_pretrained 时,传入 config=config。 扩展库和 JSON 设置必须与 QNN SDK 版本一致。 普通 JSON 配置不需要 DLC 资源管理器。 加载失败时,请查看后端日志中的库、接口或配置错误。 构造失败或关闭模型时,SDK 会释放扩展对象和库。

多图模型使用 graph 选择运行的图。 例如,graph=1, interface="runtime" 选择第二个图。 一次调用只执行所选图。 推理失败后,不要读取上一次的输出。 先修复错误,再重新执行推理。

关闭失败时,保留模型及其输入缓冲区。 检查错误日志并处理运行库错误。 然后重试 model.close()。 成功释放的电源配置不会再次释放。 关闭完成前,不要继续推理。

如果单独设置运行库路径,请保留配套的 DSP 文件路径。 AIDLUX_QNN_LIB_DIR_PATH 指定运行库目录。 ADSP_LIBRARY_PATH 可指定额外的 DSP 搜索目录。 使用同一版本的运行库、stub 和 skel。 一个进程内不要混用多个 QNN 运行时版本。

可选的 QNN 2.48 内存绑定 ​

维护中的 QNN 2.48 后端提供 QNN_BIND_MEM_HANDLES 构建选项。 默认关闭。只有包含此选项的配套构建才会检查绑定能力。 启用 config.qnn_shared_buffer 后,后端仍需报告支持该能力。 不支持时,继续使用普通共享缓冲区路径。 此选项不改变 AutoModel 或 model(x) 的调用方式。 它不等同于任意输入数组的零复制。

启用绑定后,每个图分别持有绑定信息。 加载模型时建立绑定。推理时不重复建立绑定。 销毁模型时,先解除绑定,再释放该图的内存。 如果销毁失败,保留模型对象。解决原因后重试 close()。 C++ SDK 使用 destroy()。 清理完成前,不要继续推理或替换模型。

当前 QCS8550 测试环境中的 QNN 2.48 运行库不支持该能力。 真实 NPU 测试验证了正常回退路径。 绑定和故障处理已通过主机受控测试;尚未在支持绑定的 NPU 上验证。 按实际模型测量延迟。不要假定启用此选项一定更快。 构建步骤和验证工具见 QNN 构建指南。

选择其他后端 ​

创建模型时,SDK 向当前核心查询本地后端支持情况。 导入 Python 包时,不扫描系统中的后端插件。 模型格式规则由 Python 和核心共用。 自动识别采用当前原生核心提供的格式提示。 文件名只提供提示。 参数或 aidlite.json 中的显式 framework 优先于文件名。 .dlc 默认选择通用 QNN,不再默认选择 SNPE2。 显式 framework 或有效 AIMO 元数据可指定后端。 未明确选择具体版本时,.qnn248.dlc 等文件名可提供版本提示。 .tnnmodel、.mnn、.nb 和 .ms 可以识别格式。 识别格式不代表当前核心已实现对应后端。 当前维护的核心使用 QNN 2.40 和 QNN 2.48。 它已停用 QNN 2.36 及更早版本,也已停用 SNPE 后端。 相关枚举和旧示例保留用于迁移旧项目。 .rknn 文件选择 RKNN,默认设备为 NPU。 对 QNN 和 SNPE,device="npu" 映射到 DSP。 其他后端保留 NPU 选择。 后端要求独立权重文件时,使用 model_weight_path。

区分模型声明与运行支持 ​

aidlite.json 中的 framework 声明模型所属后端。 SDK 只检查此字段的字符串类型和标识符语法。 名称按小写处理,并且只能包含字母、数字和下划线,以字母开头。 例如,未来的后端名可以保存在模型资产中。 这不表示当前 SDK 可以运行该后端。 即使文件名以 .onnx 结尾,也先保留显式后端声明。 实际运行仍由核心和插件验证。

显式参数、aidlite.json 和真实 AIMO 元数据中的后端声明必须一致。 它们之间的冲突仍会报错。

通用 qnn 声明可以细化为 qnn248 等具体版本。 例如,配套元数据声明 qnn 时,可以指定 framework="qnn248"。 这些声明中的两个具体版本必须一致。 例如,AIMO 元数据中的 qnn240 与显式 qnn248 冲突时,SDK 会报错。 元数据回退不会忽略真实的框架冲突。

需要检查当前核心的派发能力时,使用配套新版 SDK 的查询接口:

python
import aidlite

framework = aidlite.infer_framework_type("model.dlc")
backend = aidlite.get_local_backend_key(framework)
print(framework, backend)

infer_framework_type() 只根据文件名推导类型。 它不读取模型,也不检查插件文件。 无法识别格式时,返回 FrameworkType.TYPE_DEFAULT。 get_local_backend_key() 返回当前核心实现的本地后端键;未实现时返回 None。 通用 QNN 返回 "qnn",具体版本在模型创建时选择。 非空结果不表示插件已安装、依赖可加载或设备兼容。 实际加载仍需匹配的插件、SDK 和设备。

模型创建错误分为以下情况:

情况处理方法
当前原生绑定不认识后端名核对名称,并使用配套的核心和 Python 绑定。不要仅因当前安装包较旧而改写正确的模型声明。
核心没有实现该本地后端选择当前支持的后端,或重新转换模型。保留枚举不会启用已停用的后端。
插件加载、依赖或版本校验失败根据初始化错误中的后端路径和原因,检查插件及其依赖和版本。

get_last_backend_error() 可读取当前线程最近一次初始化的后端错误。 下一次 init() 会清空该信息。 在需要手动检查低层返回码时,立即读取此信息。

检查元数据回退 ​

有效的 AIMO 元数据优先提供输入输出形状。 加载时,框架通过后端张量 API 核对一次。 这项检查用于保护本地代码使用的缓冲区尺寸。 推理时复用已验证的处理计划。 无法使用时,自动模式查询 get_input_tensor_info() 和 get_output_tensor_info()。 后端信息描述转换后的模型。 它不能重建缺失的原模型名称、布局或数据类型。 使用 interface="original",可以要求严格原接口并禁止回退。 后端查询或模型加载失败时仍会报错。 SDK 错误会提供可用的操作、状态信息和建议检查项。

REMOTE 模式排查 ​

本节适用于通过进程间通信(IPC)调用 Android 服务的模式。 检查 Android 服务支持的后端版本、输入数量和数据类型。 原生后端与 REMOTE 模式的支持范围可能不同。

检查服务和后端版本 ​

先确认 Android 推理服务正常运行。 再确认模型与该服务的 QNN SDK 版本兼容。 单独更新 Linux 侧 AidLite,不会更新 Android 侧 QNN 后端。 模型需要较新的 QNN SDK 时,请更新配套服务或重新转换模型。

自定义 Android 服务的共享内存 ​

自行构建 Android 推理服务时,请使用配套的 AidLuxIPC Java 类和 Java 本地接口(JNI)库。 包含此修复的构建支持用 Java try-with-resources 释放共享内存对象。 已有 destroy_ashmem() 调用也可继续使用。 关闭对象前,先结束使用其借用文件描述符的操作。 参见 Java 资源管理和数组边界说明。

包含区间写入优化的 JNI 构建只复制请求的输入区间。 可继续复用较大的 Java 输入数组。 字节写入和对齐的浮点写入使用一次区间复制。 未对齐的浮点字节偏移仍可使用原有兼容路径。 复制出错时,保留异常,不切换路径重试。 出错前已写入的数据不会自动还原。 用实际模型测量延迟;区间写入优化不保证整次推理更快。

Python 调用者继续用 with 管理 AutoModel 或 InferenceSession。 这会释放会话;无需手动管理 Android 共享内存。

检查服务崩溃日志 ​

推理超时也可能由 Android 服务崩溃引起。 先连接测试设备的 Android 调试桥(ADB)。 用 adb devices 确认设备序列号。 将 DEVICE_SERIAL 替换为该序列号。

bash
adb -s DEVICE_SERIAL logcat -d -b crash

检查日志中的进程名和错误信息。 如果同时出现 ai.onnxruntime 和 JNI DETECTED ERROR,请提供完整日志。 如果还出现 mid == null,请由设备维护人员检查 ONNX 发布包配置。 该问题可能需要重新构建并发布 Android 服务。 服务更新后,重新检查正常推理和错误返回。

低层接口参考 ​

以下接口用于手动管理模型、配置和解释器。 其中的数据类型规则由所选后端接口决定。 这些规则与 AutoModel 的原接口适配不同。

模型数据类型 class DataType ​

对于 AidliteSDK 而言,会用来处理不同框架的不同模型,每个模型也会有不同的输入数据类型和不同的输出数据类型。调用某些接口时,需要设置模型的输入输出数据类型,就需要用到此数据类型的枚举。

成员变量名类型值描述
TYPE_DEFAULTint0无效数据类型
TYPE_UINT8int1Unsigned char 数据
TYPE_INT8int2Char 数据
TYPE_UINT32int3Unsigned int32 数据
TYPE_FLOAT32int4float 数据
TYPE_INT32int5int32 数据
TYPE_INT64int6int64 数据
TYPE_UINT64int7Unsigned int64 数据
TYPE_INT16int8Int16 数据
TYPE_UINT16int9Unsigned int16 数据
TYPE_FLOAT16int10Float16 数据
TYPE_BOOLint11Bool 数据

推理实现类型 class ImplementType ​

成员变量名类型值描述
TYPE_DEFAULTint0无效 ImplementType 类型
TYPE_MMKVint1C++ 接口中保留该枚举;当前 Python 绑定未导出,不能直接使用
TYPE_REMOTEint2远程推理实现
TYPE_FASTint2TYPE_REMOTE 的兼容别名,已废弃,不建议继续使用
TYPE_LOCALint3本地推理实现

💡注意

特别说明:

TYPE_LOCAL 与 TYPE_REMOTE 的区别在于:对于 Aplux 融合系统而言,前者的推理实现过程是在 Linux 环境本地完成的,无需数据的传输。而后者则是通过 IPC(进程间通信)的方式与 Android 环境实现数据交互,推理实现过程在 Android 环境完成的,故而会涉及到数据的传输。综上所述,TYPE_LOCAL 方式是用来完成推理过程的优选项。

模型框架类型 class FrameworkType ​

由于 AidliteSDK 整合了多种深度学习推理框架,所以在使用过程中,需要设置当前使用哪个框架的模型,就需要设置所需推理框架的类型枚举。

成员变量名类型值描述
TYPE_DEFAULTint0无效 FrameworkType 类型
TYPE_SNPEint1SNPE 1.x (DLC) 模型
TYPE_TFLITEint2TFLite 模型
TYPE_RKNNint3RKNN 模型
TYPE_QNNint4QNN 模型
TYPE_SNPE2int5SNPE 2.x (DLC) 模型
TYPE_NCNNint6NCNN 模型
TYPE_MNNint7MNN 模型
TYPE_TNNint8TNN 模型
TYPE_PADDLEint9Paddle 模型
TYPE_MSint10MindSpore 模型
TYPE_ONNXint11onnx 模型
TYPE_QNN216int101QNN2.16 模型
TYPE_SNPE216int102SNPE2.16 模型
TYPE_QNN223int103QNN2.23 模型
TYPE_SNPE223int104SNPE2.23 模型
TYPE_QNN229int105QNN2.29 模型
TYPE_SNPE229int106SNPE2.29 模型
TYPE_QNN231int107QNN2.31 模型
TYPE_QNN236int108QNN2.36 模型
TYPE_QNN240int109QNN2.40 模型
TYPE_QNN248int110QNN2.48 模型

💡注意

特别说明:

  • 枚举保留历史值,不表示当前核心实现全部列出的后端。使用 get_local_backend_key() 查询本地派发支持情况。
  • TYPE_QNN 在当前核心实现的具体 QNN 后端中,优先选择版本较新的已安装插件。当前维护版本为 QNN 2.40 和 QNN 2.48。旧 QNN 和 SNPE 后端仍已停用。
  • 一个进程内不要混用多个 QNN 运行时版本。

推理加速硬件类型 class AccelerateType ​

对于每个深度学习推理框架而言,可能会支持运行在不同的加速设备上(如 SNPE/QNN 模型运行在 DSP 设备,RKNN 模型运行在 NPU 设备),所以在使用过程中,需要设置当前模型期望运行在哪个设备,就需要使用此加速硬件枚举。

成员变量名类型值描述
TYPE_DEFAULTint0无效 AccelerateType 类型
TYPE_CPUint1CPU 加速运行
TYPE_GPUint2GPU 加速运行
TYPE_DSPint3DSP 加速运行
TYPE_NPUint4NPU 加速运行

日志级别 class LogLevel ​

AidliteSDK 提供有设置日志相关信息的接口(后续会介绍),如果需要指定 AidliteSDK 当前使用哪个日志级别,就需要使用此日志级别枚举。

成员变量名类型值描述
INFOint0消息
WARNINGint1警告
ERRORint2错误
FATALint3致命错误

设备信息类.class DeviceInfo ​

从 2.3.1 开始,Python 绑定也提供了 DeviceInfo 类型,用于描述底层可用推理设备的信息,目前主要用于 QNN DSP 场景下的设备查询与自定义设备配置。

成员变量列表 ​

成员变量名类型默认值描述
idint0设备 ID
typeint0设备类型编号,由后端解释
cores_numint1设备包含的核心数量
cores_idlist空设备核心 ID 列表

💡注意

C++ 结构体中的 version 字段当前没有在 Python 绑定层导出,Python 侧可直接使用其余四个公开字段。

输入输出信息类.class TensorInfo ​

每个模型都会有各自的输入输出,对于开发者不那么熟悉的模型而言,开发过程中可能需要查询该模型的输入输出 Tensor 信息,以方便开发者做模型推理的前后处理操作。Aidlite 为开发者提供了查询模型输入输出详细信息的接口,以及用于存储输入输出详细信息的 TensorInfo 数据类型。

成员变量列表 ​

TensorInfo 对象用于存储模型输入输出 Tensor 的详细信息,其中就包含如下的这些参数:

成员 version
类型 int
默认 0X00020205
描述 此成员用于标识 TensorInfo 版本,如果以后需要扩展更多信息时,会更新版本号
成员 index
类型 int
默认 无默认值
描述 Tensor 的索引值
成员 name
类型 str
默认 无默认值
描述 Tensor 的名称字符串
成员 element_count
类型 int
默认 0
描述 Tensor 中数据元素的数量(非字节数量)
成员 element_type
类型 enum DataType
默认 DataType::TYPE_DEFAULT
描述 Tensor 中数据元素的类型
成员 dimensions
类型 int
默认 0
描述 Tensor 中数据元素的维度值
成员 shape
类型 list[int]
默认 无默认值
描述 Tensor 中数据元素的 shape 描述

模型类 class Model ​

在创建推理解释器之前,需要设置具体模型的相关详细参数。Model 类主要用于记录模型的文件信息、结构信息、运行过程中模型相关内容。

创建空实例对象 create_instance() ​

当前 Python 绑定也提供了无参重载,可先创建一个空的 Model 实例,再由调用方在后续流程中补充模型路径或属性信息。

API create_instance
描述 构造一个不携带模型文件路径的 Model 实例对象
参数 无
返回 正常:Model 实例对象
异常:None

创建实例对象 create_instance() ​

想要设置模型相关的详细信息,当然就需要先有模型实例对象,此函数用于创建 Model 实例对象。如果模型框架(如 snpe、tflite 等)只需一个模型文件,则调用此接口。

API create_instance
描述 通过传递模型文件的路径名称,构造 Model 类型的实例对象
参数 model_path:模型文件的路径名称
返回 正常:Model 实例对象
异常:None
python
# 使用当前路径下 inceptionv3_float32.dlc 文件创建模型对象,返回值为空则报错
model = aidlite.Model.create_instance(model_path=r"./inceptionv3.dlc")
if model is None:
    print("Create model failed.")
    return False

创建实例对象 create_instance() ​

想要设置模型相关的详细信息,当然就需要先有模型实例对象,此函数用于创建 Model 实例对象。如果模型框架(如 ncnn、tnn 等)涉及两个模型文件,则调用此接口。

API create_instance
描述 通过传递模型文件的路径名称,构造 Model 类型的实例对象
参数 model_struct_path:模型结构文件的路径名称
model_weight_path:模型权重参数文件的路径名称
返回 正常:Model 实例对象;异常:None
python
# 使用当前路径下 ncnn 的两个模型文件创建模型对象,返回值为空则报错
model = aidlite.Model.create_instance( 
        model_struct_path=r"./mobilenet_ssd_voc_ncnn.param",
        model_weight_path=r"./mobilenet_ssd_voc_ncnn.bin")
if model is None:
    print("Create model failed.")
    return False

设置模型属性 set_model_properties() ​

模型实例对象创建成功之后,需要设置模型的输入输出数据类型和输入输出 tensor 数据的 shape 信息。

API set_model_properties
描述 设置模型的属性,设置模型的输入/输出数据 shape 和数据类型。
参数 input_shapes:输入 tensor 的 shape 数组,二维数组结构。
input_data_type:输入 tensor 的数据类型,DataType 枚举类型。
output_shapes:输出 tensor 的 shape 数组,二维数组结构。
output_data_type:输出 tensor 的数据类型,DataType 枚举类型。
返回 正常:0;异常:非 0
注意 使用 REMOTE 时,按后端要求设置输入输出信息。
QNN 和 SNPE 的普通低层接口默认使用 aidlite.DataType.TYPE_FLOAT32。
原生数据模式以张量信息和当前 REMOTE 服务的支持范围为准。
其他后端按所用接口声明的数据类型准备数组。
python
# 数据类型使用前述 DataType,输入输出 shape 是二维数组
input_shapes=[[1,640,640,3]]
output_shapes=[[1,10,10,255], [1,20,20,255], [1,40,40,255]]
model.set_model_properties( input_shapes=input_shapes, 
                            input_data_type=aidlite.DataType.TYPE_FLOAT32, 
                            output_shapes=output_shapes, 
                            output_data_type=aidlite.DataType.TYPE_FLOAT32)

获取模型路径 get_model_absolute_path() ​

如果模型框架(如 SNPE、TFLite 等)只涉及一个模型文件,在构建 Model 对象没有异常的情况下,会将传入的模型文件参数转换为绝对路径形式的文件路径。

API get_model_absolute_path
描述 用于获取模型文件的绝对路径
参数 无
返回 Model 对象所对应的模型文件路径字符串

获取模型路径 get_model_struct_absolute_path() ​

如果模型框架(如 NCNN、TNN 等)涉及两个模型文件,在构建 Model 对象没有异常的情况下,会将传入的模型结构文件参数转换为绝对路径形式的文件路径。

API get_model_struct_absolute_path
描述 用于获取模型结构文件的绝对路径
参数 无
返回 Model 对象所对应的模型结构文件路径字符串

获取模型路径 get_model_weight_absolute_path() ​

如果模型框架(如 NCNN、TNN 等)涉及两个模型文件,在构建 Model 对象没有异常的情况下,会将传入的模型权重参数文件参数转换为绝对路径形式的文件路径。

API get_model_weight_absolute_path
描述 用于获取模型权重参数文件的绝对路径
参数 无
返回 Model 对象所对应的模型权重参数文件路径字符串

配置类 class Config ​

在创建推理解释器之前,除了需要设置 Model 具体信息之外,还需要设置一些推理时的配置信息。Config 类用于记录需要预先设置的配置选项,这些配置项在运行时会被用到。

创建实例对象 create_instance() ​

想要设置运行时的配置信息,当然就需要先有配置实例对象,此函数用于创建 Config 实例对象。

API create_instance
描述 用于构造 Config 类的实例对象
参数 无
返回 正常:Config 实例对象
异常:None
python
# 创建配置实例对象,返回值为 None 则报错
config = aidlite.Config.create_instance()
if config is None:
    print("Create config failed.")
    return False

成员变量列表 ​

Config 对象用于设置运行时的配置信息,其中就包含如下的这些参数:

成员 accelerate_type
类型 class AccelerateType
默认 AccelerateType.TYPE_CPU
描述 加速硬件的类型
成员 implement_type
类型 class ImplementType
默认 ImplementType.TYPE_DEFAULT
描述 用于区分后端实现推理功能的不同环境
注意 开发者可以不用显式设置此配置项,
AidliteSDK 会根据当前的系统环境、模型框架等因素,适配得出更优的 ImplementType 类型
成员 framework_type
类型 class FrameworkType
默认 FrameworkType.TYPE_DEFAULT
描述 底层推理框架的类型
成员 number_of_threads
类型 int
默认 -1
描述 线程数,大于 0 有效
注意 当且仅当 framework_type 为 TFLITE 时,可以选择性设置此配置项
成员 snpe_out_names
类型 list
默认 无
描述 模型输出节点的名称列表
注意 当且仅当 framework_type 为 SNPE 时,需要设置此配置项
成员 is_quantify_model
类型 int
默认 0
描述 是否为量化模型,1 表示量化模型
注意 当且仅当 implement_type 为 REMOTE 时,需要设置此配置项
成员 remote_timeout
类型 int
默认 -1
描述 接口超时时间(毫秒,大于 0 有效)
注意 当且仅当 implement_type 为 REMOTE 时,可以选择性设置此配置项
成员 fast_timeout
类型 int
默认 -1
描述 `remote_timeout` 的历史兼容字段;当前 Python 绑定仍可访问,但不建议继续使用
成员 qnn_shared_buffer
类型 int
默认 0
描述 是否启用 QNN shared buffer,目前主要用于 QNN DSP 场景
成员 batch_invoke_size
类型 int
默认 1
描述 后端 batch 推理配置参数,目前主要用于 QNN DSP 场景
成员 backend_extension_config
类型 str
默认 空字符串
描述 后端推理框架扩展配置文件,目前主要用于 QNN DSP 场景
成员 custom_device_info
类型 list[DeviceInfo]
默认 空
描述 自定义设备信息列表,用于指定后端实际使用的设备集合
成员 reserved1
类型 int
默认 0
描述 预留字段,当前无业务语义,调用方无需主动设置

💡注意

remote_timeout 与 fast_timeout 对应同一组超时配置;其中 fast_timeout 仅为历史兼容字段,新代码应统一使用 remote_timeout。

python
config.framework_type = aidlite.FrameworkType.TYPE_QNN
config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
# 按需设置其他配置项
# ... ...

上下文类 class Context ​

用于存储执行过程中所涉及的运行时上下文,就包括 Model 对象和 Config 对象,后续可能会扩展运行时的上下文数据。

构造函数 Context() ​

API Context
描述 构造 Context 实例对象
参数 model:Model 实例对象
config:Config 实例对象
返回 正常:Context 实例对象
异常:None
python
context = aidlite.Context(model=model, config=config)

获取 Model 成员变量 get_model() ​

API get_model
描述 获取 context 管理的 Model 对象
参数 无
返回 Model 对象
python
model = context.get_model()

获取 Config 成员变量 get_config() ​

API get_config
描述 获取 context 管理的 Config 对象
参数 无
返回 Config 对象
python
config = context.get_config()

解释器类 class Interpreter ​

Interpreter 类型的对象实例是执行推理操作的主体,用于执行具体的推理过程。创建解释器对象之后,所有的操作都是基于解释器对象来完成的,所以它是 AidliteSDK 绝对的核心内容。

创建实例对象 create_instance ​

想要执行推理相关的操作,推理解释器肯定必不可少,此函数就用于构建推理解释器的实例对象。

API create_instance
描述 利用 Context 对象所管理的各种数据,构造 Interpreter 类型的对象
参数 context:Context 实例对象
返回 正常:Interpreter 实例对象
异常:None
python
# 创建解释器对象,返回值为 None 则报错
interpreter = aidlite.Interpreter.create_instance(context=context)
if interpreter is None:
    print("Create Interpreter failed.")
    return False

初始化 init() ​

解释器对象创建之后,需要执行一些初始化操作(比如环境检查、资源构建等)。

API init
描述 完成推理所需的相关的初始化工作
参数 无
返回 正常:0
异常:非 0
python
# 解释器初始化,返回值非0则报错
result = interpreter.init()
if result != 0:
    print("sample : interpreter.init() failed.")
    return False

获取设备信息 get_device_info() ​

当前 Python 绑定新增了 get_device_info(),用于查询后端实际可见的设备信息。该接口从 2.3.1 起支持,目前主要用于 QNN DSP 场景。

API get_device_info
描述 获取后端设备详情列表
返回 正常:DeviceInfo 对象列表
异常:抛出异常
python
device_info_list = interpreter.get_device_info()
for device in device_info_list:
    print(device.id, device.type, device.cores_num, device.cores_id)

加载模型 load_model() ​

解释器对象完成初始化操作之后,就可以为解释器加载所需的模型文件,完成模型加载工作。后续的推理过程就使用加载的模型资源。

API load_model
描述 完成模型加载相关的工作。
因为前述在 Model 对象中已经设置模型文件的路径,所以直接执行模型加载操作即可
参数 无
返回 正常:0
异常:非 0
python
# 解释器加载模型,返回值非 0 则报错
result = interpreter.load_model()
if result != 0:
    print("sample : interpreter.load_model() failed.")
    return False

获取输入Tensor详情 get_input_tensor_info() ​

如果想要获取模型的输入 Tensor 的详细信息,可以使用此接口获取。

API get_input_tensor_info
描述 获取模型中输入 Tensor 的详细信息
返回 正常:TensorInfo 类型数据的二维数组
异常:None
说明 此接口从 AidliteSDK 版本号 2.2.5 开始支持
python
# 获取模型的输入 Tensor 详细信息
input_tensor_info = aidlite_interpreter.get_input_tensor_info()
if len(input_tensor_info) == 0 :
    print("interpreter get_input_tensor_info() failed.")
    return False
for gi, graph_tensor_info in enumerate(input_tensor_info):
    for ti, tensor_info in enumerate(graph_tensor_info):
        print(  f"Input  tensor : Graph[{gi}]-Tensor[{ti}]-name[{tensor_info.name}]"
                f"-element_count[{tensor_info.element_count}]-element_type[{tensor_info.element_type}]"
                f"-dimensions[{tensor_info.dimensions}]-shape{tensor_info.shape}")

获取输出Tensor详情 get_output_tensor_info() ​

如果想要获取模型的输出 Tensor 的详细信息,可以使用此接口获取。

API get_output_tensor_info
描述 获取模型中输出 Tensor 的详细信息
返回 正常:TensorInfo 类型数据的二维数组
异常:None
说明 此接口从 AidliteSDK 版本号 2.2.5 开始支持
python
# 获取模型的输出 Tensor 详细信息
output_tensor_info = aidlite_interpreter.get_output_tensor_info()
if len(output_tensor_info) == 0 :
    print("interpreter get_output_tensor_info() failed.")
    return False
for gi, graph_tensor_info in enumerate(output_tensor_info):
    for ti, tensor_info in enumerate(graph_tensor_info):
        print(  f"Output tensor : Graph[{gi}]-Tensor[{ti}]-name[{tensor_info.name}]"
                f"-element_count[{tensor_info.element_count}]-element_type[{tensor_info.element_type}]"
                f"-dimensions[{tensor_info.dimensions}]-shape{tensor_info.shape}")

设置输入数据 set_input_tensor() ​

执行推理操作之前,需要传入模型所需的输入 Tensor 数据。设置输入数据之前,对于不同的模型,需要完成不同的前处理操作以适配具体模型。

API set_input_tensor
描述 设置推理所需的输入 tensor 的数据
参数 in_tensor_tag:输入 tensor 的索引值或者名称字符串,类型为 int 或者 str
input_data:支持 buffer protocol 的输入数据,如 numpy.ndarray、memoryview 或 bytes
可选参数 is_native:是否将传入数据视为原生后端数据格式;为 `false` 时按 SDK 默认逻辑处理量化/反量化,为 `true` 时直接按原始格式传入;默认值为 False
返回 正常:0
异常:非 0
说明 1. 参数 in_tensor_tag 从 AidliteSDK 版本号 2.2.5 开始支持 tensor 名字字符串
2. 对于 numpy.ndarray 和 memoryview,要求使用 C 连续内存布局;非连续数组/视图会触发 RuntimeWarning 并自动转化为连续内存副本,可能引起额外的数据拷贝开销
3. 对于 SNPE/QNN 两个推理框架来说,默认输入通常按 float32 处理;若调用原生格式接口,则需要用户自行保证数据格式与后端要求一致。
python
# 设置推理的输入数据,返回值非 0 则报错
result = interpreter.set_input_tensor(in_tensor_tag=1, input_data=obj)
# result = interpreter.set_input_tensor(in_tensor_tag="input_tensor_name", input_data=obj)
# result = interpreter.set_input_tensor(in_tensor_tag=1, input_data=obj, is_native=True)
if result != 0:
    print("interpreter->set_input_tensor() failed.")
    return False

执行推理 invoke() ​

设置输入数据之后,接下来的步骤自然就是对输入数据执行推理运行过程。

API invoke
描述 执行推理运算过程
参数 无
返回 正常:0
异常:非 0
python
# 执行推理运行操作,返回值非 0 则报错
result = interpreter.invoke()
if result != 0:
    print("sample : interpreter->invoke() failed.")
    return False

获取输出数据 get_output_tensor() ​

推理完成之后,就需要将推理得到的结果数据取出来。之前介绍流程时提到,取出结果数据之后,就可以对这些结果数据进行处理,判断结果是否正确。

API get_output_tensor
描述 推理成功之后,获取推理结果数据
参数 out_tensor_tag:结果输出 tensor 的索引值或者名称字符串,类型为 int 或者 str
output_type:结果输出的目标数据类型,可选参数,不传默认为 aidlite.DataType.TYPE_FLOAT32
可选参数 is_native:是否直接按后端原生的数据类型格式返回底层输出字节视图;默认值为 False
返回 正常:numpy.ndarray 结果数据。
异常:None。
说明 1. 参数 out_tensor_tag 从 AidliteSDK 版本号 2.2.5 开始支持字符串
2. `output_type` 用于将底层 `uint8` 结果按目标数据类型重新解释,不会额外拷贝数据
3. 对于 SNPE/QNN,默认接口通常返回 float32 语义的数据;如果使用原生格式接口,则需要按后端真实输出格式自行解析数据类型。
python
# 获取推理结果数据,返回值为 numpy.ndarray
out_data = interpreter.get_output_tensor(out_tensor_tag=1, output_type=aidlite.DataType.TYPE_INT32)
# out_data = interpreter.get_output_tensor(out_tensor_tag="output_tensor_name", output_type=aidlite.DataType.TYPE_INT32)
# out_data = interpreter.get_output_tensor(out_tensor_tag=1, is_native=True)
if out_data is None:
    print("interpreter->get_output_tensor() failed.")
    return False

资源释放 destroy() ​

前面提到解释器对象需要执行 init() 初始化操作和 load_model() 加载模型的操作,相应的,解释器也需要执行一些释放操作,将之前创建的资源予以销毁。

API destroy
描述 完成必要的释放操作
参数 无
返回 正常:0
异常:非 0
python
# 执行解释器释放过程,返回值非 0 则报错
result = interpreter.destroy()
if result != 0:
    print("sample : interpreter-> destroy() failed.")
    return False

解释器创建类 class InterpreterBuilder ​

统一的解释器 Interpreter 对象的创建函数,通过此类来创建所需的解释器对象。

构建解释器 build_interpreter_from_path() ​

构建推理解释器对象,可以提供不同的参数,最简单的就是只提供模型文件的路径和名称。如果模型框架(如 SNPE、TFLite 等)只需一个模型文件,则调用此接口。

API build_interpreter_from_path
描述 通过模型文件的路径名称,直接创建对应的解释器对象
参数 model_path:模型文件的路径名称
返回 正常:Interpreter 对象实例
异常:None
python
# 传入 Model 文件路径来构建解释器,返回值为 None 则报错
interpreter = aidlite.InterpreterBuilder.build_interpreter_from_path(model_path=r"./640.dlc")
if interpreter is None:
    print("Create Interpreter failed !")
    return False

构建解释器 build_interpreter_from_path() ​

构建推理解释器对象,可以提供不同的参数,最简单的就是只提供模型文件的路径和名称。如果模型框架(如 NCNN、TNN 等)涉及两个模型文件,则调用此接口。

API build_interpreter_from_path
描述 通过模型文件的路径名称,直接创建对应的解释器对象
参数 model_struct_path:模型结构文件的路径名称
model_weight_path:模型权重参数文件的路径名称
返回 正常:Interpreter 对象实例
异常:None

构建解释器 build_interpreter_from_model() ​

构建推理解释器对象,除了提供模型文件路径之外,也可以提供 Model 对象,这样不仅可以设置模型文件的路径名称,还可以设置模型的输入输出数据类型和输入输出数据的 shape 信息。

API build_interpreter_from_model
描述 通过传入 Model 对象来创建对应的解释器对象。而 Config 相关涉及的参数都使用默认值
参数 model:Model 类型的对象,包含模型相关的数据
返回 正常:Interpreter 对象实例
异常:None
python
# 传入 Model 对象来构建解释器,返回值为 None 则报错
interpreter = aidlite.InterpreterBuilder.build_interpreter_from_model(model=model)
if interpreter is None:
    print("Create Interpreter failed !")
    return False

构建解释器 build_interpreter_from_model_and_config() ​

构建推理解释器对象,除了前述的两种方式,也可以同时提供 Model 对象和 Config 对象,这样不仅可以提供模型相关信息,还可以提供更多的运行时配置参数。

API build_interpreter_from_model_and_config
描述 通过传入 Model 对象和 Config 来创建对应的解释器对象。
参数 model:Model 类型的对象,包含模型相关的数据
config:Config 类型的对象,包含一些配置参数
返回 正常:Interpreter 对象实例
异常:None
python
# 传入 Model 和 Config 对象来构建解释器,返回值为 None 则报错
interpreter = aidlite.InterpreterBuilder.build_interpreter_from_model_and_config(model=model, config=config)
if interpreter is None:
    print("Create Interpreter failed.")
    return False

其他方法 ​

获取 SDK 版本信息 get_library_version() ​

API get_library_version
描述 用于获取当前 Aidlite-SDK 的版本相关信息
参数 无
返回 返回值为当前 Aidlite-SDK 的版本信息字符串

获取 Python SDK 版本信息 get_py_library_version() ​

API get_py_library_version
描述 用于获取当前 Py-Aidlite-SDK 的版本相关信息
参数 无
返回 返回值为当前 Py-Aidlite-SDK 的版本信息字符串

设置日志级别 set_log_level() ​

API set_log_level
描述 设置当前的最低日志级别,输出大于等于该日志级别的日志数据。默认打印输出 WARNING 及以上级别的日志。
参数 log_level:类型 LogLevel 的取值
返回 默认返回 0 值

日志输出到标准终端 log_to_stderr() ​

API log_to_stderr
描述 设置日志信息输出到标准错误终端
参数 无
返回 默认返回 0 值

日志输出到文本文件 log_to_file() ​

API log_to_file
描述 设置日志信息输出到指定的文本文件
参数 path_and_prefix:日志文件的存放路径与名称前缀
also_to_stderr:标识是否同时输出日志到 stderr 终端,默认值为 False
返回 正常:0
异常:非 0

获取最近日志信息 last_log_msg() ​

API last_log_msg
描述 获取当前某个日志级别的最新日志信息,通常获取最新的错误信息
参数 log_level:类型 LogLevel 的取值
返回 最新日志信息

AidLite Python 示例程序 ​

💡注意

使用 Aidlite-SDK 开发需要了解如下事项:

Aidlite 的功能实现分为两个部分,软件包 Aidlite-SDK 是为开发者提供接口的,而不同框架的推理功能则是由不同的后端软件包(如Aidlite-QNN236等)提供。

示例程序由后端推理软件包提供,示例程序随软件包安装,如 Aidlite-QNN236 的示例程序路径如下:

  • cpp 示例程序路径:/usr/local/share/aidlite/examples/aidlite_qnn236/cpp/
  • Python 示例程序路径:/usr/local/share/aidlite/examples/aidlite_qnn236/python/

以后端程序 Aidlite-QNN236 为例,其 Python 示例程序大致包含如下几个部分:

初始化配置与模型加载 ​

如果开发者对模型推理有所了解,或者是看过 Aidlite API 接口文档,那么必然会知道,在真正实现推理操作之后,通常都需要设置一些关键信息,然后再为推理框架加载所需的模型文件。

python
# 此处可以使用不同数据精度的模型文件
resource_dir = "../data/qnn_yolov5_multi"
model_name = "cutoff_yolov5s_640_sigmoid_w8a8.qnn236.ctx.bin"

# 创建 Model 对象实例,可以设置模型相关的信息
model_path = os.path.join(resource_dir, model_name)
model = aidlite.Model.create_instance(model_path)
if model is None:
    print("Create model failed.")
    return False

# 创建 Model 对象实例
config = aidlite.Config.create_instance()
if config is None:
    print("Create config failed.")
    return False

# 配置一些运行时所需要的参数
config.framework_type = aidlite.FrameworkType.TYPE_QNN236
if acc_type == 1:
    config.accelerate_type = aidlite.AccelerateType.TYPE_CPU
elif acc_type == 2:
    config.accelerate_type = aidlite.AccelerateType.TYPE_GPU
elif acc_type == 3:
    config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
else:
    return show_help_prompt()

# 创建推理所需的解释器对象
interpreter = aidlite.InterpreterBuilder.build_interpreter_from_model_and_config(model, config)
if interpreter is None:
    print("build_interpreter_from_model_and_config failed.")
    return None

# 完成资源初始化的操作
result = interpreter.init()
if result != 0:
    print("interpreter init failed.")
    return False

# 完成模型的加载操作
result = interpreter.load_model()
if result != 0:
    print("interpreter load model failed.")
    return False

在上述示例代码中,开发者可以提供 不同精度的模型文件(包括非量化的 float32 模型、量化的 int8 模型等) 来创建 Model 对象。相应的,开发者也需要为此指定不同的加速硬件,也就是需要设置 Config 对象的 accelerate_type 成员变量的值。利用 Model 对象和 Config 对象创建推理所需的解释器,然后即可完成所需的初始化、模型加载的操作。

输入数据的前处理 ​

一般来讲,模型推理所需的输入数据需要满足一定的要求,所以就需要对已有的输入数据做一些处理,使其可以被模型利用。

python
# 使用 Opencv 读取图片数据
frame = cv2.imread(image_path)

# 输入图像的前处理操作
# ... ...

# 取得 Opencv Mat 对象所含的图像数据。
input_tensor_data = frame.data

前处理部分的内容究竟怎么实现,完全取决于开发者使用的模型需要什么样的输入数据。 示例程序中的前处理操作,就是针对我们示例程序提供的模型文件所适配的。

完成推理操作 ​

前处理操作完成之后,就可以将得到的数据传入给解释器,解释器就可以利用这些数据来完成推理任务,而在推理完成之后,开发者需要取出推理操作的结果数据。

python
# 将前处理完成后的数据传递给解释器对象
# result = interpreter.set_input_tensor(0, input_tensor_data)
result = interpreter.set_input_tensor("images", input_tensor_data)
if result != 0:
    print("interpreter set_input_tensor() failed.")
    return False

# 执行推理过程
result = interpreter.invoke()
if result != 0:
    print("interpreter set_input_tensor() failed.")
    return False

# 模型有三个输出 Tensor ,所以需要获取三个 Tensor 的输出数据。
# stride8 = interpreter.get_output_tensor(0)
stride8 = interpreter.get_output_tensor("_326")
if stride8 is None:
    print("sample : interpreter->get_output_tensor() 0 failed.")
    return False

# stride16 = interpreter.get_output_tensor(1)
stride16 = interpreter.get_output_tensor("_364")
if stride16 is None:
    print("sample : interpreter->get_output_tensor() 1 failed.")
    return False

# stride32 = interpreter.get_output_tensor(2)
stride32 = interpreter.get_output_tensor("_402")
if stride32 is None:
    print("sample : interpreter->get_output_tensor() 2 failed.")
    return False

前处理完成之后,就可以将输入数据给到解释器,由解释器完成推理任务,进而返回结果数据。

💡注意

QNN 和 SNPE 的普通低层接口默认使用 FP32 数组。 支持原生数据模式的后端,可按张量信息使用原生数组。 使用 REMOTE 时,先确认 Android 服务支持该数据模式。 使用 AutoModel 时,保留原模型要求的数据类型。 包装层按已验证的模型接口处理必要的转换。

输出数据的后处理 ​

一般来讲,模型推理结束之后,输出的结果数据不会是我们最终想要的数据,还需要做进一步的加工才是开发者所需要的,这就是后处理操作。

python
# 输出数据的后处理操作
# ... ...

与前处理操作同理,后处理部分的内容究竟怎么实现,完全取决于开发者需要对推理结果数据做什么样的分析处理。 示例程序中的后处理操作,就是针对我们示例程序提供的模型文件所适配的。

资源释放 ​

当开发者不再需要 Aidlite 解释器来完成推理任务时,可以显示地完成资源释放操作。

python
result = interpreter.destroy()
if result != 0:
    print("interpreter set_input_tensor() failed.")
    return False

至此,已经展示了使用 Aidlite 做模型推理的全部流程,开发者只需要根据自己的模型做对应的修改,即可完成推理任务。