互推导关系
非连续的Tensor
目前大部分算子API的输入Tensor支持“非连续的Tensor”,即一个Tensor可以通过(shape, strides, offset)表示。
示例1
例如现有一个shape=(6, 5)、strides=(10, 1)、offset=22的Tensor,其内存排布如下:
a0,0, a0,1, a0,2, a0,3, a0,4, a0,5, a0,6, a0,7, a0,8, a0,9
a1,0, a1,1, a1,2, a1,3, a1,4, a1,5, a1,6, a1,7, a1,8, a1,9
a2,0, a2,1, a2,2, a2,3, a2,4, a2,5, a2,6, a2,7, a2,8, a2,9
a3,0, a3,1, a3,2, a3,3, a3,4, a3,5, a3,6, a3,7, a3,8, a3,9
a4,0, a4,1, a4,2, a4,3, a4,4, a4,5, a4,6, a4,7, a4,8, a4,9
a5,0, a5,1, a5,2, a5,3, a5,4, a5,5, a5,6, a5,7, a5,8, a5,9
a6,0, a6,1, a6,2, a6,3, a6,4, a6,5, a6,6, a6,7, a6,8, a6,9
a7,0, a7,1, a7,2, a7,3, a7,4, a7,5, a7,6, a7,7, a7,8, a7,9
a8,0, a8,1, a8,2, a8,3, a8,4, a8,5, a8,6, a8,7, a8,8, a8,9
a9,0, a9,1, a9,2, a9,3, a9,4, a9,5, a9,6, a9,7, a9,8, a9,9
即该Tensor排布如上图的深色位置。这个完整的Tensor在内存排布上是不连续的,strides描述Tensor维度上相邻两个元素的间隔,如果在维度1上的stride为1, 该维度是连续的;如果在维度0上的stride为10,那么相邻的元素间隔10个元素,即非连续。offset表示这个Tensor的首元素相对addr的偏移。
示例2
例如现有一个shape=(4, 3)、strides=(20, 2)、offset=22的Tensor,其内存排布如下:
a0,0, a0,1, a0,2, a0,3, a0,4, a0,5, a0,6, a0,7, a0,8, a0,9
a1,0, a1,1, a1,2, a1,3, a1,4, a1,5, a1,6, a1,7, a1,8, a1,9
a2,0, a2,1, a2,2, a2,3, a2,4, a2,5, a2,6, a2,7, a2,8, a2,9
a3,0, a3,1, a3,2, a3,3, a3,4, a3,5, a3,6, a3,7, a3,8, a3,9
a4,0, a4,1, a4,2, a4,3, a4,4, a4,5, a4,6, a4,7, a4,8, a4,9
a5,0, a5,1, a5,2, a5,3, a5,4, a5,5, a5,6, a5,7, a5,8, a5,9
a6,0, a6,1, a6,2, a6,3, a6,4, a6,5, a6,6, a6,7, a6,8, a6,9
a7,0, a7,1, a7,2, a7,3, a7,4, a7,5, a7,6, a7,7, a7,8, a7,9
a8,0, a8,1, a8,2, a8,3, a8,4, a8,5, a8,6, a8,7, a8,8, a8,9
a9,0, a9,1, a9,2, a9,3, a9,4, a9,5, a9,6, a9,7, a9,8, a9,9
即该Tensor排布如上图的深色位置。这个完整的Tensor在内存排布上是不连续的,strides描述Tensor维度上相邻两个元素的间隔,如果在维度1上的stride为2, 该维度上间隔1个元素;如果在维度0上的stride为20,那么相邻的元素间隔20个元素,即非连续。offset表示这个Tensor的首元素相对addr的偏移。
父主题: 基本概念
broadcast关系
广播概念
目前大部分算子API支持NumPy的broadcast特征。“broadcast”(广播)描述了NumPy在算术运算期间如何处理具有不同形状的数组。在某些情况下,较小的数组可以“广播至”较大的数组,使两者shape互相兼容。
广播提供了一种数组向量化操作,从而使得循环在C而不是Python中发生。它无需复制不必要的数据即可完成,通常算法的效率较高。然而在某些情况下,广播并不是一种好方法,因为它会导致内存使用效率降低,从而减缓计算速度。
广播规则
一般进行广播计算时,需要理解以下规则:
-
规则1:让所有输入数组都向形状最长的数组看齐。形状不足的部分通过在前面(左侧)填充1。
:::note 说明 形状其实就是指the number of dimensions。比如计算a+b,其中a.shape=(2, 2, 3)、b.shape=(2, 3),那么数组b将被broadcast为b.shape=(1, 2, 3)。 :::
-
规则2:如果两个数组的形状在任何维度上均不匹配,但是某个数组中某一个维度为1,则该维度中形状为1的数组将被拉伸以匹配另一个数组对应维度形状。
:::note 说明 本场景下,只需保证能在某一个维度做broadcast即可。比如计算a+b,其中a.shape=(1, 3)、b.shape=(3, 1),那么两个数组会boradcast为a.shape=(3, 3)、b.shape=(3, 3)。 :::
-
规则3:如果两个数组的形状在任何维度上均不匹配,且均没有等于1的维度,则会报错。
父主题: 基本概念
互推导关系
推导规则
当一个API(如aclnnAdd、aclnnMul等)输入的Tensor数据类型不一致时,API内部会推导出一个数据类型,将输入数据转换成该数据类型进行计算。
:::note 说明
- 为方便描述,表格中使用的数据类型是简写形式,代表的含义:ACL_FLOAT(f32)、ACL_FLOAT16(f16)、ACL_DOUBLE(f64)、ACL_BF16(bf16)、ACL_INT8(s8)、ACL_UINT8(u8)、ACL_INT16(s16)、ACL_UINT16(u16)、ACL_INT32(s32)、ACL_UINT32(u32)、ACL_INT64(s64)、ACL_UINT64(u64)、ACL_BOOL(bool)、ACL_COMPLEX32(c32)、ACL_COMPLEX64(c64)、ACL_COMPLEX128(c128)。
- 表格里表头和最左侧一列分别表示待推导的两个输入数据类型,表格中对应位置表示推导出的数据类型。
- NA表示这两种类型不能进行推导计算。
- 当输入数据类型为bool与其他任意数据类型(非u16、u32、u32),其推导出的数据类型为其他任意数据类型。当输入数据类型为bool与u16、u32、u64其中一个,均不支持数据类型推导。
- 当输入数据类型为u16与u16,其推导出的数据类型仍为u16。当输入数据类型为u16与非u16的任意数据类型,不支持数据类型推导。
- 当输入数据类型为u32与u32,其推导出的数据类型仍为u32。当输入数据类型为u32与非u32的任意数据类型,不支持数据类型推导。
- 当输入数据类型为u64与u64,其推导出的数据类型仍为u64。当输入数据类型为u64与非u64的任意数据类型,不支持数据类型推导。 :::
表1 常见数据类型推导关系
| 数据类型 | f32 | f16 | f64 | bf16 | s8 | u8 | s16 | s32 | s64 | c32 | c64 | c128 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| f32 | f32 | f32 | f64 | f32 | f32 | f32 | f32 | f32 | f32 | c64 | c64 | c128 |
| f16 | f32 | f16 | f64 | f32 | f16 | f16 | f16 | f16 | f16 | c32 | c64 | c128 |
| f64 | f64 | f64 | f64 | f64 | f64 | f64 | f64 | f64 | f64 | c64 | c64 | c128 |
| bf16 | f32 | f64 | f64 | bf16 | bf16 | bf16 | bf16 | bf16 | bf16 | c32 | c64 | c128 |
| s8 | f32 | f16 | f64 | bf16 | s8 | s16 | s16 | s32 | s64 | c32 | c64 | c128 |
| u8 | f32 | f16 | f64 | bf16 | s16 | u8 | s16 | s32 | s64 | c32 | c64 | c128 |
| s16 | f32 | f16 | f64 | bf16 | s16 | s16 | s16 | s32 | s64 | c32 | c64 | c128 |
| s32 | f32 | f16 | f64 | bf16 | s32 | s32 | s32 | s32 | s64 | c32 | c64 | c128 |
| s64 | f32 | f16 | f64 | bf16 | s64 | s64 | s64 | s64 | s64 | c32 | c64 | c128 |
| c32 | c64 | c32 | c64 | c32 | c32 | c32 | c32 | c32 | c32 | c32 | c64 | c128 |
| c64 | c64 | c64 | c64 | c64 | c64 | c64 | c64 | c64 | c64 | c64 | c64 | c128 |
| c128 | c128 | c128 | c128 | c128 | c128 | c128 | c128 | c128 | c128 | c128 | c128 | c128 |
表2 特殊数据类型推导关系
| 数据类型 | f32 | f16 | f64 | bf16 | s8 | u8 | s16 | s32 | s64 | c32 | c64 | c128 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| u16 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| u32 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
| u64 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
推导示例
- 调用aclnnAdd接口时,如果两个输入参数的数据类型不一致,一个为float16,一个为float32,那么API内部就会将float16的数据类型转换成float32的数据类型然后进行计算。
- 调用aclnnAdd接口时,如果两个输入参数的数据类型不一致,一个为float32,一个为bool,那么API内部就会将bool的数据类型转换成float32的数据类型然后进行计算。
父主题: 基本概念
互转换关系
当一个API(如aclnnAdd、aclnnMul等)输出的Tensor数据类型与输入的数据类型推导后的计算类型不一致时,API内部就会将计算结果转换成输出类型对应的数据类型。
数据类型转换需要满足以下规则,不满足规则的将不能进行转换,调用API时会出现参数校验失败。
- 浮点数据类型:ACL_FLOAT16、ACL_FLOAT、ACL_DOUBLE、ACL_BF16间可以互相转换。
- 整型数据类型:ACL_INT8、ACL_UINT8、ACL_INT16、ACL_UINT16、ACL_INT32、ACL_UINT32、ACL_INT64、ACL_UINT64间可以互相转换。
- 整型数据类型可以往浮点类型转换。
- 浮点数据类型不可以向整型转换。
- 非BOOL型不可以往BOOL型转换。
- 复数类型:ACL_COMPLEX64、ACL_COMPLEX128间可以转换,复数类型不可以和非复数类型互转。
父主题: 基本概念
数据格式
数据格式(format)是用于描述一个多维Tensor的轴的业务语义,表示数据的物理排布格式,定义了解读数据的维度,比如1D、2D、3D、4D、5D等。一般在CNN(Convolutional Neural Network)类的API中需要给出具体的数据排布格式。
:::note 说明
- 数据格式一般形式为“ACL_FORMAT_X**XXX”,为方便描述,可简写为“X**XXX”。
- 数据格式中维度含义:N(Batch)表示批量大小、H(Height)表示特征图高度、W(Width)表示特征图宽度、C(Channels)表示特征图通道、D(Depth)表示特征图深度。 :::
常见数据格式
目前大部分算子API都是支持ND数据格式的。例如aclnnAdd接口,均标明支持的数据格式是ND(即多维Tensor的,低维度优先连续排布的规则)。
对于aclnnConvolution,该API要求输入的aclTensor设置具有业务语义的格式,而不是ND格式。此类算子,在计算过程中需要知道Tensor中的业务语义才可以进行对应的计算。例如2D卷积中,需要知道Batch维度、Channel维度、Height维度、Width维度与Tensor维度的对应关系是什么。
当调用aclCreateTensor接口的时候,根据API要求设置Tensor的数据格式,当前支持的数据格式有:
ACL_FORMAT_ND、ACL_FORMAT_NCHW、ACL_FORMAT_NHWC、ACL_FORMAT_HWCN、ACL_FORMAT_NDHWC、ACL_FORMAT_NCDHW、ACL_FORMAT_NC、ACL_FORMAT_NCL。
对于非ND的Tensor,Tensor的维度要求与format表述是一致的。例如:
- 5D的Tensor:要求为ACL_FORMAT_NCDHW、ACL_FORMAT_NDHWC或者ACL_FORMAT_ND(如果API参数说明中未标明支持ND,设置ND格式后API将会校验报错)。
- 4D的Tensor:要求为ACL_FORMAT_NCHW、ACL_FORMAT_NHWC、ACL_FORMAT_HWCN或者ACL_FORMAT_ND。
- 3D的Tensor:要求为ACL_FORMAT_NCL或者ACL_FORMAT_ND。
- 2D的Tensor:要求为ACL_FORMAT_NC或者ACL_FORMAT_ND。
- 其他维度的Tensor:要求为ACL_FORMAT_ND。
私有数据格式
除了常见的数据格式,还存在其他的数据格式,比如ACL_FORMAT_NC1HWC0、ACL_FORMAT_FRACTAL_Z、ACL_FORMAT_NC1HWC0_C04、ACL_FORMAT_FRACTAL_NZ、ACL_FORMAT_NDC1HWC0、ACL_FORMAT_FRACTAL_Z_3D等。
这些格式,属于NPU的一些私有格式,当前绝大多数的aclnn API还不支持这些格式。如果有个别API申明了支持的数据格式,请以该API实际描述为准。
父主题: 基本概念
数据结构
常用的数据结构如下,可以通过公共接口创建。
-
定义AscendCL张量数据结构,用来管理和存储类似向量、矩阵等数据。
typedef struct aclTensor aclTensor -
定义AscendCL标量数据结构,用来管理和存储标量数据(比如一个单独的数)。
typedef struct aclScalar aclScalar -
定义AscendCL整型数组数据结构,用来管理和存储由int类型数据构成的数组。
typedef struct aclIntArray aclIntArray -
定义AscendCL浮点型数组数据结构,用来管理和存储由float类型数据构成的数组。
typedef struct aclFloatArray aclFloatArray -
定义AscendCL布尔型数组数据结构,用来管理和存储由bool类型数据构成的数组。
typedef struct aclBoolArray aclBoolArray -
定义AscendCL张量列表数据结构,用来管理和存储由tensor类型数据构成的列表。
typedef struct aclTensorList aclTensorList -
定义AscendCL执行器数据结构,用来执行算子计算的容器。
typedef struct aclOpExecutor aclOpExecutor -
定义AscendCL流处理数据结构,用来管理和维护一些异步操作的执行顺序。
typedef void *aclrtStream
父主题: 基本概念
在线提单