MindStudio制作MindSpore TBE算子(二)算子测试

举报
塞恩斯 发表于 2025/02/10 22:42:11 2025/02/10
1.6w+ 0 0
【摘要】 MindStudio制作MindSpore TBE算子(二)算子测试

在上一节中,成功制作了Mindspore的Add算子,具体可以查看MindStudio制作MindSpore TBE算子(一)算子制作,这一节,一起看看如何对算子进行测试。
建议参考以下内容一起食用:
算子代码实现
MindSpore框架TBE算子开发全流程

制作Mindspore的TBE流程中用于测试的是test_xxx_impl.py。
image.png

算子仿真验证

算子仿真验证是进行算子单元测试(UT测试),其中UT(Unit Test)是软件工程中常见的一种测试方式,目的是对代码中的最小可测试单元(如函数、类、模块)进行验证。针对 CANN 开发来说,UT 主要用于:

  • 针对算子实现的单元级别功能测试
  • 在真实或模拟环境中运行,验证算子输入输出是否符合预期可能包括边界情况、异常情况测试

特点:

  • 以代码单元为测试对象(如 C++ 算子实现、Python 接口等)
  • 关注 API 接口行为、异常处理、性能等
  • 适用于 CI/CD 流程中的自动化测试

利用MindStudio执行UT测试

  1. 右键算子工程文件,点击New Case,创建 TBE UT CASE
    image.png

  2. 选择测试的算子为新创建的addCustom算子,点击OK
    image.png

  3. 生成了对应的test_xxx_impl.py文件
    image.png

  4. 编辑对应的py文件,清理掉对应注释,
    image.png

  5. 右击对应的python文件,执行TBE算子测试
    image.png

  6. 如果这里出现报错

2025-02-10 20:32:17  Get case names failed.The file does not exist. /home/science/MindstudioProjects/Add_custom/out/addcustom_case.json
2025-02-10 20:32:17  Result of getting case name:Traceback (most recent call last):
  File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/bin/op_ut_helper", line 20, in <module>
    from absl import app
ModuleNotFoundError: No module named 'absl'

遇到这个报错是因为:如果 op_ut_helper 依赖的是 Ascend 自带的 Python,而安装 absl 时使用的是系统 Python,那么 op_ut_helper 可能找不到 absl。
解决方法有两种:
1. 在系统python下安装缺的包;
2. 利用anaconda的mindspore环境重新安装CANN
这里我推荐适应方法2

./Ascend-cann-toolkit_8.0.0_linux-x86_64.run --uninstall
./Ascend-cann-toolkit_8.0.0_linux-x86_64.run --install

解决这个问题之后,便可以选择测试例子
7. 执行测试用例
这里需要注意的是,需要选择的SOC核心为Ascend910芯片,这里我选择Ascend910Pro。
image.png
9. bug调整
报错信息:

Soc Version: Ascend910ProB
    failed: [addcustom_impl]  addcustom_impl_pre_static_test_addcustom_impl_auto_case_name_1 (Ascend910ProB), error msg: Failed, 
      Case File "/home/science/MindstudioProjects/Add_custom/testcases/ut/ops_test/test_addcustom_impl.py", line 16
      Error trace: 
      Call op func failed, err_trace: Traceback (most recent call last):
        File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/ut/op_ut.py", line 873, in _call_op_func
          op_func(*case_info.op_params, **addition_params)
        File "/home/science/anaconda3/envs/mindspore/lib/python3.9/site-packages/mindspore/ops/op_info_register.py", line 298, in wrapped_function
          return func(*args, **kwargs)
      TypeError: addcustom_impl() missing 1 required positional argument: 'z'
      
------------------------------------------------------------------------

这里需要对之前的impl代码进行修改
addcustome_impl.py

