一文教你如何调用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-昇腾社区

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AC/DC电源模块:提供高质量的电力转换解决方案

BOSHIDA AC/DC电源模块&#xff1a;提供高质量的电力转换解决方案 AC/DC电源模块是一种电力转换器件&#xff0c;可以将交流电转换为直流电。它通常用于各种电子设备和系统中&#xff0c;提供高质量的电力转换解决方案。 AC/DC电源模块具有许多优点。首先&#xff0c;它能够提…

【学习笔记】计算机组成原理(七)

指令系统 文章目录 指令系统7.1 机器指令7.1.1 指令的一般格式7.1.2 指令字长 7.2 操作数类型和操作类型7.2.1 操作数类型7.2.2 数据在存储器中的存放方式7.2.3 操作类型 7.3 寻址方式7.3.1 指令寻址7.3.1.1 顺序寻址7.3.1.2 跳跃寻址 7.3.2 数据寻址7.3.2.1 立即寻址7.3.2.2 直…

探秘SpringBoot默认线程池:了解其运行原理与工作方式(@Async和ThreadPoolTaskExecutor)

文章目录 文章导图Spring封装的几种线程池SpringBoot默认线程池TaskExecutionAutoConfiguration&#xff08;SpringBoot 2.1后&#xff09;主要作用优势使用场景如果没有它 2.1版本以后如何查看参数方式一&#xff1a;通过Async注解--采用ThreadPoolTaskExecutordetermineAsync…

Samtec技术漫谈 | 电动自行车中的传感器和信号传输技术

【摘要/前言】 电动自行车&#xff0c;大家熟悉吗&#xff1f; 今天的话题似乎是可以唤起大家心底骑车的美好回忆&#xff0c;我们也曾骑车探索过大自然和社区&#xff0c;自行车也是我们曾经不可或缺的便捷交通工具。 怀旧思潮的影响&#xff0c;加持科技的进步&#xff0c…

Flask 蓝图路由的模块化开发

基于 Flask 蓝图路由的模块化开发 1. 编程目标 为了提高Flask应用的可维护性和可扩展性&#xff0c;我们通过使用Flask的蓝图(Blueprint)功能&#xff0c;可以将不同的功能模块拆分到独立的文件中&#xff0c;方便后续的开发和维护。 2. 项目结构 项目结构树如下&#xff1…

Uni-App开发 导入(引入)Vant-Weapp组件;支持vue3/vue2版本和微信小程序

文章目录 目录 文章目录 操作流程 小结 概要安装流程技术细节小结 概要 Vant Weapp官网&#xff1a;Vant Weapp - 轻量、可靠的小程序 UI 组件库 准备工作&#xff0c;需要确保自己的电脑上已安装Hbuilde和node 全程操作的环境都需要这些配合才能运行上&#xff0c;可参考作者…

M功能-支付平台(三)

target&#xff1a;离开柬埔寨倒计时-221day 前言 今天周六&#xff0c;但是在柬埔寨还是工作日&#xff0c;想着国内的朋友开始休周末就羡慕呀&#xff0c;记不清在这边过了多少个周六了&#xff0c;多到我已经习惯了。而且今天技术部还停电了&#xff0c;真的是热的受不了呀…

【MATLAB源码-第74期】基于matlab的OFDM-IM索引调制系统不同频偏误码率对比,对比OFDM系统。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 OFDM-IM索引调制技术是一种新型的无线通信技术&#xff0c;它将正交频分复用&#xff08;OFDM&#xff09;和索引调制&#xff08;IM&#xff09;相结合&#xff0c;以提高频谱效率和系统容量。OFDM-IM索引调制技术的基本思想…

Android 性能为王时代SparseArray和HashMap一争高下

文章目录 一、SparseArray 源码分析1. **类定义和构造函数**2. **基本方法**2.1 put(int key, E value)2.2 get(int key)2.3 delete(int key)2.4 removeAt(int index)2.5 gc()2.6 size()2.7 keyAt(int index) 和 valueAt(int index) 3. **辅助方法**3.1 binarySearch() 二、使用…

【SpringCloud】负载均衡

目录 负载均衡什么是负载均衡生活场景为什么需要负载均衡负载均衡手段负载均衡总的来说有两种实现手段负载均衡具体可以通过多种手段来实现 SpringCloud中的负载均衡组件Ribbon VS Nginx负载均衡区别集中式LB进程内LB RibbonRibbon的工作原理Ribbon在工作时分成两步 使用1.提供…

