尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
AscendNPU-IR HIVM 向量加法实战:使用 bishengir-compile 将 MLIR 编译为昇腾 NPU 可执行程序
编译器人工智能AscendCANN【免费下载链接】AscendNPU-IRAscendNPU-IR是基于MLIRMulti-Level Intermediate Representation构建的面向昇腾亲和算子编译时使用的中间表示提供昇腾完备表达能力通过编译优化提升昇腾AI处理器计算效率支持通过生态框架使能昇腾AI处理器与深度调优项目地址https://gitcode.com/Ascend/AscendNPU-IR点击查看免费下载本文以 AscendNPU-IR 仓库中 HIVM Vector Add 集成测试示例 为核心完整演示一条「从 MLIR 源码到昇腾 NPU 上真实运行」的端到端链路先用手写 HIVM 方言编写一个 16 元素 int16 向量加法 kernel再用bishengir-compile -enable-hivm-compile将其编译为 device 端二进制kernel.o最后编写基于 AscendCLACL与 Runtime 接口的 host 端封装程序完成 kernel 注册、数据搬运、启动与结果校验。读完本文你将掌握 HIVM 方言 kernel 的编写要点、集成测试的 CMake 构建方法以及宿主程序驱动 NPU 执行的全流程。一、示例概览一条完整的 HIVM 编译与执行链路该示例位于 bishengir/test/Integration/HIVM/VecAdd目录下包含五个文件构成一个可独立编译、运行并自动校验的完整用例文件作用add.mlirdevice 端 HIVM kernel 源码16 元素 int16 向量加法main.cpphost 端封装程序初始化 ACL、注册 kernel、搬运数据、启动并校验结果CMakeLists.txt集成测试构建脚本生成可执行文件bishengir-npu-hivm-vec-addlit.local.cfg声明该目录测试后缀为.cpp接入 LLVM 集成测试框架README.md/README_zh.md英文/中文使用说明本文即围绕该说明展开示例要回答两个核心问题如何编译怎样用bishengir-compile把.mlir编译成可在昇腾 NPU 上执行的二进制如何执行怎样编写 host 端封装程序把编译产物加载到 NPU 上运行。在构建层面test/Integration/CMakeLists.txt 逐层add_subdirectory(HIVM)→add_subdirectory(VecAdd)将该示例接入整个仓库的集成测试体系。二、环境准备CANN 与 ASCEND_HOME_PATH要在昇腾 NPU 上真实运行该示例前提是安装CANN昇腾异构计算架构软件包并将环境变量ASCEND_HOME_PATH指向安装路径export ASCEND_HOME_PATH/usr/local/ascend-toolkit/latestASCEND_HOME_PATH的作用在 VecAdd/CMakeLists.txt 中有直接体现target_include_directories引用${ASCEND_HOME_PATH}/include与${ASCEND_HOME_PATH}/include/experiment/msprof用于编译 host 程序所需的 ACL/Runtime 头文件target_link_directories引用${ASCEND_HOME_PATH}/lib64target_link_libraries链接runtime与ascendcl两个动态库。也就是说该环境变量既决定了 host 程序能否编译通过也决定了运行时能否找到 NPU 驱动库是整个示例的硬性前置条件。三、构建集成测试CMake 选项与产物3.1 关键 CMake 选项构建时必须在 CMake 选项中显式打开-DBISHENGIR_BUILD_EXAMPLESON该开关控制是否编译集成测试用例。参考命令如下基于仓库现有构建方式的完整示例cmake -G Ninja .. \ -DCMAKE_C_COMPILERclang \ -DCMAKE_CXX_COMPILERclang \ -DCMAKE_BUILD_TYPERelease \ -DLLVM_ENABLE_PROJECTSmlir \ -DLLVM_EXTERNAL_PROJECTSbishengir \ -DLLVM_EXTERNAL_BISHENGIR_SOURCE_DIRAscendNPU-IR \ # 项目根目录 -DBSPUB_DAVINCI_BISHENGIRON \ # 必须项使能 AscendNPU IR 对三方仓库的扩展 [其他您需要的 CMake 选项] -DBISHENGIR_BUILD_EXAMPLESON # 编译集成测试用例各选项含义CMake 选项说明-DLLVM_EXTERNAL_PROJECTSbishengir将 bishengir 作为 LLVM 外部项目一起构建-DLLVM_EXTERNAL_BISHENGIR_SOURCE_DIRAscendNPU-IR指向 AscendNPU-IR 项目根目录-DBSPUB_DAVINCI_BISHENGIRON必须开启使能 AscendNPU IR 针对三方仓库的扩展-DBISHENGIR_BUILD_EXAMPLESON编译集成测试示例本示例依赖该开关3.2 构建产物完成构建后可执行文件hivm-vec-add会出现在./bin目录下仓库源码中该可执行文件的实际 target 名为bishengir-npu-hivm-vec-add见 CMakeLists.txt 第 1 行的add_llvm_executable。该 target 声明了DEPENDS bishengir-compile确保编译 host 程序前bishengir-compile工具已就绪。四、device 端 kernel 源码解析add.mliradd.mlir是整个示例的 device 端核心完整内容如下见 add.mlirmodule { func.func add(%arg0: memref16xi16, #hivm.address_spacegm, %arg1: memref16xi16, #hivm.address_spacegm, %arg2: memref16xi16, #hivm.address_spacegm) attributes {hacc.entry, hacc.function_kind #hacc.function_kindDEVICE} { %alloc memref.alloc() : memref16xi16, #hivm.address_spaceub hivm.hir.load ins(%arg0 : memref16xi16, #hivm.address_spacegm) outs(%alloc : memref16xi16, #hivm.address_spaceub) %alloc_0 memref.alloc() : memref16xi16, #hivm.address_spaceub hivm.hir.load ins(%arg1 : memref16xi16, #hivm.address_spacegm) outs(%alloc_0 : memref16xi16, #hivm.address_spaceub) %alloc_1 memref.alloc() : memref16xi16, #hivm.address_spaceub hivm.hir.vadd ins(%alloc, %alloc_0 : memref16xi16, #hivm.address_spaceub, memref16xi16, #hivm.address_spaceub) outs(%alloc_1 : memref16xi16, #hivm.address_spaceub) hivm.hir.store ins(%alloc_1 : memref16xi16, #hivm.address_spaceub) outs(%arg2 : memref16xi16, #hivm.address_spacegm) return } }4.1 函数签名与地址空间函数add接收三个memref16xi16参数两个输入、一个输出其内存地址空间均为#hivm.address_spacegm即GMGlobal Memory全局内存。函数还带有两个关键属性hacc.entry标记该函数为 kernel 入口hacc.function_kind #hacc.function_kindDEVICE声明其为 device 端函数。HIVM 方言的地址空间在 HIVMAttrs.td 中统一定义包括gmGM全局内存、cbufL1、caL0A、cbL0B、ccL0C、ubUB统一缓冲区以及ssbuf、fixbuf、biasbuf等。本例只用到了最典型的两个GM 与 UB。4.2 三段式计算模式kernel 内部体现了昇腾向量计算经典的「加载 → 计算 → 存储」三段式流水GM → UB 加载hivm.hir.load把两个输入从 GM 分别搬入 UB 临时缓冲区对应两次memref.alloc分配 UB 空间UB 内向量计算hivm.hir.vadd在 UB 中对两个输入做逐元素加法结果写入第三个 UB 缓冲区UB → GM 存储hivm.hir.store把结果从 UB 搬回 GM 输出参数。其中hivm.hir.vadd即 HIVM 向量加法指令其方言定义位于 HIVMVectorOps.tddef VAddOp : HIVM_ElementwiseBinaryOpvadd, ...约束要求输入/输出元素类型一致支持向量-向量与向量-标量两种形式。本示例中它接收两个memref16xi16, ub输入、一个memref16xi16, ub输出含义非常直观out[i] in0[i] in1[i]。五、编译 device 端二进制bishengir-compile环境与工程就绪后用bishengir-compile把add.mlir编译为 device 端二进制bishengir-compile add.mlir -enable-hivm-compile -o kernel.o参数说明add.mlir输入的 HIVM 方言 MLIR 源文件-enable-hivm-compile开启 HIVM 编译流程是走 HIVM 方言到昇腾指令降级的关键开关-o kernel.o输出的 device 端二进制ELF 格式供 host 程序注册加载。该选项在 HIVMCConfig.cpp 中定义cl::optbool enableHIVMCompile(enable-hivm-compile, cl::desc(Enable BiShengHIR HIVM compile), ...)默认值为true。从源码结构看bishengir-compile工具入口位于 bishengir-compile.cpp会根据输入的方言类型与选项组合选择对应的编译流水线。值得注意的是kernel.o是一个独立的可执行产物与 host 程序分离它只需要编译一次host 端通过rtDevBinaryRegister在运行时加载它。六、host 端封装程序解析main.cppmain.cpp见 main.cpp展示了如何用 AscendCLacl/acl.h与 Runtimeexperiment/runtime/runtime/rt.h接口驱动 NPU 执行。整体流程分为六个阶段6.1 初始化 NPU 环境error aclInit(nullptr); // 初始化 ACL error aclrtSetDevice(0); // 绑定设备 0 error aclrtCreateStream(stream); // 创建 stream6.2 注册 device 端二进制registerBinaryKernel函数完成两步关键注册rtDevBinary_t binary; binary.data *buffer; // kernel.o 的二进制内容 binary.length bufferSize; binary.magic RT_DEV_BINARY_MAGIC_ELF_AIVEC; // AIVEC 指令集 ELF 魔数 rtDevBinaryRegister(binary, binHandle); // 注册二进制并获取句柄 rtFunctionRegister(binHandle, stubFunc, kernelName, kernelName, 0); // 注册 kernel 入口函数其中stubFunc add与 MLIR 中的函数名add一一对应Runtime 通过该符号在二进制中定位 kernel 入口。读取二进制文件使用自定义的readBinFile基于std::filebuf的二进制读取。6.3 准备输入数据并搬运到 deviceint16_t input0Value[] {0, 1, 2, ..., 15}; // 输入 0 int16_t input1Value[] {1, 1, 1, ..., 1}; // 输入 116 个 1 aclrtMalloc(input0Device, ...); // 在 device 上分配显存 aclrtMemcpy(input0Device, ..., input0Value, ..., ACL_MEMCPY_HOST_TO_DEVICE); // H2D 拷贝6.4 启动 kernelvoid *args[] {input0Device, input1Device, outputDevice}; rtKernelLaunch(stubFunc, 1, args, sizeof(args), nullptr, stream); aclrtSynchronizeStream(stream);rtKernelLaunch以参数数组的形式把三个 device 端指针传给 kernelstream上执行并同步等待完成。6.5 取回结果并校验aclrtMallocHost(outHost, sizeof(expectedValue)); aclrtMemcpy(outHost, ..., outputDevice, ..., ACL_MEMCPY_DEVICE_TO_HOST); // D2H 拷贝 for (int i 0; i 16; i) { printf(i%d\t Expect: %d\t\t\t\tResult: %d\n, i, expectedValue[i], outHost[i]); }期望值expectedValue {1, 2, ..., 16}恰好等于input0 input1的逐元素结果011112…15116以此验证 kernel 计算正确性。6.6 资源释放最后依次释放 device/host 内存aclrtFree、aclrtFreeHost、销毁 streamaclrtDestroyStream、复位设备aclrtResetDevice并aclFinalize()收尾。七、运行与预期输出按 README 步骤依次执行bishengir-compile add.mlir -enable-hivm-compile -o kernel.o # 编译 device 二进制 ./hivm-vec-add # 运行 host 程序./hivm-vec-add会依次打印初始化、kernel 注册、数据搬运、stream 同步等[success]日志并输出 16 行逐元素比对结果README 中省略了部分行i0 Expect: 1 Result: 1 i1 Expect: 2 Result: 2 i2 Expect: 3 Result: 3 i3 Expect: 4 Result: 4完整输出包含i0~i15共 16 行每行Expect与Result一致即代表向量加法 kernel 在昇腾 NPU 上执行正确。八、作为自动化集成测试的价值该示例不仅是入门教程还是一条可自动执行的集成测试用例验证 HIVM 方言「编译 → 加载 → 运行 → 结果正确」的全链路lit.local.cfg 声明测试后缀为.cpp使main.cpp进入 lit 测试发现范围main.cpp顶部内嵌 lit 指令RUN:/DEFINE:/CHECK:其中DEFINE指定-enable-hivm-compiletrue与add.mlir的仓库内路径RUN先执行bishengir-compile ... -o kernel.o再执行bishengir-npu-hivm-vec-add最后用FileCheck逐行匹配i0~i15的Expect/Result输出顶层 test/CMakeLists.txt 将该示例列为bishengir-npu-hivm-vec-add测试依赖纳入仓库整体测试构建。因此读者既可以把本示例当作手动上手的「hello world」也可以借助它理解 AscendNPU-IR 集成测试的组织方式一段 MLIR、一个 host 程序、一组 lit/FileCheck 断言即可构成一条可回归验证的 NPU 端到端用例。九、延伸阅读从示例到更多源码如果想进一步深入可从以下仓库文件继续探索HIVM 向量指令族定义HIVMVectorOps.tdvadd等逐元素二元运算HIVM 地址空间与属性定义HIVMAttrs.tdgm、ub、cbuf等地址空间枚举编译选项解析实现HIVMCConfig.cpp-enable-hivm-compile等选项集成测试根目录与相关用例bishengir/test/Integration/HIVM/VecAdd、bishengir/test/Integration更多 HIVM 方言测试用例bishengir/test/Dialect/HIVM借助这条「编写 kernel → 编译 device 二进制 → host 封装 → 运行校验」的完整链路开发者可以在昇腾 NPU 上快速验证 HIVM 方言的能力并为后续编写更复杂的 kernel如涉及 L1/L0A/L0B 多级缓存、DMA 搬移或矩阵计算的用例打下基础。赞分享编译器人工智能AscendCANN【免费下载链接】AscendNPU-IRAscendNPU-IR是基于MLIRMulti-Level Intermediate Representation构建的面向昇腾亲和算子编译时使用的中间表示提供昇腾完备表达能力通过编译优化提升昇腾AI处理器计算效率支持通过生态框架使能昇腾AI处理器与深度调优项目地址https://gitcode.com/Ascend/AscendNPU-IR点击查看免费下载相关推荐AscendNPU-IR Python 绑定指南用 ascendnpuir.compile 将 MLIR 一键编译为昇腾 NPU 二进制AscendNPU IR Python 绑定指南用 ascendnpuir.compile 将 MLIR 一键编译为昇腾 NPU 二进制 AscendNPU编译器人工智能AscendCANNAscendNPU-IR 全面解读基于 MLIR 的昇腾算子编译中间表示与快速上手指南AscendNPU IR 全面解读基于 MLIR 的昇腾算子编译中间表示与快速上手指南 AscendNPU IRAscendNPU Intermediate编译器人工智能AscendCANN如何在AscendNPU-IR中开发新方言MLIR TableGen与ODS实战教程如何在AscendNPU IR中开发新方言MLIR TableGen与ODS实战教程 AscendNPU IR 是基于 MLIR 构建的昇腾算子编译中间表示编译器人工智能AscendCANN上一篇vuegg高级功能详解自定义组件、样式编辑与代码优化下一篇如何快速掌握FilesWindows上最强大的现代化文件管理器创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

