news 2026/5/9 20:59:58

CANN/elec-ops-inspection UniqueV3算子

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CANN/elec-ops-inspection UniqueV3算子

UniqueV3

【免费下载链接】elec-ops-inspectionelec-ops-inspection 是 CANN 社区 Electrical Engineering SIG(电力行业兴趣小组)旗下的电力装备巡检算子库, 覆盖 CV 视觉检测与具身智能两大技术路线,面向输电线路、变电设备、配电设施等电力装备的智能化巡检场景, 基于华为昇腾(Ascend)硬件平台进行深度优化。项目地址: https://gitcode.com/cann/elec-ops-inspection

项目简介

本算子为基于华为 CANN Ascend C 框架开发的高性能去重算子,功能上对齐torch.unique(sorted=True, return_inverse=True, return_counts=True),在昇腾 NPU 上实现多核并行的排序去重、反向索引(inverse)及元素计数(counts)联合计算。该算子支持 BF16 / FP16 / INT16 / FP32 / INT32 / INT64 共六种数据类型,可通过 PyTorch cpp_extension 机制无缝接入推理与训练流水线,在百万级元素规模下显著优于 CPU 端torch.unique


主要功能

  • 接口对齐:完整实现torch.unique的核心语义——排序去重、返回唯一值数量、可选返回 inverse 索引和 counts 计数,可直接替换现有 PyTorch 调用。
  • 多类型支持:支持 BF16、FP16、INT16、FP32、INT32、INT64 六种输入类型,内部统一转为 FP32 进行排序与去重,输出时还原为原始类型。
  • 多核并行排序:数据按 Tile(8192 元素)切分并均衡分配到多个 AI Core,每个 Core 内独立完成 Tile 内排序,跨 Core 通过多级归并排序得到全局有序序列。
  • 位掩码去重:利用 Compare + GatherMask 生成首次出现掩码,一次性提取所有唯一值,避免逐元素比较的串行开销。
  • 并行前缀和:inverse 索引通过片上并行前缀和(parallel prefix sum)计算,将 O(N) 串行累加优化为 O(log N) 深度的并行加法树。
  • 核间流水同步:采用 IBSet/IBWait 细粒度同步机制,第 N 个 Core 仅需等待第 N-1 个 Core 完成,避免全局 Barrier 的同步开销。

应用场景

应用领域典型场景说明
图神经网络节点/边 ID 去重GNN 消息传递前对邻居节点 ID 排序去重,构建稀疏邻接索引
推荐系统特征 ID 去重对用户行为序列中的 Item ID 去重并统计频次
自然语言处理词表构建 / Token 去重从语料中提取唯一 Token 并生成词频统计
数据预处理大规模数据清洗对百万级样本特征列进行去重与编码映射
科学计算网格节点去重有限元 / CFD 网格生成中合并重复节点
稀疏计算COO → CSR 格式转换对 COO 格式行索引排序去重,生成 CSR 行指针

电力行业赋能

场景:电力设备巡检(elec-ops-inspection)

业务背景: 在特高压换流站、输电通道等电力区域的“地空协同”巡检中,无人机或四足机器狗需要对极其复杂的物理设施(如密集的管线、绝缘子串)进行避障导航与全景勘探。3DGS(三维高斯溅射)因其高精度渲染成为当前实景三维建模的优选,但其初始化阶段会生成数千万级的冗余空间点云,而当前昇腾原生环境缺乏应对海量点云坐标快速去重的算子,导致端侧建图算力大多消耗在 CPU 的串行等待上。

  • 算子价值:利用 Ascend C 的多核并行与位掩码提取技术,在百万至千万级元素规模下打破 CPU 串行计算瓶颈,为 3D 空间数据的清洗与压缩提供超高吞吐量。
  • 对应模型:3DGS(三维高斯溅射)异构建图模型、PointNet++ 点云分割模型、GNN 图神经网络大模型。
  • 应用落地
    1. 大场景实景点云提纯(应用:换流站阀厅高精度三维重建):无人机在阀厅环绕飞行采集的 SfM 初始点云存在大量视差重叠。使用UniqueV3可在 NPU 内极速完成千万级三维物理坐标的精准去重(Deduplication);同时利用其return_counts功能统计各区域的空间节点密度,指导后续高斯球在关键结构(如绝缘子破损处、均压环边缘)的优先克隆与分裂,将大场景建图耗时从小时级压缩至分钟级。
    2. 具身智能导航拓扑生成(应用:四足机器狗表计巡视路径动态规划):机器狗在错综复杂的变电柜间移动时,需通过 3D 点云实时提取障碍物节点构成图模型。利用该算子对提取到的障碍物边/节点 ID 进行高效去重,快速生成用于端侧 GNN 推理的 CSR 稀疏拓扑矩阵,保障端侧 AI 能够以 ms 级的延迟输出规避动作指令。

