CANN训练营,算子开发1(基础背景知识介绍)
1.什么是算子
当前流行的深度学习等方法,可视化展示出来就是一个计算图,一个有向无环图,这个图里面的每个节点,我们就可以称之为算子(Operator简称Op),在网络模型中算子对应层中的计算逻辑。
算子的数学定义,可以看做一个函数,一个(一组)输入经过一番处理,得到一个(一组)输出。一个复杂的数学函数其实是由很多基础操作构成的,这些基础操作就是算子。
2.为什么需要学习算子开发
诚然,当前大部分的神经网络,昇腾官方已经准备好了性能完备的官方实现的算子,大部分的模型在进行模型转换后都可以一次性转换成功,因此大部分的人其实是接触不到算子开发的。为什么我建议大家都去学习一下我认为有以下几点,
- 有些非常规的算子,因为使用不是特别广泛,昇腾官方可能并没有实现,如果我们有需求,虽然可以向官方提出申请,但是等官方开发出来以后经过测试上线,一个月都未必足够,如果自己会开发,可以解决燃眉之急。
- 已有算子的性能无法满足开发者的要求。昇腾官方的算子实现未必是最优解,如果我们有更好的实现方案,可以替换成我们的方案。
- 开发者想通过自定义算子的方式实现应用程序中的某些处理逻辑(例如对模型输出的后处理),从而将相应处理推送到昇腾AI处理器执行,用昇腾AI处理器进行加速。
3.算子的应用流程
一个神经网络往往包含几十甚至上百个算子,如果神经网络中的每一个算子大家都自己实现一遍,那神经网络构建的工作量之大可想而知。因此算子开发也可以看做一种代码重用。大大提高构建网络的效率。
4.昇腾算子库包含的算子类型
- NN(Neural Network)算子库:覆盖了包括TensorFlow、Pytorch、MindSpore、ONNX框架在内的,常用深度学习算法的计算类型,在算子库中占有最大比重。
- BLAS(Basic Linear Algebra Subprograms)算子库:基础线性代数程序集,是进行向量和矩阵等基本线性代数操作的数值库。
- DVPP(Digital Vision Pre-Processing)算子库:提供高性能的视频编解码、图片编解码、图像裁剪缩放等预处理能力。
- AIPP(AI Pre-Processing)算子库:主要实现改变图像尺寸、色域转换(转换图像格式)、减均值/乘系数(图像归一化),并与模型推理过程融合,以满足推理输入要求。
- HCCL(Huawei Collective Communication Library)算子库:提供单机多卡以及多机多卡间的Broadcast,allreduce,reducescatter,allgather等集合通信功能,在分布式训练中提供高效的数据传输能力
5.算子开发的类型及方式
AI Core是昇腾AI处理器的计算核心,负责执行矩阵、向量、标量计算密集的算子任务,采用达芬奇架构,在AI Core上执行的算子称为TBE算子。
AI CPU负责执行不适合跑在AI Core上的算子,主要承担非矩阵类的复杂计算,在AI CPU上执行的算子称为AI CPU算子。
TBE算子开发主要分为两种方式,DSL方式,TIK方式。
AI CPU算子只有AICPU算子开发这一种方式。
- 区别如下
参数 | TBE DSL方式 | TBE TIK方式 | AI CPU方式 |
---|---|---|---|
语言 | Python | Python | C++ |
运用场景 | 常用于各种算术逻辑简单向量运算,或内置支持的矩阵运算及池化运算 | 适用各类算子的开发,对于无法通过lambda表达描述的复杂计算场景也有很好的支持,例如排序类操作 | 无法通过AI Core实现自定义算子的场景 |
难度 | 较低 | 较高 | 中等 |
特点 | TBE DSL接口已高度封装,用户仅需要使用DSL接口完成计算过程的表达,后续的Schedule创建、优化及编译都可通过已有接口一键式完成 | 入门难度高,程序员直接使用TIK提供的API完成计算过程的描述及Schedule过程,需要手工控制数据搬运的参数和Schedule。用户无须关注Buffer地址的分配及数据同步处理,由TIK工具进行管理 | 开发的流程和DSL都是类似的, 不需要了解AI Core的内部架构设计,入门较快 |
不足 | 某些场景下算子的性能较低,复杂逻辑的算子可能无法支持表达 | 需要开发者手动控制数据的搬运,和调度 | 没有单独封装的计算接口,受限于硬件单元的算力,开发出的算子性能较低 |
6.TBE算子开发介绍
首先欢迎大家浏览昇腾社区,以及多多看官方的文档
6.1文档使用建议
全套流程在MindStudio拥有全套的方案,实际演示关注之后的博客
6.2算子计算开发中概念介绍
- 张量
- 形状
- 数据类型
- 排布格式
- 广播
- 降维
- 转换
6.2.1张量
张量(Tensor)是算子的计算容器,与编程语言中的数组概念差不多,但是编程语言的数组大多是1维或者2维,而张量可以无限扩展维度,进行多维运算,同时张量中对数据类型与数据排布格式有着对应的要求。
- 张量的形状:
张量的形状,以(D0, D1, … ,Dn-1)的形式表示,D0到Dn是任意的正整数。
如形状(3,4)表示第一维有3个元素,第二维有4个元素,(3,4)表示一个3行4列的矩阵数组。
在形状的小括号中有多少个数字,就代表这个张量是多少维的张量。形状的第一个元素要看张量最外层的中括号中有几个元素,形状的第二个元素要看张量中从左边开始数第二个中括号中有几个元素,依此类推。
假设有一些照片,每个像素点都由红/绿/蓝3色组成,即shape里面3的含义,照片的宽和高都是20,也就是20*20=400个像素,总共有4张的照片,这就是shape=(4, 20, 20, 3)的物理含义
如果要操作这些元素的话,就需要一层一层进行遍历 - 张量的数据类型
为了适应不同数据计算精度,张量中有
int4,int8,int32,int64,float16,float32,float64,等等不同的数据类型,一旦指定了数据类型,就指定了张量中每一个数据的类型。 - 张量的排布格式
在深度学习领域,多维数据通过多维数组存储,比如卷积神经网络的特征图(Feature Map)通常用四维数组保存,即4D
NCHW和NHWC
- N:Batch数量,例如图像的数目。
- H:Height,特征图高度,即垂直高度方向的像素个数。
- W:Width,特征图宽度,即水平宽度方向的像素个数。
- C:Channels,特征图通道,例如彩色RGB图像的Channels为3。
由于数据只能线性存储,因此这四个维度有对应的顺序。不同深度学习框架会按照不同的顺序存储特征图数据,比如Caffe,排列顺序为[Batch, Channels, Height, Width],即NCHW。TensorFlow中,排列顺序为[Batch, Height, Width, Channels],即NHWC
如下图(NCHW和NHWC存储示例)所示,以一张格式为RGB的图片为例,NCHW中,C排列在外层,实际存储的是“RRRRRRGGGGGGBBBBBB”,即同一通道的所有像素值顺序存储在一起;而NHWC中C排列在最内层,实际存储的则是“RGBRGBRGBRGBRGBRGB”,即多个通道的同一位置的像素值顺序存储在一起
在昇腾AI处理器中数据排布格式为 NC1HWC0
为了提高通用矩阵乘法(GEMM)运算数据块的访问效率,所有张量数据统一采用NC1HWC0的五维数据格式。其中C0与微架构强相关,等于AI Core中矩阵计算单元的大小,对于FP16类型为16,对于INT8类型则为32,这部分数据需要连续存储。
C1=C/C0。如果结果不整除,向上取整
NHWC到NC1HWC0的格式转换示意图如下
- NHWC -> NC1HWC0的转换过程
a.将NHWC数据在C维度进行分割,变成C1份NHWC0。
b.将C1份NHWC0在内存中连续排列,由此变成NC1HWC0。
Tensor.reshape( [N, H, W, C1, C0]).transpose( [0, 3, 1, 2, 4] )
- NCHW变换为NC1HWC0的过程
Tensor.reshape( [N, C1, C0, H, W]).transpose( [0, 1, 3, 4, 2] )
6.2.1张量广播
广播可以理解为数据的复制,TBE支持的广播规则:可以将一个数组的每一个维度扩展为一个固定的shape,需要被扩展的数组的每个维度的大小或者与目标shape相等,或者为1,广播会在元素个数为1的维度上进行。
TBE的计算接口加、减、乘、除等不支持自动广播,要求输入的两个Tensor的shape相同,所以操作前,我们需要先计算出目标shape,然后将每个输入Tensor广播到目标shape再进行计算
例如,Tensor A的shape为(4, 3, 1, 5),Tensor B的shape为(1, 1, 2, 1),执行Tensor A + Tensor B ,具体计算过程如下:
- 计算出目标shape C
- 调用广播接口分别将Tensor A与Tensor B扩展到目标Shape C
- 需要广播的tensor的shape需要满足规则:每个维度的大小或者与目标shape相等,或者为1。
- 调用计算接口,进行Tensor A + Tensor B。
6.2.2张量降维
降维有很多种算子,例如TensorFlow中的Sum、Min、Max、All、Mean等,Caffe中的Reduction算子,此处以Caffe中的Reduction算子为例进行讲解,Reduction是将多维数组的指定轴及之后的数据做降维操作。
算子类型 | 说明 |
---|---|
SUM | 对被reduce的所有轴求和。 |
ASUM | 对被reduce的所有轴求绝对值后求和。 |
SUMSQ | 对被reduce的所有轴求平方后再求和。 |
MEAN | 对被reduce的所有轴求均值。 |
Reduction需要指定一个轴,会对此轴及其之后的轴进行reduce操作,取值范围为:[-N,N-1]。
输入的张量的形状为(5,6,7,8)。
- 如果指定的轴是3,则输出tensor的形状为(5,6,7)。
- 如果指定的轴是2,则输出tensor的形状为(5,6,8)。
- 如果指定的轴是1,则输出tensor的形状为(5,7,8)。
- 如果指定的轴是0,则输出tensor的形状为(6,7,8)。
降维如图操作 - 如果对轴Axis: 0 进行降维,Axis=0, 对2维矩阵来说就是行,也就是对这个2维矩阵每行对应的数据进行相加,得到[2,2,2],降为1维,如下所示
- 如果Axis=1,就是每列对应的数据进行相加
- 如果Axis=[0,1],可以理解为先对轴0进行降维求和得到[2,2,2], 再对[2,2,2]继续降维求和得到6,最后得到是0维。
- 如果Axis=[],就是不降维,原样输出。
- 如果Axis为空(NULL),就是对所有维度进行降维,最后得到0维的标量。
6.2.3张量转换,(数据类型,数据排布格式)
转换算子是一种特殊的算子,用于转换Tensor的Data Type与Format等信息,使得图中上下游节点能够被正常处理。
- Format格式转换
- Tensorflow网络中Conv2d、Matmul算子使用的变量format为HWCN,其他算子使用变量format为NCHW或NHWC。
- AI Core模块中Conv2d、Matmul算子使用变量format为FZ,其他算子使用变量format为NC1HWC0。
- AI CPU模块中的TF Ops使用的format与Tensorflow网络一致。
网络运行时,不同的算子在不同的模块执行,涉及到Format的转换如下
- Data Type格式转换
- 点赞
- 收藏
- 关注作者
评论(0)