基于ST测试样例
简介
命令行场景下,开发者可以直接基于Ascend开源社区samples仓中提供的算子测试样例代码进行修改,适配自己的算子测试代码。
样例获取:单击Gitee或Github,进入Ascend samples开源仓,参见README中的“版本说明”下载配套版本的sample包,从“cplusplus/level1_single_api/4_op_dev/2_verify_op”目录中获取样例。
ST测试用例实现思路
ST测试用例的实现思路为:进行算子测试用例json文件的定义,将自定义算子转换成单个算子的离线模型文件(*.om),然后使用AscendCL(Ascend Computing Language)提供的单算子模型加载接口加载离线模型,并传入算子输入数据,进行算子执行,通过查看输出结果验证算子功能是否正确,如下图所示。

下面详细讲解基于样例代码实现自定义算子ST测试用例的步骤。
配置算子测试用例定义文件(*.json)
自定义算子json文件用于进行算子的描述,需要按照算子原型定义进行配置,包括算子的输入、输出及属性信息。
固定shape算子配置示例如下所示:
[ { "op": "ReshapeCust", "input_desc": [ { "format": "ND", "shape": [9], "type": "int32" }, { "format": "ND", "shape": [2], "type": "int32" } ], "output_desc": [ { "format": "ND", "shape": [3,3], "type": "int32" } ] } ]
动态shape算子配置示例如下所示:
[ { "op": "xxx", "input_desc": [ { "format": "ND", "shape": [-1,16], "shape_range": [[0, 32]], "type": "int64" }, { "format": "ND", "shape": [-1,16], "shape_range": [[0, 32]], "type": "int64" } ], "output_desc": [ { "format": "ND", "shape": [-1,16], "shape_range": [[0,32]], "type": "int64" } ] } ]
使用ATC工具生成单算子模型文件
- 请参见环境准备,配置CANN软件所需基本环境变量。
- 使用ATC工具,加载单算子描述文件(json文件)生成单算子的离线模型。
atc --singleop=test_data/config/xxx.json --soc_version=${soc_version} --output=op_models
- singleop:算子描述的json文件,为相对于执行atc命令所在目录的相对路径。
- soc_version:请配置为用户当前实际使用的昇腾AI处理器BS9SX1A AI处理器的型号。
- output:生成的模型文件的存储路径,为相对于执行atc命令所在目录的相对路径。
构造输入数据
进行单算子验证的AscendCL代码实现前,开发者需要自行构造算子测试数据的二进制文件,二进制文件以input_x.bin命名,x请从0开始命名,例如input_0.bin,input_1.bin
AscendCL算子测试代码实现
- 构造算子描述对象。
Ascend开源社区中提供了单算子验证样例代码,开发者可直接基于样例代码进行修改。
样例获取:单击Gitee或Github,进入Ascend samples开源仓,参见README中的“版本说明”下载配套版本的sample包,从“cplusplus/level1_single_api/4_op_dev/2_verify_op/acl_execute_reshape”目录中获取样例。
修改src/main.cpp文中的CreateOpDesc()函数,构造算子描述对象。
- 带属性的Conv2D算子的opDesc构造示例如下:
OperatorDesc CreateOpDesc() { std::vector<int64_t> shape{8, 512, 7, 7}; std::string opType = "Conv2D"; aclDataType dataType = ACL_FLOAT16; aclFormat format = ACL_FORMAT_NCHW; OperatorDesc opDesc(opType); opDesc.AddInputTensorDesc(dataType, shape.size(), shape.data(), format); // Conv2D算子的第一个输入 std::vector<int64_t> shape1{512,512,3,3}; opDesc.AddInputTensorDesc(dataType, shape1.size(), shape1.data(), format); // Conv2D算子的第二个输入 std::vector<int64_t> shape2{8, 512, 7, 7}; opDesc.AddOutputTensorDesc(dataType, shape2.size(), shape2.data(), format); // Conv2D算子的输出 int64_t intList[4]{1, 1, 1, 1}; auto opAttr = opDesc.opAttr; aclopSetAttrListInt(opAttr, "strides", 4, intList); aclopSetAttrListInt(opAttr, "pads", 4, intList); aclopSetAttrListInt(opAttr, "dilations", 4, intList); return opDesc; }
- 自定义算子ReshapeCust算的opDesc构造示例如下:
OperatorDesc CreateOpDesc() { // define operator std::vector<int64_t> inputShape0{9}; std::vector<int64_t> inputShape1{2}; std::vector<int64_t> outputShape{3,3}; std::string opType = "ReshapeCust"; aclDataType dataType = ACL_INT32; aclFormat format = ACL_FORMAT_ND; OperatorDesc opDesc(opType); opDesc.AddInputTensorDesc(dataType, inputShape0.size(), inputShape0.data(), format); opDesc.AddInputTensorDesc(dataType, inputShape1.size(), inputShape1.data(), format); opDesc.AddOutputTensorDesc(dataType, outputShape.size(), outputShape.data(), format); return opDesc; }
OperatorDesc为“acl_execute_reshape/inc/operator_desc.h”中构造的算子描述对象,其中:
- std::string opType为算子的类型。
- std::vector<aclTensorDesc *> inputDesc,为算子的输入描述。
- std::vector<aclTensorDesc *> outputDesc,为算子的输出描述。
- aclopAttr *opAttr,为算子的属性。
调用aclopSetAttr**( )接口进行属性的构造,不同类型的属性调用的aclopSetAttr*的接口不同,详细的接口可参见《应用软件开发指南 (C&C++)》中的“AscendCL API参考 > 数据类型及其操作接口”章节中的“aclopAttr”类型的接口。
- OperatorDesc &AddInputTensorDesc(aclDataType dataType, int numDims, const int64_t *dims, aclFormat format)
用于构造算子的输入,若算子有多个输入,需要使用多条opDesc.AddInputTensorDesc( )语句进行构造。
- OperatorDesc &AddOutputTensorDesc(aclDataType dataType, int numDims, const int64_t *dims, aclFormat format)
用于构造算子的输出,若算子有多个输出,需要使用多条opDesc.AddOutputTensorDesc( )语句进行构造。
aclDataType与aclFormat的取值范围请参见《应用软件开发指南 (C&C++)》中的“AscendCL API参考 > 数据类型及其操作接口”章节中的“aclDataType”与“aclFormat”。
- 带属性的Conv2D算子的opDesc构造示例如下:
- 加载单算子模型并进行算子的执行。
主要包括以下关键接口:
调用aclInit接口进行AscendCL初始化并调用aclrtSetDevice接口指定用于运算的Device。
调用aclopSetModelDir接口,设置加载模型文件的目录,目录下存放单算子模型文件(*.om文件)。
调用aclrtMalloc接口申请Device上的内存,存放执行算子的输入、输出数据。
根据构造的算子描述信息(输入输出Tensor描述、算子属性等)、申请存放算子输入输出数据的内存,然后调用aclopExecuteV2接口加载并执行算子。
调用aclrtSynchronizeStream接口阻塞应用运行,直到指定Stream中的所有任务都完成。
调用aclrtDestroyStream接口释放stream。
调用aclrtResetDevice接口释放Device上的资源。
调用aclFinalize接口实现AscendCL去初始化。
测试用例编译运行
编译测试用例代码,并将生成的动态库文件、单算子模型文件以及测试数据在运行环境执行,详细操作步骤可参见样例参考。