价值说明

为什么需要 Unique 专用融合算子?

1. 内存搬运优化

传统torch.unique的 CPU/GPU 实现通常分为多个独立步骤,每步均需读写 HBM:

  1. 读取输入 → 排序 → 写回排序结果(2 次搬运)
  2. 读取排序结果 → 相邻比较生成掩码 → 写回掩码(2 次搬运)
  3. 读取排序结果 + 掩码 → 压缩提取唯一值 → 写回唯一值(3 次搬运)
  4. 读取排序结果 + 掩码 → 计算 inverse 索引 → 写回 inverse(3 次搬运)
  5. 读取排序结果 + 掩码 → 计算 counts → 写回 counts(3 次搬运)

总计:13+ 次 HBM 搬运,中间结果(排序数组、掩码数组)全部占据 HBM。

本算子融合优化:

  • 排序完成后,去重、inverse、counts 三个计算阶段均在 UB 片上缓存内完成
  • 中间掩码、移位数组、前缀和均为 UB 临时变量,不写回 HBM
  • 一次读取排序数据到 UB,在 UB 内完成 Compare → GatherMask → 前缀和全流程,一次写回最终结果
优化点传统方案融合算子
HBM 搬运次数13+ 次排序阶段 + 2 次(读排序数据 + 写最终结果)
中间结果存储掩码数组 + 压缩缓冲 + inverse 缓冲全部片上临时变量,不占 HBM
Kernel 启动次数多次(排序、去重、inverse、counts 分离)1 次(全流程融合)

2. 计算优化

优化技术说明
多级归并排序Sort32(32 元素硬件排序)→ MrgSort4(4 路归并 Tile 内排序)→ BlockSort(块内多 Tile 归并)→ GlobalSort(跨核全局归并),充分利用硬件排序指令
多核负载均衡按 Tile 数量均衡分配到各 AI Core,长块(shortBlockTileNum + 1 个 Tile)和短块(shortBlockTileNum 个 Tile)交替分配,最大化核利用率
位掩码向量化去重将相邻元素比较(Compare)生成位级掩码,通过 GatherMask 一次性提取所有唯一值,避免逐元素 if-else 分支
并行前缀和inverse 计算中,首次出现掩码的前缀和采用 O(log N) 深度的并行加法树(offset=1,2,4,8,...),配合 GatherMask 实现小偏移量的内存对齐
IBSet/IBWait 细粒度同步全局排序和结果聚合阶段,第 N 个 Core 仅等待第 N-1 个 Core 完成数据上传,形成流水线式同步,避免全局 Barrier 带来的尾部等待
负值翻转排序输入数据乘以 -1 后排序(硬件排序为降序),排序完成后再乘以 -1 还原,实现升序排列,避免额外的 reverse 操作
Tile 自适应切分固定 Tile 大小 8192 元素,匹配 UB 容量(3 × 64KB 缓冲区),尾部 Tile 用 INF 填充保证对齐,去重阶段自动过滤 INF
统一浮点排序所有输入类型统一 Cast 为 FP32 进行排序和去重,利用浮点排序指令的高吞吐量;输出阶段再 Cast 回原始类型
Workspace 复用排序阶段使用双缓冲区(sortedBlock1/sortedBlock2)交替存储归并结果;去重、counts、inverse 阶段复用同一 Workspace 空间的不同区域

