一文教你如何调用Ascend C算子

Ascend C是CANN针对算子开发场景推出的编程语言,原生支持C和C++标准规范,兼具开发效率和运行性能。基于Ascend C编写的算子程序,通过编译器编译和运行时调度,运行在昇腾AI处理器上。使用Ascend C,开发者可以基于昇腾AI硬件高效实现自定义的创新算法。
本文重点介绍基于Ascend C算子编程语言完成自定义算子的开发和部署后,如何调用自定义算子验证算子功能。

三种常见的算子调用方式

 目前,Ascend C算子有三种常见的调用方式:

1. Kernel直调:完成算子核函数开发和Tiling实现后,可基于内核调用符方式进行完成算子的调用,用来快速验证算法逻辑。

2. 单算子调用:相比于Kernel直调,单算子调用是一种较为标准的调用方式。开发者在完成所有算子交付件开发、编译部署之后,一般通过单算子调用方式验证单算子功能以满足交付条件,包括两种调用方式:

  • 单算子API执行:基于C语言的API执行算子,直接调用单算子API接口,无需提供单算子描述文件进行离线模型的转换。
  • 单算子模型执行:基于图IR执行算子,先编译算子(例如,使用ATC工具将Ascend IR定义的单算子描述文件编译成算子om模型文件),再调用AscendCL接口加载算子模型,最后调用AscendCL接口执行算子。

3. 在PyTorch、ONNX、TensorFlow等三方框架中调用算子:需要完成框架适配开发,即可从第三方框架实现算子调用。

 当然,除了可以调用自定义算子进行功能验证外,开发者也可以通过单算子调用方式直接调用昇腾算子库中预制的算子,使用昇腾算力。

 

通过单算子API执行方式调用算子

 通过单算子API执行方式调用算子,是算子交付阶段最重要的一种调用方式,也是Ascend C算子开发人员必须掌握的算子调用手段,下面做重点讲解。开发者若想了解其他方式,可以移至文末查阅“Ascend C一站式学习资源”[1]。

Ascend C算子开发并编译部署完成后,会在算子包安装目录下的op_api目录下会自动生成单算子API,以默认安装场景为例,单算子调用的头文件.h和动态库libcust_opapi.so所在的目录结构为:

├── opp    //算子库目录
│   ├── vendors     //自定义算子所在目录
│       ├── config.ini
│       └── vendor_name1   // 存储对应厂商部署的自定义算子,此名字为编译自定义算子安装包时配置的vendor_name,若未配置,默认值为customize
│           ├── op_api
│           │   ├── include
│           │   │  └── aclnn_xx.h
│           │   └── lib
│           │       └── libcust_opapi.so
...

 aclnn_xx.h中的算子API形式一般定义为“两段式接口”,形如:

aclnnStatus aclnnXxxGetWorkspaceSize(const aclTensor *src, ..., aclTensor *out, uint64_t workspaceSize, aclOpExecutor **executor);
aclnnStatus aclnnXxx(void* workspace, int64 workspaceSize, aclOpExecutor* executor, aclrtStream stream);

单算子API可以直接在应用程序中调用,大致过程为:

  1. 使用第一段接口aclnnXxxGetWorkspaceSize计算本次API调用计算过程中需要多少的workspace内存
  2. 获取到本次API计算需要的workspace大小后,按照workspaceSize大小申请Device侧内存
  3. 调用第二段接口aclnnXxx,调用对应的单算子二进制执行计算

完整调用流程如下:

 

下面提供单算子调用的关键代码示例,供开发者参考:  

// 1.AscendCL初始化
aclRet = aclInit("../scripts/acl.json");
 
// 2.运行管理资源申请
int deviceId = 0;
aclRet = aclrtSetDevice(deviceid);
// 获取软件栈的运行模式,不同运行模式影响后续的接口调用流程(例如是否进行数据传输等)
aclrtRunMode runMode;
bool g_isDevice = false;
aclError aclRet = aclrtGetRunMode(&runMode);
g_isDevice = (runMode == ACL_DEVICE);
 
// 3.申请内存存放算子的输入输出
// ......
 
// 4.传输数据
if (aclrtMemcpy(devInputs_[i], size, hostInputs_[i], size, kind) != ACL_SUCCESS) {
    return false;
}
 
// 5.计算workspace大小并申请内存
size_t workspaceSize = 0;
aclOpExecutor *handle = nullptr;
auto ret = aclnnAddCustomGetWorkspaceSize(inputTensor_[0], inputTensor_[1], outputTensor_[0],
                                          &workspaceSize, &handle);
// ...
void *workspace = nullptr;
if (workspaceSize != 0) {
    if (aclrtMalloc(&workspace, workspaceSize, ACL_MEM_MALLOC_NORMAL_ONLY) != ACL_SUCCESS) {
        ERROR_LOG("Malloc device memory failed");
    }
}
 
