跳到主要内容

固定Shape算子

固定Shape算子

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

父主题: 单算子调用

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

基本原理

对于支持动态Shape的算子:

示例代码

调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝运行,仅供参考。

import acl
## ......

## 此处算子输入tensor数据的内存必须根据应用运行模式来确定,应用运行在Host时,此处需申请Host上的内存。
## 应用运行在Device时,此处需申请Device上的内存。
ret = acl.op.infer_shape(op_type, self.in_desc_list, self.in_list, num_outputs, self.out_desc_list, self.attr)

tensor_dims = []
## 循环算子的每一个输出,推导或预估Shape值:
for i in range(len(infer_desc_list)):
dim_nums = acl.get_tensor_desc_num_dims(infer_desc_list[i])
dim_size = []
for j in range(dim_nums):
dim, ret = acl.get_tensor_desc_dim_v2(infer_desc_list[i], j)
# 表示动态Shape场景下维度值是动态的。
if dim == -1:
# 获取Shape范围,使用该范围的Shape最大值来构造输出tensor_desc,作为acl.op.execute_v2的输入。
dim_range, ret = acl.get_tensor_desc_dim_range(infer_desc_list[i], j, 2)
dim = dim_range[1]
dim_size.append(dim)
tensor_dims.append(dim_size)

## 以上给出了执行算子时输出的shape,根据tensor_dims中的dims构造输出tensor_desc(即self.out_desc_list参数值),用于调用acl.op.execute_v2。
ret = acl.op.execute_v2(op_type, self.in_desc_list, self.in_list, self.out_desc_list, self.out_list, self.attr, self.stream)

out_tensor_dims = []
## 针对上面用户预估Shape值以及使用Shape范围中的最大Shape的场景,设在算子执行结束后,需增加下面的调用,获取准确的shape。
for i in range(len(self.out_desc_list)):
dim_nums = acl.get_tensor_desc_num_dims(self.out_desc_list[i])
dim_size = []
for j in range(dim_nums):
dim, ret = acl.get_tensor_desc_dim_v2(self.out_desc_list[i], j)
dim_size.append(dim)
out_tensor_dims.append(dim_size)

## ......

父主题: 单算子调用

内存二次分配管理

用户内存管理有两种管理方式:

  • 独立内存管理,根据需要单独申请所需的内存,内存不做拆分或者二次分配
  • 内存池管理内存,用户一次性申请一块较大内存,并在使用时从这块较大内存中二次分配所需内存。

在内存二次分配时,请使用如下接口从内存池申请对应内存。由于各接口对申请的内存地址、大小有约束,在内存池管理时,需要对该情况关注处理,否则容易出现内存越界。

内存管理的总体说明请参见总体说明

接口用途输入内存/输出内存
acl.rt.memcpy_async实现异步内存复制。调用本接口进行内存复制时,源地址和目的地址都必须64字节对齐。
acl.rt.malloc在Device上申请size大小的线性内存,该接口对用户申请的size向上对齐成32字节整数倍后再多加32字节,并通过“dev_ptr”返回已分配内存的指针地址。若用户使用本接口申请大块内存并自行划分、管理内存时,每段内存需同时满足以下需求:
- 内存大小向上对齐成32整数倍加32字节(m = ALIGN_UP[len, 32] + 32字节)。
- 内存起始地址需满足64字节对齐(ALIGN_UP[m, 64])。
(说明:len 表示某段内存的大小,ALIGN_UP[len, k]表示向上按k字节对齐:((len - 1) / k + 1) * k。)
acl.rt.malloc_host应用在Device上运行时,调用该接口申请的是Device内存,且Device上的内存按普通页申请,如需首地址64字节对齐,需要用户自行处理对齐。同步接口。若用户使用本接口申请大块内存并自行划分、管理内存时,每段内存需同时满足以下需求:
- 内存大小向上对齐成32整数倍加32字节(m = ALIGN_UP[len, 32] + 32字节)。
- 内存起始地址需满足64字节对齐(ALIGN_UP[m, 64])。
(说明:len 表示某段内存的大小,ALIGN_UP[len, k]表示向上按k字节对齐:((len - 1) / k + 1) * k。)
acl.rt.malloc_cached申请Device上的内存,同步接口,该接口在任何场景下申请的内存都是支持cache缓存。在Device上申请size大小的线性内存,通过dev_ptr返回已分配内存的指针地址。其它约束与acl.rt.malloc接口相同。

计算机视觉领域一般涉及使用媒体数据处理功能,因此会涉及以上多种内存申请接口。内存首地址涉及64字节或128字节对齐,为方便统一管理,内存首地址对齐值建议选取较大,比如内存首地址128字节对齐。

关于媒体数据处理时自行管理内存时的典型场景如下,媒体数据处理的功能点介绍请参见媒体数据处理V1

图1 VDEC场景

图2 JPEGD场景

父主题: 扩展更多特性

多Device场景

开发应用时,如果涉及多Device之间的任务等待,则应用程序中必须包含相关的代码逻辑。关于该场景的接口调用流程,请依次参见pyACL接口调用流程以及本节中的说明。

图1 同步等待流程_多Device场景

父主题: 扩展更多特性

多模型串联推理

多模型推理的基本流程与单模型类似,请参见模型推理基本场景

多模型推理与单模型推理的不同点如下:

  • 关于模型加载,如果涉及多个模型,需调用多次模型加载接口。模型加载请参见模型加载

  • 关于模型执行,如果涉及多个模型,需调用多次模型执行接口。模型执行请参见模型执行

    例如,调用acl.mdl.execute接口实现同步模型推理。

父主题: 扩展更多特性

在线提单