MxMatmul场景
背景介绍
浮点数在科学计算、图像处理、神经网络等领域应用广泛。以AI训练为例,现有的浮点数格式或数值范围不足,或精度不高,这影响了模型的收敛速度和性能。如果要同时满足数值范围和精度的要求,将会导致内存占用过大,从而增加数据存储和传输的成本。基于此种情况,业内提出了一种新的浮点数格式——微缩放(Microscaling,MX)格式。MX格式的浮点数可以支持更低比特位宽的AI训练和推理,并且占用的内存更少。符合MX标准的数据格式在使用8位或更低比特位的情况下,能够实现稳健的AI训练和推理模型精度。
- 共享缩放因子X,位宽为w bits;
- 私有元素Pi,位宽为d bits;
- 块大小k,表示多少个低比特数据形成一个块;
所有k个元素Pi有相同的位宽和数据类型,并且共享一个缩放因子X,每个包含k个元素的块可以使用(w+k*d)位进行编码。元素的数据类型和缩放因子可以独立选择。
下图为MX格式的浮点数的数据结构,S、E和M分别用于表示浮点数的符号、指数和尾数字段的值。其中,共享缩放因子X是一个用于整个数据块的缩放比例因子,它决定了数据块中所有元素的动态范围。通过引入共享缩放因子,MX格式的数据能够在保持低位宽的同时,灵活地表示不同范围的数据。块大小k指的是组成一个数据块(或组)的低比特数据的数量。私有元素Pi是指数据块中的每个低比特数据元素。这些元素经过缩放因子X的调整后,共同表示了一个高精度的浮点数或整数。
MX格式的数据类型包含多种,例如MXFP8、MXFP4、MXFP16、MXINT4等。下表列举了MxMatmul场景(全称Microscaling Matmul)支持的数据类型。
功能介绍
MxMatmul(全称Microscaling Matmul)为带有量化系数的矩阵乘法,即左矩阵和右矩阵均有对应的量化系数矩阵,左量化系数矩阵scaleA和右量化系数矩阵scaleB。MxMatmul场景中,左量化系数矩阵与左矩阵乘积,右量化系数矩阵与右矩阵乘积,对两个乘积的结果做矩阵乘法。
MxMatmul的计算公式为:C = (scaleA ⊗ A) * (scaleB ⊗ B) + Bias,“⊗”表示广播乘法,左/右矩阵与左/右量化系数矩阵做乘积时,K方向上每32个元素共享一个量化因子,如图2所示。
- A、scaleA、B、scaleB为源操作数。A为左矩阵,形状为[M, K];scaleA为左量化系数矩阵,形状为[M, K/32];B为右矩阵,形状为[K, N];scaleB为右量化系数矩阵,形状为[K/32, N]。
- C为目的操作数,存放矩阵乘结果的矩阵,形状为[M, N]。
- Bias为矩阵乘偏置,形状为[1, N]。对(scaleA ⊗ A) * (scaleB ⊗ B)结果矩阵的每一行都采用该Bias进行偏置。
矩阵A、scaleA、B、scaleB在不同位置中的排布格式分别如下图所示。
使用场景
矩阵计算之前,需要对A、B矩阵进行量化操作的场景。当前该场景下,Matmul输入输出矩阵支持的数据类型如下表所示。
|
A矩阵 |
B矩阵 |
ScaleA矩阵/ScaleB矩阵 |
Bias矩阵 |
C矩阵 |
支持平台 |
|---|---|---|---|---|---|
|
fp4x2_e1m2_t |
fp4x2_e1m2_t/fp4x2_e2m1_t |
fp8_e8m0_t |
float/half/bfloat16_t |
float/half/bfloat16_t |
Atlas 350 加速卡 |
|
fp4x2_e2m1_t |
fp4x2_e2m1_t/fp4x2_e1m2_t |
fp8_e8m0_t |
float/half/bfloat16_t |
float/half/bfloat16_t |
Atlas 350 加速卡 |
|
fp8_e4m3fn_t |
fp8_e4m3fn_t/fp8_e5m2_t |
fp8_e8m0_t |
float/half/bfloat16_t |
float/half/bfloat16_t |
Atlas 350 加速卡 |
|
fp8_e5m2_t |
fp8_e4m3fn_t/fp8_e5m2_t |
fp8_e8m0_t |
float/half/bfloat16_t |
float/half/bfloat16_t |
Atlas 350 加速卡 |
实现流程
Host侧自动获取Tiling参数的关键步骤介绍如下:
- 创建Tiling对象。
1 2
auto ascendcPlatform = platform_ascendc::PlatformAscendC(context->GetPlatformInfo()); matmul_tiling::MatmulApiTiling cubeTiling(ascendcPlatform);
传入硬件平台信息创建PlatformAscendC对象,然后创建Tiling对象,硬件平台信息可以通过GetPlatformInfo获取。
- 设置A、B、C、Bias的内存逻辑位置、格式、数据类型以及是否转置的信息,设置scaleA、scaleB的内存逻辑位置、格式以及是否转置的信息。调用SetScaleAType、SetScaleBType接口,设置scaleA、scaleB的内存逻辑位置、格式以及是否转置。
1 2 3 4 5 6
cubeTiling.SetAType(AscendC::TPosition::GM, CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT8_E5M2, false); cubeTiling.SetBType(AscendC::TPosition::GM, CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT8_E5M2, true); cubeTiling.SetScaleAType(AscendC::TPosition::GM, CubeFormat::ND, false); cubeTiling.SetScaleBType(AscendC::TPosition::GM, CubeFormat::ND, true); cubeTiling.SetCType(AscendC::TPosition::GM, CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT); cubeTiling.SetBiasType(AscendC::TPosition::GM, CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT);
- 使能MxMatmul场景。
- 设置矩阵shape信息。
1 2
cubeTiling.SetShape(M, N, K); cubeTiling.SetOrgShape(M, N, K); // 设置原始完整的形状M、N、K
- 设置可用空间大小信息。设置Matmul计算时可用的L1 Buffer/L0C Buffer/Unified Buffer空间大小,-1表示AI处理器对应Buffer的大小。
1cubeTiling.SetBufferSpace(-1, -1, -1);
- 按需设置其他参数,比如设置bias参与计算。
1cubeTiling.EnableBias(true);
- 获取Tiling参数。
1 2 3 4
MatmulCustomTilingData tiling; if (cubeTiling.GetTiling(tiling.cubeTilingData) == -1){ return ge::GRAPH_FAILED; }
- Tiling参数的序列化保存等其他操作。
Kernel侧的关键步骤介绍如下:
- 创建Matmul对象。
1 2 3 4 5 6 7
// MxMatmul场景通过MatmulTypeWithScale定义A、scaleA、B、scaleB的参数类型信息 typedef AscendC::MatmulTypeWithScale<AscendC::TPosition::GM, AscendC::TPosition::GM, CubeFormat::ND, fp8_e5m2_t, isTransposeA> aType; typedef AscendC::MatmulTypeWithScale<AscendC::TPosition::GM, AscendC::TPosition::GM, CubeFormat::ND, fp8_e5m2_t, isTransposeB> bType; typedef AscendC::MatmulType<AscendC::TPosition::GM, CubeFormat::ND, float> cType; typedef AscendC::MatmulType<AscendC::TPosition::GM, CubeFormat::ND, float> biasType; // 定义matmul对象时,传入MatmulWithScalePolicy表明使能MxMatmul模板策略 AscendC::Matmul<aType, bType, cType, biasType, CFG_MDL, MatmulCallBackFunc<nullptr, nullptr, nullptr>, AscendC::Impl::Detail::MatmulWithScalePolicy> mm;
创建对象时需要传入A、scaleA、B、scaleB、C、Bias的参数类型信息, A、scaleA、B、scaleB类型信息通过MatmulTypeWithScale来定义,C、Bias类型信息通过MatmulType来定义,包括:内存逻辑位置、数据格式、数据类型、转置信息。同时,通过模板参数MatmulPolicy传入MatmulWithScalePolicy表明使能MxMatmul场景。
1 2 3 4 5 6 7
template <TPosition POSITION, TPosition SCALE_POSITION, CubeFormat FORMAT, typename TYPE, bool ISTRANS = false, TPosition SRCPOS = TPosition::GM, CubeFormat SCALE_FORMAT = FORMAT, bool SCALE_ISTRANS = ISTRANS, TPosition SCALE_SRCPOS = SRCPOS> struct MatmulTypeWithScale: public MatmulType<POSITION, FORMAT, TYPE, ISTRANS> { constexpr static TPosition scalePosition = SCALE_POSITION; constexpr static CubeFormat scaleFormat = SCALE_FORMAT; constexpr static bool isScaleTrans = SCALE_ISTRANS; constexpr static TPosition srcScalePos = SCALE_SRCPOS; };
- 初始化操作。
1REGIST_MATMUL_OBJ(&pipe, GetSysWorkSpacePtr(), mm, &tiling); // 初始化
- 设置左矩阵A、右矩阵B、左量化系数矩阵scaleA、右量化系数矩阵scaleB、Bias。通过SetTensorScaleA、SetTensorScaleB设置左量化系数矩阵scaleA、右量化系数矩阵scaleB。
1 2 3 4 5
mm.SetTensorA(gm_a, isTransposeA); // 设置左矩阵A mm.SetTensorB(gm_b, isTransposeB); // 设置右矩阵B mm.SetTensorScaleA(gm_scaleA, isTransposeScaleA); // 设置左量化系数矩阵scaleA mm.SetTensorScaleB(gm_scaleB, isTransposeScaleB); // 设置右量化系数矩阵scaleB mm.SetBias(gm_bias); // 设置Bias
- 完成矩阵乘操作。
- 结束矩阵乘操作。
1mm.End();
更多完整的算子样例请参考Scale的K方向为偶数的MxMatmul样例、Scale的K方向为奇数的MxMatmul样例、mx_ub_tscm_nz样例、matmul_mx_typepara样例。
参数说明
|
参数 |
说明 |
|---|---|
|
POSITION |
左右矩阵的内存逻辑位置。 针对Atlas 350 加速卡: A矩阵可设置为TPosition::GM,TPosition::VECOUT,TPosition::TSCM B矩阵可设置为TPosition::GM,TPosition::VECOUT,TPosition::TSCM 注意:A、B矩阵设置为TPosition::TSCM时,对应的Format仅支持CubeFormat::NZ。 |
|
量化系数矩阵的内存逻辑位置。 针对Atlas 350 加速卡: scaleA矩阵可设置为TPosition::GM,TPosition::VECOUT,TPosition::TSCM scaleB矩阵可设置为TPosition::GM,TPosition::VECOUT,TPosition::TSCM 注意:scaleA、scaleB矩阵设置为TPosition::TSCM时,对应的SCALE_FORMAT仅支持CubeFormat::NZ。 |
|
|
数据的物理排布格式,详细介绍请参考数据格式。 针对Atlas 350 加速卡: A矩阵可设置为CubeFormat::ND,CubeFormat::NZ,CubeFormat::VECTOR B矩阵可设置为CubeFormat::ND,CubeFormat::NZ 注意:NZ排布格式,A/B的排布格式请参考数据格式。 |
|
|
TYPE |
数据类型。 针对Atlas 350 加速卡: A矩阵可设置为fp4x2_e1m2_t、fp4x2_e2m1_t、fp8_e4m3fn_t、fp8_e5m2_t B矩阵可设置为fp4x2_e1m2_t、fp4x2_e2m1_t、fp8_e4m3fn_t、fp8_e5m2_t 注意:具体数据类型组合关系请参考MxMatmul支持数据类型。 |
|
是否开启使能A、B矩阵转置的功能。默认值为false。参数支持的取值如下: true:开启使能矩阵转置的功能,开启后,分别通过SetTensorA和SetTensorB中的isTransposeA、isTransposeB参数设置A、B矩阵是否转置。若设置A、B矩阵转置,Matmul会认为A矩阵形状为[K, M],B矩阵形状为[N, K]。 false:不开启使能矩阵转置的功能,通过SetTensorA和SetTensorB不能设置A、B矩阵的转置情况。Matmul会认为A矩阵形状为[M, K],B矩阵形状为[K, N]。 |
|
|
A/B矩阵的POSITION参数配置为TPosition::TSCM时,要设置TSCM中矩阵数据的来源的内存逻辑位置,默认为TPosition::GM。 针对Atlas 350 加速卡: A矩阵可设置为TPosition::GM,TPosition::VECOUT B矩阵可设置为TPosition::GM,TPosition::VECOUT |
|
|
量化系数矩阵的物理排布格式,详细介绍请参考数据格式。默认值为FORMAT。 针对Atlas 350 加速卡: scaleA矩阵可设置为CubeFormat::ND,CubeFormat::NZ,CubeFormat::VECTOR scaleB矩阵可设置为CubeFormat::ND,CubeFormat::NZ 注意: NZ排布格式请参考NZ。MxMatmul场景,scaleA、scaleB的数据类型为fp8_e8m0_t,分形大小H0=16,W0=2。 在Scale矩阵为ND格式的场景中,当通过SetTensorScaleA接口设置scaleA矩阵转置时,scaleA内存排布格式必须按照(K/64, M,2)排布,通过SetTensorScaleB接口设置scaleB矩阵不转置时,scaleB内存排布格式必须按照(K/64,N, 2)排布,详细介绍请参考数据格式。 |
|
|
是否开启使能scaleA、scaleB矩阵转置的功能。默认值为ISTRANS。参数支持的取值如下: true:开启使能矩阵转置的功能。开启后,分别通过SetTensorScaleA和SetTensorScaleB中的isTransposeScaleA、isTransposeScaleB参数设置scaleA、scaleB矩阵是否转置。在Scale矩阵为ND格式的场景中,若设置scaleA、scaleB矩阵转置,Matmul会认为scaleA矩阵形状为[Ceil(K/64), M, 2],scaleB矩阵形状为[N, Ceil(K/64), 2]。 false:不开启使能矩阵转置的功能。通过SetTensorScaleA和SetTensorScaleB不能设置scaleA、scaleB矩阵的转置情况。Matmul会认为scaleA矩阵形状为[M, Ceil(K/64), 2],scaleB矩阵形状为[Ceil(K/64), N, 2]。 使用该参数的完整样例请参考scaleA转置scaleB不转置的的MxMatmul样例、scaleA不转置scaleB转置的的MxMatmul样例。 |
|
|
SCALE_SRCPOS |
scaleA、scaleB矩阵的SCALE_POSITION参数设置为TPosition::TSCM时,需要通过本参数设置TSCM中矩阵数据来源的内存逻辑位置,默认值为SRCPOS。 针对Atlas 350 加速卡: scaleA矩阵可设置为TPosition::GM,TPosition::VECOUT scaleB矩阵可设置为TPosition::GM,TPosition::VECOUT |
约束说明
- 在MxMatmul场景中,如果A与B矩阵的位置同时为GM,对singleKIn没有特殊限制,在这种情况下,若scaleA和scaleB的K方向大小(即Ceil(singleKIn, 32))为奇数,用户需自行在scaleA和scaleB的K方向补0至偶数。例如,当singleKIn为30时,Ceil(singleKIn, 32)为1,用户需要自行在scaleA和scaleB的K方向补0,使K方向为偶数。对于其它A、B矩阵逻辑位置的组合情况,即A与B矩阵的位置不同时为GM,singleKIn以32个元素向上对齐后的数值必须是32的偶数倍。
- 在MxMatmul场景中,当输入数据类型为fp4x2_e2m1_t/fp4x2_e1m2_t时,内轴必须为偶数。
- 在MxMatmul场景中,通过将A矩阵和scaleA矩阵的数据格式设置为VECTOR,来开启GEMV模式。在此模式下,A和scaleA矩阵仅支持内存逻辑位置为GM,并且均不支持转置。
- A矩阵、B矩阵为UB输入时,矩阵的内轴需要向上32字节对齐,例如,A矩阵的形状为(M, K)时,将K对齐到32字节;A矩阵的形状为(K, M)时,将M对齐到32字节。
- scaleA矩阵、scaleB矩阵为UB输入时,矩阵的内轴需要向上32字节对齐,例如,scaleA矩阵的形状为(M, K/32)时,将K/32对齐到32字节;scaleA矩阵的形状为(K/32, M)时,将M对齐到32字节。
- 当scaleA和scaleB矩阵以ND格式输入时,高阶API在内部实现格式转换时,需要占用UB临时空间。开发者需使用SetLocalWorkspace接口配置临时空间,临时空间大小(单位字节)的计算公式如下。
int32_t scaleATmpBuf = 0; int32_t scaleBTmpBuf = 0; if constexpr (A_TYPE::scalePosition == TPosition::VECOUT) { if (A_TYPE::isScaleTrans) { scaleATmpBuf = CeilAlign(SingleCoreM, 32) * scaleK; } else { scaleATmpBuf = CeilAlign(scaleK, 32) * SingleCoreM; } } if constexpr (B_TYPE::scalePosition == TPosition::VECOUT) { if (B_TYPE::isScaleTrans) { scaleBTmpBuf = SingleCoreN * CeilAlign(scaleK, 32); } else { scaleBTmpBuf = scaleK * CeilAlign(SingleCoreN, 32); } } int32_t totalTmpBuf = scaleATmpBuf + scaleBTmpBuf;


