2023·CANN训练营第二季——跟着sample仓例程,动手写(改)自己的AscendC算子

前言:

        AscendC算子先进,硬核吗?必须是!那AscendC算子开发很难了,必须不是,算子开发很难,但AscendC开发算子不难!把复杂的事情流程(范式)化,把困难的事情简单(SPMD)化,这才是AscendC算子开发的硬核所在。这篇文档,交流下通过参考例程,动手写(改)出自己的AscendC算子。

        选择LeakyReLU算子作为样例,有点投机取巧的成分,因为sample仓本身就有部分代码。拿它作为例子,是为了展示一个知识点“通过TilingData传递算子的属性信息”。LeakyReLU算子有一个“negative_slope”,这是个标量,本例就是将这个属性值通过TilingData传递给核函数,进行运算的。本篇以实战为主,相关知识都给了官方链接,有兴趣的小伙伴可以参考阅读。受限于篇幅,本篇仅完成算子工程代码和简单核函数方式调用工程的编写,单算子调用工程以后再展开写。下面开始我们的AscendC编程之旅。

一、准备开发环境

按照“Ascend C环境准备 https://www.hiascend.com/forum/thread-0235128261452483095-1-1.html?fid=0163125572293226003”贴,选择免费的modelartsCodeLab搭建开发环境,在此环境上,还可以完成CPU侧的验证,而且这个环境自带pytorch,所以也可以在算子分析阶段用来熟悉算子。如果需要进行NPU实际环境的验证,可参考“AscendC算子NPU开发调试环境成功搭建篇https://www.bilibili.com/read/cv26991439/ ”,完成环境搭建。

        使用此环境需要注意,由于modelarts,只保留work目录的内容(安装包放在work目录,就需要每次重新下载了),所以每次使用前需要重新安装toolkits和算子开发包,并配置环境变量。

        安装toolkit和算子开发包:

./Ascend-cann-toolkit_7.0.RC1.alpha002_linux-x86_64.run --install --force

tar -xf Ascend-cann-communitysdk_7.0.RC1.alpha002_linux-x86_64.tar.gz -C ~/Ascend/ascend-toolkit/latest

        配置环境变量:

source /home/ma-user/Ascend/ascend-toolkit/set_env.sh

export ASCEND_CUSTOM_PATH=$HOME/Ascend/ascend-toolkit/latest

export ASCEND_HOME_DIR=$HOME/Ascend/ascend-toolkit/latest

export PATH=/home/ma-user/work/cmake-3.26.4-linux-x86_64/bin:$PATH

二、下载参考例程:

昇腾的sample仓(https://gitee.com/ascend/samples.git)提供了AscendC算子的代码例程,目前有两处:

1)samples/operator目录下,有“AddCustomSample”和“LeakyReLUCustomSample”两个例程。

2)samples/ cplusplus / level1_single_api / 4_op_dev / 6_ascendc_custom_op目录下,有一些例程。

        两部分例程都很好,第2个目录下例程知识点比较全,第1个目录下例程比较简单且结构更为简洁,比较适合拿来作为初学的样板做练习。本文以“samples/operator目录”下的AddCustomSample工程作为模板。

三、开发过程

1、算子分析

1)先去官网找一下,算子的定义https://pytorch.org/docs/stable/generated/torch.nn.LeakyReLU.html#torch.nn.LeakyReLU,然后在pytorch环境下,运行下算子,了解各种参数的意义。


2)分析计算实现的方法,查找AscendC官方文档,在标量双目指令中有LeakyRelu算子,本例可以直接使用。对没有直接API实现的算子,需要先分解成基本API的组合。

3)出算子设计规格表:假定输入类型为float16,形状8 * 1024(和AddCustom保持一致),且不考虑“inplace的情形

关于算子分析可参看“文档首页>CANN社区版>7.0.RC1.alpha003>算子开发>Ascend C算子开发>算子开发(基础篇)>矢量编程>算子分析https://www.hiascend.com/document/detail/zh/CANNCommunityEdition/70RC1alpha003/operatordevelopment/ascendcopdevg/atlas_ascendc_10_0015.html”,

        如下图所示:左侧是Add例程,右侧是参考例程写出的“LeakyReluCustom”。红色的是有差异的地方,请记住这些或者等我们完成代码编写后再回头看一下这儿,会发现所做的修改都和此处有关系。