// 6.执行算子
if (aclnnAddCustom(workspace, workspaceSize, handle, stream) != ACL_SUCCESS) {
    (void)aclrtDestroyStream(stream);
    ERROR_LOG("Execute Operator failed. error code is %d", static_cast<int32_t>(ret));
    return false;
}
 
// 7.同步等待
aclrtSynchronizeStream(stream);
 
// 8.处理执行算子后的输出数据,例如在屏幕上显示、写入文件等,由用户根据实际情况自行实现
// ......
 
// 9.释放运行管理资源
aclRet = aclrtResetDevice(deviceid);
// ....
 
// 10.AscendCL去初始化
aclRet = aclFinalize();

运行一个完整的算子调用程序 

昇腾的gitee仓中提供了完整的样例工程LINK,工程目录结构如下: 

├──input                                                 // 存放脚本生成的输入数据目录
├──output                                                // 存放算子运行输出数据和真值数据的目录
├── inc                           // 头文件目录  
│   ├── common.h                 // 声明公共方法类,用于读取二进制文件  
│   ├── operator_desc.h          // 算子描述声明文件,包含算子输入/输出,算子类型以及输入描述与输出描述  
│   ├── op_runner.h              // 算子运行相关信息声明文件,包含算子输入/输出个数,输入/输出大小等  
├── src  
│   ├── CMakeLists.txt    // 编译规则文件
│   ├── common.cpp         // 公共函数,读取二进制文件函数的实现文件
│   ├── main.cpp    // 单算子调用应用的入口
│   ├── operator_desc.cpp     // 构造算子的输入与输出描述  
│   ├── op_runner.cpp   // 单算子调用主体流程实现文件
├── scripts
│   ├── verify_result.py    // 真值对比文件
│   ├── gen_data.py    // 输入数据和真值数据生成脚本文件
│   ├── acl.json    // acl配置文件

步骤 1 增加头文件引用。 

安装部署完成后,会在算子包安装目录下的op_api目录生成单算子调用的头文件aclnn_xx.h和动态库libcust_opapi.so,编写单算子的调用代码时,要包含自动生成的单算子API执行接口头文件:

#include "aclnn_add_custom.h"

步骤 2  修改CMakeLists文件。

编译算子调用程序时,需要在头文件的搜索路径include_directories中增加算子包安装目录下的op_api/include目录,便于找到该头文件;同时需要链接cust_opapi动态库。

  • 设置CUST_PKG_PATH变量为算子包安装目录下的op_api目录,以下样例仅为参考,请根据算子包部署的实际目录位置进行设置。

if (NOT DEFINED ENV{DDK_PATH})
    set(INC_PATH "/usr/local/Ascend/ascend-toolkit/latest")
    message(STATUS "set default INC_PATH: ${INC_PATH}")
else ()
    message(STATUS "env INC_PATH: ${INC_PATH}")
endif()
set(CUST_PKG_PATH "${INC_PATH}/opp/vendors/customize/op_api")

  • 在头文件的搜索路径include_directories中增加算子包安装目录下的op_api/include目录。

include_directories(
    ${INC_PATH}/runtime/include
    ${INC_PATH}/atc/include
    ../inc
    ${CUST_PKG_PATH}/include 
)

  • 链接cust_opapi链接库。

target_link_libraries(execute_add_op
    ascendcl
    cust_opapi 
    acl_op_compiler
    nnopbase
    stdc++
)

 

步骤 3 生成测试数据。

 在样例工程目录下,执行如下命令:

python3 scripts/gen_data.py

会在工程目录下input目录中生成两个shape为(8,2048),数据类型为float16的数据文件input_0.bin与input_1.bin,用于进行AddCustom算子的验证。代码样例如下:

import numpy as np
a = np.random.randint(100, size=(8, 2048,)).astype(np.float16)
b = np.random.randint(100, size=(8, 2048,)).astype(np.float16)
a.tofile('input_0.bin')
b.tofile('input_1.bin')

