开发者
我要评分
获取效率
正确性
完整性
易理解
在线提单
论坛求助

对接KUPL MMA使能矩阵计算加速

KUPL矩阵编程模块提供了诸如D=A*B+C形式的MMA接口,便于发挥鲲鹏硬件的矩阵算力。其设计理念是KUPL矩阵编程上层MMA接口通过C++模板库实现多种矩阵计算Ops,底层则使能鲲鹏硬件的矩阵算力进行加速,从而达到屏蔽用户感知底层硬件能力的情况下快速使能加速。相较于鲲鹏数学库KML_BLAS和加速算子库KuDNN而言,KUPL矩阵编程MMA只提供Kernel Level的接口,具体在Gemm算子场景开发者既可以通过直接调用数学库BLAS Gemm接口加速也可以通过调用KUPL MMA接口+矩阵分块等优化手段加速;然后在矩阵乘融合算子场景开发者只能通过KUPL MMA接口加速。KUPL矩阵编程具体接口介绍参考:《KUPL矩阵编程接口函数概念说明》

在此基于精度为Float64、Size为32*16*512的矩阵乘kernel算子为例,来介绍如何使用KUPL MMA接口来加速,具体代码示例如下:
#include "stdlib.h"

// 引用KUPL矩阵编程模块头文件并加载相应namespace
#include "kupl_mma.h"
using namespace kupl::tensor;

int main()
{
    constexpr int MATRIX_M  = 32;
    constexpr int MATRIX_N  = 16;
    constexpr int MATRIX_K = 512;
    double *data_a = (double *)malloc(sizeof(double) * MATRIX_M * MATRIX_K);
    double *data_b = (double *)malloc(sizeof(double) * MATRIX_K * MATRIX_N);
    double *data_c = (double *)malloc(sizeof(double) * MATRIX_M * MATRIX_N);

    /*
    创建KUPL Shape对象,用以描述计算矩阵的形状
    如A矩阵的size为32*512,则KUPL Shape对象一维大小应设置成32(表示行数)、二维大小应设置成512(表示列数)
    */
    auto shape_a = make_shape(Int<32>{}, Int<512>{});
    auto shape_b = make_shape(Int<512>{}, Int<16>{});
    auto shape_c = make_shape(Int<32>{}, Int<16>{});

    /*
    创建KUPL Stride对象,用以描述计算矩阵的各维度步长
    如A矩阵是32*512大小的列主序矩阵,则KUPL Stride对象一维大小应设置成1(表示同一列相邻两行的元素在原始buffer中下标差值为1)、二维大小应设置成32(表示同一行相邻两列的元素在原始buffer中下标差值为32)    
    */
    auto stride_a = make_stride(Int<1>{}, Int<32>{});
    auto stride_b = make_stride(Int<16>{}, Int<1>{});
    auto stride_c = make_stride(Int<16>{}, Int<1>{});

    /* 创建KUPL Layout对象,包含Shape和Stride信息 */
    auto layout_a = make_layout(shape_a, stride_a);
    auto layout_b = make_layout(shape_b, stride_b);
    auto layout_c = make_layout(shape_c, stride_c);

    /* 定义KUPL mma和store方法从而供后续mma和store接口调用 */
    /*
    基于底层Ops按照atom_shape进行各维度计算尺寸扩展,从而确实mma行为
    如采用底层Ops为double精度下32x16x1的mma kernel,此处在M/N/K方向上atom_shape扩展分别为1/1/512,因此最终实现32x16x512的mma行为
    */
    auto mma_atom_shape = make_shape(Int<1>{}, Int<1>{}, Int<1>{});
    auto tiled_mma = make_tiled_mma(Ops<MMA_32x16x512_F64F64F64>{}, mma_atom_shape);
    /*
    基于底层Ops按照atom_shape进行各维度写回尺寸扩展,从而确定store行为
    如采用底层Ops为double精度下32x16的矩阵store kernel,此处在M/N方向上atom_shape扩展分别为1/1,因此最终实现32x16的矩阵store行为
    */
    auto store_atom_shape = make_shape(Int<1>{}, Int<1>{});
    auto tile_store = make_tiled_store(Ops<STORE_32x16_F64>{}, store_atom_shape);

    /* 创建KUPL tensor对象纳管用户矩阵buffer */
    auto tensor_a = make_tensor(data_a, layout_a);
    auto tensor_b = make_tensor(data_b, layout_b);
    auto tensor_c = make_tensor(data_c, layout_c);

    /* 调用mma和store接口进行计算及写回,从而快速使能矩阵算力 */
    tensor_tiled_mma(tiled_mma, tensor_c, tensor_a, tensor_b, tensor_c);
    tensor_tiled_store(tile_store, tensor_c);

    free(data_a);
    free(data_b);
    free(data_c);
    return 0;
}