昔日辉煌不再,PHP老矣,尚能饭否?

导语 | 近期 TIOBE 最新指数显示&#xff0c;PHP 的流行度降至了历史最低&#xff0c;排在第 17 名&#xff0c;同时&#xff0c;在年度 Stack Overflow 开发者调查报告中&#xff0c;PHP 在开发者中的受欢迎程度已经从之前的约 30% 萎缩至现在的 18%。“PHP 是世界上最好的语言…

【开源】大学生竞赛管理系统 JAVA+Vue+SpringBoot+MySQL

目录 一、系统介绍 学生管理模块 教师管理模块 竞赛信息模块 竞赛报名模块 二、系统截图 三、核心代码 一、系统介绍 基于Vue.js和SpringBoot的大学生竞赛管理系统&#xff0c;分为管理后台和用户网页端&#xff0c;可以给管理员、学生和教师角色使用&#xff0c;包括学…

【Flutter】Dialog组件PageView组件

&#x1f525; 本文由 程序喵正在路上 原创&#xff0c;CSDN首发&#xff01; &#x1f496; 系列专栏&#xff1a;Flutter学习 &#x1f320; 首发时间&#xff1a;2024年5月27日 &#x1f98b; 欢迎关注&#x1f5b1;点赞&#x1f44d;收藏&#x1f31f;留言&#x1f43e; 目…

如何确保大模型 RAG 生成的信息是基于可靠的数据源?

在不断发展的人工智能 (AI) 领域中&#xff0c;检索增强生成 (RAG) 已成为一种强大的技术。 RAG 弥合了大型语言模型 (LLM) 与外部知识源之间的差距&#xff0c;使 AI 系统能够提供更全面和信息丰富的响应。然而&#xff0c;一个关键因素有时会缺失——透明性。 我们如何能够…

mysql中单表查询的成本

大家好。我们知道MySQL在执行一个查询时&#xff0c;经常会有多个执行方案&#xff0c;然后从中选取成本最低或者说代价最低的方案去真正的执行查询。今天我们来聊一聊单表查询的成本。 那么到底什么是成本呢&#xff1f;这里我们说的成本或者代价是由两方面组成的&#xff1a…

vscode插件-03 PHP

PHP Intelephense 如果php在远程计算机上&#xff0c;要把插件安装在远程&#xff0c;而不是本地。 这个插件&#xff0c;要求php版本大于7&#xff0c;且设置环境变量&#xff08;好像不一定要设置&#xff09;。 设置里面搜索php.executablePath&#xff0c;打开setting.js…

element ui 的el-input输入一个字后失去焦点,需重新点击输入框才能再次输入

解决方案&#xff1a; 我是form表单嵌套表格&#xff0c;里面的el-input输入框&#xff0c;输入第一个值的时候会突然失去焦点&#xff0c;需要再次点击输入框才能正常输入&#xff0c;原因是table的key值&#xff0c;需要改成正常的index即可&#xff0c;如果你是循环的&…

ESP32入门:1、VSCode+PlatformIO环境搭建

文章目录 背景安装vscode安装配置中文 安装Platform IO安装PIO 新建ESP32工程参考 背景 对于刚接触单片机的同学&#xff0c;使用vscodeplatformIO来学习ESP32是最方便快捷的&#xff0c;比IDF框架简单&#xff0c;且比arduino文件管理性能更好。但是platformIO安装较为麻烦&a…

gnocchi学习小结

背景 总结gnocchi 4.4版本gnocchi-metricd工作流程 入口 gnocchi.cli.metricd metricd stop after processing metric默认为0&#xff0c;调servicemanager run MetricdServiceManager __init__ 服务逻辑封装到MetricdServiceManager初始化中 主要由MetricProcessor, Met…

【方法】ZIP压缩文件的密码如何设置和取消?

ZIP是一种常见的压缩文件格式&#xff0c;今天来分享一下&#xff0c;ZIP压缩文件如何设置密码保护&#xff0c;以及如何取消密码&#xff0c;不清楚的小伙伴一起来看看吧&#xff01; 设置ZIP文件密码&#xff1a; 想要给ZIP压缩包设置密码&#xff0c;需要用到支持ZIP格式的…