Matmul常量化算子性能提升案例
案例介绍
本案例呈现了在使用Matmul高阶API进行矩阵乘法计算时,使能Matmul Tiling常量化对算子性能的提升效果。Matmul Tiling常量化的介绍请参考Matmul Tiling常量化。
Matmul API在初始化和迭代过程中有大量Scalar计算,Matmul初始化时的Scalar计算影响指令头开销,Matmul迭代间的Scalar计算可能阻塞MTE2流水。在调用Matmul API实现矩阵乘法时,通过使用全量常量化的MatmulApiStaticTiling模板参数,替代非常量TCubeTiling参数。将Scalar计算提前到编译期,以减少运行时的Scalar计算开销,实现算子性能的提升。
Matmul常量化的适用场景:
- Matmul初始化时的Scalar计算较多,影响指令头开销。
- Matmul迭代之间的Scalar计算较多,阻塞MTE2流水。
Matmul常量化需要在编译期确定部分Tiling参数,根据确定参数的不同,分为全量常量化和部分常量化两种场景,使用Matmul常量化需要满足两种场景中任一场景的条件:
- 全量常量化:能够确定常量singleCore Shape(singleCoreM/singleCoreN/singleCoreK)和常量Base Shape(basicM/basicN/basicK,或者说成baseM/baseN/baseK)。
- 部分常量化:能够确定常量Base Shape(basicM/basicN/basicK,或者说成baseM/baseN/baseK)。
其中,全量常量化场景比部分常量化场景可以减少更多的Scalar计算开销。
本案例的算子规格如下:
输入 |
Shape |
Data type |
Format |
---|---|---|---|
a |
32, 2048 |
float16 |
ND |
b |
2048, 32 |
float16 |
ND |
更多的使能Matmul Tiling常量化的完整样例请参考matmul_api_constant。
获取性能数据
使用msProf工具获取算子的Profiling数据,重点分析Scalar的流水情况。
分析主要瓶颈点

由以上Profiling数据,可以看出Scalar耗时占比较大,当前性能瓶颈点在于Scalar流水。性能优化前,算子执行多次的平均耗时为21.88us。
设计优化方案
使能Matmul Tiling常量化:在创建Matmul对象时,使用常量化模板参数。具体步骤如下。
- 调用获取MatmulConfig模板的接口GetMMConfig时,使用常数值设置MatmulShapeParams,得到带有常量化参数的自定义MatmulConfig模板。
- 调用GetMatmulApiTiling接口,将Tiling信息常量化,得到常量化模板参数,包括常量化的Matmul Tiling信息和MatmulConfig模板。
- 创建Matmul对象时,使用步骤2的常量化模板参数。
在该算子规格下,根据GetTiling接口获取的最优Tiling,singleCoreM/singleCoreN/singleCoreK的数值为32/32/2048,baseM/baseN/baseK的数值为32/32/256。在原始代码的基础上,仅需修改创建Matmul对象的部分,具体如下。
1 2 3 4 5 6 |
constexpr static MatmulShapeParams shapeParams = {32, 32, 2048, 32, 32, 256}; constexpr static MatmulConfig MM_CFG = GetMMConfig<MatmulConfigMode::CONFIG_NORM>(shapeParams); constexpr MatmulApiStaticTiling static MM_CFG_CONSTANT = GetMatmulApiTiling<A_TYPE, B_TYPE, C_TYPE, BIAS_TYPE>(MM_CFG); AscendC::MatmulImpl<A_TYPE, B_TYPE, C_TYPE, BIAS_TYPE, MM_CFG_CONSTANT> mm; |
验证优化方案性能收益
性能优化后,算子执行多次的平均耗时为17.728us,其中Scalar计算减少了44.4%,较优化前有较大提升。

总结
在Matmul单核、单次计算的Shape信息(singleCoreM/singleCoreN/singleCoreK、baseM/baseN/baseK)确定的情况下,可以考虑使能Matmul Tiling常量化,减少Scalar计算开销,提升算子性能。