码力全开特辑领航员学习笔记—MatMul算子基础详解
收藏回复举报
码力全开特辑领航员学习笔记—MatMul算子基础详解
新人帖
发表于2025-05-24 10:03:44
0 查看

1.对码力全开特辑课程的建议:

直播回放更新比较慢,可以提提速。

2.笔记内容:

MatMul 是矩阵乘法(Matrix Multiplication)的缩写,是深度学习和科学计算中最核心的算子之一。理解 MatMul 对于掌握神经网络原理和优化计算效率至关重要。

(一)基础知识

(1)矩阵乘基础

MatMul的计算公式如下:C=A*B+Bias。 

A、B为源操作数,A为左矩阵,形状为[M,K];B为右矩阵,形状为[K,N]。 

C为目的操作数,存放矩阵乘结果的矩阵,形状为[M,N]。 

Bias为矩阵乘偏置,形状为[N]。

cke_3696.png

(2)分格形式

cke_9842.png

(3)TPosition

Ascend C管理不同层级的物理内存时,用一种抽象的逻辑位置(TPosition)来表达各级别的存储,代替了片上物理存储的概念,开发者无需感知硬件架构。 

GM :AICore的外部存储 

VECCALC :计算过程中中间变量的存储位置 

TSCM :从L1上划分出一块内存,新增加了一个QuePosition类型TSCM。 

用户可以提前将数据存放在TSCM中,在Matmul运算时可以减少搬运。

(二)、核函数开发

(1)矩阵乘

实现Matmul矩阵乘运算的具体步骤如下: 

1.创建Matmul对象。 

2.初始化 

3.设置左矩阵A、右矩阵B、Bias。 

4.完成矩阵乘操作。

5.结束矩阵乘操作。

cke_20079.png

(2)API列表

cke_22517.png

(3)创建Matmul对象

创建对象时需要传入A、B、C、Bias的参数类型信息,类型信息通过MatmulType来定义,包括:内存逻辑位置(GM\VECCALC\TSCM)、数据格式(ND\NZ)、数据类型(halffoat)。参数设置的具体约束请参考API说明。

(4)设置左矩阵A、右矩阵B、Bias

cke_27747.png

(5)完成矩阵乘操作

调用lterate完成单次迭代计算,叠加while循环完成单核全量数据的计算。Iterate方式,可以自行控制迭代次数,完成所需数据量的计算,方式比较灵活。

while (mm.lterate()){

mm.GetTensorC(gm c); 

}

调用lterateAll完成单核上所有数据的计算。lterateAll方式,无需循环迭代,使用比较简单。mm.lterateAll(gm c);

(6)API算法

cke_38372.png

cke_42515.png

调用一次lterateAl,会计算出singleCoreM*singleCoreN大小的C矩阵。迭代顺序可通过tiling参数iterateOrder调整。

不可遗忘的End函数 aicore inline void End(); 一次Matmul计算结束时需要调用一次End函数。

(三)Matmul Tiling

大多数情况下,Local Memory的存储,无法完整的容纳算子的输入与输出,需要每次搬运一部分输入进行计算然后搬出,再搬运下一部分输入进行计算,直到得到完整的最终结果,这个数据切分、分块计算的过程称之为Tiling。 

静态shape场景下的Tiling过程,由于输入的大小都是已知的,每次搬运多少数据、总共需要搬运多少次均可以在编译时直接计算出来。但是在动态Shape场景下,输入的Shape是未知的,无法直接计算出来每次搬运的块大小,以及总共循环多少次。所以需要通过很多的循环次数变量,搬运大小变量来保存这些数据在运行时确定具体的输入shape大小后,才能进行计算出这些变量的值,传递给Kernel。这个计算变量的程序,就是动态Shape算子的Tiling函数。

(1)参数介绍

cke_63967.png

(2)API算法

cke_72931.png

(3)如何获取Tiling参数

Ascend C提供一组Matmul Tiling API,方便用户获取Matmul kernel计算时所需的Tiling参数。

获取Tiling参数的流程如下:

1.创建一个单核Tiling对象或者多核Tiling对象 

2.设置A、B、C、Bias的参数类型信息;M、N、K形状信息等, 

3.调用GetTiling接口,获取Tiling信息。

cke_84057.png

(4)单核Tiling接口

单核的Matmul tiling会将用户设置的singleM,singleN,singleK切分为多份baseM,baseN,baseK供MatmuAPI计算。 

Matmu API在取矩阵数据和写数据时,需要感知到原始矩阵的内存排布,所以需要设置OrgShape,但实际参与Matmul计算的shape可以是原始shape中的一部分,所以需要设置singleM,singleN, singleK。

在单核的情况下,single,singleN,singleK会透传给singleCoreM,singleCoreN,singleCoreK。

在融合算子的开发中,可能会占用一部分L1、LOC、UB的空间做其他业务需求,于是留给Matmul的空间需要相应减少,使用SetBufferSpace可以限制Matmul tiling切分的大小。

(5)多核Tiling接口

多核的tiling切分中,Matmultiling会根据用户设置的可用核数,将singleM,singleN,singleK切分为多份singleCoreM, singleCoreN, singleCoreK,再将每一份singleCoreM, singleCoreN,singleCoreK切分为多份baseM,baseN. basek。

其中用户可以根据业务需要,限制部分singleCore shape的部分维度的大小,比如使用SetSingleShape限制singleCoreM的大小,若不设置或设置为-1,比如设置singleCoreN为-1,则singleCoreN会默认设置为singleN的大小。

我要发帖子