需完成自定义算子的开发,包括算子实现代码和算子原型定义,详情可参见算子代码实现(TBE DSL)和算子原型定义。
若已经存在了算子的UT测试用例,可以右键单击“testcases”目录或“testcases > ut”目录,选择,创建UT测试用例。

若已存在此算子的UT测试用例,系统会提示“testcases/ut/ops_test/xx already exists. Do you want to overwrite?”。
可以选择“Overwrite”覆盖当前测试用例或者“Cancel”取消覆盖。
创建完成后,会在算子工程根目录下生成testcases文件夹,目录结构如下所示:
├── MyOperator //工程根目录 │ ├── testcases │ │ ├── libs // gtest框架,为第三方依赖,用户无需关注 │ │ ├── ut │ │ │ ├── ops_test │ │ │ │ ├── add │ │ │ │ │ ├── CMakeLists.txt //用于编译可执行文件 │ │ │ │ │ ├── test_add_impl.py //算子实现代码的测试用例文件 │ │ │ │ │ ├── test_add_proto.cc //算子原型定义代码的测试用例文件 │ │ │ │ ├── CMakeLists.txt //用于编译可执行文件 │ │ │ │ ├── test_main.cc //测试用例调用总入口 │ │ │ ├ CMakeLists.txt
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
set(CMAKE_CXX_FLAGS "-std=c++11")
set(PROJECT_DIR "$ENV{PROJECT_PATH}")
set(GTEST_DIR ${PROJECT_DIR}/testcases/libs/gtest)
set(ADK_DIR "$ENV{ADK_PATH}")
set(ATC_DIR ${ADK_DIR}/atc)
set(OP_PROTO_SRC_DIR ${PROJECT_DIR}/op_proto)
message(STATUS "ATC_DIR=${ATC_DIR}")
enable_testing()
include_directories(
"${GTEST_DIR}/include"
"${ATC_DIR}/include"
"${OP_PROTO_SRC_DIR}"
)
aux_source_directory(${OP_PROTO_SRC_DIR} OP_PROTO_SOURCE_SRCS)
file(GLOB OP_PROTO_TEST_FILES **proto.cc)
link_directories(
"${ATC_DIR}/lib64"
"${GTEST_DIR}"
"/usr/local/gcc7.3.0/lib64/"
)
set(CUSTOM_OBJECT_NAME "add_proto_test")
add_executable(${CUSTOM_OBJECT_NAME}
${PROJECT_DIR}/testcases/ut/ops_test/test_main.cc ${OP_PROTO_SOURCE_SRCS} ${OP_PROTO_TEST_FILES})
target_link_libraries(${CUSTOM_OBJECT_NAME} gtest c_sec alog pthread error_manager graph register)
UT测试要求gcc版本为7.5.0及以上,若gcc版本不满足要求,请升级gcc版本。
开关,将隐藏当前字段的配置项。import ...
from op_test_frame.ut import BroadcastOpUT # 导入UT测试类,可根据算子类型选择使用哪个测试类
ut_case = BroadcastOpUT("add") # 实例化UT测试用例,ut_case为UT测试框架关键字,不可修改;add为算子的Type
def calc_expect_func(input_x, input_y, output_z): # 自定义实现生成期望数据的函数
res = input_x["value"] + input_y["value"]
return [res, ] # 返回期望数据
# 添加测试用例
ut_case.add_precision_case("all", {
"params": [{"dtype": "float16", "format": "ND", "ori_format": "ND", "ori_shape": (32,), "shape": (32,),
"param_type": "input"},
{"dtype": "float16", "format": "ND", "ori_format": "ND", "ori_shape": (32,), "shape": (32,),
"param_type": "input"},
{"dtype": "float16", "format": "ND", "ori_format": "ND", "ori_shape": (32,), "shape": (32,),
"param_type": "output"}],
"calc_expect_func": calc_expect_func
})
# 若定义多个用例,定义多个ut_case.add_precision_case函数
ut_case.add_precision_case("all", {
"params": [{"dtype": "float16", "format": "ND", "ori_format": "ND", "ori_shape": (16,2), "shape": (16,2),
"param_type": "input"},
{"dtype": "float16", "format": "ND", "ori_format": "ND", "ori_shape": (16,2), "shape": (16,2),
"param_type": "input"},
{"dtype": "float16", "format": "ND", "ori_format": "ND", "ori_shape": (16,2), "shape": (16,2),
"param_type": "output"}],
"calc_expect_func": calc_expect_func
})
目前Windows版本不支持导入te或者tbe模块。故在编写算子实现代码的UT Python测试用例时不支持导入算子实现文件及涉及te或tbe模块的文件。
测试用例“params”中字段和字段取值范围需根据算子实现文件入口参数确定。输入tensor中的“ori_shape”和“ori_format”字段为可选字段,但若使用参数校验修饰器检验参数,“ori_shape”和“ori_format”字段必选。
可参见UT测试接口参考查看每个测试类接口的使用方法。
若要与期望数据进行结果的比对,请使用add_precision_case接口。
在“testcases/ut/ops_test/add/test_add_proto.cc”文件中,编写算子原型定义的UT C++测试用例,用于定义算子实例、更新算子输入输出并调用InferShapeAndType函数,最后验证InferShapeAndType函数执行过程及结果的正确性。
UT的C++用例采用的是gtest框架,所以需要导入gtest测试框架;算子原型定义在原型定义头文件中,所以需要导入原型定义的*.h文件。
//导入gtest框架 #include <gtest/gtest.h> //导入基础的vector类库 #include <vector> //导入算子的IR定义头文件 #include "add.h"
UT的C++用例采用的是gtest框架,所以需要定义一个类来继承gtest的测试类。
#include <gtest/gtest.h>
#include <vector>
#include "add.h"
class AddTest : public testing::Test {
protected:
static void SetUpTestCase() {
std::cout << "add test SetUp" << std::endl;
}
static void TearDownTestCase() {
std::cout << "add test TearDown" << std::endl;
}
};
测试类的名称可自定义,以“Test”为后缀。
每一个场景写一个测试用例函数,该用例中需要构造算子实例,包括算子名称、shape、数据类型。然后调用InferShapeAndType函数,并将推导出的shape、dtype与预期结果进行对比。
示例如下:
TEST_F(AddTest, add_test_case_1) {
// 定义算子实例及输入shape和type,以TensorDesc实例承载
ge::op::Add add_op; //Add为算子的Type,需要与原型定义的REG_OP(OpType)中的OpType保持一致
ge::TensorDesc tensorDesc;
ge::Shape shape({2, 3, 4});
tensorDesc.SetDataType(ge::DT_FLOAT16);
tensorDesc.SetShape(shape);
tensorDesc.SetOriginShape(shape);
// 更新算子输入,输入的名称需要与原型定义*.h文件中的名称保持一致,例如:x1与x2分别为Add算子的两个输入
add_op.UpdateInputDesc("x1", tensorDesc);
add_op.UpdateInputDesc("x2", tensorDesc);
// 调用InferShapeAndType函数,InferShapeAndType()接口为固定接口,用例执行时会自动调用算子原型定义中的shape推导函数
auto ret = add_op.InferShapeAndType();
// 验证调用过程是否成功
EXPECT_EQ(ret, ge::GRAPH_SUCCESS);
// 获取算子输出并比较shape和type,算子输出的名字需要与原型定义*.h文件中的名称保持一致,例如:算子的输出为y
auto output_desc = add_op.GetOutputDesc("y");
EXPECT_EQ(output_desc.GetDataType(), ge::DT_FLOAT16);
std::vector<int64_t> expected_output_shape = {2, 3, 4};
EXPECT_EQ(output_desc.GetShape().GetDims(), expected_output_shape);
}
若不同输入的shape不同,请自行定义多个TensorDesc对象进行设置,例如:
ge::op::Operator1 operator1_op; //Operator1为算子的Type
ge::TensorDesc tensorDesc1;
ge::TensorDesc tensorDesc2;
ge::Shape shape1({2, 3, 4});
ge::Shape shape2({3, 4, 5});
tensorDesc1.SetDataType(ge::DT_FLOAT16);
tensorDesc1.SetShape(shape1);
tensorDesc1.SetOriginShape(shape1);
tensorDesc2.SetDataType(ge::DT_FLOAT16);
tensorDesc2.SetShape(shape2);
tensorDesc2.SetOriginShape(shape2);
// 更新算子输入
operator1_op.UpdateInputDesc("x1", tensorDesc1);
operator1_op.UpdateInputDesc("x2", tensorDesc2);
Windows版本的MindStudio在进行以下操作时需获取UT Case Names,如图1所示将出现进度提示框(预计耗时10s左右)。
|
参数 |
说明 |
|---|---|
|
Name |
运行配置名称,用户可以自定义。 |
|
Test Type |
选择ut_impl。 |
|
Compute Unit |
选择计算单元,TBE算子仅支持配置AI Core/Vector Core。 |
|
SoC Version |
下拉选择当前版本的昇腾AI处理器类型。 |
|
Target |
运行环境。
|
|
Enable Advisor |
开启专家系统。 当Target为Simulator_TMModel时,可以对单测试用例性能进行专家系统分析。专家系统请参见算子工程入口。 |
|
Operator Name |
选择运行的测试用例。
|
|
CANN Machine |
CANN工具所在设备的deployment信息。
说明:
仅支持Windows操作系统。 |
|
Case Names |
勾选需要运行的测试用例,即算子实现代码的UT Python测试用例。支持全选或勾选部分测试用例。 |
运行完成后,通过界面下方的“Run”日志打印窗口查看运行结果。
测试结果:
查看UT测试用例运行结果需要使用浏览器,如果未安装浏览器,请用户自行安装。
如果出现"Page'http://***.html'requested without authorization, you can copy URL and open it in browser to trust it."提示,请参考配置不受信任的网址访问浏览器解决。

