mindspore.mint接口测试任务
mindspore.mint接口测试任务
任务
任务背景
mindspore.mint提供了大量的functional、nn、优化器接口,API用法及功能等与业界主流用法一致,方便用户参考使用。 mint接口当前是实验性接口,在图编译模式为O0和PyNative模式下性能比ops更优。当前暂不支持图下沉模式及CPU、GPU后端,后续会逐步完善。
mindspore.mint.div逐元素计算 input 除以 other 的商。
mindspore.mint.divide
mindspore.mint.erf
mindspore.mint.erfc
mindspore.mint.erfinv
需求描述
- 对应Pytorch 的相应接口进行测试:
a) 测试random输入不同dtype,对比两个框架的支持度
b) 测试固定dtype,random输入值,对比两个框架输出是否相等(误差范围为小于1e-3)
c) 测试固定shape,固定输入值,不同输入参数(string\bool等类型),两个框架的支持度
d) 测试随机混乱输入,报错信息的准确性 - 测试使用接口构造函数/神经网络的准确性
a) Github搜索带有该接口的代码片段/神经网络
b) 使用Pytorch和MindSpore,固定输入和权重,测试正向推理结果(误差范围小于1e-3,若报错则记录报错信息)
c) 测试该神经网络/函数反向,如果是神经网络,则测试Parameter的梯度,如果是函数,则测试函数输入的梯度
验收标准
测试过程中遇到的其他问题记录,包括但不限于:
a) 环境安装
b) 框架运行时报错(如memcpy、 CANN报错等等)
c) 感觉不好用或者和Pytorch无法对齐的地方
将测试代码写成测试用例形式,提交打包:
a) 文件名命名为test_xxx.py,xxx为测试的接口名
b) 每个测试点构造一个函数,函数名为test_xxx,需要在函数名体现清晰的测试内容信息,如:test_linear_random_shape
背景知识(别上传这一部分)
-
numpy.allclose
Returns True if two arrays are element-wise equal within a tolerance.
-
MindSpore支持两种运行模式:参考文献
- Graph模式:静态图模式或者图模式,将神经网络模型编译成一整张图,然后下发执行。该模式利用图优化等技术提高运行性能,同时有助于规模部署和跨平台运行。
- PyNative模式:动态图模式,将神经网络中的各个算子逐一下发执行,方便用户编写和调试神经网络模型。
默认情况下,MindSpore处于Graph模式,可以通过
context.set_context(mode=context.PYNATIVE_MODE)
切换为PyNative模式;同样地,MindSpore处于PyNative模式时,可以通过context.set_context(mode=context.GRAPH_MODE)
切换为Graph模式。Graph和PyNative两种模式的区别主要有:
- 使用场景:Graph模式需要一开始就构建好网络结构,然后框架做整图优化和执行,比较适合网络固定没有变化,且需要高性能的场景。而PyNative模式逐行执行算子,支持单独求梯度。
- 网络执行:Graph模式和PyNative模式在执行相同的网络和算子时,精度效果是一致的。由于Graph模式运用了图优化、计算图整图下沉等技术,Graph模式执行网络的性能和效率更高。
- 代码调试:在脚本开发和网络流程调试中,推荐使用PyNative模式进行调试。在PyNative模式下,可以方便地设置断点,获取网络执行的中间结果,也可以通过pdb的方式对网络进行调试。而Graph模式无法设置断点,只能先指定算子进行打印,然后在网络执行完成后查看输出结果。
下面以Graph模式为例,演示MindSpore单算子、普通函数、模型的执行方式,并进一步说明如何在PyNative模式下进行性能改进及梯度求取。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import numpy as np
import mindspore.nn as nn
from mindspore import context, Tensor, ParameterTuple, ms_function
import mindspore.ops as ops
from mindspore import dtype as mstype
from mindspore.common.initializer import Normal
from mindspore.nn import Dense, WithLossCell, SoftmaxCrossEntropyWithLogits, Momentum
# 设定为Graph模式,也可替换为PYNATIVE_MODE
# MindSpore的默认方式GRAPH_MODE
context.set_context(mode=context.GRAPH_MODE, device_target="Ascend")
conv = nn.Conv2d(3, 4, 3, bias_init='zeros')
input_data = Tensor(np.ones([1, 3, 5, 5]).astype(np.float32))
output = conv(input_data)
print(output.asnumpy()) -
CANN错误分析,参考文献来自错误分析
只适用于Ascend平台。CANN(Compute Architecture for Neural Networks)是华为针对AI场景推出的异构计算架构,Ascend平台的MindSpore运行在CANN之上。这类报错一般在日志中会有
Ascend error occurred
关键字,报错消息由错误码和错误内容组成
pytest
pytest是一个用于 Python 的测试框架,支持简单的单元测试和复杂的功能测试。它以其简单、易用、灵活的特点,受到了许多开发者的青睐。强大的断言:内置丰富的断言方法,提供详细的失败信息。自动发现:自动发现测试文件和测试函数,无需显式地注册测试。
把函数和类用@pytest修饰之后,运行pytest+文件名称,即可测试所有带修饰的函数和类。
编写要求
-
默认测试用例的格式:
-
模块名:模块名(文件名)通常被统一放在一个testcases文件夹中,然后需要保证模块名以test_开头或_test结尾,例如test_demo1或demo2_test
-
类名:测试类类名必须以Test开头,并且不能带有init方法
-
方法名:测试方法名(Case 名)必须以test_开头,例如test_demo1(self)、test_demo2(self)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29# test_demo1.py
class TestDemo:
def test_demo1(self):
print("测试用例1")
def test_demo2(self):
print("测试用例2")
workage2 = 5
workage3 = 20
# 只需采用 skip 或 skipif 方法来指定参数并贴在方法上即可跳过。满足条件就不会测试
@pytest.mark.skip(reason="无理由跳过")
def test_demo1(self):
print("我被跳过了")
@pytest.mark.skipif(workage2<10,reason="工作经验少于10年跳过")
def test_demo2(self):
print("由于经验不足,我被跳过了")
# 我们在Case上采用@pytest.mark. + 分组名称,就相当于该方法被划分为该分组中
# 注意:一个分组可以有多个方法,一个方法也可以被划分到多个分组中,运行时候pytest -vs -m user_manage指定分组
@pytest.mark.user_manage
def test_demo1(self):
print("user_manage_test1")
@pytest.mark.product_manage
def test_demo2(self):
print("product_manage_test1")
-
-
如果不想用默认的格式,可在根目录下自己写一个pytest.ini
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17[pytest]
#参数
addopts = ‐vs
# 默认的执行路径,它会默认执行该文件夹下所有的满足条件的测试case
testpaths = ./testcases
# 文件命名规则
python_files = test_*.py
# 类名命名规则
python_classes = Test*
# Case命名规则
python_functions = test_*
# 标记
markers =
# 冒烟规则
smoke:冒烟用例
product_manage:商品管理
指定执行顺序
- 默认方法(固件方法):如果说有些函数需要指定在某个时间才能运行,则需要加修饰词和使用指定的函数名
1 | import unittest |
执行
只需采用 skip 或 skipif 方法来指定参数并贴在方法上即可跳过。
1 | # -vs: -v输出详细信息 -s输出调试信息 |
@pytest.mark.parametrize
Pytest参数化有两种方式:
- @pytest.fixture(params=[])
- @pytest.mark.parametrize(),@pytest.mark.parametrize()使用方法更丰富一些
1 | @pytest.mark.parametrize(self,argnames, argvalues, indirect=False, ids=None, scope=None)): |
快速入门
1 | # 1、单个参数【测试方法入参只有一个参数】 |
程序
查阅API对应表
mindspore.mint.div | torch.div | 逐元素计算 input 除以 other 的商。 |
mindspore.mint.divide | torch.divide | mindspore.mint.div() 的别名。那就只需要写一个 |
mindspore.mint.erf | torch.erf | 逐元素计算 input 的高斯误差 |
mindspore.mint.erfc | torch.erfc | 逐元素计算 input 的互补误差函数 |
mindspore.mint.erfinv | torch.erfinv | 计算输入的逆误差函数。 |
注意:任务b实际上测试的是除了计算参数之外的设定,比如div函数的rounding参数,如果没有多余参数可以不测试
任务a
- 查API支持的数据类型,如mindspore.mint.erf标注支持数据类型:Ascend: float16、float32、float64、int64、bool、bfloat16。则设置在两种模式下分别进行计算。
- 如果支持这个参数则跳过,不支持则打印
- 如果两个框架都支持这个类型的参数则比较两个计算结果是否相同
任务b
- 设置类型为常见的float32,但是输入的tensor大小给出多种,然后创建随机tensor,注意erfinv的数据要在-1到1之间,在两种模式下分别进行计算。
- 如果该模式下的计算结果和torch的相同则跳过,不相同则打印
任务c
- 针对比如div函数需要rounding参数, parameters = [None, “trunc”, “floor”],分别传入这个参数,然后和任务b一样进行计算。
- 如果该模式下的计算结果和torch的相同则跳过,不相同则打印
任务d
- 在API页面含有报错抛出信息,进行测试比如mindspore.mint.erf,异常为
- TypeError - input 不是Tensor。
- TypeError -Ascend: 如果 input 的数据类型不是float16、float32、float64、int64、bool、bfloat16。
任务2
固定一个尺寸固定数据的tensor,计算正向传播和梯度,进行对比
服务器使用
启智社区注册账号,建立项目,然后建立一个环境,环境选择Acend910b,镜像选择为mindtorch0.3_mindspore2.3.0_torchnpu2.2.0_cann8.0,上传代码,代码会默认压缩安放在/tmp/code/master.zip,首先需要解压。
1 | unzip master.zip |
结果
div
环境信息:
硬件: 新疆大学智算中心NPU: 1*Ascend-D910B(显存: 32GB), CPU: 20, 内存: 60GB
镜像:mindtorch0.3_mindspore2.3.0_torchnpu2.2.0_cann8.0
命令行:
1 | # 每次打开终端安装环境 |
- 类型支持测试,API未编写支持类型,但是不支持UInt16,UInt32,UInt64,BFloat16
环境 | 不支持的数据类型 | 支持的数据类型 | 错误 |
---|---|---|---|
mindspore (GRAPH_MODE) | UInt16 UInt32 UInt64 BFloat16 |
ms.int8, ms.int16, ms.int32, ms.int64, ms.uint8,ms.float16, ms.float32, ms.float64, ms.bool_ | |
mindspore(PYNATIVE_MODE) | UInt16 UInt32 UInt64 BFloat16 |
ms.int8, ms.int16, ms.int32, ms.int64, ms.uint8,ms.float16, ms.float32, ms.float64, ms.bool_ | |
torch | torch.bfloat16 | torch.int8, torch.int16, torch.int32, torch.int64, torch.uint8, torch.uint16, torch.uint32, torch.uint64, torch.float16, torch.float32, torch.float64, torch.bool |
- 计算测试,通过
test_div.py::test_div_random_input_fixed_dtype[0] PASSED
test_div.py::test_div_random_input_fixed_dtype[1] PASSED
-
参数输入
模式 参数 计算结果是否通过 GRAPH_MODE None 通过 trunc 通过 floor 通过 GRAPH_MODE None 通过 trunc 通过 floor 通过 -
报错测试
均通过
-
梯度测试
均通过
divide
环境信息:
硬件: 新疆大学智算中心NPU: 1*Ascend-D910B(显存: 32GB), CPU: 20, 内存: 60GB
镜像:mindtorch0.3_mindspore2.3.0_torchnpu2.2.0_cann8.0
命令行:
1 | # 每次打开终端安装环境 |
- 类型支持测试,API未编写支持类型,但是不支持UInt16,UInt32,UInt64,BFloat16
环境 | 不支持的数据类型 | 支持的数据类型 | 错误 |
---|---|---|---|
mindspore (GRAPH_MODE) | UInt16 UInt32 UInt64 BFloat16 |
ms.int8, ms.int16, ms.int32, ms.int64, ms.uint8,ms.float16, ms.float32, ms.float64, ms.bool_ | |
mindspore(PYNATIVE_MODE) | UInt16 UInt32 UInt64 BFloat16 |
ms.int8, ms.int16, ms.int32, ms.int64, ms.uint8,ms.float16, ms.float32, ms.float64, ms.bool_ | |
torch | torch.bfloat16 | torch.int8, torch.int16, torch.int32, torch.int64, torch.uint8, torch.uint16, torch.uint32, torch.uint64, torch.float16, torch.float32, torch.float64, torch.bool |
- 计算测试,通过
test_div.py::test_divide_random_input_fixed_dtype[0] PASSED
test_div.py::test_divide_random_input_fixed_dtype[1] PASSED
-
参数输入
模式 参数 计算结果是否通过 GRAPH_MODE None 通过 trunc 通过 floor 通过 GRAPH_MODE None 通过 trunc 通过 floor 通过 -
报错测试
均通过
-
梯度测试
均通过
erf
环境信息:
硬件: 新疆大学智算中心NPU: 1*Ascend-D910B(显存: 32GB), CPU: 20, 内存: 60GB
镜像:mindtorch0.3_mindspore2.3.0_torchnpu2.2.0_cann8.0
命令行:
1 | # 每次打开终端安装环境 |
- 类型支持测试,不通过,需要支持 BFloat16
环境 | 不支持的数据类型 | 支持的数据类型 | 错误 |
---|---|---|---|
mindspore (GRAPH_MODE) | BFloat16 | ms.float16, ms.float32, ms.float64, ms.int64, ms.bool_, ms.bfloat16 | Float32,Int64,Bool和torch的计算结果不同 |
mindspore(PYNATIVE_MODE) | BFloat16 | ms.float16, ms.float32, ms.float64, ms.int64, ms.bool_, ms.bfloat16 | Float32,Int64,Bool和torch的计算结果不同 |
torch | torch.bfloat16 | torch.float16, torch.float32, torch.float64, torch.int64, torch.bool, torch.bfloat16 |
-
计算测试
-
测试组,小数点后5位不同,不知道是否算测试通过
input_data: [-0.37975368 -0.34422294 -1.42222966 -1.04481118 0.95105012]
ms_result: [-0.4087475 -0.37358218 -0.9556926 -0.860494 0.8213899 ]
torch_result: [-0.408769 -0.37360325 -0.95571023 -0.8604813 0.8213707 ] -
测试组,小数点后5位不同
input_data: [ 2.22057531 -1.10386126 -0.54387706 0.14834316 1.51924453]
ms_result: [ 0.99830514 -0.8815062 -0.5581943 0.16617936 0.96830803]
torch_result: [ 0.99831253 -0.88149875 -0.5582007 0.16616759 0.96832895]
-
-
参数输入
无参数设置,均通过
-
报错测试
均通过
-
梯度测试
均通过
erfc
环境信息:
硬件: 新疆大学智算中心NPU: 1*Ascend-D910B(显存: 32GB), CPU: 20, 内存: 60GB
镜像:mindtorch0.3_mindspore2.3.0_torchnpu2.2.0_cann8.0
命令行:
1 | # 每次打开终端安装环境 |
- 类型支持测试,不通过,需要支持 BFloat16
环境 | 不支持的数据类型 | 支持的数据类型 | 错误 |
---|---|---|---|
mindspore (GRAPH_MODE) | BFloat16 | ms.float16, ms.float32, ms.float64, ms.int64, ms.bool_, ms.bfloat16 | Float32,Int64,Bool和torch的计算结果不同 |
mindspore(PYNATIVE_MODE) | BFloat16 | ms.float16, ms.float32, ms.float64, ms.int64, ms.bool_, ms.bfloat16 | Float32,Int64,Bool和torch的计算结果不同 |
torch | torch.bfloat16 | torch.float16, torch.float32, torch.float64, torch.int64, torch.bool, torch.bfloat16 |
-
计算测试
-
测试组,小数点后5位不同,不知道是否算测试通过
input_data: [ 0.55593791 0.44808426 -2.71790637 -0.53732477 -0.45158543]
ms_result: [0.43174636 0.5263032 1.9998777 1.5526736 1.4769242 ]
torch_result: [0.4317416 0.52628523 1.9998788 1.5526809 1.4769417 ] -
测试组,小数点后5位不同
input_data: [ 0.53237093 -0.99921068 0.81374149 0.05919775 -0.15359628]
ms_result: [0.45152628 1.8423889 0.24979174 0.93325967 1.1719722 ]
torch_result: [0.4515183 1.8423729 0.24981277 0.93328047 1.1719615 ]
-
-
参数输入
无参数设置,均通过
-
报错测试
均通过
-
梯度测试
均通过
erfinv
环境信息:
硬件: 新疆大学智算中心NPU: 1*Ascend-D910B(显存: 32GB), CPU: 20, 内存: 60GB
镜像:mindtorch0.3_mindspore2.3.0_torchnpu2.2.0_cann8.0
命令行:
1 | # 每次打开终端安装环境 |
- 类型支持测试,通过
环境 | 不支持的数据类型 | 支持的数据类型 | 错误 |
---|---|---|---|
mindspore (GRAPH_MODE) | ms.float16, ms.float32, ms.int8, ms.int16,ms.int32, ms.int64, ms.uint8, ms.bool_ | ||
mindspore(PYNATIVE_MODE) | ms.float16, ms.float32, ms.float64, ms.int64, ms.bool_, ms.bfloat16 | ||
torch | torch.float16, torch.float32, torch.int8, torch.int16,torch.int32, torch.int64, torch.uint8, torch.bool |
-
计算测试,通过
在GRAPH模式下,tensor大小在为[4, 6, 7, 8] 时计算结果与torch不同,但是差距很小
在PYNATIVE模式下,tensor大小在[5,4, 3]时与torch不同,但是差距很小
input_data: [[[-0.16848439 -0.2019851 0.36715633]
[ 0.3096696 -0.11560675 0.91190031]
[ 0.94261078 0.95440446 -0.5036123 ]
[ 0.95595146 -0.54710461 -0.42151996]][[ 0.69609619 0.33447626 -0.91189684]
[-0.44852735 0.45557708 0.03501383]
[ 0.2079667 0.10272845 -0.29821255]
[-0.17657432 0.57332459 0.78557388]][[-0.92765529 0.46980589 -0.54225893]
[ 0.46168587 -0.29652803 0.94215718]
[ 0.34109872 0.2191107 0.21868642]
[-0.54319334 -0.30351475 -0.53197152]][[ 0.19239459 -0.52627742 -0.80364875]
[ 0.8073855 0.70755351 0.08547598]
[ 0.3102941 -0.44570836 -0.50435729]
[-0.63445313 -0.98493728 -0.24300708]][[-0.57635299 -0.52763846 -0.63903526]
[-0.2464637 -0.30461796 -0.35513484]
[ 0.66277941 0.006608 0.56438567]
[ 0.94051533 -0.03502053 -0.54777088]]]
ms_result: [[[-0.15044294 -0.18096098 0.33780497]
[ 0.28171614 -0.10281489 1.2059761 ]
[ 1.3437392 1.4135892 -0.48096272]
[ 1.4238497 -0.53075176 -0.39287293]][[ 0.72697484 0.3056821 -1.205963 ]
[-0.42112073 0.4286044 0.03104022]
[ 0.18644391 0.09129365 -0.27075744]
[-0.15778473 0.5620745 0.8778638 ]][[-1.2706298 0.44385767 -0.5250773 ]
[ 0.43512827 -0.26915175 1.3413013 ]
[ 0.3121386 0.19668916 0.1962984 ]
[-0.52616894 -0.27582082 -0.5131406 ]][[ 0.17219217 -0.50659615 -0.9135943 ]
[ 0.92127806 0.74442077 0.07589649]
[ 0.28231534 -0.4181416 -0.48179516]
[-0.6398228 -1.7188823 -0.21880175]][[-0.56576306 -0.5081564 -0.645962 ]
[-0.22201757 -0.2768761 -0.3259106 ]
[ 0.67859024 0.00585618 0.55127466]
[ 1.3326088 -0.03104615 -0.5315348 ]]]
torch_result: [[[-0.15044273 -0.18096067 0.33780485]
[ 0.2817161 -0.10281495 1.2059764 ]
[ 1.3437395 1.4135904 -0.48096296]
[ 1.4238504 -0.530752 -0.39287296]][[ 0.7269749 0.3056819 -1.2059633 ]
[-0.42112085 0.42860448 0.03104016]
[ 0.18644369 0.09129371 -0.27075735]
[-0.1577846 0.5620746 0.87786347]][[-1.2706304 0.44385782 -0.5250774 ]
[ 0.4351283 -0.26915163 1.3413019 ]
[ 0.3121386 0.19668904 0.19629823]
[-0.52616906 -0.2758207 -0.51314074]][[ 0.17219207 -0.50659627 -0.91359407]
[ 0.9212778 0.74442065 0.07589659]
[ 0.28231534 -0.41814157 -0.48179537]
[-0.6398229 -1.7188824 -0.21880147]][[-0.5657633 -0.5081566 -0.6459621 ]
[-0.22201732 -0.276876 -0.32591063]
[ 0.6785902 0.00585625 0.5512749 ]
[ 1.332609 -0.03104611 -0.5315349 ]]] -
无参数设置,均通过
-
报错测试
均通过
-
梯度测试
均通过
如何进行任务提交
-
哪里有问题,就在mindspore的gitee仓库提交issue,里面有模板,需要填写硬件和软件以及报错截图。基本上每个函数都要提交一个issue
-
然后在mindspore的gitee仓库mindspore-test仓库提交一个pullreuqust,内容就是把issue列进去,然后把test文件贴进去
-
在gitee或者github,fork原仓库A到我的仓库B(B是A的fork版本)
-
将仓库B clone到我本地电脑
git clone XXX-
kex_exchange_identification: Connection closed by remote host
Connection closed by 20.205.243.166 port 22
fatal: 无法读取远程仓库。请确认您有正确的访问权限并且仓库存在。
- 临时关闭代理
虽然关闭代理最简单,但是可能会导致下载速度过慢
2. 修改代理软件配置,22 端口走直连最安全的办法是修改代理软件的配置,将 22 端口走直连,不同的代理软件配置方式不同,这里就不详细介绍了
3. 改用 HTTPS 协议,走 443 端口个人最推荐的办法是改用 HTTPS 协议,走 443 端口,因为这样不仅可以解决上面的问题,还可以通过代理提高下载速度
-
-
在本地创建一个分支,如bugfix/issue-12,该分支用于存放我的代码修改。同时在我的github上的仓库B也创建一个同名的该分支
-
切换到该分支bugfix/issue-12,修改代码
git checkout -b bugfix/issue-12 -
修改好了,add,commit,然后push到我远程的仓库B的bugfix/issue-12分支
git push -u origin bugfix/issue-12 -
在我的github的仓库B中创建pull request。选择仓库B的该分支,推送到原仓库A的某一个分支。具体是哪个分支,参考仓库A的contributing说明,一般是dev分支;如果没说,就只能选择master分支咯
-