步骤 4 程序编译与运行。

  1. 开发环境上,设置环境变量,配置AscendCL单算子验证程序编译依赖的头文件与库文件路径,如下为设置环境变量的示例。${INSTALL_DIR}表示CANN软件安装目录,例如,$HOME/Ascend/ascend-toolkit/latest。{arch-os}为运行环境的架构和操作系统,arch表示操作系统架构,os表示操作系统,例如x86_64-linux。

    export DDK_PATH=${INSTALL_DIR}
    export NPU_HOST_LIB=${INSTALL_DIR}/{arch-os}/lib64
  2. 编译样例工程,生成单算子验证可执行文件。
    a. 切换到样例工程根目录,然后在样例工程根目录下执行如下命令创建目录用于存放编译文件,例如,创建的目录为“build”。

    mkdir -p build

    b. 进入build目录,执行cmake编译命令,生成编译文件,命令示例如下所示:

    cd build
    cmake ../src

    c. 执行如下命令,生成可执行文件。

    make
    会在工程目录的output目录下生成可执行文件execute_add_op
  3. 执行单算子
    a. 以运行用户(例如HwHiAiUser)拷贝开发环境中样例工程output目录下的execute_add_op到运行环境任一目录。
    说明: 若您的开发环境即为运行环境,此拷贝操作可跳过。

    b. 在运行环境中,执行execute_add_op

    chmod +x execute_add_op
    ./execute_add_op

    会有如下屏显信息:
    [INFO]  Set device[0] success
    [INFO]  Get RunMode[1] success
    [INFO]  Init resource success
    [INFO]  Set input success
    [INFO]  Copy input[0] success
    [INFO]  Copy input[1] success
    [INFO]  Create stream success
    [INFO]  Execute aclnnAddCustomGetWorkspaceSize success, workspace size 0
    [INFO]  Execute aclnnAddCustom success
    [INFO]  Synchronize stream success
    [INFO]  Copy output[0] success
    [INFO]  Write output success
    [INFO]  Run op success
    [INFO]  Reset Device success
    [INFO]  Destory resource success

    如果有Run op success,表明执行成功,会在output目录下生成输出文件output_z.bin。
  4. 比较真值文件
    切换到样例工程根目录,然后执行如下命令:

    python3 scripts/verify_result.py output/output_z.bin output/golden.bin

    会有如下屏显信息:

    test pass

    可见,AddCustom算子验证结果正确。

----结束

 

 更多学习资源

 [1]Ascend C一站式学习资源:Ascend C-昇腾社区

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Postman快捷功能-快速填写请求头

大家好&#xff0c;之前给大家分享关于 Postman 工具的基础使用&#xff0c;今天给大家介绍一个快捷功能&#xff0c;可以一定程度提高我们使用 Postman 工具的效率&#xff0c;在我们进行接口测试时&#xff0c;几乎每个接口都需要填写 Headers&#xff0c;且 Headers 中的参数…

MySQL--联合索引应用细节应用规范

目录 一、索引覆盖 1.完全覆盖 2.部分覆盖 3.不覆盖索引-where条件不包含联合索引的最左则不覆盖 二、MySQL8.0在索引中的新特性 1.不可见索引 2.倒序索引 三、索引自优化--索引的索引 四、Change Buffer 五、优化器算法 1.查询优化器算法 2.设置算法 3.索引下推 …

如何使用OutputStream类实现文件的读写操作?

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

如何提升项目经理的汇报能力?从这四点做起

项目经理不仅需要管理项目进度、预算和资源&#xff0c;更需要与各方进行有效的沟通&#xff0c;确保项目的顺利进行。而在所有沟通形式中&#xff0c;当众演讲无疑是难度最大的一种。 他们需要向团队成员传达项目的最新进展和要求&#xff0c;向领导和客户汇报工作成果&…

Java 定义类型处理MySQL point类型数据

1.三个类来处理 引入maven依赖 <!-- 引入 jts 库解析 POINT --><dependency><groupId>com.vividsolutions</groupId><artifactId>jts</artifactId><version>1.13</version></dependency>import javax.validation.constr…

推送邮件接口设置的方法?邮件接口的作用?

推送邮件接口如何与现有系统集成&#xff1f;怎么调试邮件接口&#xff1f; 通过推送邮件接口&#xff0c;应用程序可以自动向用户发送邮件通知&#xff0c;提醒他们重要事件或更新。AokSend将介绍如何设置推送邮件接口&#xff0c;以便您的应用程序能够充分利用这一功能。 推…

和为k的子数组 ---- 前缀和

题目链接 题目: 分析: 思考: 此题能否用滑动窗口来解决? 滑动窗口的适用前提是具有单调性, left和right指针是不回退的, 此题中数组有负数和零, 很难保证指针不回退, 所以不能用滑动窗口利用前缀和的思想, 计算以i结尾的所有子数组, 前缀和为sum[i] 想要找到和为k的数组, 我…

基于图鸟UI的圈子商圈:一个全栈前端模板的探索与应用

摘要&#xff1a; 本文介绍了一个基于图鸟UI的纯前端模板——圈子商圈&#xff0c;它支持微信小程序、APP和H5等多平台开发。该模板不仅包含丰富的UI组件和页面模板&#xff0c;还提供了详尽的使用文档&#xff0c;旨在帮助开发者快速构建出酷炫且功能齐全的前端应用。本文将从…

让WSL内核使用BBR拥塞控制算法