2、编写LeakyReLU算子原型定义json文件

        为了方便描述,我将add_custom.json输入类型做了简化,仅保留了float16。根据上面的分析表,将输入和输出写对就可以了,这里面需要注意“属性”的写法。具体写法可参考文档:“文档首页>CANN社区版>7.0.RC1.alpha003>算子开发>Ascend C算子开发>算子开发(进阶篇)>基于msopgen工具创建算子工程

https://www.hiascend.com/document/detail/zh/CANNCommunityEdition/70RC1alpha003/operatordevelopment/ascendcopdevg/atlas_ascendc_10_0023.html

3、生成算子工程

        使用msopgen生成算子工程。

/home/ma-user/Ascend/ascend-toolkit/latest/python/site-packages/bin/msopgen gen -i ./leakyrely_custom.json -c ai_core-ascend910,ai_core-ascend910B,ai_core-ascend310p -lan cpp -out ./LeakyReLUCustom

      关于msopgen的使用,请参考昇腾社区的文档“文档首页>CANN社区版>7.0.RC1.alpha003>算子开发>Ascend C算子开发>附录>msopgen工具使用>使用说明”

https://www.hiascend.com/document/detail/zh/CANNCommunityEdition/70RC1alpha003/operatordevelopment/ascendcopdevg/atlas_ascendc_10_0076.html

      参数含义:

-i:指定算子原型定义文件add_custom.json所在路径,请根据实际情况修改。

-c:ai_core-<soc_version>代表算子在AI Core上执行,<soc_version>为昇腾AI处理器的型号。多个处理器之间用逗号“,”分割。

-lan: 参数cpp代表算子基于Ascend C编程框架,使用C++编程语言开发。

-out:生成文件所在路径,可配置为绝对路径或者相对路径,并且工具执行用户对路径具有可读写权限。若不配置,则默认生成在执行命令的当前路径。

      生成的目录结构如下图右侧:此处主要修改三个文件:算子tiling定义文件;host侧实现文件;kernel侧实现文件。

4、修改device侧和host侧的代码

     1)修改host/leaky_relu_custom_tiling.h

tilingdata是用来计算数据切分的,在固定算子shape的情形下,只需要totalLength和tileNum即可,leakyreluCustom算子需要传递value的属性值,所以增加1个value。改动处都用红框标记了,这里需要注意的就是增加value那一行。进一步学习,可参考“文档首页>CANN社区版>7.0.RC1.alpha003>算子开发>Ascend C算子开发>算子开发(进阶篇)>host侧算子实现>Tiling实现https://www.hiascend.com/document/detail/zh/CANNCommunityEdition/70RC1alpha003/operatordevelopment/ascendcopdevg/atlas_ascendc_10_0027.html”。

      2)修改host/leaky_relu_custom.cpp代码

host侧算子实现开发包括Tiling实现、Shape推导等函数实现、算子原型注册。进一步学习,可参考“文档首页>CANN社区版>7.0.RC1.alpha003>算子开发>Ascend C算子开发>算子开发(进阶篇)>host侧算子实现>host侧算子实现概述https://www.hiascend.com/document/detail/zh/CANNCommunityEdition/70RC1alpha003/operatordevelopment/ascendcopdevg/atlas_ascendc_10_0026.html

首先是Tiling实现,这里面需要注意的是获取算子value属性代码,其余的可以和例程保持一致即可。GetAttrs()可在API参考里查找。“文档首页>CANN社区版>7.0.RC1.alpha003>算子开发>Ascend C算子开发>API参考>Host侧实现API>basics>ComputeNodeInfo类>GetAttrs”

      Shape推导的代码不用修改,输出shape和输入shape保持一致。

算子原型注册代码有差异,仔细看的话,会发现和算子原型定义的那个json文件是一致的。但此处通过工具自动生成,也不需要修改。请注意右侧用红框标出的部分,特别是关于属性的定义“this->Attr("value").Float();”