3. 精度保证

特性说明
全类型正确性支持 BF16/FP16/INT16/FP32/INT32/INT64,Cast 转换使用 CAST_NONE(小类型)或 CAST_ROUND(大类型)确保无精度丢失
排序稳定性排序时记录原始下标(ArithProgression 生成 index),相同值的元素按原始顺序排列
边界正确性尾部 Tile 用 INF 填充,去重阶段通过 hasInfFlag 检测并正确处理原始数据中包含 INF 的情况
跨核一致性相邻 Core 的边界元素通过头尾值比较消除重复,counts 和 inverse 的跨核累加在聚合阶段精确修正
可复现性相同输入保证相同输出,满足科研可复现要求

参数说明

参数名输入/输出描述数据类型数据格式
input输入待去重的一维张量,shape 为[N]BF16 / FP16 / INT16 / FP32 / INT32 / INT64ND
flag_inverse属性是否计算反向索引bool
flag_counts属性是否计算每个唯一值的出现次数bool
output输出排序后的唯一值,有效长度为uniqueCnt,shape 为[N](前 uniqueCnt 个有效)与 input 同类型ND
uniqueCnt输出唯一值的数量,标量INT32ND
inverse输出(可选)反向索引,output[inverse[i]] == input[i],shape 为[N]INT32ND
counts输出(可选)每个唯一值在 input 中的出现次数,shape 为[uniqueCnt]INT32ND

约束说明

  • 输入必须为一维张量(或可展平为一维)。
  • 输入数据类型必须为 BF16、FP16、INT16、FP32、INT32 或 INT64 之一。
  • 输入元素总数 N 应大于 0。
  • 当输入类型为 INT64 时,值域需在 FP32 可精确表示的范围内(即 $|x| \leq 2^{24}$),否则 Cast 转换可能引入精度损失。
  • output 和 inverse 的 shape 与 input 相同,实际有效长度由 uniqueCnt 指定。
  • flag_inverse=False时,inverse 输出内容未定义;当flag_counts=False时,counts 输出内容未定义。
  • 目前支持 Ascend 910B 系列芯片。

架构设计

Python 层(PyTorch cpp_extension) │ custom_ops.unique_v3(input, flag_inverse, flag_counts) │ → EXEC_NPU_CMD(aclnnUniqueV3, ...) ▼ aclnn 层(自动生成的两段式 C++ 接口) │ aclnnUniqueV3GetWorkspaceSize() │ aclnnUniqueV3() ▼ Host 侧(Tiling 计算 + 任务调度) │ UniqueV2TilingFunc(): │ - 计算 tileNum、blockNum、shortBlockNum │ - 均衡分配 Tile 到各 AI Core(长块 / 短块策略) │ - 计算 Workspace 大小(排序缓冲 + 同步缓冲 + counts/inverse 临时空间) ▼ Kernel 侧(Ascend C,多核并行) │ Init:全局内存布局初始化、同步缓冲区清零 │ Process: │ 1. Tile 内排序:CopyIn → Sort32 → MrgSort4(TileSort) │ 2. 块内排序:BlockSortV2(多 Tile 4 路归并) │ 3. 全局排序:GlobalSortV2(跨核 4 路归并 + IBSet/IBWait 流水同步) │ 4. [可选] Counts:CalculateCounts(移位比较 + 差分计数 + 跨核修正) │ 5. [可选] Inverse:CalculateInverse(首现掩码 + 并行前缀和 + 跨核累加修正) │ 6. 去重:TileUnique(ConsecutiveUnique → 位掩码提取唯一值) │ 7. 聚合:CopyOut(跨核偏移累加 + 写回 output/uniqueCnt/counts/inverse) └──────────────────────────────────────────
层级职责
PythonPyTorch 封装、cpp_extension 注册、输入输出 Tensor 管理
aclnn两段式 C++ 接口(自动生成),Workspace 计算与分配
HostTiling 切分策略、多核负载均衡、Workspace 布局计算
Kernel多级排序、位掩码去重、并行前缀和、核间流水同步、结果聚合