Parallel Analysis:并行度视图。并行度视图展示单算子运行中各个指令执行的并行度情况,横轴为时间(Tick,时钟周期),纵轴为各指令单元,鼠标移动到时间块上,可以显示单条指令的消耗时间以及相关指令。

若用户使用TIK方式实现算子开发,MindStudio UT测试支持流线图到TIK代码和CCE代码的跳转,帮助用户快速定位到流水图中对应的代码位置,配置详情请参见设置代码跳转功能。
在芯片进行运算前,vector、cube、MTE1、MTE2、MTE3等单元会做初始化操作,对应在timeline显示上会出现数据还未搬运,各个单元就产生流水数据。
按钮,显示和隐藏专家建议。开发人员可以执行当前工程中所有算子的UT测试用例,也可以执行单个算子的UT测试用例。
|
参数 |
说明 |
|---|---|
|
Name |
运行配置名称,用户可以自定义。 |
|
Test Type |
选择ut_proto。 |
|
Compute Unit |
选择计算单元,TBE算子仅支持配置AI Core/Vector Core。 |
|
Operator Name |
选择运行的测试用例。
|
|
Case Names |
勾选需要运行的测试用例,即TEST_F中定义的用例。支持全选或勾选部分测试用例。 |
运行完成后,通过界面下方的日志打印窗口,查看运行结果。结果中展示此次运行测试用例、成功用例和失败用例的数量,如下图所示。