from __future__ import absolute_import
from tbe import tvm
import tbe.dsl as tbe
from tbe.common.register import register_op_compute
from tbe.common.utils import shape_refine
from tbe.common.utils import shape_util
from tbe.common.utils import para_check
from functools import reduce
from mindspore.ops.op_info_register import op_info_register, TBERegOp, DataType

SHAPE_SIZE_LIMIT = 2147483648

@register_op_compute("addcustom")
def addcustom_compute(x, y):
    """
    The compute function of the Addcustom implementation.
    """
    # shape转为list
    shape_x = shape_util.shape_to_list(x.shape)
    shape_y = shape_util.shape_to_list(y.shape)

    # shape_max取shape_x与shape_y的每个维度的大值
    shape_x, shape_y, shape_max = shape_util.broadcast_shapes(shape_x, shape_y,
                                                              param_name_input1="input_x",
                                                              param_name_input2="input_y")
    shape_size = reduce(lambda x, y: x * y, shape_max[:])
    if shape_size > SHAPE_SIZE_LIMIT:
        raise RuntimeError("the shape is too large to calculate")

    # 将input_x的shape广播为shape_max
    input_x = tbe.broadcast(x, shape_max)
    input_y = tbe.broadcast(y, shape_max)

    # 执行input_x + input_y
    res = tbe.vadd(input_x, input_y)

    return res

# 算子注册信息
# Define the kernel info of Addcustom
# 算子注册名称
addcustom_op_info = (TBERegOp("Addcustom") \
    # 融合策略,这里选择不融合
    .fusion_type("OPAQUE") \
    .partial_flag(True) \
    .async_flag(False) \
    # 生成算子二进制名称
    .binfile_name("addcustom.so") \
    .compute_cost(10) \
    .kernel_name("addcustom_impl") \
    # 算子输入信息
    .input(0, "x", False, "required", "all")\
    .input(1, "y", False, "required", "all")\
    .output(0, "z", False, "required", "all")\
    # 数据格式名称
    .dtype_format(DataType.F16_Default, DataType.F16_Default, DataType.F16_Default)\
    .get_op_info())
# 算子的入口函数,描述了算子的编译过程
# Binding kernel info with the kernel implementation.
# 装饰器与算子注册信息绑定,执行后会注册到后端
@op_info_register(addcustom_op_info)
def addcustom_impl(x, y, z, kernel_name="addcustom_impl"):
    """
    The entry function of the Addcustom implementation.
    """
    # 获取算子输入tensor的shape与dtype
    shape_x = x.get("shape")
    shape_y = y.get("shape")

    # 检验算子输入类型
    check_tuple = ("float16")
    input_data_type = x.get("dtype").lower()
    para_check.check_dtype(input_data_type, check_tuple, param_name="input_x")

    # shape_max取shape_x与shape_y的每个维度的最大值
    shape_x, shape_y, shape_max = shape_util.broadcast_shapes(shape_x, shape_y,
                                                              param_name_input1="x",
                                                              param_name_input2="y")
    # 如果shape的长度等于1,就直接赋值,如果shape的长度不等于1,做切片,将最后一个维度舍弃(按照内存排布,最后一个维度为1与没有最后一个维度的数据排布相同,例如2*3=2*3*1,将最后一个为1的维度舍弃,可提升后续的调度效率)
    if shape_x[-1] == 1 and shape_y[-1] == 1 and shape_max[-1] == 1:
        shape_x = shape_x if len(shape_x) == 1 else shape_x[:-1]
        shape_y = shape_y if len(shape_y) == 1 else shape_y[:-1]
        shape_max = shape_max if len(shape_max) == 1 else shape_max[:-1]

    # 使用TVM的placeholder接口对输入tensor进行占位,返回一个tensor对象
    data_x = tvm.placeholder(shape_x, name="data_1", dtype=input_data_type)
    data_y = tvm.placeholder(shape_y, name="data_2", dtype=input_data_type)

    with tvm.target.cce():
        # 计算过程
        res = addcustom_compute(data_x, data_y)
        # 自动调度模块
        sch = tbe.auto_schedule(res)
    # 配置编译信息
    config = {"print_ir": False,
              "name": kernel_name,
              "tensor_list": [data_x, data_y, res]}

    tbe.build(sch, config)