cangjie_build 仓颉 SDK macOS 原生构建实战:从环境准备到 Hello, Cangjie 全流程

cangjie_build 仓颉 SDK macOS 原生构建实战:从环境准备到 Hello, Cangjie 全流程

文档教程构建工具 【免费下载链接】cangjie_build 仓颉SDK集成构建指导书。 项目地址: https://gitcode.com/Cangjie/cangjie_build 点击查看 免费下载 本文基于 cangjie_build 仓库中的 macOS 构建指导书(中文版见 docs/macos.md)&#xff…

📅 2026/10/14 1:49:57
神龙卡新一代驱动:解决玄学掉卡与批量部署稳定性实战

神龙卡新一代驱动:解决玄学掉卡与批量部署稳定性实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/14 1:44:57
CAN Signal Layout排查指南:DBC字节序与起始位如何影响信号解析

CAN Signal Layout排查指南:DBC字节序与起始位如何影响信号解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/14 1:44:57
MORE NEWS

更多资讯

📰

AI驱动测试用例生成:从需求描述到可执行自动化脚本的完整实践指南

1. 为什么需要AI驱动用例生成:从两条完全不同的语言体系说起我见过的绝大多数测试团队,都卡在同一个地方:需求文档写了一大堆,测试用例却少得可怜。产品经理交付的需求描述,是人话,带上下文、带业务背景、带…

