本案例呈现了在使用Matmul高阶API进行矩阵乘法计算时,使能Matmul Tiling常量化对算子性能的提升效果。Matmul Tiling常量化的介绍请参考Matmul Tiling常量化。
Matmul API在初始化和迭代过程中有大量Scalar计算,Matmul初始化时的Scalar计算影响指令头开销,Matmul迭代间的Scalar计算可能阻塞MTE2流水。在调用Matmul API实现矩阵乘法时,通过使用全量常量化的MatmulApiStaticTiling模板参数,替代非常量TCubeTiling参数。将Scalar计算提前到编译期,以减少运行时的Scalar计算开销,实现算子性能的提升。
Matmul常量化的适用场景:
Matmul常量化需要在编译期确定部分Tiling参数,根据确定参数的不同,分为全量常量化和部分常量化两种场景,使用Matmul常量化需要满足两种场景中任一场景的条件:
其中,全量常量化场景比部分常量化场景可以减少更多的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对象时,使用常量化模板参数。具体步骤如下。
在该算子规格下,根据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计算开销,提升算子性能。