# # 算子调用,测试算子计算正确性
# if __name__ == '__main__':
#     input_output_dict = {"shape": (5, 6, 7),"format": "ND","ori_shape": (5, 6, 7),"ori_format": "ND", "dtype": "float16"}
#     addcustom_impl(input_output_dict, input_output_dict, input_output_dict, kernel_name="add")

test_addcustom_impl.py

# # -*- coding:utf-8 -*-
import sys
import numpy as np
from op_test_frame.ut import BroadcastOpUT

# [TODO] change op_func_name here
ut_case = BroadcastOpUT("addcustom_impl", op_func_name="addcustom_impl")

# [TODO] coding expect function here
def calc_expect_func(input_x, input_y, output):
    res = input_x["value"] + input_y["value"]  # 计算加法
    return [res, ]

# [TODO] coding cases here
ut_case.add_precision_case("all", {
    "params": [
        {"dtype": "float16", "format": "ND", "ori_format": "ND", "ori_shape": (32,), "shape": (32,), "param_type": "input"},  # input_x
        {"dtype": "float16", "format": "ND", "ori_format": "ND", "ori_shape": (32,), "shape": (32,), "param_type": "input"},  # input_y
        {"dtype": "float16", "format": "ND", "ori_format": "ND", "ori_shape": (32,), "shape": (32,), "param_type": "output"}  # 添加输出参数
    ],
    "calc_expect_func": calc_expect_func
})
  1. 测试结果
addcustom ut_impl start running...
Run command is: 
export PATH=%%PYTHON_BIN%%:/home/science/Ascend/ascend-toolkit/8.0.0/atc/ccec_compiler/bin/:%%PYTHON_BIN%%:/home/science/Ascend/ascend-toolkit/8.0.0/compiler/ccec_compiler/bin/:/home/science/Ascend/ascend-toolkit/8.0.0/atc/bin/:/home/science/Ascend/ascend-toolkit/8.0.0/compiler/bin/:${PATH} && export PYTHONPATH=/home/science/MindstudioProjects/Add_custom/mindspore:/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages:/home/science/Ascend/ascend-toolkit/8.0.0/atc/python/site-packages:/home/science/Ascend/ascend-toolkit/8.0.0/compiler/python/site-packages:${PYTHONPATH}:${PYTHONPATH} && export ADK_PATH=/home/science/Ascend/ascend-toolkit/8.0.0 && export LD_LIBRARY_PATH=/home/science/Ascend/ascend-toolkit/8.0.0/atc/lib64:/home/science/Ascend/ascend-toolkit/8.0.0/compiler/lib64:/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/tools/simulator/Ascend910ProB/lib:${LD_LIBRARY_PATH} && export CAMODEL_LOG_PATH=/home/science/MindstudioProjects/Add_custom/out/model && export ASCEND_OPP_PATH=/home/science/Ascend/ascend-toolkit/8.0.0/opp && export PROJECT_PATH=/home/science/MindstudioProjects/Add_custom && export TVM_AICPU_OS_SYSROOT=/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/toolchain/hcc/sysroot && export SIMULATOR_PATH=/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/tools/simulator && unset LD_PRELOAD && rm -rf /home/science/MindstudioProjects/Add_custom/out/coverage_report/ut_impl && rm -rf /home/science/MindstudioProjects/Add_custom/out/model && mkdir -p -m750 /home/science/MindstudioProjects/Add_custom/out/model && rm -rf /home/science/MindstudioProjects/Add_custom/out/bin && mkdir -p -m750 /home/science/MindstudioProjects/Add_custom/out/bin  && cd /home/science/MindstudioProjects/Add_custom/out/bin && /home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/bin/op_ut_run --case_files=/home/science/MindstudioProjects/Add_custom/testcases/ut/ops_test --data_path=./data --simulator_data_path=/home/science/MindstudioProjects/Add_custom/out/model --simulator_lib_path=/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/tools/simulator --simulator_mode=pv --soc_version=Ascend910ProB  --cov_report=html --cov_report_path=/home/science/MindstudioProjects/Add_custom/out/coverage_report/ut_impl --case_name=addcustom_impl_pre_static_test_addcustom_impl_auto_case_name_1
run /home/science/MindstudioProjects/Add_custom ut test
===============================================================================
>>>>                                                                       <<<<
>>>>                           Model Init Suc                              <<<<
>>>>                                                                       <<<<
===============================================================================
[DRVSTUB_LOG] driver_queue.c:75 drvMoveTsReport:memcpy one report from TS to Driver stub successfully.

