征程 6 工具链 BEVPoolV2 算子使用教程 【2】-BEVPoolV2 QAT 链路实现示例

1.引言

在上一篇帖子中,我们已详尽阐述了 BEVPoolV2 相较于 BEVPoolV1 的改进之处,并对 BEVPoolV2 实现的代码进行了解析。想必大家对 BEVPoolV2 算子的功能及实现已有了一定程度的理解,此篇帖子将展示 征程 6 工具链 BEVPoolV2 单算子 QAT 链路的实现范例,以进一步增进用户对 BEVPoolV2 算子使用的认知。

2.QAT 代码实现

征程 6 工具链对齐 mmdet3d 的实现,目前已经支持了 BEVPoolV2 算子,QAT 链路中的核心函数如下:

def bev_pool_v2(depth: Tensor,feat: Tensor,ranks_depth: Tensor,ranks_feat: Tensor,ranks_bev: Tensor,interval_starts: Tensor,interval_lengths: Tensor,bev_feat_shape,
):"""BEVPoolv2 implementation for Lift-Splat-Shoot view transformation.This impl is same as following 
exceptthe layout of inout feature:https://github.com/HuangJunJie2017/BEVDet/blob/dev3.0/mmdet3d/ops/bev_pool_v2/bev_pool.pyArgs:depth (Tensor[b, n, d, h, w]): Input depth.feat (Tensor[b, n, c, h, w]): Input features.ranks_depth (Tensor[n_points]): Depth index of points.ranks_feat (Tensor[n_points]): Feat index of points.ranks_bev (Tensor[n_points]): Output index of points.interval_starts (Tensor[n_pillars]): Starting position in ranks_xxx for each pooled point.  # noqa: E501interval_lengths (Tensor[n_pillars]): How many points in each pooled point.  # noqa: E501bev_feat_shape: Output shape in [b, z_out, h_out, w_out, c] or[z_out, h_out, w_out] or [h_out, w_out] format.When z_out is not given, its value will be 1 by default.Returns:Tensor[b, c, z_out, h_out, w_out]: Output features."""if len(bev_feat_shape) not in (2, 3, 5):raise ValueError("Illegal bev_feat_shape length")if len(bev_feat_shape) < 5:bev_feat_shape = tuple(bev_feat_shape)if len(bev_feat_shape) == 2:bev_feat_shape = (1,) + bev_feat_shapeb = feat.size(0)c = feat.size(2)bev_feat_shape = (b,) + tuple(bev_feat_shape) + (c,)if has_torch_function((depth, feat)):return handle_torch_function(bev_pool_v2,(depth, feat),depth,feat,ranks_depth,ranks_feat,ranks_bev,interval_starts,interval_lengths,bev_feat_shape, )x = torch.ops.horizon.bev_pool_v2(depth,feat,ranks_depth,ranks_feat,ranks_bev,interval_starts,interval_lengths,bev_feat_shape,)return x

docker 中代码路径: /usr/local/lib/python3.10/dist-packages/horizon_plugin_pytorch/nn/bev_pool_v2.py

详细说明 BEVPoolV2 算子在整个 QAT 链路使用流程

下面我们将以一个简单的单算子示例来详细说明 BEVPoolV2 算子在整个 QAT 链路使用流程。

首先,我们需要了解 QAT 链路的基本概念和工作原理,读者可以自行去学习 征程 6 工具链用户手册的快速上手章节。接下来,我们将详细介绍 BEVPoolV2 算子在 QAT 链路中的使用流程,涉及模型搭建、QAT 模型改造、模型导出与编译等。

本示例只为演示流程,未涉及到浮点训练和量化训练等流程。

3.输入准备

在进行 演示 QAT 链路之前,我们首先进行输入数据构建,这里要特别注意的是, BEVPoolV2 算子的性能和输入索引强相关,建议构建模型的时候使用真实输入。后面会结合代码进行说明。

4.示例代码

本示例代码基本遵循以下图中的 QAT 链路流程:

