对接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;
}
父主题: 鲲鹏920专业版矩阵算力编程