[DRVSTUB_LOG] driver_queue.c:75 drvMoveTsReport:memcpy one report from TS to Driver stub successfully.

[DRVSTUB_LOG] driver_queue.c:75 drvMoveTsReport:memcpy one report from TS to Driver stub successfully.

[DRVSTUB_LOG] driver_queue.c:61 drvMoveTsReport:taskReportQueue is empty
[DRVSTUB_LOG] driver_queue.c:75 drvMoveTsReport:memcpy one report from TS to Driver stub successfully.

[DRVSTUB_LOG] driver_queue.c:75 drvMoveTsReport:memcpy one report from TS to Driver stub successfully.

[DRVSTUB_LOG] driver_queue.c:61 drvMoveTsReport:taskReportQueue is empty
[DRVSTUB_LOG] driver_queue.c:75 drvMoveTsReport:memcpy one report from TS to Driver stub successfully.

[DRVSTUB_LOG] driver_queue.c:75 drvMoveTsReport:memcpy one report from TS to Driver stub successfully.

[DRVSTUB_LOG] driver_queue.c:75 drvMoveTsReport:memcpy one report from TS to Driver stub successfully.

[DRVSTUB_LOG] driver_queue.c:61 drvMoveTsReport:taskReportQueue is empty
[DRVSTUB_LOG] driver_queue.c:75 drvMoveTsReport:memcpy one report from TS to Driver stub successfully.

[DRVSTUB_LOG] driver_queue.c:75 drvMoveTsReport:memcpy one report from TS to Driver stub successfully.

[DRVSTUB_LOG] driver_queue.c:61 drvMoveTsReport:taskReportQueue is empty
[DRVSTUB_LOG] driver_queue.c:75 drvMoveTsReport:memcpy one report from TS to Driver stub successfully.

