尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

ops-cv 快速入门:基于 AddExample 算子跑通 CANN 算子编译、开发、调试与验证全流程

ops-cv 快速入门:基于 AddExample 算子跑通 CANN 算子编译、开发、调试与验证全流程 ops-cv 快速入门基于 AddExample 算子跑通 CANN 算子编译、开发、调试与验证全流程【免费下载链接】ops-cv本项目是CANN提供的图像处理、目标检测相关的算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-cv本文是 docs/QUICKSTART.md 的深度实践指南。它以ops-cv仓库内置的 AddExample 示例算子为主线带你从零体验「源码编译 → 打包安装 → 运行样例 → 修改 Kernel → 打印调试 → 性能采集 → 修改输入验证」的完整算子开发闭环。读完本文你将掌握build.sh编译与运行命令的正确用法、Ascend C 算子 Kernel 的基本结构与修改方法以及使用 printf / DumpTensor / msprof 定位算子问题的实用技能。使用须知先准备好环境再动手ops-cv是 CANN 算子库中提供图像处理、目标检测等能力的高阶算子库包含 image、objdetect 两大类算子。在开始编译算子之前需要先按项目 README.md 完成环境准备与源码下载前提条件参考 README.md 完成 NPU 驱动、CANN 包安装等环境准备更详细的部署指引见 环境部署。推荐部署方式快速入门场景推荐使用CANNLab 云开发环境或 Docker 部署操作最简单——这两类环境默认已提供最新版本 CANN 包如需体验 master 分支最新能力则需手动搭建环境并注意源码分支与 CANN 版本的配套关系。版本配套源码会跟随 CANN 软件版本发布务必选择与 CANN 版本配套的 GitCode 标签源码使用 master 分支可能存在版本不匹配的风险参见 README.md。为方便快速了解算子开发全流程本指南以AddExample 算子为实践对象其源码位于 examples/add_example整体操作分为四个阶段编译运行编译自定义算子包并安装实现快速调用算子算子开发通过修改现有算子 Kernel体验开发、编译、验证的完整闭环算子调试掌握算子打印和性能采集方法算子验证学习如何修改算子 example 样例以验证算子在不同输入下的功能正确性。一、编译运行快速验证环境可用性本阶段目的是快速体验项目标准流程验证环境能否成功进行算子源码编译、打包、安装和运行。本指南以单算子编译过程为例也支持编译整个算子库、离线编译等多种场景编译过程中的常见问题均可参考 《源码构建指南》。1. 进入项目源码CANNLab 云开发环境默认提供最新版本 CANN 包配套的项目源码资源一般在/mnt/workspace/gitCode目录下进入目标分支源码目录即可。非 CANNLab 云开发环境根据 release 仓库 源码与 CANN 版本配套关系执行如下命令下载源码${tag_version}替换为目标分支标签例如9.0.0git clone -b ${tag_version} https://gitcode.com/cann/ops-cv.git cd ops-cv如需切换源码分支版本在源码目录执行git branch查询当前源码版本在源码目录执行git checkout ${tag_version}切换到目标分支源码注意满足源码与 CANN 版本配套关系若源码已存在执行git pull拉取最新源码。2. 编译 AddExample 算子通用命令格式为bash build.sh --pkg --soc芯片版本 --ops算子名。说明编译前请确保已配置 CANN 环境变量否则可能因找不到ASCEND_HOME_PATH等导致编译失败。默认路径安装时执行source /usr/local/Ascend/cann/set_env.sh。以 AddExample 算子为例编译命令如下bash build.sh --pkg --soc${soc_version} --opsadd_example -j16参数含义--pkg表示编译并打包生成 run 包--soc指定目标芯片版本--ops指定待编译的算子名-j16表示 16 线程并行编译。产品名对应的${soc_version}取值如下请按实际场景传参产品系列soc_version 取值Atlas A2 训练系列产品 / Atlas A2 推理系列产品ascend910bAtlas A3 训练系列产品 / Atlas A3 推理系列产品ascend910_93950 系列产品Ascend 950PR / 950DTascend950若提示如下信息说明编译成功Self-extractable archive cann-ops-cv-custom_linux-${arch}.run successfully created.编译成功后run 包存放于项目根目录的build_out目录下。3. 安装 AddExample 算子包./build_out/cann-ops-cv-*linux*.runAddExample安装在${ASCEND_HOME_PATH}/opp/vendors路径中${ASCEND_HOME_PATH}表示 CANN 软件安装目录。4. 配置环境变量将自定义算子包的路径加入环境变量确保运行时能够找到export LD_LIBRARY_PATH${ASCEND_HOME_PATH}/opp/vendors/custom_cv/op_api/lib:${LD_LIBRARY_PATH}5. 快速验证运行算子样例通用的运行命令格式bash build.sh --run_example 算子名 运行模式 包模式。以 AddExample 为例其提供了简单算子样例 test_aclnn_add_example.cpp运行该样例验证算子功能是否正常bash build.sh --run_example add_example eager cust --vendor_namecustom --soc${soc_version}注意运行样例时需确保--soc参数与编译算子包时使用的--soc取值一致否则可能报error 161001如aclnnXxxGetWorkspaceSize failed。如遇此错误请回到上文第 2 节核对--soc取值后重新编译安装。预期输出打印算子AddExample的加法计算结果表明算子已成功部署并正确执行add_example first input[0] is: 1.000000, second input[0] is: 1.000000, result[0] is: 2.000000 add_example first input[1] is: 1.000000, second input[1] is: 1.000000, result[1] is: 2.000000 add_example first input[2] is: 1.000000, second input[2] is: 1.000000, result[2] is: 2.000000 add_example first input[3] is: 1.000000, second input[3] is: 1.000000, result[3] is: 2.000000 add_example first input[4] is: 1.000000, second input[4] is: 1.000000, result[4] is: 2.000000 add_example first input[5] is: 1.000000, second input[5] is: 1.000000, result[5] is: 2.000000 add_example first input[6] is: 1.000000, second input[6] is: 1.000000, result[6] is: 2.000000 add_example first input[7] is: 1.000000, second input[7] is: 1.000000, result[7] is: 2.000000 ...6. 从源码看 AddExample 的完整算子工程在动手改代码前先通过源码结构了解一个标准算子工程包含哪些部分。AddExample 工程位于 examples/add_example其目录组织如下目录/文件作用op_kernel/add_example.h、op_kernel/add_example.cppAI Core 上的 Kernel 实现与入口函数op_kernel/add_example_tiling_data.h、op_kernel/add_example_tiling_key.hTiling 数据结构与 tiling key 声明op_host/add_example_def.cpp算子定义输入/输出规格、数据类型、AI Core 配置op_host/add_example_infershape.cppshape 与数据类型推理op_host/add_example_tiling.cppTiling分块策略计算op_host/config/ascend910b/算子二进制与简化 key 配置examples/test_aclnn_add_example.cppaclnn 方式调用样例examples/test_geir_add_example.cpp图模式GEIR调用样例tests/ut/host 侧与 kernel 侧单元测试几个关键实现事实均来自本仓库源码算子定义add_example_def.cppAddExample 声明两个必选输入x1、x2和一个必选输出y支持FLOAT、INT32两种数据类型格式为ND并通过AICore().AddConfig(...)为ascend910b、ascend910_93、ascend950三个 SOC 注册了 AI Core 编译配置。shape 推理add_example_infershape.cpp输出 shape 与输入 shape 相同输出数据类型与输入数据类型相同——这正对应公式y x1 x2。Tiling 策略add_example_tiling.cppTiling 函数通过GetPlatformInfo查询 AI Core 数量GetCoreNumAiv与 UB 大小然后按totalNum先做核切分blockFactor CeilDiv(totalIdx, coreNum)再按 UB 容量计算每核内的分块ubFactor最终结果写入 add_example_tiling_data.h 定义的AddExampleTilingData{totalNum, blockFactor, ubFactor}结构并由 Kernel 侧GET_TILING_DATA_WITH_STRUCT取用。Kernel 入口add_example.cpp根据 tiling key 使用if constexpr分发——schMode 0走AddExamplefloatschMode 1走AddExampleint32_t。二、算子开发把 Add 改成 Mul本阶段目的是对已成功运行的 AddExample 算子尝试修改核函数代码体验开发、编译、验证的完整闭环。1. 修改 Kernel 实现找到 AddExample 算子的核心 kernel 实现文件 op_kernel/add_example.h尝试将算子中的 Add 操作改为 Mul 操作__aicore__ inline void AddExampleT::Compute(int64_t currentNum) { AscendC::LocalTensorT xLocal inputQueueX.DeQueT(); AscendC::LocalTensorT yLocal inputQueueY.DeQueT(); AscendC::LocalTensorT zLocal outputQueueZ.AllocTensorT(); // 在此处将Add替换为Mul // AscendC::Add(zLocal, xLocal, yLocal, currentNum); AscendC::Mul(zLocal, xLocal, yLocal, currentNum); outputQueueZ.EnQueT(zLocal); inputQueueX.FreeTensor(xLocal); inputQueueY.FreeTensor(yLocal); }从源码看Compute只是 Kernel 流水线中的一个环节。完整的 add_example.h 实现了标准的 Ascend C 三级流水CopyIn通过DataCopyPad从 Global Memory 拷贝到 Local Tensor 并EnQue入队→ComputeDeQue取数、执行向量指令、EnQue出队→CopyOutDeQue后将结果写回 GM。TPipe配合TQueQuePosition::VECIN, BUFFER_NUM使用双缓冲BUFFER_NUM 2隐藏搬运与计算延迟Process()则按blockLength_与ubLength_计算循环次数逐块驱动整条流水线。2. 编译与验证重复上文编译运行章节中的步骤重新编译回到项目根目录bash build.sh --pkg --soc${soc_version} --opsadd_example -j16说明${soc_version}请根据实际芯片型号填写取值方式同上文编译 AddExample 算子中的说明。重新安装./build_out/cann-ops-cv-*linux*.run重新验证bash build.sh --run_example add_example eager cust --vendor_namecustom --soc${soc_version}成功标志输出结果变成乘法结果每组结果应等于两个输入之积add_example first input[0] is: 1.000000, second input[0] is: 1.000000, result[0] is: 1.000000 add_example first input[1] is: 1.000000, second input[1] is: 1.000000, result[1] is: 1.000000 add_example first input[2] is: 1.000000, second input[2] is: 1.000000, result[2] is: 1.000000 add_example first input[3] is: 1.000000, second input[3] is: 1.000000, result[3] is: 1.000000 add_example first input[4] is: 1.000000, second input[4] is: 1.000000, result[4] is: 1.000000 add_example first input[5] is: 1.000000, second input[5] is: 1.000000, result[5] is: 1.000000 add_example first input[6] is: 1.000000, second input[6] is: 1.000000, result[6] is: 1.000000 add_example first input[7] is: 1.000000, second input[7] is: 1.000000, result[7] is: 1.000000 ...补充仓库还内置了 Kernel 侧的单元测试 tests/ut/op_kernel/test_add_example.cpp它基于 gtest 与tikicpulib在 CPU 上模拟运行 KernelICPU_RUN_KF(add_example0, ...)并通过 gen_data.py 生成输入数据、比对输出结果可在无 NPU 环境下先行验证 Kernel 逻辑正确性。三、算子调试打印与性能采集本阶段以 AddExample 为例在算子中添加打印并采集算子性能数据以便后续问题分析定位。1. 打印算子如果出现执行失败、精度异常等问题添加打印进行问题分析和定位。请在 examples/add_example/op_kernel/add_example.h 中进行代码修改。printf该接口支持打印 Scalar 类型数据如整数、字符型、布尔型等详细介绍参见《Ascend C API》文档中算子调测 API printf小节blockLength_ (remainderLength tilingData-blockFactor) ? tilingData-blockFactor : remainderLength; ubLength_ tilingData-ubFactor; // 打印当前核计算Block长度 AscendC::PRINTF(Tiling blockLength is %ld\n, blockLength_);上面的blockLength_与ubLength_正是 Tiling 阶段计算出的每核元素数与本核内分块大小打印它们可以直观确认切分是否符合预期。DumpTensor该接口支持 Dump 指定 Tensor 的内容同时支持打印自定义附加信息比如当前行号等详细介绍参见《Ascend C API》文档中算子调测 API DumpTensor小节AscendC::LocalTensorT xLocal inputQueueX.DeQueT(); AscendC::LocalTensorT yLocal inputQueueY.DeQueT(); AscendC::LocalTensorT zLocal outputQueueZ.AllocTensorT(); AscendC::Add(zLocal, xLocal, yLocal, currentNum); AscendC::DumpTensor(zLocal, 0, 128); outputQueueZ.EnQueT(zLocal);示例中DumpTensor(zLocal, 0, 128)表示从第 0 个元素开始Dump 输出张量zLocal的前 128 个元素便于核对中间计算结果。2. 性能采集当算子功能验证正确后可通过msprof op命令采集算子级性能数据。生成可执行文件调用 AddExample 算子的 example 样例生成可执行文件test_aclnn_add_example该文件位于项目ops-cv/build目录bash build.sh --run_example add_example eager cust --vendor_namecustom --soc${soc_version}采集性能数据进入 AddExample 算子可执行文件目录ops-cv/build/执行如下命令msprof op --application./test_aclnn_add_example执行后会直接打印算子基础信息如 Op Name、Op Type、Task Duration、Block Dim 等和性能瓶颈提示。采集结果保存在项目ops-cv/build/目录下的OPPROF_*文件夹中命令执行完后会自动解析并导出性能数据文件。如需进一步解读各项性能指标如流水占比、带宽利用率等请参见 msProf 性能数据文件参考文档。四、算子验证修改输入数据本阶段通过修改 AddExample 算子 example 样例中的输入数据验证该算子在多种场景下的功能正确性。1. 修改测试输入找到并编辑 AddExample 的样例 examples/test_aclnn_add_example.cpp修改输入张量的形状和数值——修改输入、输出的 shape 信息以及初始化数据构造相应的输入、输出 tensorint main() { // ... 初始化代码... // ① 修改selfX的输入 // 修改前shape {32, 4, 4, 4}, 数值全为1 // 修改后将输入shape改为 {8, 8, 8, 8}并填充不同的测试数据 std::vectorint64_t selfXShape {8, 8, 8, 8}; auto selfXNumElements GetShapeSize(selfXShape); std::vectorfloat selfXHostData(selfXNumElements); // 可使用循环填充更有区分度的数据例如递增序列 for (int64_t i 0; i selfXNumElements; i) { selfXHostData[i] static_castfloat(i % 10); // 填充0-9的循环值 } // ② 参考selfX同理修改selfY和out并确保hostData长度与shape元素数一致 // ... 后续执行代码... }从该样例源码可以看到一个完整的 aclnn 调用范式Init完成aclInit、aclrtSetDevice、aclrtCreateStream初始化CreateAclTensor完成 device 内存申请aclrtMalloc、host→device 拷贝aclrtMemcpy与aclCreateTensor创建张量随后按两段式接口执行——先调用aclnnAddExampleGetWorkspaceSize获取 workspace 大小并申请内存再调用aclnnAddExample真正下发任务最后aclrtSynchronizeStream同步等待并回拷结果打印。2. 重新编译并验证由于只修改了 example 测试代码无需重新编译算子包。重新执行验证命令bash build.sh --run_example add_example eager cust --vendor_namecustom --soc${soc_version}观察算子输出结果是否符合预期——例如填充i % 10的循环数据后可核对result[i] selfXHostData[i] selfYHostData[i]若上一阶段已改为 Mul则核对乘积。结语体验完上述流程你已经跑通了编译 → 安装 → 运行 → 改码 → 调试 → 验证的算子开发全流程既会用bash build.sh --pkg --soc芯片 --ops算子名编译打包也掌握了--run_example的快速验证方法既修改过 Kernel 中 Add→Mul 的核心逻辑也学会了 printf / DumpTensor / msprof 三板斧式调测手段。如果想要进一步贡献新算子或学习更多高阶开发、调试技能如算子调用、图模式、性能调优等请访问项目 README.md 中的进阶教程与 贡献指南继续深入 ops-cv 的算子世界。【免费下载链接】ops-cv本项目是CANN提供的图像处理、目标检测相关的算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-cv创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表