---
title: 矩阵乘输出的量化/反量化
description: "对于特定输入输出数据类型，Matmul支持将计算结果从CO1搬出到Global Memory时，对输出C矩阵元素执行数据量化或反量化操作。"
url: https://www.hiascend.com/document/detail/zh/canncommercial/latest/programug/Ascendcopdevg/atlas_ascendc_10_10017.html
sourcePath: /source/zh/canncommercial/900/programug/Ascendcopdevg/atlas_ascendc_10_10017.html
indexId: f4922b8b4078ef9e6d4f2a94e7221aa80edd92da730b9c189fe97fb6f52e55f281
---
# 矩阵乘输出的量化/反量化

#### 功能介绍

对于特定输入输出数据类型，Matmul支持将计算结果从CO1搬出到Global Memory时，对输出C矩阵元素执行数据量化或反量化操作。

- Matmul量化场景：Matmul计算时左矩阵A、右矩阵B为half或bfloat16_t数据类型，输出C矩阵为int8_t数据类型。该场景下，C矩阵的数据从CO1搬出到Global Memory时，会执行量化操作，将最终结果量化为int8_t类型，如下图所示。
  图1 Matmul量化场景示意图


- Matmul反量化场景：Matmul计算时左矩阵A、右矩阵B为int8_t或int4b_t数据类型，输出C矩阵为half数据类型，或者左矩阵A、右矩阵B为int8_t数据类型，输出C矩阵为int8_t数据类型。该场景下，C矩阵的数据从CO1搬出到Global Memory时，会执行反量化操作，将最终结果反量化为对应的half类型或int8_t类型，如下图所示。
  图2 Matmul反量化场景示意图


