公司动态
【地平线J6工具链入门教程】J6工具链模型X86推理方式说明
J6工具链模型X86推理方式说明X86 推理是指 开发机X86 CPU/GPU上针对不同阶段的模型ONNX模型、Hbir模型和hbm模型进行相应的推理验证。绝大多数的推理验证不需要实际开发板但是使用hbm_infer需要board_ip来连续开发板。以下是工具链常见的几种推理方式说明。ONNX模型HBRuntime推理库HBRuntime是地平线提供的一套x86端模型推理库支持PTQ链路各阶段产出的ONNX模型进行推理并通过dict的数据格式传入推理接口中。使用流程详见如下链HBRuntime推理库。使用示例如下import numpy as np # 加载地平线依赖库 from horizon_tc_ui.hb_runtime import HBRuntime # 准备模型运行的输入此处input.npy为处理好的数据 data np.load(input.npy) # 加载模型文件根据实际模型进行设置 # ONNX模型 sess HBRuntime(model.onnx) # 获取输入输出节点名称 input_names sess.input_names output_names sess.output_names # 准备输入数据根据实际输入类型和layout进行准备配置格式要求为字典形式输入名称和输入数据组成键值对 # 如模型仅有一个输入 input_feed {input_names[0]: data} # 直接获取字符串列表 # 如模型有多个输入 input_feed {input_names[0]: data1, input_names[1]: data2} # 进行模型推理推理的返回值是一个list依次与output_names指定名称一一对应 output sess.run(output_names, input_feed)ORTExecutorORTExecutor 是 HMCTHorizon Model Convert Toolkit提供的 ONNX 模型推理封装接口底层基于onnxruntime。import numpy as np import onnx from hmct.api import ORTExecutor # 1. 加载 ONNX 模型 onnx_model onnx.load(model.onnx) # 需要 onnx.ModelProto 对象 # 2. 创建 ORTExecutor executor ORTExecutor(onnx_model) # 3. 创建 Session session executor.create_session() # 4. 获取输入输出信息 inputs executor.get_inputs() # list[NodeArg] outputs executor.get_outputs() # list[NodeArg] # 5. 推理返回 Dict[str, np.ndarray] input_feed {inputs[0].name: data)} # 通过 NodeArg.name 获取 result executor.inference(input_feed) # Dict: {output_name: ndarray}Hbir 模型 (.bc)编译器feed接口feed() 是 hbdk4.compiler 中 Function 对象的方法用于对 hbir即.bc 模型进行推理。接口信息详见模型推理使用示例需要注意的是feed()只接受 np.ndarray 和 torch.Tensor 两种 Python 对象类型。.npy的输入数据不能直接传给该接口需要先 np.load() 加载成 np.ndarray。该接口所需要的输入格式和输出格式一致均包装成字典。使用示例如下import numpy as np from hbdk4.compiler import load # 加载 BC 模型 model load(model.bc) fn model.functions[0] # 查看输入输出信息 for i in fn.flatten_inputs: print(f输入: {i.name}, shape{i.type.shape}, dtype{i.type.torch_dtype}) for o in fn.flatten_outputs: print(f输出: {o.name}, shape{o.type.shape}, dtype{o.type.torch_dtype}) # 从 npy 文件加载输入数据 input_data np.load(input.npy) # 准备输入并推理 output fn.feed({fn.flatten_inputs[0].name: input_data}) # output 是 Dict[str, np.ndarray] print(output[fn.flatten_outputs[0].name].shape)HBRuntime推理库HBRuntime是地平线提供的一套x86端模型推理库支持对转换过程中产出的HBIRbc模型进行推理并通过dict的数据格式传入推理接口中。使用流程详见如下链HBRuntime推理库。推理的原理是基于hbdk4 的 load() function.feed()。因此需要注意hbdk的版本是否匹配。使用示例如下import numpy as np # 加载地平线依赖库 from horizon_tc_ui.hb_runtime import HBRuntime # 准备模型运行的输入此处input.npy为处理好的数据 data np.load(input.npy) # 加载模型文件根据实际模型进行设置 # HBIR模型 sess HBRuntime(model.bc) # 获取输入输出节点名称 input_names sess.input_names output_names sess.output_names # 准备输入数据根据实际输入类型和layout进行准备配置格式要求为字典形式输入名称和输入数据组成键值对 # 如模型仅有一个输入 input_feed {input_names[0]: data} # 如模型有多个输入 input_feed {input_names[0]: data1, input_names[1]: data2} # 进行模型推理推理的返回值是一个list依次与output_names指定名称一一对应 output sess.run(output_names, input_feed)hrt_model_exec使用 X86 版本的 hrt_model_exec 工具进行模型信息查看和单帧推理支持推理 quantized.bc 模型及 hbm 模型相同quantized.bc编译的hbm可以使用相同输入文件进行推理。hrt_model_exec详细介绍与使用示例请参考 hrt_model_exec工具介绍 。该工具推理功能支持多输入模型的推理支持图片输入、二进制文件输入、文本文件输入及NumPy数组文件输入输入数据用逗号隔开。 模型的输入信息可以通过 model_info 进行查看。hrt_model_exec工具模型输入说明详见模型输入说明章节。X86 仿真环境使用 hrt_model_exec 工具推理 quantized.bc但需要 hbdk4相关的库 和 hrt_model_execUCP的版本要匹配如UCP 3.14.7 配套 HBDK 4.9.7。需要注意的是板端的hrt_model_exec不支持推理quantized.bc。# 1、不加 dump只跑推理看时间 # --frame_count 1 只跑一帧 default为200 hrt_model_exec infer --model_file simple_quantized_model.bc --input_file input.npy --frame_count 1 # 2、加 dump需要验证一致性的时候额外保存输入输出文件 hrt_model_exec infer \ --model_file simple_quantized_model.bc \ --input_file input.npy \ --frame_count 1 \ --enable_dump true \ --dump_path /tmp/output_dir # 3、该工具还支持反量化输出和去除 Padding hrt_model_exec infer \ --model_file model.bc \ --input_file input.npy \ --frame_count 1 \ --enable_dump true \ --dequantize_process true \ --remove_padding_process true该命令还有以下两个关键的参数配置--dump_format来控制模型的输出格式默认为bin的输出。--dump_precision控制txt 格式时的小数精度默认 9 位。其他参数配置详见参数说明章节。UCP推理库(C)注意X86 上推理hbm是指令级仿真速度非常慢。推荐推理 quantized.bc定点部分和 hbm 二进制一致。使用 UCP 推理接口进行验证代码的开发支持推理 quantized.bc 模型及 hbm 模型。UCP 仿真库接口与嵌入式接口完全一致只是采用了不同的编译配置。X86 仿真环境使用 UCP 推理接口推理 hbm 模型前需要设置 HB_UCP_SIM_PLATFORM_TYPE 环境变量用以指定要模拟的 BPU 架构。板端链接deps_aarch64/ucp/lib/libhbucp.so X86链接 deps_x86/ucp/lib/libhbucp.so ← 换这个 # 1. 设置仿真平台类型必需否则不知道仿真哪个架构 export HB_UCP_SIM_PLATFORM_TYPEnash-e # J6E # export HB_UCP_SIM_PLATFORM_TYPEnash-m # J6MUCP 推理接口使用示例请参考 模型推理应用开发指导 章节。hbm 模型注意X86 上推理hbm是指令级仿真速度非常慢。推荐推理 quantized.bc定点部分和 hbm 二进制一致。因此只建议使用3.1节的方式进行推理。其他方法仅做示例补充了解即可。hbm_inferhbm_infer是一个X86板端联合通信模式的Validation工具在X86端使用Python代码做模型前后处理工作由板端Server执行实际推理过程用于提升模型精度评测效率降低开发成本。和其他的python推理接口一样传入的数据形状只需要和模型的输入validShape 一致即可不需要padding。使用流程详见如下链接hbm_infer工具用户只需传 host local_hbm_path 即可一键完成 SSH部署 文件上传 gRPC连接。使用demo如下import time import torch from hbm_infer.hbm_rpc_session import HbmRpcSession def run_hbm_infer(run_epoch10): # 创建session sess HbmRpcSession( hostavailable_ip, local_hbm_pathlocal_hbm_path ) # 准备输入数据 input_data { img: torch.ones((1, 3, 224, 224), dtypetorch.int8) } # 执行推理并返回结果 for i in range(run_epoch): output_data sess(input_data) print([output_data[k].shape for k in output_data]) # 关闭server sess.close_server() if __name__ __main__: run_hbm_infer()使用该工具推理需要注意输入的合法性检查以及数据预处理相关操作合法检查名称检查input dict 的 key 必须与 get_input_info() 返回的输入名称完全匹配。类型检查不显式做数据类型强制转换需要用户保证 tensor_type与模型预期一致。shape 检查需要用户确保 shape 与模型的 valid_shape 匹配动态维度用 input_valid_shape 或 input_stride 指定。数据预处理建议对于 NV12 等 Pyramid/Resizer 输入hbm_infer 不会自动做颜色空间转换或归一化用户需按 input_type_rt 准备好数据如将 RGB 转为 Y/UV 分量的 NV12 格式。如果配置了 mean_value/scale_value这些归一化由模型内部完成用户不需要手动减均值除方差。编译器feed接口不推荐feed() 是 hbdk4.compiler 中 Function 对象的方法用于对hbm模型进行推理。接口信息详见模型推理使用示例具体使用方式和输入输出信息和见本文21节。针对该接口的输入的合法性检查以及数据预处理需注意合法检查由 hbdk runtime 做数据类型校验输入的 numpy dtype 必须与模型预期的 tensor_type 兼容。Shape 校验静态维度必须完全匹配动态维度同样需要满足 shape 约束不匹配时会抛出异常。数量校验输入 tensor 的数量必须与模型定义一致。没有隐式的布局转换NCHW/NHWC需要用户按模型预期准备。数据预处理同 hbm_infer的相关方式。HBRuntime推理库不推荐HBRuntime是地平线提供的一套x86端模型推理库支持对地平线工具链转换过程中产出的HBM模型进行推理并通过dict的数据格式传入推理接口中。HBRuntime是X86端推理库你传入的数据形状只需要和模型的输入一致即可不需要padding。使用流程详见如下链HBRuntime推理库。HB_HBMRuntime 底层会加载 hbdk4-runtime 的动态库因此需要注意hbdk的版本是否匹配。使用示例如下import numpy as np # 加载地平线依赖库 from horizon_tc_ui.hb_runtime import HBRuntime # 准备模型运行的输入此处input.npy为处理好的数据 data np.load(input.npy) # 加载模型文件根据实际模型进行设置 # HBM模型 sess HBRuntime(model.hbm) # 获取输入输出节点名称 input_names sess.input_names output_names sess.output_names # 准备输入数据根据实际输入类型和layout进行准备配置格式要求为字典形式输入名称和输入数据组成键值对 # 如模型仅有一个输入 input_feed {input_names[0]: data} # 如模型有多个输入 input_feed {input_names[0]: data1, input_names[1]: data2} # 进行模型推理推理的返回值是一个list依次与output_names指定名称一一对应 output sess.run(output_names, input_feed)合法检查输入 tensor 数量检查feed dict 中提供的输入数量必须与模型输入数量一致。输入名称匹配feed 的 key 必须匹配模型注册的输入名称。数据类型对齐如果 feed 的数据类型与模型预期的 tensor_type 不匹配runtime 会尝试隐式转换或报错。Shape 校验静态 shape 必须完全匹配动态 shape 需要满足 valid_shape 约束。数据预处理同 hbm_infer的相关方式。hrt_model_exec仅推荐模型信息查看hrt_model_exec使用方式和板端相同但需要配置HB_UCP_SIM_PLATFORM_TYPE环境变量用以指定要模拟的 BPU 架构具体可参考hrt_model_exec infer使用示例。# 推理hbm需要设置仿真平台 export HB_UCP_SIM_PLATFORM_TYPEnash-e # J6E # export HB_UCP_SIM_PLATFORM_TYPEnash-m # J6M推理接口的详细链接如下模型推理鉴于 hbm 在 X86 端推理速度较慢因此只建议在 X86端查看model_info。具体可参考hrt_model_exec model_info使用示例