本案例呈现了在矩阵乘算子场景中,使用Matmul高阶API进行矩阵乘法计算,使能多核切K功能对算子性能的提升效果。为了实现算子在多核上并行执行,提升计算效率,需要将矩阵数据进行切分,切分后的数据块被分配到不同的核上处理。通常情况下,切分矩阵数据时仅切分M、N轴,不切分K轴。若M和N较小,切分M和N轴较困难,此时需要考虑K轴切分;使能多核切K功能后,该场景下可以对矩阵的K轴进行切分,从而使算子在多核上并行执行。由于K轴较大,在该场景下不切分K轴通常会导致单核的输入数据量过大,使能K轴切分后,切分策略能够更有效地平衡输出带宽和输入带宽。
本案例的算子规格如下:
|
输入 |
Shape |
Data type |
Format |
|---|---|---|---|
|
a |
16, 1024 |
float16 |
ND |
|
b |
1024, 16 |
float16 |
ND |
当前案例使用的AI处理器共24个核,算子中使能高阶API Matmul的纯Cube模式。Tiling参数如下:
使用msProf工具获取算子仿真流水图和上板Profiling数据。
使能多核切K后,矩阵的K方向数据可以进行切分。如下图所示,C矩阵中的R矩阵块,是通过A1*B1+A2*B2+A3*B3累加得到的,其中,A1*B1、A2*B2、A3*B3可在多个核上并行计算。
使能多核切K功能的方式为:在GetTiling接口前调用EnableMultiCoreSplitK接口,使能多核切K,并在Kernel实现中,对C矩阵的Global Memory地址清零后开启AtomicAdd。使能多核切K的完整样例请参考多核切K场景的算子样例。具体步骤如下:
1 2 3 4 5 6 7 8 9 10 |
cubeTiling.SetOrgShape(M, N, K); cubeTiling.SetShape(M, N, K); cubeTiling.EnableBias(isBias); cubeTiling.SetBufferSpace(-1, -1, -1); // tiling enable split K cubeTiling.EnableMultiCoreSplitK(true); if (cubeTiling.GetTiling(tilingData) == -1) { std::cout << "gen tiling failed." << std::endl; return {}; } |
1 2 3 |
cGlobal.SetGlobalBuffer(reinterpret_cast<__gm__ cType*>(c), tiling.M * tiling.N); // clear gm Fill(cGlobal, tiling.M * tiling.N, (cType)0); |
1 2 3 |
// set AtomicAdd uint8_t enAtomic = 1; matmulObj.IterateAll(cGlobal, enAtomic); |
当算子使用Matmul API完成矩阵计算时,原始矩阵的M和N方向无法进行有效切分,且结果输出到Global Memory时,可以考虑使能多核切K功能,实现多核并行,提升计算效率。