Matmul量化/反量化包含两种模式：同一系数的量化/反量化模式、向量的量化/反量化模式，开发者在算子Tiling侧调用SetDequantType(https://www.hiascend.comdocument/detail/zh/canncommercial/900/API/ascendcopapi/atlasascendc_api_07_0698.html)接口设置量化或反量化模式，这两种模式的具体区别为：- 同一系数的量化/反量化模式（PER_TENSOR模式）：整个C矩阵对应一个量化参数，量化参数的shape为[1]。开发者在算子Kernel侧调用接口  SetQuantScalar(https://www.hiascend.comdocument/detail/zh/canncommercial/900/API/ascendcopapi/atlasascendc_api_07_0649.html)
设置量化参数。
- 向量的量化/反量化模式（PER_CHANNEL模式）：C矩阵的shape为[m, n]，每个channel维度即C矩阵的每一列，对应一个量化参数，量化参数的shape为[n]。开发者在算子Kernel侧调用接口  SetQuantVector(https://www.hiascend.comdocument/detail/zh/canncommercial/900/API/ascendcopapi/atlasascendc_api_07_0650.html)
设置量化参数。


**表1 量化/反量化模式对应的接口配置**

| 模式 | Tiling侧接口 | Kernel侧接口 |
| --- | --- | --- |
| 同一系数的量化/反量化 | SetDequantType(DequantType::SCALAR) | SetQuantScalar(gmScalar) |
| 向量的量化/反量化 | SetDequantType(DequantType::TENSOR) | SetQuantVector(gmTensor) |


#### 使用场景

需要对矩阵计算结果进行量化/反量化操作的场景，当前该场景下，Matmul输入输出矩阵支持的数据类型如下表所示。


**表2 Matmul量化/反量化支持的数据类型**

| A矩阵 | B矩阵 | C矩阵 | 支持平台 |
| --- | --- | --- | --- |
| half | half | int8\_t | Atlas 350 加速卡 Atlas A3 训练系列产品 / Atlas A3 推理系列产品 Atlas A2 训练系列产品 / Atlas A2 推理系列产品 |
| bfloat16\_t | bfloat16\_t | int8\_t | Atlas 350 加速卡 Atlas A3 训练系列产品 / Atlas A3 推理系列产品 Atlas A2 训练系列产品 / Atlas A2 推理系列产品 |
| int8\_t | int8\_t | half | Atlas 350 加速卡 Atlas A3 训练系列产品 / Atlas A3 推理系列产品 Atlas A2 训练系列产品 / Atlas A2 推理系列产品 |
| int4b\_t | int4b\_t | half | Atlas A3 训练系列产品 / Atlas A3 推理系列产品 Atlas A2 训练系列产品 / Atlas A2 推理系列产品 |
| int8\_t | int8\_t | int8\_t | Atlas 350 加速卡 Atlas A3 训练系列产品 / Atlas A3 推理系列产品 Atlas A2 训练系列产品 / Atlas A2 推理系列产品 |
| int8\_t | int8\_t | bfloat16\_t | Atlas 350 加速卡 |
| fp8\_e4m3fn\_t/fp8\_e5m2\_t | fp8\_e4m3fn\_t/fp8\_e5m2\_t | fp8\_e4m3fn\_t/half/bfloat16\_t/float | Atlas 350 加速卡 |
| hifloat8\_t | hifloat8\_t | hifloat8\_t/half/bfloat16\_t/float | Atlas 350 加速卡 注意： 输出为hifloat8\_t时，采用Half to Away Round方式量化。 量化场景的输出为float类型时，该量化模式精度无法达到双万分之一，可以达到双千分之一。如果有双万分之一的精度要求，建议使用AscendDeQuant(https://www.hiascend.comdocument/detail/zh/canncommercial/900/API/ascendcopapi/atlasascendc\_api\_07\_0820.html)高阶API。 |


#### 约束说明

-   SetQuantScalar(https://www.hiascend.comdocument/detail/zh/canncommercial/900/API/ascendcopapi/atlasascendc_api_07_0649.html)
和  SetQuantVector(https://www.hiascend.comdocument/detail/zh/canncommercial/900/API/ascendcopapi/atlasascendc_api_07_0650.html)
接口必须在  Iterate(https://www.hiascend.comdocument/detail/zh/canncommercial/900/API/ascendcopapi/atlasascendc_api_07_0638.html)
或者  IterateAll(https://www.hiascend.comdocument/detail/zh/canncommercial/900/API/ascendcopapi/atlasascendc_api_07_0640.html)
接口前调用。

- 在Kernel侧与Tiling侧设置的量化/反量化模式需要保持一致：

  - Kernel侧调用SetQuantScalar接口设置同一系数的量化/反量化模式，对应Tiling侧调用SetDequantType接口配置模式为DequantType::SCALAR。
  - Kernel侧调用SetQuantVector接口设置向量的量化/反量化模式，对应Tiling侧调用SetDequantType接口配置模式为DequantType::TENSOR。


- 当A、B矩阵为int8_t或int4b_t类型，C矩阵为half时，本节特性的输出结果不支持INF_NAN模式。若结果需要以INF_NAN输出，建议在调用Matmul API时将结果输出到TPosition::VECIN，同时将输出的数据类型设置为int32_t，再基于AIV核使用高阶API  AscendDequant(https://www.hiascend.comdocument/detail/zh/canncommercial/900/API/ascendcopapi/atlasascendc_api_07_0820.html)
将该结果反量化为half类型。

#### 调用示例

完整的算子样例请参考matmul_quant样例(https://gitcode.com/cann/asc-devkit/tree/9.0.0/examples/01_simd_cpp_api/03_libraries/00_matrix/matmul_quant)。

- Tiling实现
  调用SetDequantType(https://www.hiascend.comdocument/detail/zh/canncommercial/900/API/ascendcopapi/atlasascendc_api_07_0698.html)接口设置量化或反量化模式，其他实现内容与基础场景相同。 1 2 3 4 5 6 7 8 9 10 11 12 auto ascendcPlatform = platform_ascendc::PlatformAscendC(context->GetPlatformInfo()); matmul_tiling::MatmulApiTiling tiling(ascendcPlatform); tiling.SetAType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_INT8); tiling.SetBType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_INT8); tiling.SetCType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_FLOAT16); tiling.SetBiasType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, matmul_tiling::DataType::DT_INT32); tiling.SetShape(M, N, K); tiling.SetOrgShape(M, N, K); tiling.EnableBias(true); tiling.SetDequantType(DequantType::SCALAR); // 设置同一系数的量化/反量化模式 // tiling.SetDequantType(DequantType::TENSOR); // 设置向量的量化/反量化模式 ... // 执行其他配置

- Kernel实现
  根据具体量化模式场景，调用SetQuantScalar(https://www.hiascend.comdocument/detail/zh/canncommercial/900/API/ascendcopapi/atlasascendc_api_07_0649.html)
  或SetQuantVector(https://www.hiascend.comdocument/detail/zh/canncommercial/900/API/ascendcopapi/atlasascendc_api_07_0650.html)
  接口设置量化参数。其他实现内容与基础场景相同。
  - 同一系数的量化/反量化模式
    1 2 3 4 5 6 7 8 REGIST_MATMUL_OBJ(&pipe, GetSysWorkSpacePtr(), mm, &tiling); float tmp = 0.1; // 输出gm时会乘以0.1 uint64_t ans = static_cast<uint64_t>(*reinterpret_cast<int32_t*>(&tmp)); // 浮点值量化系数转换为uint64_t类型进行设置 mm.SetQuantScalar(ans); mm.SetTensorA(gm_a); mm.SetTensorB(gm_b); mm.SetBias(gm_bias); mm.IterateAll(gm_c);

  - 向量的量化/反量化模式
    1 2 3 4 5 6 7 8 GlobalTensor gmQuant; ... REGIST_MATMUL_OBJ(&pipe, GetSysWorkSpacePtr(), mm, &tiling); mm.SetQuantVector(gmQuant); mm.SetTensorA(gm_a); mm.SetTensorB(gm_b); mm.SetBias(gm_bias); mm.IterateAll(gm_c);
