文档首页 > > 推理场景> 应用软件开发指南 (C&C++)> 开发典型功能点的介绍> 单算子调用> 未被封装成AscendCL接口的算子>

动态Shape算子(不注册算子选择器)

动态Shape算子(不注册算子选择器)

分享
更新时间:2021/01/27 GMT+08:00

对于昇腾AI处理器不支持的算子,用户需参考TBE自定义算子开发指南先完成自定义算子的开发,再参考如下内容执行单算子。

基本原理

对于支持动态Shape的算子,如果算子输出Shape明确时,该类算子执行的基本流程与固定Shape算子执行类似,基本流程请参见固定Shape算子

不同点在于执行单算子:

  • 对于支持动态Shape的算子,无法明确算子的输出Shape时,需要用户调用配合调用aclopInferShape接口、aclGetTensorDescNumDims接口、aclGetTensorDescDimV2接口、aclGetTensorDescDimRange等接口,推导或预估算子的输出Shape,作为算子执行接口aclopExecuteV2的输入。
  • 将用户APP代码编译成可执行文件后,在执行可执行文件前,需确保运行环境上已设置如下环境变量:
    //opp软件包的安装路径
    export install_path=/home/HwHiAiUser/Ascend/ascend-toolkit/latest # 软件包安装路径,请根据实际修改
    export ASCEND_OPP_PATH=${install_path}/opp

示例代码

调用接口后,需增加异常处理的分支,示例代码中不一一列举。以下是关键步骤的代码示例,用于说明如何推导或预估算子的输出Shape,不可以直接拷贝编译运行,仅供参考:

 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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
//......

const char *opType;
int numInputs;
aclTensorDesc *inputDesc[2];
aclDataBuffer *inputs[2]
int numOutputs;
aclTensorDesc *outputDesc[1];
aclopAttr *attr;
aclError ret = aclopInferShape(opType, numInputs, inputDesc, inputsnumOutputs, outputDesc, attr);
if (ret != ACL_ERROR_NONE) {
	printf("aclopInferShape fail\n");
	return;
}

std::vector<std::vector<int64_t>> tensorDims; // inferShape之后的输出tensor的Shape
//循环算子的每一个输出,做以下处理:
for (int index = 0; index < numOutputs; ++index) {
	std::vector<int64_t> dimSize; //表示执行算子时,输出的shape
	size_t dimNums = aclGetTensorDescNumDims(outputDesc[index]);
        //表示动态Shape场景下维度个数未知,该场景预留
	if (dimNums == ACL_UNKNOWN_RANK)  {
		//由用户预估最大Shape值max shape
		dimSize.push_back(max_shape);
	} else {
		for (size_t i = 0; i < dimNums; ++i) {
		    int64_t dim;
			ret = aclGetTensorDescDimV2(outputDesc[index], i, &dim);
			if (ret != ACL_ERROR_NONE) {
				printf("aclGetTensorDescDimV2 fail\n");
				return;
			}
                        //表示动态Shape场景下维度值是动态的
			if(dim == -1) {
			    int64_t dimRange[2];
                                //获取Shape范围,使用该范围中的Shape最大值来构造输出tensorDesc,作为aclopExecuteV2的输入
				ret = aclGetTensorDescDimRange(outputDesc[index], i, 2, dimRange);
				if (ret != ACL_ERROR_NONE) {
					printf("aclGetTensorDescDimRange fail\n");
					return;
				}
				dim = dimRange[1];
			}
			dimSize.push_back(dim);
		}
	}
	tensorDims.push_back(dimSize);
}

//以上给出了执行算子时输出的shape, 根据tensorDims中的dims构造输出tensorDesc(即outputDescNew参数值), 用于调用aclOpExecuteV2
ret = aclOpExecuteV2(opType, numInputs, inputDesc, inputs, numOutputs, outputDescNew, outputs, attr, stream);
if (ret != ACL_ERROR_NONE) {
	printf("aclOpExecuteV2 fail\n");
	return;
}

//针对上面用户预估Shape值以及使用Shape范围中的最大Shape的场景,设在算子执行结束后,需增加下面的调用,获取准确的shape:
//for 循环每一个设置为maxshape的outputDesc,做以下处理
std::vector<std::vector<int64_t>> outTensorDims; // 准确的输出tensorShape
for (int index = 0; index < numOutputs; ++index) {
    std::vector<int64_t> dimSize;
	int dimNums = aclGetTensorDescNumDims(outputDescNew[index]);
	for (int i = 0; i < dimNums; i++){
		int64_t dim;
		ret = aclGetTensorDescDimV2(outputDescNew[index], i, &dim);
		if (ret != ACL_ERROR_NONE) {
			printf("aclGetTensorDescDimV2 fail\n");
			return;
		}
		dimSize.push_back(dim);
	}
	outTensorDims.push_back(dimSize);
}
//......
分享:

    相关文档

    相关产品

文档是否有解决您的问题?

提交成功!非常感谢您的反馈,我们会继续努力做到更好!
反馈提交失败,请稍后再试!

*必选

请至少选择或填写一项反馈信息

字符长度不能超过200

提交反馈 取消

如您有其它疑问,您也可以通过华为云社区论坛频道来与我们联系探讨

智能客服提问云社区提问