动态shape算子工程涉及OP Tiling时执行以下操作,不涉及tiling实现的算子无需关注。

若已经存在了算子的UT测试用例,可以右键单击“testcases”目录,或者“testcases > ut”目录,选择,创建OP Tiling UT测试用例。

若已存在此算子的OP Tiling UT测试用例,系统会提示“testcases/ut/ops_tiling_test/xx already exists. Do you want to overwrite?”
可以选择“Overwrite”或者“Cancel”。
创建完成后,会在算子工程根目录下生成testcases文件夹,目录结构如下所示:
├── MyOperator //工程根目录 │ ├── testcases │ │ ├── libs // gtest框架,为第三方依赖,用户无需关注 │ │ ├── ut │ │ │ ├── ops_tiling_test │ │ │ │ ├──add │ │ │ │ │ ├── CMakeLists.txt //用于编译可执行文件 │ │ │ │ │ ├── test_add_tiling.cc //算子tiling的测试用例文件 │ │ │ │ ├── CMakeLists.txt //用于编译可执行文件 │ │ │ │ ├── test_main.cc //测试用例调用总入口
开发人员可以执行当前工程中所有算子的OP Tiling UT测试用例,也可以执行单个算子的OP Tiling UT测试用例。
|
参数 |
说明 |
|---|---|
|
Name |
运行配置名称,用户可以自定义。 |
|
Test Type |
选择ut_tiling。 |
|
Compute Unit |
计算单元,选择AI Core/Vector Core。 |
|
Operator Name |
选择运行的测试用例。
|
|
Case Names |
勾选需要运行的测试用例,即TEST_F中定义的用例。 支持全选或勾选部分测试用例。 |
运行完成后,通过界面下方的日志打印窗口,查看运行结果。结果中展示此次一共运行几个用例,成功几个,失败几个。如图4所示。