专栏中心

EEPW首页 > 专栏 > bc 与 hbm 一致性比对

bc 与 hbm 一致性比对

发布人:地平线开发者 时间:2024-12-15 来源:工程师 发布文章

01 引言


使用地平线 征程 6 算法工具链时,算法侧在验证 quantized.bc 精度符合预期后,软件侧反馈 hbm 精度不符合预期,此时应该怎么做呢?(“打一架!”)


对于熟悉地平线算法工具链的用户而言,可能会立刻想到,使用 hb_verifier 工具比对 bc 与 hbm 的一致性即可,so easy!


但对于不太熟悉的同学,可能会遇到如下问题:


  1. hb_verifier 工具怎么用?

  2. 输入数据怎么准备?准备几个输入?准备什么 shape?什么 type?


为了结合用户的疑问详细介绍该过程,本文会举个非常详细的例子来介绍。有没有比 hb_verifier 更“优雅”的比对方式?当然是有的,欢迎往下看。



02 模型定义


quantized.bc 与 hbm 可以分为以下几类:


  • convert 后什么都不做的:quantized_stage1.bc,对应 quantized_stage1.hbm


图片


  • 在 stage1 的基础上,插入前处理 nv12 节点的:quantized_nv12_stage2.bc,对应 quantized_nv12_stage2.hbm


图片


  • 在 stage2 的基础上,删除尾部反量化节点的:quantized_nv12_remove_stage3.bc,对应 quantized_nv12_remove_stage3.hbm


图片


理论上,大家直接比对 stage3.bc 与 stage3.hbm 的一致性即可,而这一步,也是最复杂的。



03 hb_verifier 简介


hb_verifier 比对 bc 与 hbm 一致性时,需要关注的信息如下:


图片


bc 与 hbm 一致性比对时,输出信息如下:


图片



本文的例子中,命令如下:


hb_verifier -m quantized_nv12_remove_stage3.bc,quantized_nv12_remove_stage3.hbm -i y_data.npy,uv_data.npy



04 输入数据准备


在地平线 docker 中,可以使用 hb_model_info 查看 bc 以及 hbm 的输入信息,或在 docker/开发板上使用 hrt_model_exec 工具查看模型输入信息,然后根据终端打印的模型输入数量、输入类型来准备输入数据,以 quantized_nv12_remove_stage3.bc/quantized_nv12_remove_stage3.hbm 为例,来准备输入数据。


hb_model_info quantized_nv12_remove_stage3.bc
hb_model_info quantized_nv12_remove_stage3.hbm


图片图片


输入数据准备的代码如下:


from PIL import Image
import numpy as np