📰

三阶RC低通滤波器定点化与移位优化:无FPU MCU的高效实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

为什么两台电脑直连都无法通信

网线类型:现代网卡大多支持 Auto-MDI/MDIX,普通直通线也能直连。但如果是老设备,直连需要 交叉线(一头 568A、一头 568B)。最稳妥:换一根确认好的网线试试。我怀疑是网线类型的原因:直连到底要不…

📰

高效图论图像分割:并查集与贪心合并的实现原理详解

图像分割在计算机视觉里的位置,有点像“人人都知道重要,但真正用起来总是不顺手”的公共组件。早些年做识别、检索、目标提取,第一步几乎都是先把图像切成有意义的块;这几年深度模型虽然端到端扛起了大局,但凡是需要精…

📰

SpringBoot+Vue全栈开发实战:游戏管理平台构建指南

1. 项目概述这个全栈项目是一个典型的Web及游戏管理平台信息管理系统,采用当下最流行的前后端分离架构。后端基于SpringBoot框架构建,前端使用Vue.js实现,数据存储则选用MySQL关系型数据库。整套系统开箱即用,源码结构清晰&#x…

📰

JTT 697.7交通地理信息数据元标准:从字段定义到建表落地的实操指南

简介:《JTT 697.7-2014 交通信息基础数据元 第7部分》是交通运输行业标准,属于《交通信息基础数据元》系列的第7部分,专门规定道路运输信息基础数据元的编制原则、分类方法、具体内容与值域代码。该标准覆盖基本信息、行政许可、日常管理、行…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