实现过程
本章节详细描述自定义算子部署到算子库后,如何进行单算子的网络验证。
配置自定义算子json文件
自定义算子json文件用于进行算子的描述,需要按照算子原型定义进行配置,包括算子的输入、输出及属性信息,配置示例如下所示:
[ { "op": "Conv2D", "input_desc": [ { "format": "NCHW", "shape": [8, 512, 7, 7], "type": "float16" }, { "format": "NCHW", "shape": [512, 512, 3, 3], "type": "float16" } ], "output_desc": [ { "format": "NCHW", "shape": [8, 512, 7, 7], "type": "float16" } ], "attr": [ { "name": "strides", "type": "list_int", "value": [1, 1, 1, 1] }, { "name": "pads", "type": "list_int", "value": [1, 1, 1, 1] }, { "name": "dilations", "type": "list_int", "value": [1, 1, 1, 1] } ] } ]
json文件为OpDesc的数组,参数解释如下所示:
属性名 |
类型 |
说明 |
是否必填 |
---|---|---|---|
op |
string |
算子类型。 |
是 |
input_desc |
TensorDesc数组 |
算子输入描述。 |
是 |
output_desc |
TensorDesc数组 |
算子输出描述。 |
是 |
attr |
Attr数组 |
算子属性。 |
否 |
TensorDesc数组参数说明如下所示:
属性名 |
类型 |
说明 |
是否必填 |
---|---|---|---|
format |
string |
Tensor的排布格式,配置为算子原始框架支持的format。 当前支持的format格式如下:
|
是 |
type |
string |
Tensor的数据格式,支持的type如下:
|
是 |
shape |
int数组 |
Tensor的shape,例如[1, 224, 224, 3]。 |
是 |
name |
string |
Tensor的名称。 如果算子的输入为动态输入,则需要设置该字段。如ConcatD算子在算子原型中,其动态输入定义为: DYNAMIC_INPUT(input_values, …),则此处需要设置为”input_values0”, “input_values1”,…。 |
否 |
Attr数组的参数说明如下所示:
属性名 |
类型 |
说明 |
是否必填 |
---|---|---|---|
name |
string |
属性名。 |
是 |
type |
string |
属性值的类型,支持的类型有:
|
是 |
value |
由type的取值决定 |
属性值,根据type不同,属性值不同:
|
是 |
使用ATC工具生成单算子模型文件
- 设置环境变量。
环境变量设置示例如下所示,环境变量的详细解释请参考《ATC工具使用指南》中的转换样例。
export install_path=/home/HwHiAiUser/Ascend/ascend-toolkit/latest export PATH=${install_path}/atc/ccec_compiler/bin:${install_path}/atc/bin:$PATH export PYTHONPATH=${install_path}/atc/python/site-packages:${install_path}/atc/python/site-packages/auto_tune.egg/auto_tune:${install_path}/atc/python/site-packages/schedule_search.egg:$PYTHONPATH export LD_LIBRARY_PATH=${install_path}/atc/lib64:$LD_LIBRARY_PATH export ASCEND_OPP_PATH=${install_path}/opp
install_path为ATC与OPP组件的安装路径。
- 使用ATC工具,加载单算子描述文件(json文件)生成单算子的离线模型。
atc --singleop=test_data/config/xxx.json --soc_version={soc_version} --output=op_models
- singleop:算子描述的json文件,为相对于执行atc命令所在目录的相对路径。
- soc_version:昇腾AI处理器的版本,请根据实际情况替换。
可从ATC安装路径的atc/data/platform_config目录下查看支持的昇腾AI处理器的类型,对应“*.ini”文件的名字即为soc_version。
- output:生成的模型文件的存储路径,为相对于执行atc命令所在目录的相对路径。
ATC工具的其他参数解释请参考《ATC工具使用指南》中的转换样例。
构造输入数据
进行单算子验证的AscendCL代码实现前,开发者需要自行构造算子测试数据的二进制文件,二进制文件以input_x.bin命名,x请从0开始命名,例如input_0.bin,input_1.bin。
说明:您可以使用numpy的random函数生成测试数据并将其输出到二进制文件。
AscendCL单算子网络验证代码实现
- 构造算子描述对象。
ACLlib安装包中提供了单算子验证样例模板,开发者可直接基于样例模板进行修改。
修改src/main.cpp文中的CreateOpDesc()函数,构造算子描述对象。
- 不带属性的Add算子的opDesc构造示例如下:
OperatorDesc CreateOpDesc() { std::string opType = "Add"; // 算子的类型 // 构造算子的输入输出描述 std::vector<int64_t> shape{8, 16}; aclDataType dataType = ACL_INT32; aclFormat format = ACL_FORMAT_ND; OperatorDesc opDesc(opType); opDesc.AddInputTensorDesc(dataType, shape.size(), shape.data(), format); opDesc.AddInputTensorDesc(dataType, shape.size(), shape.data(), format); opDesc.AddOutputTensorDesc(dataType, shape.size(), shape.data(), format); return opDesc; }
- 带属性的ConcatD算子的opDesc构造示例如下:
OperatorDesc CreateOpDesc() { std::string opType = "ConcatD"; std::vector<int64_t> shape1{1, 1, 4, 4}; std::vector<int64_t> shape2{1, 2, 4, 4}; aclDataType dataType = ACL_INT32; aclFormat format = ACL_FORMAT_ND; OperatorDesc opDesc(opType); opDesc.AddInputTensorDesc(dataType, shape1.size(), shape1.data(), format); opDesc.AddInputTensorDesc(dataType, shape1.size(), shape1.data(), format); opDesc.AddOutputTensorDesc(dataType, shape2.size(), shape2.data(), format); // 构造算子属性 auto opAttr = opDesc.opAttr; aclopSetAttrInt(opAttr, "N", 2); aclopSetAttrInt(opAttr, "concat_dim", 1); return opDesc; }
- 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; }
OperatorDesc为“acl_execute_add/inc/operator_desc.h”中构造的算子描述对象,其中:
- std::string opType为算子的类型。
- std::vector<const aclTensorDesc *> inputDesc,为算子的输入描述。
- std::vector<const aclTensorDesc *> outputDesc,为算子的输出描述。
- aclopAttr *opAttr,为算子的属性。
调用aclopSetAttr**( )接口进行属性的构造,不同类型的属性调用的aclopSetAttr*的接口不同,详细的接口可参见《应用软件开发指南》中的“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的取值范围请参见《应用软件开发指南》中的“AscendCL API参考 > 数据类型及其操作接口”章节中的“aclDataType”与“aclFormat”。
- 不带属性的Add算子的opDesc构造示例如下:
- 加载单算子模型并进行算子的执行。
主要包括以下关键接口:
调用aclInit接口进行AscendCL初始化并调用aclrtSetDevice接口指定用于运算的Device。
调用aclopSetModelDir接口,设置加载模型文件的目录,目录下存放单算子模型文件(*.om文件)。
调用aclrtMalloc接口申请Device上的内存,存放执行算子的输入、输出数据。
根据构造的算子描述信息(输入输出Tensor描述、算子属性等)、申请存放算子输入输出数据的内存,然后调用aclopExecute接口加载并执行算子。
调用aclrtSynchronizeStream接口阻塞应用运行,直到指定Stream中的所有任务都完成。
调用aclrtDestroyStream接口释放内存。
调用aclrtResetDevice接口释放Device上的资源
“acl_execute_add/src/main.cpp”中提供了单算子的模型加载与执行的通用流程样例代码,开发者可直接使用此部分样例代码加载自己的单算子模型文件及算子描述对象进行单算子功能验证。