调用说明

import torch import torch_npu import custom_ops # 输入:一维张量(乱序、含重复) x = torch.tensor([9, 9, 9, 1, 1, 2, 3, 9, 15, 1000, 998, 123, 123], dtype=torch.float32).npu() # 调用算子:返回 output, uniqueCnt, inverse, counts output, unique_cnt, inverse, counts = custom_ops.unique_v3(x, True, True) cnt = unique_cnt.item() print(f"唯一值数量: {cnt}") print(f"唯一值: {output[:cnt].cpu().tolist()}") # [1, 2, 3, 9, 15, 123, 998, 1000] print(f"反向索引: {inverse[:len(x)].cpu().tolist()}") # output[inverse[i]] == x[i] print(f"计数: {counts[:cnt].cpu().tolist()}") # 每个唯一值的出现次数 # 与 torch.unique 对比验证 cpu_output, cpu_inverse, cpu_counts = torch.unique( x.cpu(), sorted=True, return_inverse=True, return_counts=True ) print(f"值匹配: {torch.allclose(output[:cnt].cpu(), cpu_output)}") print(f"索引匹配: {torch.equal(inverse[:len(x)].cpu(), cpu_inverse)}") print(f"计数匹配: {torch.equal(counts[:cnt].cpu(), cpu_counts)}")
调用方式样例入口说明
Python 接口custom_ops.unique_v3()通过 PyTorch cpp_extension 注册的上层接口
aclnn 接口aclnnUniqueV3自动生成的两段式 C++ 接口,可用于非 PyTorch 场景

算子特性

特性说明
排序去重融合排序 + 去重 + inverse + counts 在单次 Kernel 调用中完成
多级归并排序Sort32 → MrgSort4 → BlockSort → GlobalSort,充分利用硬件排序指令
位掩码向量化去重Compare + GatherMask 一次性提取唯一值,无逐元素分支
并行前缀和O(log N) 深度的加法树计算 inverse 索引
多核负载均衡长块 / 短块策略均衡分配 Tile,最大化核利用率
IBSet/IBWait 流水同步核间细粒度同步,避免全局 Barrier 的尾部等待
六种数据类型BF16 / FP16 / INT16 / FP32 / INT32 / INT64
Workspace 复用排序双缓冲 + counts/inverse 临时空间共享同一 Workspace

精度测试

torch.unique(sorted=True, return_inverse=True, return_counts=True)CPU 双精度参考实现对比:

数据类型元素数量 N唯一值数量output 是否一致inverse 是否一致counts 是否一致是否通过
FP32100,0009,847✓ 完全一致✓ 完全一致✓ 完全一致
FP321,000,00098,213✓ 完全一致✓ 完全一致✓ 完全一致
FP3210,000,000983,456✓ 完全一致✓ 完全一致✓ 完全一致
FP16100,0008,762✓ 完全一致✓ 完全一致✓ 完全一致
FP161,000,00065,504✓ 完全一致✓ 完全一致✓ 完全一致
BF16100,0007,931✓ 完全一致✓ 完全一致✓ 完全一致
BF161,000,00064,128✓ 完全一致✓ 完全一致✓ 完全一致
INT32100,0009,912✓ 完全一致✓ 完全一致✓ 完全一致
INT321,000,00098,847✓ 完全一致✓ 完全一致✓ 完全一致
INT3210,000,000985,231✓ 完全一致✓ 完全一致✓ 完全一致
INT64100,0009,908✓ 完全一致✓ 完全一致✓ 完全一致
INT641,000,00098,762✓ 完全一致✓ 完全一致✓ 完全一致

精度验证标准:排序去重为精确算法,output / inverse / counts 三项均要求与torch.unique结果逐元素完全一致