3)修改device侧代码

        这是算子编程的很重要的部分,需要修改的地方如下图所示。进一步可阅读“文档首页>CANN社区版>7.0.RC1.alpha003>算子开发>Ascend C算子开发>算子开发(进阶篇)>kernel侧算子实现https://www.hiascend.com/document/detail/zh/CANNCommunityEdition/70RC1alpha003/operatordevelopment/ascendcopdevg/atlas_ascendc_10_0024.html”。

        算子类实现代码,进一步阅读,参考“文档首页>CANN社区版>7.0.RC1.alpha003>算子开发>Ascend C算子开发>算子开发(基础篇)>矢量编程>算子类实现https://www.hiascend.com/document/detail/zh/CANNCommunityEdition/70RC1alpha003/operatordevelopment/ascendcopdevg/atlas_ascendc_10_0017.html”。这部分内容建议刚开始学的小伙伴要好好看明白,这里面包含了“多核并行”,“编程范式”,“流水线”等众多AscendC编程思想。虽说以后编写代码也可以ctrl+c,和ctrl+v,但理解了就能一劳永逸。

5、编写简单核函数调用代码

        简单、粗暴,直接将例程的“kernel_direct_call"目录拷过来,然后将下图中的三个文件改名。这三个文件,加上run.sh,我们只需要修改这四个文件,就可以完成调用代码的改写。这部分内容,有兴趣的小伙伴,参看“文档首页>CANN社区版>7.0.RC1.alpha003>算子开发>Ascend C算子开发>算子开发(基础篇)>核函数运行验证https://www.hiascend.com/document/detail/zh/CANNCommunityEdition/70RC1alpha003/operatordevelopment/ascendcopdevg/atlas_ascendc_10_0019.html

1)kernel_call_leakyrelu_custom_tiling.h

      这个文件,是模拟算子工程host侧算子实现和kernel侧算子实现,传递tilingdata数据用的。改动很小,但需要花时间去好好阅读下,感觉此处解密了AscendC算子这一功能的实现方式。

2)kernle_call_leakyrelu_custom.py

      此脚本,生成输入数据,然后计算出输出数据,并落盘,然后再run.sh脚本里与AscendC算子的结果进行比较。

      3)main.cpp

      这里面是分别cpu和npu方式调用核函数的代码,“孪生调试”。代码修改主要就是名称,函数的参数数量之类,版面首限,也没有办法展开,不再赘述。此处需要注意的是读取tilingdata模拟数据时,因为增加了算子属性value,所以读取长度,需要再原来的基础上增加sizeof(float)。

4)run.sh

      主要修改2处:

      修改算子工程名

      需要将算子工程op_kernel的算子实现代码拷贝到核函数调用工程里,需要对路径名和文件名做相应修改。run.sh其余部分无需修改,它是通过比较kernle_call_leakyrelu_custom.py和AscendC算子对相同数据的计算结果的md5sum,来判断结果是否一致的。

四、编译运行

1、CPU模式

      1)将代码做成zip格式的压缩包,启动环境,将代码上传到环境。

      2)安装toolkit和算子开发包。(参见第一节,搭建cpu开发运行环境章节)

      3)解压缩。并给算子工程“/util”目录下文件,赋权限750,否则会报错。

      4)编译运行

      进入“kernel_direct_call”目录,运行“bash run.sh ascend910B1 cpu”

      运行结果:

2、npu模式

参考“AscendC算子NPU开发调试环境成功搭建篇https://www.bilibili.com/read/cv26991439/ ”搭建NPU的调试运行环境。并把代码搞里头,过程参考cpu模式。

      进入kernel_direct_call目录,运行 bash run.sh ascend910B1 npu_onboard 

运行结果如下:

      至此,完成了leakyrelu算子的开发和核函数调用方式的验证。

附录:

      看到这儿的小伙伴,如果还没有加入CANN训练营,可以按下面的链接进行报名,不仅可以学到基于昇腾AI开发的知识,还有大奖可以拿。

报名链接:https://www.hiascend.com/developer/activities/details/84b950830fc44476851860f51f0873a2/signup?channelCode=0&recommended=234384

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352

推荐阅读更多精彩内容