import copy
import torch
import torch.nn as nn
import numpy as np
from horizon_plugin_pytorch.nn.bev_pool_v2 import BevPoolV2
from horizon_plugin_pytorch.quantization.hbdk4 import export
from torch.quantization import DeQuantStub
from horizon_plugin_pytorch.quantization import (QuantStub,set_fake_quantize,FakeQuantState,
)
from horizon_plugin_pytorch.quantization.qconfig_template import default_calibration_qconfig_setter
from horizon_plugin_pytorch.quantization.prepare import prepare, PrepareMethod
from horizon_plugin_pytorch.march import March, set_march
from hbdk4.compiler import convert, compile, save
def load_input(b, d, h_out, w_out, c):#load 真实输入#b:batch#d:depth数#h_out, w_out:输出特征图大小#c:通道数depth = torch.Tensor(np.load("real_inputs/depth.npy"))feat = torch.Tensor(np.load("real_inputs/feat.npy"))ranks_depth = torch.Tensor(np.load("real_inputs/new_ranks_depth.npy")).type(torch.int32) #ranks_feat = torch.Tensor(np.load("real_inputs/new_ranks_feat.npy")).type(torch.int32)ranks_bev = torch.Tensor(np.load("real_inputs/new_ranks_bev.npy")).type(torch.int32)interval_starts = torch.Tensor(np.load("real_inputs/new_interval_starts.npy")).type(torch.int32)interval_lengths = torch.Tensor(np.load("real_inputs/new_interval_lengths.npy")).type(torch.int32)bev_feat_shape = (b, d, h_out, w_out, c)return depth, feat, ranks_depth, ranks_feat, ranks_bev, interval_starts, interval_lengths, bev_feat_shape
#step1;构建复现浮点模型
class SimpleBEVModel(nn.Module):def 
__init__
(self,bev_feat_shape):super(SimpleBEVModel, self).
__init__
()self.bev_feat_shape = bev_feat_shapeself.bev_pool = BevPoolV2(self.bev_feat_shape)self.quant1 = QuantStub()self.quant2 = QuantStub()self.dequant = DeQuantStub()_, _, self.ranks_depth, self.ranks_feat, self.ranks_bev, self.interval_starts, self.interval_lengths, _ = load_input(1, 1,640, 128, 64)def forward(self, data):depth = data["depth"]feat = data["feat"]#step2:改造模型#在输入/输出分别插入QuantStub和DeQuantStubdepth = self.quant1(depth)feat = self.quant2(feat)#调用BevPoolV2算子bev_feat = self.bev_pool(depth, feat, self.ranks_depth, self.ranks_feat, self.ranks_bev, self.interval_starts, self.interval_lengths)print("output shape:",bev_feat.shape)bev_feat = self.dequant(bev_feat)return bev_feat
if 
name== '
__main__
':b, d, h_out, w_out, c=1,1,640, 128, 64depth, feat, ranks_depth, ranks_feat, ranks_bev, interval_starts, interval_lengths, bev_feat_shape = load_input(b, d, h_out, w_out, c)print(f"Depth shape: {depth.shape} {depth.dtype}")print(f"Feat shape: {feat.shape} {feat.dtype}")print(f"Ranks depth shape: {ranks_depth.shape} {ranks_depth.dtype}")print(f"Ranks feat shape: {ranks_feat.shape} {ranks_feat.dtype}")print(f"Ranks bev shape: {ranks_bev.shape} {ranks_bev.dtype}")print(f"Interval starts shape: {interval_starts.shape} {interval_starts.dtype}")print(f"Interval lengths shape: {interval_lengths.shape} {interval_lengths.dtype}")print(f"BEV feat shape: {bev_feat_shape}")model = SimpleBEVModel(bev_feat_shape)example_inputs = dict(depth=depth,feat=feat,)import logginglogging.basicConfig(filename='error.log', level=logging.ERROR)try:res_float = model(example_inputs)passexcept Exception as e:logging.error("An error occurred: %s", e, exc_info=True)#配置marchset_march(March.NASH_M)#step3:将浮点模型 prepare为伪量化模型calib_model = prepare(copy.deepcopy(model),example_inputs=(example_inputs,),qconfig_setter=(default_calibration_qconfig_setter,),method=PrepareMethod.JIT_STRIP,)calib_model.eval()set_fake_quantize(calib_model, FakeQuantState.CALIBRATION)res_calib = calib_model(example_inputs)#step4:export出 qat.bcqat_hbir = export(calib_model,example_inputs,name="bevpool",)save(qat_hbir,"bevpoolv2_qat.bc")#step5:将qat.bc convert为 quantized.bcquanti_hbir = convert(qat_hbir, "nash-e")save(quanti_hbir, "bevpoolv2_quantized.bc")compile(quanti_hbir,path="bevpoolv2.hbm",march='nash-e',opt=2,jobs=64,balance=100,progress_bar=True,)

运行此示例代码后,目录下会有 3 个文件生成:

  • bevpoolv2_qat.bc: 单算子伪量化 bc
  • bevpoolv2_quantized.bc:单算子定点 bc
  • bevpoolv2.hbm:上板部署的 hbm

5.模型可视化

获取以上模型后,可视化查看输入输出属性是否符合预期。

