矩阵编程算子实现
========

#### 实现流程

上文介绍了Matmul矩阵乘的数据切分方案和数据流。AscendC提供一组Matmul高阶API，封装了这些常用的切分和数据搬运、计算的算法逻辑，方便开发者快速实现Matmul矩阵乘法的运算操作。开发者在host侧通过调用API自动获取Tiling参数，该参数传递到kernel侧后，在初始化操作时传入，通过几个简单的API即可完成矩阵乘操作。以下代码仅包含Matmul的关键步骤，不能直接运行。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/34/v3/rnO2yF66QCyVOY72k6w18g/zh-cn_image_0000002594669542.png?HW-CC-KV=V1&HW-CC-Date=20260612T073658Z&HW-CC-Expire=86400&HW-CC-Sign=DB75493CAAEF8B3D53D5011CE8528F1723419F279D9F81803FD2323E2F2FDF8A)

**host侧自动获取Tiling参数的关键步骤介绍如下。**

1.  创建Tiling对象。
    
    auto ascendcPlatform = platform\_ascendc::PlatformAscendC(context->GetPlatformInfo());
    matmul\_tiling::MatmulApiTiling cubeTiling(ascendcPlatform);
    
    创建对象时需要传入硬件平台信息，硬件平台信息可以通过[GetPlatformInfo](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/cannkit-getplatforminfo)获取。
    
2.  设置A、B、Bias的数据类型和格式。
    
    cubeTiling.SetAType(AscendC::TPosition::GM, CubeFormat::ND, matmul\_tiling::DataType::DT\_FLOAT16);
    cubeTiling.SetBType(AscendC::TPosition::GM, CubeFormat::ND, matmul\_tiling::DataType::DT\_FLOAT16);
    cubeTiling.SetCType(AscendC::TPosition::GM, CubeFormat::ND, matmul\_tiling::DataType::DT\_FLOAT);
    cubeTiling.SetBiasType(AscendC::TPosition::GM, CubeFormat::ND, matmul\_tiling::DataType::DT\_FLOAT);
    
3.  设置矩阵shape信息。
    
    cubeTiling.SetShape(M, N, K);
    cubeTiling.SetOrgShape(M, N, K);
    
4.  设置可用空间大小信息。
    
    cubeTiling.SetBufferSpace(-1, -1, -1);
    
5.  按需设置其他参数，比如设置bias参与计算。
    
    cubeTiling.SetBias(true);
    
6.  获取Tiling参数。
    
    MatmulCustomTilingData tiling;
    if (cubeTiling.GetTiling(tiling.cubeTilingData) == -1){
        return ge::GRAPH\_FAILED;
    }
    
7.  Tiling参数的序列化保存等其他操作。
    

**kernel侧使用Matmul API矩阵乘运算的具体步骤如下。**

1.  创建Matmul对象。示例如下。
    
    #include "lib/matmul\_intf.h"
    typedef matmul::MatmulType<AscendC::TPosition::GM, CubeFormat::ND, half> aType;
    typedef matmul::MatmulType<AscendC::TPosition::GM, CubeFormat::ND, half> bType;
    typedef matmul::MatmulType<AscendC::TPosition::GM, CubeFormat::ND, float> cType;
    typedef matmul::MatmulType<AscendC::TPosition::GM, CubeFormat::ND, float> biasType;
    matmul::Matmul<aType, bType, cType, biasType> mm;
    
    创建对象时需要传入A、B、C、Bias的参数类型信息， 类型信息通过MatmulType来定义，包括：内存逻辑位置、数据格式、数据类型。
    
2.  初始化操作。
    
    mm.Init(&tiling.cubeTilingData, &pipe); // 初始化
    
3.  设置左矩阵A、右矩阵B、Bias。
    
    mm.SetTensorA(gm\_a); // 设置左矩阵A
    mm.SetTensorB(gm\_b); // 设置右矩阵B
    mm.SetBias(gm\_bias); // 设置Bias
    