[DRVSTUB_LOG] driver_queue.c:61 drvMoveTsReport:taskReportQueue is empty
[INFO] model_api.cc:782 stopModel Model stopped successfully.
start run ops ut time: 2025-02-10 22:33:55.804219
[INFO] 2025-02-10 22:33:55.841581 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/ut/op_ut_runner.py", line 366] multiprocess_run_args count: 2
[INFO] 2025-02-10 22:33:55.841770 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/ut/op_ut_runner.py", line 369] process_num is 1, run cases one by one
[INFO] 2025-02-10 22:33:55.842073 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/ut/op_ut_runner.py", line 205] start run: /home/science/MindstudioProjects/Add_custom/testcases/ut/ops_test/test_addcustom_impl.py
>>>> start run test case
[Ascend910ProB] addcustom_impl test start running...
addcustom_impl_pre_static_test_addcustom_impl_auto_case_name_1 (addcustom_impl) (precision) ... [INFO] 2025-02-10 22:34:01.097596 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 105] Load RTS shared library...
[INFO] 2025-02-10 22:34:01.098069 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 219] start load ascend simulator
[INFO] 2025-02-10 22:34:01.107970 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 231] Load ascend simulator success.
[INFO] 2025-02-10 22:34:02.181230 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 780] Runtime API call rtSetDevice() success.
[INFO] 2025-02-10 22:34:02.182355 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 780] Runtime API call rtStreamCreate() success.
[INFO] 2025-02-10 22:34:02.184036 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 780] Runtime API call rtMalloc() success.
[INFO] 2025-02-10 22:34:02.193498 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 780] Runtime API call rtMemcpy() success.
[INFO] 2025-02-10 22:34:02.194372 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 780] Runtime API call rtMalloc() success.
[INFO] 2025-02-10 22:34:02.195212 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 780] Runtime API call rtMemcpy() success.
[INFO] 2025-02-10 22:34:02.195873 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 780] Runtime API call rtMalloc() success.
[INFO] 2025-02-10 22:34:02.196505 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 780] Runtime API call rtMemset() success.
[INFO] 2025-02-10 22:34:02.197192 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 780] Runtime API call rtDevBinaryRegister() success.
[INFO] 2025-02-10 22:34:02.197720 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 780] Runtime API call rtFunctionRegister() success.
[INFO] 2025-02-10 22:34:02.206531 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 780] Runtime API call rtKernelLaunch() success.
[INFO] 2025-02-10 22:34:02.221129 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 780] Runtime API call rtStreamSynchronize() success.
[INFO] 2025-02-10 22:34:02.222081 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 780] Runtime API call rtMallocHost() success.
[INFO] 2025-02-10 22:34:02.222630 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 780] Runtime API call rtMemcpy() success.
[INFO] 2025-02-10 22:34:02.223189 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 780] Runtime API call rtFree() success.
[INFO] 2025-02-10 22:34:02.223564 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 780] Runtime API call rtFree() success.
[INFO] 2025-02-10 22:34:02.223956 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 780] Runtime API call rtFree() success.
[INFO] 2025-02-10 22:34:02.224431 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 780] Runtime API call rtStreamDestroy() success.
[INFO] 2025-02-10 22:34:02.244534 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/runtime/rts_api.py", line 780] Runtime API call rtDeviceReset() success.
Error count: 0, Max atol error count: 0, Threshold count(rtol * data_size):0.032
ok
----------------------------------
run 1 tests, success: 1
>>>> end run test case, op_type:addcustom_impl cost time: 2 
[INFO] 2025-02-10 22:34:02.248955 [File "/home/science/Ascend/ascend-toolkit/8.0.0/toolkit/python/site-packages/op_test_frame/ut/op_ut_runner.py", line 255] end run: /home/science/MindstudioProjects/Add_custom/testcases/ut/ops_test/test_addcustom_impl.py
/home/science/MindstudioProjects/Add_custom/out/bin/report/combine_rpt_path [] ['rpt_1_test_addcustom_impl.data']
load /home/science/MindstudioProjects/Add_custom/out/bin/report/combine_rpt_path/rpt_1_test_addcustom_impl.data success, case cnt: 1
========================================================================
------------------------------------------------------------------------
- test soc: [Ascend910ProB]
- test case count: 1
- success count: 1
- failed count: 0
- error count: 0
------------------------------------------------------------------------
Soc Version: Ascend910ProB
    success: [addcustom_impl]  addcustom_impl_pre_static_test_addcustom_impl_auto_case_name_1 (Ascend910ProB) (precision)
------------------------------------------------------------------------
========================================================================

end run ops ut time: 2025-02-10 22:34:02.266352

TBE TestRun Finished

Ut_Impl report index.html: http://localhost:63342/Add_custom/out/coverage_report/ut_impl/index.html?_ijt=laasfbagsbclwufgwngbqcposk

从报告中也可以看到,依然是有代码是UT测试中没有覆盖的内容,这也代表着我们需要进行更多更全面的测试用例编写。
image.png
image.png

image.png

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。