可视化方式可以使用 hb_model_info 命令行工具或者 visualize 接口来可视化 bc/hbm 模型。

bevpoolv2_qat.bc可视化:

bevpoolv2_quantized.bc可视化:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/896959.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

包装类--java进阶day05

1.包装类比如要让s+100,输出223.如果直接相加,结果是123100,这时就可以将s转换为包装类,然后再用包装类进行相加 2.包装类类型3.手动拆/装箱 我们这里只介绍Integer,其他包装类都是一个模板 第一个方式已经过时,不建议使用.4.自动拆/装箱.5.包装类常用方法 可以直接类名调…

掌握这些 UI 交互设计原则,提升产品易用性

在当今数字化时代,用户对于产品的体验要求越来越高,UI 交互设计成为决定产品成败的关键因素之一。一个易用的产品能够让用户轻松、高效地完成各种操作,而实现这一目标的核心在于遵循一系列科学合理的 UI 交互设计原则。本文将详细阐述简洁性、一致性、反馈、可访问性以及用户…

C++ this

今天开始进入C++学习了,之前的这周末复习下 侧重与底层原理 当把函数放到结构体里面,编译器会帮我们传递一个参数:结构体的地址this指针本质就是对象地址

【由技及道】镜像星门开启:Harbor镜像推送的量子跃迁艺术【人工智障AI2077的开发日志010】

当构建产物需要穿越多维宇宙时,当Docker镜像要同时存在于72个平行世界——这就是镜像推送的量子艺术。本文记录一个未来AI如何通过Harbor建立镜像星门,让每个构建产物都能瞬间抵达所有维度。![量子镜像跃迁示意图]( 摘要:当构建产物需要穿越多维宇宙时,当Docker镜像要同时存…

构造矩形

构造矩形 题目描述 现有 \(n\) 条长度为 \(m\) 的线段,垂直于 x 轴分布,且互不重合。第 \(i\) 条线段的两个端点均为整数点,分别为 \((a_i, 0)\) 和 \((a_i, m)\)。每条线段上有 \(m+1\) 个整数点,纵坐标分别为 \(0, 1, 2, …, m\)。 现在,你需要选择两条不同的线段,并在…

Llama 4 即将发布,引入语音能力;AI 智能运动眼镜 BleeqUp:实时对讲、AI 自动成片等功能丨日报

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的 技术 」、「有亮点的 产品 」、「有思考的 文章 」、「有态度的 观点 」、「有看点的 活动 」,但内容仅代表编辑…

BigDecimal类--java进阶day05

1.BigDecimal出现的原因2.BigDecimal的创建不推荐第一种形式,会有误差第二种方式创建对象第三种方式调用方法2.BigDecimal常用方法除法的特殊事项 如果有除不尽的情况,常规的除法会出现问题divide的另一种方法 divide还有一个重载方法,可以解决除不尽的问题舍入模式中,进一…

3.10 学习记录

实现了员工页面的前端代码实现点击查看代码 <script setup> import { ref, onMounted } from vue import axios from axiosconst searchEmp = ref({name: ,gender: ,job: , })onMounted(() => {search(); })const search = async () => {const url = `https://web-…

transformer 中的掩码类型

知识是我们已知的也是我们未知的基于已有的知识之上我们去发现未知的由此,知识得到扩充我们获得的知识越多未知的知识就会更多因而,知识扩充永无止境

如何设计、维护和推广 API:专业人士的实用指南

API 在今天的数字化环境中扮演着至关重要的角色,它们作为系统和应用程序之间的连接纽带。对于公司而言,打造用户喜爱的 API、有效地维护它们并成功地在内部和外部推广,不仅能提高数字价值,还能带来巨大的业务收益。 API 设计是创建一个标准化、易于理解且稳定的应用程序接口…

springboot引入nacos

springboot引入nacos 一、 环境准备(windows为例)安装nacos(github镜像网址:Releases alibaba/nacos) 推荐下载发行版启动nacos本地服务 下载完毕,建议解压到没有中文路径的文件夹,在bin目录下打开cmd对话框输入下面命令启动nacos startup.cmd -m standalone启动成功出现以…

95%开发者不知道的调试黑科技:Apipost让WebSocket开发效率翻倍的秘密

在现代 Web 开发中,Websocket 作为一种常见的 Web 协议,与 Restful API 有着本质的不同。Restful API是基于请求-响应模式的单向通信,而 WebSocket 提供全双工通信渠道,允许客户端和服务器之间进行实时双向数据传输。这种特性使得它在需要实时交互的场景中大放异彩,比如 I…