news 2026/6/16 2:59:43

【NPU】【精度】【数据踩踏】AdaptiveMaxpool3D算子indices精度问题

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【NPU】【精度】【数据踩踏】AdaptiveMaxpool3D算子indices精度问题

AdaptiveMaxpool3D功能说明文档:https://gitcode.com/cann/ops-nn/blob/master/pooling/adaptive_max_pool3d/README.md。

1. 精度异常表现

AdaptiveMaxPool​(自适应最大池化)是深度学习领域常见的池化操作,可将任意输入尺寸映射为固定输出尺寸。在NPU上调试AdaptiveMaxpool3D算子时,碰到一些索引与cpu标杆差异的地方,对此问题做一个记录。
简化用例信息如下:输入一个[1,1,1,15,17]张量,通过控制属性参数outputSize为[1,2,17],输出[1,1,1,2,17]大小的最大值和索引两个张量。

op_namex_shapex_dtypey_shapey_dtypeargmax_shapeargmax_dtypeoutputSizedata_format_str
AdaptiveMaxpool3D1,1,1,15,17float161,1,1,2,17float161,1,1,2,17int321,2,17NCDHW

笔者将用例输出的结果同cpu进行比对如下:与cpu的结果比较中最大值输出正确,但索引位置错误,cpu为202,npu为49271
AdaptiveMaxPool返回结果中,索引是用来记录获取的最大值位置,便于反向传播进行正确路径的梯度更新,以torch_cpu功能作为参考,假设输入张量是[N,C,D,H,W],那么索引位置会是D*H*W输入尺寸铺平成一维后的索引位置(扁平化绝对索引)。根据输入用例尺寸来看索引位置最大为1*15*170~254的范围,不可能是49271,很明显,npu的索引输出存在异常。

2. 定位过程

通过多次运行相同用例shape,发现都在同一位置输入错误索引。我们首先粗略排查索引的计算过程,但并没有发现明显逻辑问题。既然运行是必现的,最简单方式就是找到49271异常值是什么时候出现的。
原先笔者已经将用例简化到[1,1,1,15,17]大小,小量数据可以帮助我们更好进行观察。我们通过从计算索引→搬出结果的反向过程插入DumpTensor(GlobalTensor/LocalTensor, 代码行号, 元素个数)函数重新编译算子运行,可以逐步打印NPU上的Tensor内容值进行观察,发现错误数据第一次出现在上述红框的for循环中Select函数之后。

