浮点数在科学计算、图像处理、神经网络等领域应用广泛。以AI训练为例,现有的浮点数格式或数值范围不足,或精度不高,这影响了模型的收敛速度和性能。如果要同时满足数值范围和精度的要求,将会导致内存占用过大,从而增加数据存储和传输的成本。基于此种情况,业内提出了一种新的浮点数格式——微缩放(Microscaling,MX)格式。MX格式的浮点数可以支持更低比特位宽的AI训练和推理,并且占用的内存更少。符合MX标准的数据格式在使用8位或更低比特位的情况下,能够实现稳健的AI训练和推理模型精度。
所有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、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参数的关键步骤介绍如下:
1 2 |
auto ascendcPlatform = platform_ascendc::PlatformAscendC(context->GetPlatformInfo()); matmul_tiling::MatmulApiTiling cubeTiling(ascendcPlatform); |
传入硬件平台信息创建PlatformAscendC对象,然后创建Tiling对象,硬件平台信息可以通过GetPlatformInfo获取。
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); |
1
|
cubetiling.SetMadType(MatrixMadType::MXMODE); |
1 2 |
cubeTiling.SetShape(M, N, K); cubeTiling.SetOrgShape(M, N, K); // 设置原始完整的形状M、N、K |
1
|
cubeTiling.SetBufferSpace(-1, -1, -1); |
1
|
cubeTiling.EnableBias(true); |
1 2 3 4 |
MatmulCustomTilingData tiling; if (cubeTiling.GetTiling(tiling.cubeTilingData) == -1){ return ge::GRAPH_FAILED; } |
Kernel侧的关键步骤介绍如下:
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; }; |
1
|
REGIST_MATMUL_OBJ(&pipe, GetSysWorkSpacePtr(), mm, &tiling); // 初始化 |
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 |
1 2 3 |
while (mm.Iterate()) { mm.GetTensorC(gm_c); } |
1
|
mm.IterateAll(gm_c); |
1
|
mm.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 |
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;