4.  完成矩阵乘操作。
    
    *   调用Iterate完成单次迭代计算，叠加while循环完成单核全量数据的计算。Iterate方式，可以自行控制迭代次数，完成所需数据量的计算，方式比较灵活。
        
        while (mm.Iterate()) {
             mm.GetTensorC(gm\_c);
         }
        
    *   调用IterateAll完成单核上所有数据的计算。IterateAll方式，无需循环迭代，使用比较简单。
        
        mm.IterateAll(gm\_c);
        
5.  结束矩阵乘操作。
    
    mm.End();
    

#### 设置format格式

创建Matmul对象时需要传入A、B、C、Bias的参数类型信息， 类型信息通过MatmulType来定义，包括：内存逻辑位置、数据格式、数据类型。示例如下。

typedef matmul::MatmulType<AscendC::TPosition::GM, CubeFormat::ND, half> aType;
typedef matmul::MatmulType<AscendC::TPosition::GM, CubeFormat::ND, half> bType;
typedef matmul::MatmulType<AscendC::TPosition::GM, CubeFormat::ND, float> cType;
typedef matmul::MatmulType<AscendC::TPosition::GM, CubeFormat::ND, float> biasType;
matmul::Matmul<aType, bType, cType, biasType> mm;

针对数据格式，包括CubeFormat::ND, CubeFormat::NZ, CubeFormat::ND\_ALIGN三种，ND和NZ格式在[数据格式](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/cannkit-basic-knowledge#数据格式)章节已经介绍。

ND\_ALIGN用于配置输出矩阵时按照一定的补齐规则进行输出。ND–>ND\_ALIGN变换过程下图所示，矩阵数据类型为uint32\_t，假设输出矩阵输出到UB，原矩阵N方向没有32字节对齐，设置ND\_ALIGN则在其后补0，将其对齐到32字节。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/74/v3/9YzUw7joTjmP7rlgEqCJug/zh-cn_image_0000002594829470.png?HW-CC-KV=V1&HW-CC-Date=20260612T073658Z&HW-CC-Expire=86400&HW-CC-Sign=3266AF5ECE78A958CE9D2C10194952030AF6CD3CD20C4F173612169A80E3D1A1)

#### 设置Shape信息

Host Tiling时可以设置Shape信息，用于Tiling计算；kernel侧运行时也可以修改部分shape信息，用于尾块设置、Matmul复用（多个Matmul计算复用一个Matmul对象）等场景。本节对涉及到的Shape概念进行介绍，并给出host侧和kernel侧设置Tiling信息的指导。

*   orgShape：M、N、K
    
*   singleCoreShape：singleCoreM、singleCoreN、singleCoreK
    
*   singleShape：singleM、singleN、singleK
    
*   baseShape：baseM、baseN、baseK
    

通过[数据分块(Tiling)](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/cannkit-basic-knowledge#数据分块tiling)的介绍我们已经了解了orgShape(M、N、K)，singleCoreShape(singleCoreM、singleCoreN、singleCoreK)，baseShape(baseM、baseN、baseK)的概念，如下图所示：

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/88/v3/FpQiJOj5S26KWMGZ4Jj26Q/zh-cn_image_0000002625188917.png?HW-CC-KV=V1&HW-CC-Date=20260612T073658Z&HW-CC-Expire=86400&HW-CC-Sign=CE9C8BE749F2138C413239AFE492F210CC76E81046EB6207263758E5F667F574)

除此之外，单核的Matmul Tiling时，实际参与Matmul计算的shape可以是原始shape中的一部分，singleM, singleN, singleK用于表达实际参与Matmul计算的shape，如下图所示。在单核的情况下，singleM, singleN, singleK会透传给singleCoreM, singleCoreN, singleCoreK。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/65/v3/tD0e3fAwRl2Tr15y7-xwdg/zh-cn_image_0000002625109061.png?HW-CC-KV=V1&HW-CC-Date=20260612T073658Z&HW-CC-Expire=86400&HW-CC-Sign=6743FF902E9FF66943E9512478267DE60EE8217B14B37E1028CD8E50D7AE2F9F)