使用git命令从Linux内核的Git仓库中获取源代码,$ git clone https://github.com/microsoft/WSL2-Linux-Kernel.git,找到对应的内核版本$ git log --grep="5.15.146.1-microsoft-standard-WSL2",回退到本机安装的内核版本$ git checkout <commit-id> ee5b8e3…

在 Rocky 9 上编译 MySQL 8.2.0 Debug 版本编译指南

↑ 关注“少安事务所”公众号&#xff0c;欢迎⭐收藏&#xff0c;不错过精彩内容~ unsetunset前情提要unsetunset 前文已经介绍了如何安装 Rocky Linux 9.2&#xff0c;这里便不再赘述。 同时&#xff0c;也已经介绍过 MySQL 8.2.0 的参数变化&#xff0c;以及提及如何安装 MyS…

力扣:236.二叉树的最近公共祖先(C++)

文章目录 1. 题目描述2. 题目解析2.1 思路一2.1 思路二 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 题目来源: 力扣…二叉树的最近公共祖先 1. 题目描述 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表…

代码随想录算法训练营第四十一天 | 理论基础、509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯

理论基础 代码随想录 视频&#xff1a;从此再也不怕动态规划了&#xff0c;动态规划解题方法论大曝光 &#xff01;| 理论基础 |力扣刷题总结| 动态规划入门_哔哩哔哩_bilibili 动归五部曲 1.dp数组以及下标的含义 2.递推公式 3.dp数组如何初始化 4.遍历顺序(例如先背包再…

ue的event dispatch.操作步骤,最详细了

功能&#xff1a;按下键盘1&#xff0c;send方监控键盘事件&#xff0c;recv方打印success Dispatch 间接通信 示例&#xff1a;1.发送方按下键盘1。2.接收方打印success 蓝图很简单&#xff1a; 发送方 接收方 具体操作步骤如下&#xff1a; 1.场景发送方运行监听键盘 2.接受…

Seurat Dimplot函数学习总结

今天为了画这个cluster中怎么显示标签的图&#xff0c;研究了一个Seurat中怎么画这个图的&#xff0c;下面是学习过程中做的总结 运行例子 rm(listls()) library(Seurat) library(SeuratData) library(ggplot2) library(patchwork) pbmc3k.final <- LoadData("pbmc3k…

学浪的缓存怎么导出来

学浪的缓存导出问题困扰着许多用户&#xff0c;备份和管理数据变得至关重要。在数字化时代&#xff0c;保护和利用数据是企业和个人不可或缺的需求。在这篇文章中&#xff0c;我们将深入探讨学浪缓存导出的方法&#xff0c;为您解决疑惑&#xff0c;让您轻松掌握数据的安全与便…

自定义类型详解(结构体,位段,枚举,联合体)

目录 结构体 结构体的自引用 匿名结构体 结构体内存对齐 结构体内存对齐的意义 修改默认对齐数 位段 位段的内存分配 位段的跨平台问题 位段的应用 枚举 枚举类型的定义 枚举和#define的区别 联合体&#xff08;共用体&#xff09; 联合体大小的计算 结构体 C语…

斐讯N1刷OpenWRT并安装内网穿透服务实现远程管理旁路由

文章目录 前言1. 制作刷机固件U盘1.1 制作刷机U盘需要准备以下软件&#xff1a;1.2 制作步骤 2. N1盒子降级与U盘启动2.1 N1盒子降级2.2 N1盒子U盘启动设置2.3 使用U盘刷入OpenWRT2.4 OpenWRT后台IP地址修改2.5 设置旁路由&无线上网 3. 安装cpolar内网穿透3.1 下载公钥3.2 …

08Django项目--用户管理系统--查(前后端)

对应视频链接点击直达 TOC 一些朋友加我Q反馈&#xff0c;希望有每个阶段的完整项目代码&#xff0c;那从今天开始&#xff0c;我会上传完整的项目代码。 用户管理&#xff0c;简而言之就是用户的增删改查。 08项目点击下载&#xff0c;可直接运行&#xff08;含数据库&…

3个完美恢复方案!苹果手机恢复视频就是这么简单

在日常生活中&#xff0c;我们使用苹果手机记录了许多珍贵的视频&#xff0c;包括家庭聚会、旅行经历等。但是我们不小心删除了&#xff0c;在“最近删除”文件夹中也找不到。 别担心&#xff0c;这并不困难&#xff01;无论您是意外删除了重要的视频还是遇到了其他数据丢失问…

PawSQL: 企业级SQL审核工具的新玩家

随着数据库应用在企业中的广泛使用&#xff0c;确保SQL代码质量的重要性日益凸显。现有的SQL审核工具很多&#xff0c;包括Yearning、goInception、Bytebase、爱可生的SQLE、云和恩墨的SQM等等&#xff0c;但是它们或者规则覆盖度、或者是在正确率等方面存在明显不足&#xff1…