再往前Select函数的输入Tensor数值打印出来没有明显异常值,因此我们深入分析Select的配置参数和功能逻辑是否存在与预想不一致的地方。在官网文档中发现该接口使用一个8K的预留空间,是一个疑点。
(官网文档:https://www.hiascend.com/document/detail/zh/CANNCommunityEdition/850alpha002/API/ascendcopapi/atlasascendc_api_07_0070.html)

笔者通过搜索InitBuffer函数快速查验一下空间分配情况,这个算子使用了固定大小分配,比较好分析,计算了一下大概为185kb185+8=193kb!!!这超过了芯片最大提供的192kbub空间大小,这会导致内存空间被踩!!!

// 初始化que pipe->InitBuffer(inputQue, 1, 32 * 1024); pipe->InitBuffer(maxQue, 1, 8 * 1024); pipe->InitBuffer(indexQue, 1, 8 * 1024); // 初始化Tbuf pipe->InitBuffer(cmpMaskBuffer, 512); pipe->InitBuffer(cmpNanMaskBuffer, 512); pipe->InitBuffer(inputTransBuffer, 32 * 1024); pipe->InitBuffer(resetIndexBuf, 4 * 1024); pipe->InitBuffer(nextCmpBuffer, 4 * 1024); pipe->InitBuffer(mulWBuffer, 64 * 1024); pipe->InitBuffer(mulWIdxBuffer, 32 * 1024);

3. 解决方式

单核在进行pipe->InitBuffer在进行192kb空间分配时是按顺序分的。在空间分配时,mulWBuffer的空间申请有一部分作用用于复用计算,我们将其移动到最后进行空间的分配,这样子改动最小化,Select接口的预留的8kb即使踩到mulWBuffer也只涉及到无效数据部分,不影响计算结果。在调整完顺序后重新进行验证,验证结果通过。

// 初始化que pipe->InitBuffer(inputQue, 1, 32 * 1024); pipe->InitBuffer(maxQue, 1, 8 * 1024); pipe->InitBuffer(indexQue, 1, 8 * 1024); // 初始化Tbuf pipe->InitBuffer(cmpMaskBuffer, 512); pipe->InitBuffer(cmpNanMaskBuffer, 512); pipe->InitBuffer(inputTransBuffer, 32 * 1024); pipe->InitBuffer(resetIndexBuf, 4 * 1024); pipe->InitBuffer(nextCmpBuffer, 4 * 1024); pipe->InitBuffer(mulWIdxBuffer, 32 * 1024); pipe->InitBuffer(mulWBuffer, 64 * 1024); //移动到最后

4. 根因

Select接口的使用需要预留8K的Unified Buffer空间,但是原有kernel已经申请了185kb空间,185+8=193kb超过了芯片最大提供的192kbub空间大小,导致Select函数踩到有效数据,输出异常索引值。

5. 启发

1、对于一些可复现异常,可以通过简化输入条件来降低定位的复杂度,通过二分打印数据的变化找到异常引入点。
2、在算子开发中,要考虑到最大的ub内存空间进行合理的分配,留意API接口中容易忽视的约束,部分的指令可能需要预留一部分的ub空间,不然可能会造成内存踩踏。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/13 8:27:51

三维EKF实现无人机高精度悬停控制

目录 1. 三维 EKF 设计 状态向量 状态方程(预测) 2. 观测方程(更新) GPS 观测矩阵: 光流观测矩阵: 气压计观测矩阵: 3. 代码实现(STM32 HAL 库) 4. 集成到无人机…

作者头像 李华
网站建设 2026/6/12 16:46:20

虾皮店铺页面如何优化

在Shopee经营店铺时,卖家常常需要依据商品类目与店铺配置来增加产品曝光,这使得优化店铺页面变得十分重要。那么具体可以从哪些方面着手改进呢? 1、店铺头像 头像最好与销售品类相关,并符合当地审美偏好,设计应鲜明、…

作者头像 李华
网站建设 2026/6/13 7:25:30

YOLOv8 Panoptic Segmentation全景分割实现

YOLOv8 全景分割实现:从镜像部署到工业级应用 在自动驾驶、智能监控和机器人视觉等前沿领域,对场景的理解早已不再满足于“图中有几辆车”这样的粗粒度判断。人们需要的是更精细的感知能力——比如,“哪一辆车挡住了行人”,“每个…

作者头像 李华
网站建设 2026/6/15 9:39:54

YOLOv8 MAE掩码自编码器预训练方案

YOLOv8 MAE掩码自编码器预训练方案 在工业质检、医疗影像分析等实际场景中,一个普遍存在的困境是:高质量标注数据稀缺而昂贵,但无标签图像却大量存在。比如一条自动化产线每天能拍摄数万张产品照片,真正被打上“缺陷”标签的可能不…

作者头像 李华
网站建设 2026/6/13 9:19:57

laravel基于PHP的“绿上优选网站”绿色商品网上环保商城的设计与制作vue

目录具体实现截图项目介绍论文大纲核心代码部分展示可定制开发之亮点部门介绍结论源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作具体实现截图 本系统(程序源码数据库调试部署讲解)同时还支持Python(flask,django)、…

作者头像 李华
网站建设 2026/6/15 9:15:39

小程序三端校园宿舍小卖部商城系统_p032l5o9 人脸识别

目录 已开发项目效果实现截图关于博主开发技术介绍 核心代码参考示例1.建立用户稀疏矩阵,用于用户相似度计算【相似度矩阵】2.计算目标用户与其他用户的相似度系统测试总结源码文档获取/同行可拿货,招校园代理 :文章底部获取博主联系方式! 已…

作者头像 李华