def generate_nv12(img):
   w,h = img.size
   # Convert images to YUV format
   yuv_img = img.convert('YCbCr')
   y_data, u_data, v_data = yuv_img.split()

   # Convert Y, U, and V channel data to byte streams
   y_data_bytes = y_data.tobytes()
   u_data_bytes = u_data.resize((u_data.width // 2, u_data.height // 2)).tobytes()
   v_data_bytes = v_data.resize((v_data.width // 2, v_data.height // 2)).tobytes()

   # Arrange the UV data in the form of UVUVUVUV...
   uvuvuv_data = bytearray()
   for u_byte, v_byte in zip(u_data_bytes, v_data_bytes):
       uvuvuv_data.extend([u_byte, v_byte])

   # Input for the hbir model
   y = np.frombuffer(y_data_bytes, dtype=np.uint8).reshape(1, h, w, 1).astype(np.uint8)
   np.save("y_data.npy", y)
   uv = np.frombuffer(uvuvuv_data, dtype=np.uint8).reshape(1, h//2, w//2, 2).astype(np.uint8)
   np.save("uv_data.npy", uv)
   return y, uv

if __name__ == "__main__":
   # Create a random image with the shape (1, 512, 960, 3)
   # Generate random RGB values in the range 0-255
   image_data = np.random.randint(0, 256, (512, 960, 3), dtype=np.uint8)

   # Convert the numpy array to a PIL image
   img = Image.fromarray(image_data)
   y, uv = generate_nv12(img)


述代码只介绍了 NV12 输入时,如何准备输入数据,对于 int8、int16、bool 等类型如何准备输入数据呢?

import numpy as np
# 定义所有输入数据的形状和数据类型
data_dict = {
   'A_input': {'shape': (1, 32, 16), 'dtype': np.int8},
   'B_input': {'shape': (1, 1, 320, 4), 'dtype': np.int16},
   'C_input': {'shape': (32, 10, 10), 'dtype': np.bool_},
}

# 生成数据并保存为 .npy 文件
for idx, (name, info) in enumerate(data_dict.items()):
   shape = info['shape']
   dtype = info['dtype']
   # 生成随机数据
   data = np.random.randint(0, 100, size=shape, dtype=dtype) if dtype == np.int16 else np.random.choice([True, False], size=shape)
   # 保存为 .npy 文件,文件名前加上编号
   np.save(f"{idx}_{name}.npy", data)
   print(f"Saved {idx}_{name}.npy")



05 hb_verfier 比对 bc 与 hbm 一致性


此时有模型:quantized_nv12_remove_stage3.bc,quantized_nv12_remove_stage3.hbm,有输入数据:y_data.npy,uv_data.npy。


在地平线征程 6 工具链提供的 docker 中,运行如下命令:

hb_verifier -m quantized_nv12_remove_stage3.bc,quantized_nv12_remove_stage3.hbm -i y_data.npy,uv_data.npy


结果如下:


图片


可以发现,二者输出一致。



06 优雅的方案


使用一套数据,在 docker 中推理 bc 与 hbm,并比对一致性的 python 代码如下:

from hbdk4.compiler import load, Hbm
import numpy as np
from PIL import Image

def generate_nv12(img):
   w,h = img.size
   # Convert images to YUV format
   yuv_img = img.convert('YCbCr')
   y_data, u_data, v_data = yuv_img.split()

   # Convert Y, U, and V channel data to byte streams
   y_data_bytes = y_data.tobytes()
   u_data_bytes = u_data.resize((u_data.width // 2, u_data.height // 2)).tobytes()
   v_data_bytes = v_data.resize((v_data.width // 2, v_data.height // 2)).tobytes()

   # Arrange the UV data in the form of UVUVUVUV...
   uvuvuv_data = bytearray()
   for u_byte, v_byte in zip(u_data_bytes, v_data_bytes):
       uvuvuv_data.extend([u_byte, v_byte])

   # Input for the hbir model
   y = np.frombuffer(y_data_bytes, dtype=np.uint8).reshape(1, h, w, 1).astype(np.uint8)
   # np.save("y_data.npy", y)
   uv = np.frombuffer(uvuvuv_data, dtype=np.uint8).reshape(1, h//2, w//2, 2).astype(np.uint8)
   # np.save("uv_data.npy", uv)
   return y, uv

def compare_arrays(array1, array2, decimal_places=2):
   """
   Compare two arrays for consistency up to a specified number of decimal places.

   Parameters:
   - array1: First numpy array.
   - array2: Second numpy array.
   - decimal_places: Number of decimal places to consider for alignment.

   Returns:
   - are_equal: True if arrays are consistent up to the specified decimal places, False otherwise.
   - max_difference: Maximum difference (absolute value) if arrays are not consistent, else 0.
   """
   # Round the arrays to the specified decimal places
   rounded1 = np.round(array1, decimals=decimal_places)
   rounded2 = np.round(array2, decimals=decimal_places)
   
   # Check equality
   are_equal = np.array_equal(rounded1, rounded2)
   
   # Calculate maximum difference if not equal
   max_difference = 0
   if not are_equal:
       max_difference = np.max(np.abs(array1 - array2))
   
   return are_equal, max_difference

hbir = load("./quantized_nv12_remove_stage3.bc")
hbm = Hbm("./quantized_nv12_remove_stage3.hbm")

# Create a random image with the shape (1, 512, 960, 3)
# Generate random RGB values in the range 0-255
image_data = np.random.randint(0, 256, (512, 960, 3), dtype=np.uint8)
# Convert the numpy array to a PIL image
img = Image.fromarray(image_data)
y, uv = generate_nv12(img)

inputs = {"input_0_y": y, "input_0_uv": uv}

# 分别进行hbir和Hbm推理
hbir_outputs = hbir[0].feed(inputs)
# print("hbir_outputs:", hbir_outputs)
hbm_x86_outputs = hbm[0].feed(inputs)
# print("hbm_x86_outputs:", hbm_x86_outputs)

# 比较Hbir和hbm输出
for idx, v in enumerate(hbir[0].outputs):
   hbir_data = hbir_outputs[v.name]
   hbm_x86_data = hbm_x86_outputs[v.name]

   # Compare arrays
   are_equal, max_difference = compare_arrays(hbir_data, hbm_arrch64_data, decimal_places=4)
   if not are_equal:
       print("Maximum difference:", max_difference)
   else:
       print(f"outputs[{idx}] is equal!")




专栏文章内容及配图由作者撰写发布,仅供工程师学习之用,如有侵权或者其他违规问题,请联系本站处理。 联系我们

关键词: 算法 自动驾驶 算法工具链 地平线 征程5

相关推荐

自动驾驶的现状与未来(节选)

视频 2020-03-16

简单实用的单片机CRC 快速算法

资源下载 2007-02-16

加密算法之MD5算法

掘金自动驾驶,不要把大坑当机会

汽车电子 2026-04-17

Ouster推出 Rev8 OS 激光雷达系列 原生彩色激光雷达正式落地

面向算法硬件加速的FPGA实现方法

加快实现自动驾驶(完整小组讨论)

视频 2020-06-12

2035年自动驾驶出租车市场规模将达1680亿美元

汽车电子 2026-04-21

数字PID控制算法之一

资源下载 2007-12-28

地平线征程 6 系列集成 Cadence Tensilica Vision DSP,实现规模化量产,合作加速智能驾驶解决方案部署

自动驾驶正推动汽车行业加速布局人形机器人

高阶智驾要落地,线控底盘为什么必须执行得准

曲面显示屏取代传统汽车挡风玻璃

PID算法

资源下载 2007-02-16

76-81GHz自动驾驶CMOS RADAR

视频 2018-05-31

实时训练驾驶人工智能

携手ADI赢得未来

视频 2019-11-08

特斯拉监督版FSD加入中国市场

2026-05-22

CRC算法原理及C语言实现

资源下载 2007-02-16

ADI:传感技术助力未来自动驾驶的发展

视频 2020-03-16
更多 培训课堂
更多 焦点
更多 视频

技术专区