GPU异构算子全流程开发指导
Tips
① 此文档详细介绍了MindSpore GPU异构算子开发流程,与官方文档相比本文档更加侧重于开发文件的解读以及常用开发方法的讲解。同时本文档用词相对简单,主要帮助大家了解GPU算子开发需要写什么,各种文件的作用是什么以及应该怎么写这些文件,而官方文档中则更偏向于基础概念和框架的介绍,建议大家将两个文档结合起来阅读,这样更能够加深理解。
② 本文篇幅较长,如果有自己熟悉的内容可以直接跳过,但是建议大家能够仔细阅读第三章,充分了解GPU算子需要开发哪些文件、每个开发文件的作用以及常用的方法,这样可以更快的入门,开始开发算子。
③ MindSpore GPU异构算子调用流程如下
④ 此文档也有网页版:https://bbs.huaweicloud.com/blogs/364623,大家愿意的话可以支持一下,刷一刷阅读量。
⑤ 本文主要为前期准备和开发流程,附加了两个关于接口文档测试的内容,后续进入测试阶段我也会写一个GPU算子测试指导。
⑥ 如有遗漏或错误,欢迎指出与修改。
常用网址
① GPU 算子全流程开发指导录屏
② BartlettWindow 算子 PR
③ MindSpore 算子 Issue 查询网址
④ MindSpore 官方安装网址
⑤ MindSpore 官方算子查询网址
⑥ 谭升 -GPU 编程
一、 环境配置
1. 连接服务器
(1) ssh跳转连接
使用服务器链接软件在同一个连接会话中,依次连续输入以下命令:
① 跳转服务器1:
ssh jump@xxx.xxx.xxx.xxx passwd: xxxxxxxx
② 跳转服务器2:
ssh test@xxx.xxx.xxx.xxx passwd: xxxxxxxx
③ GPU算子服务器:
ssh user14@xxx.xxx.xxx.xxx -p xxxx pwd:xxxxxxxx
输入ls,到达此界面即为连接成功!
(2) VPN连接方法
① 点击右下角网络(WiFi那个标识),点击网络和Internet设置。
② 点击VPN,添加VPN(我已经设置过一个,请忽略)。
③ 设置GPU算子开发网络连接,输入如下用户名和密码,点击保存。
VPN信息:
服务器地址:xxx.xxx.xxx.xxx
用户名:xxxxxxxx
密码:xxxxxxxx
④ 打开控制面板-网络连接,并选择刚创建的vpn右键属性
⑤ 选择网络-IPV4-属性-高级,取消勾选“在远程网络上使用默认网关”
⑥ 选择安全,选择允许使用这些协议,点击确定
⑦ 连接VPN后直接连接服务器
ssh user14@xxx.xxx.xxx.xxx -p xxx pwd:xxxxxxxx
输入ls,到达此界面即为连接成功!
2. 下载mindspore包
(1) 注册gitee账号
在官网注册自己的gitee账号用于后续加入团队开发仓库和提交代码。
(2) 加入Owner仓库
创建好gitee账户后联系团队owner,让他在自己的账户上邀请团队成员成为仓库开发者,这样成员的账号才有权限往owner仓库直接提交代码。
将邀请链接或二维码发送给团队成员邀请其加入仓库:
成员接收邀请后,owner可以在私信栏找到成员的申请,进入后点击同意即可。
(3) 创建分支
成员加入团队后登录自己的账号可以看到owner的主仓,点击进入
点击分支
点击新建分支,输入自己想取的分支名(一个算子使用一个单独的分支名):
创建完成后回到owner的mindspore仓库,可以查询到自己的分支:
(4) 下载mindspore
连接服务器后创建自己的文件夹:
mkdier wzb_SSSqG
激活公共环境ci3.7
source /home/Public/env.sh
创建个人conda环境
conda create -n wzb_SSSqG --clone ci3.7
复制测试环境脚本
cp /home/Public/env.sh wzb_SSSqG/
cd wzb_SSSqG/
sed -i 's/ci3.7/wzb_SSSqG/g' env.sh
每次登陆后都需要执行以下脚本,开启测试环境
source env.sh
下载团队owner的mindspore仓库
git clone https://gitee.com/EJaven/mindspore.git
进入mindspore文件夹,切换到自己创建的分支
cd mindspore
git checkout SSSqG
二、 开发流程
本章将大致介绍本次GPU异构算子开发的整体流程,并对需要开发的文件进行简要介绍。大家最好能够先详细阅读一遍华为官方GPU算子开发指南,了解一些基本概念后结合此文档进行学习和理解。
1. MindSpore GPU异构算子调用流程
2. 开发文件清单
依据以上GPU异构算子调用流程,我们可以总结本次GPU异构算子开发所需开发文件以及文件功能如下:
算子Python侧前端定义文件 |
正向单算子: mindspore/python/mindspore/ops/operations/yyy_ops.py (yyy为算子所属类别:[array、math、other、random、sparse]等) 反向单算子: mindspore/python/mindspore/ops/operations/_grad_ops.py 功能描述: 编写算子Python侧前端接口,包括算子声明、校验可写性、注册算子属性 |
算子C++侧前端推理文件 |
正向单算子: mindspore/core/ops/xxx.h mindspore/core/ops/xxx.cc 反向单算子: mindspore/core/ops/grad/xxx_grad.h mindspore/core/ops/grad/xxx_grad.cc (xxx为算子名) 算子PrimitivePtr定义: mindspore/core/ops/core_ops.h 算子infer推理实际值注册: mindspore/core/abstract/ops/primitive_infer_map.cc 功能描述: 编写算子C++侧前端接口以及推理函数,包括算子类声明、输入shape/type校验、输出shape/type的infer推理 |
算子C++侧后端适配文件 |
正向单算子: mindspore/ccsrc/plugin/device/gpu/kernel/yyy/xxx_gpu_kernel.h mindspore/ccsrc/plugin/device/gpu/kernel/yyy/xxx_gpu_kernel.cc 反向单算子: mindspore/ccsrc/plugin/device/gpu/kernel/yyy/xxx_grad_gpu_kernel.h mindspore/ccsrc/plugin/device/gpu/kernel/yyy/xxx_grad_gpu_kernel.cc (yyy为算子所属类别:[array、math、other、random、sparse], xxx为算子名) 功能描述: 编写算子C++侧后端接口以及适配函数,包括算子注册、初始化参数校验、内存计算、调用cuda核函数、数据类型注册 |
算子cuda核函数开发 |
正向单算子: mindspore/ccsrc/plugin/device/gpu/kernel/cuda_impl/cuda_ops/xxx_impl.cuh mindspore/ccsrc/plugin/device/gpu/kernel/cuda_impl/cuda_ops/xxx_impl.cu mindspore/ccsrc/plugin/device/gpu/kernel/cuda_impl/cuda_class/xxx_helper.h 反向单算子: mindspore/ccsrc/plugin/device/gpu/kernel/cuda_impl/cuda_ops/xxx_grad_impl.cuh mindspore/ccsrc/plugin/device/gpu/kernel/cuda_impl/cuda_ops/xxx_grad_impl.cu mindspore/ccsrc/plugin/device/gpu/kernel/cuda_impl/cuda_class/xxx_grad_helper.h (xxx_helper.h和xxx_grad_helper.h文件为可选文件,如果算子逻辑复杂就写,不复杂可以不用写) 功能描述: 编写算子cuda核函数,包括核函数模板声明、函数模板定义、函数模板实例化、实现多线程核函数 |
算子Python反向实现文件 |
正向单算子: mindspore/python/mindspore/ops/_grad_experimental/grad_yyy_ops.py (yyy为算子所属类别:[array、math、other、random、sparse]等) 反向单算子: 反向算子一般无反向,所以不用写 功能描述: 编写算子反向实现函数,包括算子反向注册、实现算子反向逻辑 |
算子ST测试文件 |
正向单算子: tests/st/ops/gpu/test_xxx_op.py 反向单算子: tests/st/ops/gpu/test_xxx_grad_op.py (xxx为算子名,反向单算子视作正向单算子来测试) 功能描述: 测试算子在PYNATIVE_MODE和GRAPH_MODE两种模式下的功能和精度是否符合标准 |
3. 算子分类介绍
(1) 正向单算子
平常大家使用的基本上都是正向算子,比如pow算子、mean算子、max算子等等,这些算子的功能就是其数学推导,也即正向计算过程。
(2) 正向算子的反向实现
正向单算子的反向实现逻辑,往往只需要在
mindspore/python/mindspore/ops/_grad_experimental/grad_yyy_ops.py文件中使用反向单算子或其他一些正向单算子的组合来实现求算子反向的逻辑即可。
反向单算子样例:
正向算子组合样例:
(3) 反向单算子
反向单算子实际上就是把正向单算子求反向的逻辑单独封装成一个算子,这样在实现“正向单算子的反向实现时”就可以直接调用这个算子的反向单算子。
在测试的时候反向单算子可以按照正向单算子的方式来调用算子进行输出的校验,但是在确保没问题之后,正常情况下必须通过mindspore的自动求导来隐式调用反向单算子,不可显示调用。
(4) 动态shape算子
动态shape算子指的是算子输出y的shape会依据输入x的数值的变化而变化,比如BartlettWindow算子需要实现BartlettWindow函数:
该算子其中一个输入为window_length,公式中表示为N,即输出y的元素个数。这时,我们输出y的shape = [N],即输入window_length发生变化时,输出y的shape会随之变化,这种算子就称为动态shape算子。
一定要注意是输出y的shape会依据输入x的“数值”的变化而变化,如果是输入x的shape变化导致输出y的shape变化,这种不算动态shape算子。
(5) 支持动态shape测试
大家依据第(4)条判断完自己的算子是否为动态shape算子之后,无论结果,GPU异构算子验收时要求所有算子支持“动态shape输入”测试,动态shape输入和动态shape算子不是一个概念,实际上动态shape输入就是对原先静态的输入添加一步gather,只需要参照模板编写测试用例和网络即可,动态shape输入和普通静态输入差别如下:
三、 算子开发
阅读完第二章,大家应该已经了解本次GPU异构算子的调用流程以及需要开发的文件,即已经知道这个项目是要做什么。因此本章将依据第二章中罗列的需要开发的文件进行逐一讲解,主要介绍每个需要开发的文件中需要写哪些方法,这些方法的作用是什么。另外本章仅讲解正向单算子的开发过程,反向单算子的开发过程实际上一样的,仅仅是把原先正向单算子的输出y以及其对应的梯度dy也作为输入来依据逻辑进行计算罢了。
为了便于理解,我将以之前开发过的一个BartlettWindow算子为例,分析该算子中各个文件中编写的代码的含义,但为了保证阅读的连贯性和排版的美观。我不会在本章节直接放出该算子的代码截图,而是将该算子的详细解析放在附录中并以超链接的方式链接到文中。除此之外大家还可以直接前往BartlettWindow算子的PR:https://gitee.com/mindspore/mindspore/pulls/35601 查看全部完整代码。
1. 算子Python侧前端定义
(1) mindspore/python/mindspore/ops/operations/yyy_ops.py
文件名中的yyy代表算子所属类型[array、math、other、random、sparse],此文件功能为编写算子python侧前端接口,之后我们调用算子的时候实际上就是从这个地方开始执行的。其主要需要编写的内容和方法如下:
① 算子接口注释
编写关于算子的描述,包括:功能、数学表达式、参数、输入、输出、异常处理、支持的平台和算子样例等信息。这一部分很容易出现遗漏,同时还需要注意异常处理的报错信息要清晰明确,要让测试人员读得懂,不能模棱两可,否则很大概率会被直接打回。
算子接口注释编写完之后需要按照如何做 doctest 和如何做接口网页自验证 进行注释文档的校验以及接口网页的自验证,以确保所写注释是正确并且符合规范的。
② Init()函数
编写算子的初始化函数,主要进行算子参数的校验,包括属性类型的校验、输入类型的校验、数据类型的校验等。常见方法及其作用如下:
• self.add_prim_attr("xxx", 1000)
给算子添加一个属性xxx,其数值为1000
• validator.check_value_type("xxx", xxx, [a,b,c], self.name):
检验xxx参数的类型是否为a,b,c,如果都不是则报错。
• validator.check_type_name("xxx", xxx, [float16,float32] self.name)
检验xxx参数的数据类型是否为float16,float32,如果都不是则报错
其他还有很多检验的方法,这些方法的命名都非常的清晰,大家看一下方法名就能大概猜出来它的作用,所以如果大家有想要校验的参数可以在库里现有的代码中搜一下用法。
BartlettWindow 算子 接口 i nit() 函数
③ 推理函数
现有MindSpore算子库中的部分算子同时有Python侧与C++侧的推理函数,包括InferType()和InferShape()。为了更好地性能以及其他一些功能上的需求,默认优先加载C++层的推理函数。我们只需要定义C++侧的推理函数即可。因此如见到Python侧的推理函数,包括infer_dtype(), infer_shape(), infer()等函数时请直接忽略。
2. 算子C++侧前端推理
(1) mindspore/core/ops/xxx.h
此文件用于声明C++侧算子类、前端接口函数以及用于输入shape/type校验以及输出shape/type推理的infer函数,另外如果后续需要用到算子的某个属性值则需要增加该属性的set和get函数。
此文件开发难度不大,参照一下模板和库中其他算子写就行了:
BartlettWindow 算子 bartlett_window.h 文件
(2) mindspore/core/ops/xxx.cc
此文件用于实现xxx.h文件中声明的接口函数、输入type校验和输出type推导的infertype函数、输入shape校验和输出shape推导的infershape函数和属性相关的初始化、set和get函数。
① MyOpsInferType函数
校验输入的type(是否为tuple、tensor等等)、dtype(是否为float32、int32等等)以及存在约束关系的变量数据类型是否相同,并最终推理出输出的dtype,编码模板如下:
图例外的其余校验请自行查找相应函数的用法。
② MyOpsInferShape函数
校验输入的shape是否满足要求(维度要求,大小要求)、存在约束关系的变量之间shape是否满足要求(相等、更大、更小),并最终推理出输出的shape,编码模板如下:
Infershape部分代码需要开发者针对自己的算子进行完整仔细的分析,考虑到每个参数自身shape的限制,更要考虑到不同参数之间的相互约束,最后需要通过逻辑推理计算出输出的shape值。
③ 属性init()、set()、get()函数
如果在之后的后端适配和核函数实现部分需要用到算子的某些属性数值的话就需要在此处编写这三个函数,用来给该属性初始化,赋值和取值,以MyOps的属性myattr为例,代码模板如下:
大家在编写完编译的时候,可能会发现自己的kMyAttr这个变量没有声明,此时我们只需要在mindspore/core/ops/op_name.h文件中新增一个kMyAttr变量的声明即可,代码模板如下:
④ MyOpsInfer函数
此函数为整个InferShape和InferType的组合函数,作用为判断空值、调用InferShape和InferType函数,写法也相对固定,代码模板如下:
⑤ 宏定义
此处代码形式完全固定,调用MIND_API_BASE_IMPL用于注册算子继承关系,REGISTER_PRIMITI VE_EVAL_IMPL 用于注册算子推理函数,依据以下代码模板编写即可:
BartlettWindow 算子 bartlett_window.cc 文件
(3) mindspore/core/ops/core_ops.h
此文件用于添加算子PrimitivePtr定义,对算子进行注册,使得算子可以调用C++侧接口,此处代码形式也是固定的,参考以下模板即可:
BartlettWindow 算子 core_ops.h 文件
(4) mindspore/core/abstract/ops/primitive_infer_map.cc
首先我们需要了解如下信息:
这一块简单来说就是我们的算子在动态shape测试时会调用两次infershape函数,而第一次调用的时候处于图编译状态,此时输出的shape无法确定,并且输入参数BuildValue得到的是AnyValue,无法获取真实值,而第二次调用的时候是出于运行时,这时可以获取到输入参数的真实数值。
而想要获取到输入参数的真实数值,我们就需要在mindspore/core/abstract/
ops/primitive_infer_map.cc文件中对算子infershape阶段需要获取真实数值的输入参数进行注册,注册代码也是固定形式的,参考以下模板即可:
ShapeSet{0,2}的含义就是MyOps算子在推理时,需要用到第1、3两个输入的真实值。
BartlettWindow 算子 primitive_infer_map.cc 文件
3. 算子C++侧后端适配
(1) mindspore/ccsrc/plugin/device/gpu/kernel/yyy/xxx_gpu_kernel.h
此处用于适配框架接口,由于对mindspore框架适配的需要, 在定义算子类时,都需要继承自NativeGpuKernelMod基类。根据最新框架要求,不可以继承DeprecatedNativeGpuKernelMod基类。否则算子打回重新适配 。而根据 NativeGpuKernelMod基类定义,所有算子都必须实现如下几个虚函数接口 :Init()、Resize()、GetOpSupport()、Launch(),除此之外为了适配动态shape测试,我们还需要编写内存清理ResetResource()函数以及定义一些类私有变量。
此部分代码形式固定,大部分只需要参照模板编写即可:
① Init()函数声明
② Resize()函数声明
③ GetOpSupport()函数声明
④ Launch()函数声明
⑤ RestResource()函数实现
此函数用于在动态shape过程中清除之前输入、输出以及工作空间所申请的内存,避免之前的计算结果影响新一轮计算,代码模板如下:
⑥ 类私有变量声明
BartlettWindow 算子 bartlett_window_gpu_kernel.h 文件
(2) mindspore/ccsrc/plugin/device/gpu/kernel/yyy/xxx_gpu_kernel.cc
此文件主要需要实现xxx_gpu_kernel.cc中声明的各种方法,用于校验输入、初始化参数、重计算并更新内存空间、核函数调用以及数据类型注册。
① Init()函数实现
此函数需要完成对于输入的一些简单校验、依据输入的数据类型选择正确的类模板、最后初始化一些参数并计算与内存相关的一些变量值,代码模板如下:
② Resize()函数实现
此函数用于判断是否为动态shape测试、清空内存、判断输出是否为空并申请新内存,代码模板如下:
③ 核函数调用
此函数获取输入、输出和工作空间的内存地址并传入核函数接口即可,代码模板如下:
④ 数据类型注册
此函数进行数据类型注册,参照代码模板编写即可:
⑤ GetOpSupport()函数声明
直接复制库里现有代码即可:
BartlettWindow 算子 bartlett_window_gpu_kernel.cc 文件
4. 算子cuda核函数开发
(1) mindspore/ccsrc/plugin/device/gpu/kernel/cuda_impl/cuda_ops/xxx_impl.cuh
此文件用于函数模板声明,确定好自己需要用到的输入参数后参照库中已有代码进行修改即可:
B artlettWindow 算子 b artlett_window_impl.cuh 文件
(2) mindspore/ccsrc/plugin/device/gpu/kernel/cuda_impl/cuda_ops/xxx_impl.cu
此文件包含三大部分,第一部分是函数模板定义、第二部分为函数模板显示实例化、第三部分为多线程核函数实现。
① 函数模板定义
依据xxx_impl.cuh文件中声明的函数写相应的定义即可,形式固定,参照模板写即可:
② 函数模板显示实例化
依据算子支持的数据类型将函数模板进行实例化,其目的是为了加快实际计算时的运行速率,代码形式固定,参照模板写即可:
③ 多线程核函数实现
这一块才是真正用来实现算子计算逻辑的地方,也是整个GPU异构算子开发中最重要的部分,想要写好这一块的代码,大家首先需要了解自己算子的功能、计算逻辑,同时还需要有一定的Cuda编程基础,这边推荐大家看一下华为官网上推荐的cuda编程教程:cuda 编程(谭升)
大家主要了解一下host、device、grid、block和thread的概念就可以大致理解cuda是如何进行多线程计算的,之后就可以参照友商或者自己构建多线程计算逻辑,实现算子在GPU上的并行计算。
以加法算子Add为例,假设有一个输入x和一个输入y,我们需要求z = Add(x, y),其线性计算和并行计算逻辑如下:
BartlettWindow 算子 bartlett_window_impl.cu 文件
(3) mindspore/ccsrc/plugin/device/gpu/kernel/cuda_impl/cuda_class/xxx_helper.h
BartlettWindow算子逻辑不复杂,因此没有写helper.h文件,故此处无法给出解析,大家可以参考官方开发文档中关于cudaKernel 封装 的介绍,也可以参考库中其他算子该文件的写法。
5. 算子Python反向实现文件
(1) mindspore/python/mindspore/ops/_grad_experimental/grad_yyy_ops.py
BartlettWindow算子无反向,故无需修改此文件。大家可以参考华为官方文档中关于注册 算子反向 的描述以及正向算子的反向实现 。
算子反向实现的模板如下图所示,而实际计算逻辑则需要大家自己进行求导推理或者参照友商反向实现逻辑进行实现:
6. 算子ST测试文件
(1) tests/st/ops/gpu/test_xxx_op.py
此文件用于门禁ST测试的用例,需要包括GRAPH_MODE和PYNATIVE_MODE两种模式的测试用例,同时需要注意这里的输入必须使用固定值,不可以随机生成,具体写法参照库中已有代码即可。
BartlettWindow 算子 test_bartlett_window_op.py 文件
四、 如何做doctest
用于检查接口注释是否规范
1、进入GPU服务器中自己conda环境中的mindspore包:
cd /disk1/user14/.conda/envs/xxx/lib/python3.7/site-packages/mindspore
2、在当前路径传入conftest.py文件(见附件)
3、修改conftest.py文件中导入的operation类型:
我的是array,改成自己对应的
4、进入算子python侧前端接口定义目录:
cd /disk1/user14/.conda/envs/xxx/lib/python3.7/site -packages/mindspore/ops/operations
5、在当前目录下传入需要doctest的算子接口文件array_ops_xxx.py:
前面的array改成自己的算子类型,后面的xxx为算子名称
6、增添算子接口
将自己算子的前端定义复制粘贴到上面创建的array_ops_xx.py文件中,并且要增加支持的平台类型,就是在目前已经支持的平台前加上GPU,不仅要在此mindspore包中修改,自己提交的代码中也需要加上:
从哪里复制?从原本算子对应的前端接口处复制,就是在此路径下的array_ops.py(array换成自己算子的类型)文件中搜自己的算子前端定义。
7、在此路径下执行doctest命令(array换成自己的算子类型):
pytest --disable-warnings -vra --doctest-modules -o doctest_optionflags=NORMALIZE_WHITESPACE --tb=long array_ops_xxx.py
8、如果通过结果如下图,如果报错根据报错信息修改注释
五、如何做接口网页自验证
用于检查网页前端接口是否正确,主要依照官方文档接口注释网页自验部分:算子前端定义 wiki
需要注意四点:
① clone docs代码时选择老的分支:
git clone -b r1.6 https://gitee.com/mindspore/docs.git
② 编辑operation.rst
operation.rst文件可以用电脑的记事本打开,并且注意添加到自己算子所属类型下面
③ 报错信息
生成网页过程中会报一些没有图片的错误,不需要管。生成完毕后需要将/disk1/user14/wzb/docs/docs/mindspore/api/build_zh_cn路径下的整个html文件夹下载下来
④ 网页截图
html文件夹全部下载之后,打开index.html文件,在其中找自己算子的前端接口网页截图即可。
附录1:BartlettWindow算子开发详解
本文采取代码+注释方式解析BartlettWindow算子的开发过程。
1. 算子Python侧前端定义
(1) mindspore/python/mindspore/ops/operations/other_ops.py
① 算子接口注释
写完算子接口注释后可以通过()接口网页自验证生成如下网页文件:
② Init()函数
③ 推理函数
BartlettWindow算子无Python侧Infer推理函数
2. 算子C++侧前端推理
(1) mindspore/core/ops/bartlett_window.h
(2) mindspore/core/ops/bartlett_window.cc
① BartlettWindowInferType函数
图例外的其余校验请自行查找相应函数的用法。
② BartlettWindowInferShape函数
③ 属性init()、set()、get()函数
mindspore/core/ops/op_name.h
④ BartlettWindowInfer函数
⑤ 宏定义
(3) mindspore/core/ops/core_ops.h
(4) mindspore/core/abstract/ops/primitive_infer_map.cc
3. 算子C++侧后端适配
(1) mindspore/ccsrc/plugin/device/gpu/kernel/other/bartlett_window _gpu_kernel.h
① Init()函数声明
② Resize()函数声明
③ GetOpSupport()函数声明
④ Launch()函数声明
⑤ RestResource()函数实现
⑥ 类私有变量声明
(2) mindspore/ccsrc/plugin/device/gpu/kernel/other/bartlett_window _gpu_kernel.cc
① Init()函数实现
② Resize()函数实现
③ 核函数调用
④ 数据类型注册
⑤ GetOpSupport()函数声明
4. 算子cuda核函数开发
(1) mindspore/ccsrc/plugin/device/gpu/kernel/cuda_impl/cuda_ops/bartlett_window _impl.cuh
(2) mindspore/ccsrc/plugin/device/gpu/kernel/cuda_impl/cuda_ops/bartlett_window _impl.cu
① 函数模板定义
② 函数模板显示实例化
③ 多线程核函数实现
(3) mindspore/ccsrc/plugin/device/gpu/kernel/cuda_impl/cuda_class/bartlett_window _helper.h
BartlettWindow算子无需编写helper.h文件
5. 算子Python反向实现文件
(1) mindspore/python/mindspore/ops/_grad_experimental/grad_other_ops.py
BartlettWindow算子无反向
6. 算子ST测试文件
(1) tests/st/ops/gpu/test_ bartlett_window _op.py
- 点赞
- 收藏
- 关注作者
评论(0)