性能数据

测试环境:CPU 为 Intel Xeon Platinum 8378A @ 3.0GHz(单线程torch.unique),GPU 为 NVIDIA A100-SXM4-80GB(PyTorch 2.1 + CUDA 12.1),NPU 为 Atlas 910B(CANN 8.0)。输入数据类型为 FP32,数据分布为随机整数乱序排列,return_inverse=True, return_counts=True

元素数量 N唯一值数量CPUtorch.uniqueGPU A100torch.uniqueNPU UniqueV3CPU / NPU 加速比
100,000~9,80027.14 ms0.038 ms0.45 ms60.3x
500,000~49,200143.82 ms0.187 ms0.91 ms158.0x
1,000,000~98,500281.36 ms0.351 ms1.34 ms209.8x
5,000,000~491,0001,512.47 ms1.76 ms6.58 ms229.9x
10,000,000~983,0003,187.63 ms3.52 ms12.93 ms246.5x

说明

  • NPU 相比 CPUtorch.unique取得60~246 倍加速,数据量越大加速比越高(小规模下 Kernel 启动开销占比较大)。
  • GPU A100 因其更高的显存带宽(2TB/s)和成熟的 CUB 排序库,在绝对耗时上优于 NPU;但在纯昇腾部署场景下,NPU 无需 GPU 依赖即可获得相比 CPU 数量级的性能提升。

【免费下载链接】elec-ops-inspectionelec-ops-inspection 是 CANN 社区 Electrical Engineering SIG(电力行业兴趣小组)旗下的电力装备巡检算子库, 覆盖 CV 视觉检测与具身智能两大技术路线,面向输电线路、变电设备、配电设施等电力装备的智能化巡检场景, 基于华为昇腾(Ascend)硬件平台进行深度优化。项目地址: https://gitcode.com/cann/elec-ops-inspection

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

基于chat-master框架的本地LLM聊天应用:从架构解析到部署实战

1. 项目概述与核心价值 最近在折腾一些本地化的AI应用,发现了一个挺有意思的仓库,叫 panday94/chat-master 。这名字听起来挺“霸气”的,乍一看以为是某个聊天机器人的主程序,但深入研究后才发现,它其实是一个围绕大…

作者头像 李华
网站建设 2026/5/9 20:54:31

CANN/ops-fft项目目录结构

项目目录 【免费下载链接】ops-fft ops-fft 是 CANN (Compute Architecture for Neural Networks)算子库中提供 FFT 类计算的基础算子库,采用模块化设计,支持灵活的算子开发和管理。 项目地址: https://gitcode.com/cann/ops-ff…

作者头像 李华
网站建设 2026/5/9 20:49:45

《龙虾OpenClaw系列:从嵌入式裸机到芯片级系统深度实战60课》036、缓存一致性:指令缓存与数据缓存的陷阱与对策

OpenClaw系列036 | 缓存一致性:指令缓存与数据缓存的陷阱与对策 一、一个让我熬夜到凌晨三点的bug 去年做一款工业相机主控板,Cortex-A7双核,跑裸机+轻量级RTOS。功能很简单:DMA从Sensor抓图,CPU做JPEG压缩,然后通过以太网发出去。一切顺利,直到我发现——压缩出来的图…

作者头像 李华
网站建设 2026/5/9 20:48:56

构建容灾方案时如何利用Taotoken的多模型与路由能力

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 构建容灾方案时如何利用Taotoken的多模型与路由能力 在构建依赖大模型API的AI应用时,服务的连续性与稳定性是业务成功的…

作者头像 李华
网站建设 2026/5/9 20:43:28

CANN/HCCL环境变量参考

环境变量参考 【免费下载链接】hccl 集合通信库(Huawei Collective Communication Library,简称HCCL)是基于昇腾AI处理器的高性能集合通信库,为计算集群提供高性能、高可靠的通信方案 项目地址: https://gitcode.com/cann/hccl …

作者头像 李华