AscendDequant

Applicability

Product

Supported

Atlas 350 Accelerator Card

Atlas A3 training product / Atlas A3 inference product

Atlas A2 training product / Atlas A2 inference product

Atlas 200I/500 A2 inference product

x

Atlas inference product AI Core

Atlas inference product Vector Core

x

Atlas training product

x

Function Usage

Performs dequantization by element. For example, dequantize the int32_t data type to the half or float data type. This API supports input of data no more than two dimensions.

  • Assuming that the shape of the input srcTensor is (m, n), the number of bytes occupied by each row of data (n pieces of input data) must be 32-byte aligned, and the number of elements to be dequantized in each row is calCount.
  • The dequantization coefficient deqScale can be a scalar or vector. If deqScale is a vector, calCount is less than or equal to the number of elements in deqScale, and only the first CalCount dequantization coefficients take effect.
  • The shape of the output dstTensor is (m, n_dst). If n x sizeof(dstT) does not meet the 32-byte alignment requirement, it needs to be padded to 32 bytes. n_dst indicates the number of columns after the padding.

The following provides two specific examples to explain the parameter configurations and compute logics: (The DequantParams type in the following is a {m, n, calCount} structure that stores shape information.)

  • As shown in the following figure, the data type of srcTensor is int32_t, m equals 4, n equals 8, and calCount equals 4, indicating that the number of elements to be dequantized in each row of srcTensor is 4, the first four elements in deqScale take effect, and the last 12 elements are not involved in dequantization. The data type of dstTensor is bfloat16_t, m equals 4, and n_dst equals 16 (16 × sizeof(bfloat16_t) % 32 = 0). The compute logic is that every n elements in srcTensor are arranged in a row. For the first calCount elements in each row, the ith element of srcTensor is multiplied by the ith element of deqScale and this product is written into the ith element in the corresponding row of dstTensor. Elements from calCount + 1 to n_dst in the corresponding row of dstTensor are uncertain values.

  • As shown in the following figure, the data type of srcTensor is int32_t, m equals 4, n equals 8, and calCount equals 4, indicating that the number of elements to be dequantized in each row of srcTensor is 4. The data type of dstTensor is float, m equals 4, and n_dst equals 8 (8 × sizeof(float) % 32 = 0). The first four elements in each row of srcTensor are multiplied by the scalar deqScale and the products are written to the corresponding positions in each row of dstTensor.

Set the template parameter mode to DEQUANT_WITH_SINGLE_ROW:

If DequantParams {m, n, calCount} meets the following three conditions:

  1. m = 1
  2. calCount is a multiple of 32/sizeof (dstT).
  3. n % calCount = 0

In this case, {1, n, calCount} is considered as {n/calCount, calCount, calCount} for dequantization.

The following figure shows the effect, in which the passed DequantParams is {1, 16, 8}. Since dstT is float, calCount must be a multiple of 8. In DEQUANT_WITH_SINGLE_ROW mode, {1, 2 × 8, 8} is converted to {2, 8, 8} for calculation.

  • PER_TOKEN dequantization: The elements in each group of tokens (m groups of tokens in the n direction) of srcTensor share the deqscale parameter. When srcTensor is [m, n], deqscale is [m, 1].

  • PER_GROUP dequantization: The compute direction of groups is defined as k. In the k direction, each groupSize elements of srcTensor share the deqscale parameter. When the shape of srcTensor is [m, n], if kDim is 0, k is in the m direction, and the shape of deqscale is [(m + groupSize – 1)/groupSize, n]; if kDim is 1, k is in the n direction, and the shape of deqscale is [m, (n + groupSize – 1)/groupSize].
    • kDim = 0:

    • kDim = 1:

Principles

The figure below illustrates the internal algorithm block diagram of AscendDequant high-level APIs, taking the input srcTensor with a data type of int32_t and a shape of [m, n], input deqScale with a data type of scaleT and a shape of [n], and output dstTensor with a data type of dstT and a shape of [m, n] as examples.

Figure 1 AscendDequant internal algorithm block diagram

The computation process is divided into the following steps, all of which are performed on vectors:

  1. Precision conversion: Convert srcTensor and deqScale into FP32 tensors to obtain srcFP32 and deqScaleFP32, respectively.
  2. Mul computation: srcFP32 has a total of m rows, each with a length of n. Each row of srcFP32 is multiplied by deqScaleFP32 through m cycles. The mask limits the Mul computation to only the first dequantParams.calcount elements. The value range of index in the figure is [0, m), corresponding to each row of srcFP32. The calculation result is mulRes, whose shape is [m, n].
  3. Precision conversion of result data: Convert mulRes from FP32 to a dstT tensor. The result is dstTensor with a shape of [m, n].

In the PER_TOKEN and PER_GROUP scenarios, the data type of the input srcTensor is int32_t or float. The following diagram shows the internal algorithm.

Figure 2 Internal algorithm of AscendDequant in the PER_TOKEN and PER_GROUP scenarios

The computation logic in the PER_TOKEN and PER_GROUP scenarios is as follows:

  1. Data reading: Read the input srcTensor continuously, and use different modes to read the input deqscale based on actual scenarios. For example, the input data is broadcast in the PER_TOKEN scenario, and gathered in the PER_GROUP scenario.
  2. Precision conversion: Convert the data types of srcTensor and deqscale based on the input data type combination.
  3. Computation: Perform multiplication on srcTensor and deqscale data after type conversion.
  4. Precision conversion: Convert the computation result to the dstT type as the final output.

Prototype

  • The deqScale parameter is a vector.
    • Pass the temporary space through the sharedTmpBuffer input parameter.
      1
      2
      template <typename dstT, typename scaleT, DeQuantMode mode = DeQuantMode::DEQUANT_WITH_SINGLE_ROW>
      __aicore__ inline void AscendDequant(const LocalTensor<dstT>& dstTensor, const LocalTensor<int32_t>& srcTensor, const LocalTensor<scaleT>& deqScale, const LocalTensor<uint8_t>& sharedTmpBuffer, DequantParams params)
      
    • Allocate the temporary space through the API framework.
      1
      2
      template <typename dstT, typename scaleT, DeQuantMode mode = DeQuantMode::DEQUANT_WITH_SINGLE_ROW>
      __aicore__ inline void AscendDequant(const LocalTensor<dstT>& dstTensor, const LocalTensor<int32_t>& srcTensor, const LocalTensor<scaleT>& deqScale, DequantParams params)
      
    • PER_TOKEN or PER_GROUP quantization
      It is supported only by the Atlas 350 Accelerator Card.
      • Pass the temporary space through the sharedTmpBuffer input parameter.
        1
        2
        template <typename dstT, typename srcT, typename scaleT, const AscendDeQuantConfig& config, const AscendDeQuantPolicy& policy>
        __aicore__ inline void AscendDequant(const LocalTensor<dstT>& dstTensor, const LocalTensor<srcT>& srcTensor, const LocalTensor<scaleT>& scaleTensor, const LocalTensor<scaleT>& offsetTensor, const LocalTensor<uint8_t>& sharedTmpBuffer, const AscendDeQuantParam& para)
        
      • Allocate the temporary space through the API framework.
        1
        2
        template <typename dstT, typename srcT, typename scaleT, const AscendDeQuantConfig& config, const AscendDeQuantPolicy& policy>
        __aicore__ inline void AscendDequant(const LocalTensor<dstT>& dstTensor, const LocalTensor<srcT>& srcTensor, const LocalTensor<scaleT>& scaleTensor, const LocalTensor<scaleT>& offsetTensor, const AscendDeQuantParam& para)
        
  • The deqScale parameter is a scalar.
    • Pass the temporary space through the sharedTmpBuffer input parameter.
      1
      2
      template <typename dstT, typename scaleT, DeQuantMode mode = DeQuantMode::DEQUANT_WITH_SINGLE_ROW>
      __aicore__ inline void AscendDequant(const LocalTensor<dstT>& dstTensor, const LocalTensor<int32_t>& srcTensor, const scaleT deqScale, const LocalTensor<uint8_t>& sharedTmpBuffer, DequantParams params)
      
    • Allocate the temporary space through the API framework.
      1
      2
      template <typename dstT, typename scaleT, DeQuantMode mode = DeQuantMode::DEQUANT_WITH_SINGLE_ROW>
      __aicore__ inline void AscendDequant(const LocalTensor<dstT>& dstTensor, const LocalTensor<int32_t>& srcTensor, const scaleT deqScale, DequantParams params)
      

Due to the complex mathematical computation involved in the internal implementation of this API, extra temporary space is required to store intermediate variables generated during computation. The temporary space can be allocated through the API framework or passed by developers through the sharedTmpBuffer input parameter.

  • When the API framework is used for temporary space allocation, developers do not need to allocate the space, but must reserve the required size for the temporary space.
  • When the sharedTmpBuffer input parameter is used for passing the temporary space, the tensor serves as the temporary space. In this case, the API framework is not required for temporary space allocation. This enables developers to manage the sharedTmpBuffer space and reuse the buffer after calling the API, so that the buffer is not repeatedly allocated or deallocated, improving the flexibility and buffer utilization.

If the API framework is used, developers must reserve the temporary space. If sharedTmpBuffer is used, developers must allocate space for sharedTmpBuffer. To obtain the size of the temporary space (BufferSize) to be reserved, use the GetAscendDequantMaxMinTmpSize API provided in GetAscendDequantMaxMinTmpSize.

The following APIs are not recommended. Do not use them for newly developed content:

1
2
template <typename dstT, typename scaleT, DeQuantMode mode = DeQuantMode::DEQUANT_WITH_SINGLE_ROW>
__aicore__ inline void AscendDequant(const LocalTensor<dstT>& dstTensor, const LocalTensor<int32_t>& srcTensor, const LocalTensor<scaleT>& deqScale, const LocalTensor<uint8_t>& sharedTmpBuffer, const uint32_t calCount)
1
2
template <typename dstT, typename scaleT, DeQuantMode mode = DeQuantMode::DEQUANT_WITH_SINGLE_ROW>
__aicore__ inline void AscendDequant(const LocalTensor<dstT>& dstTensor, const LocalTensor<int32_t>& srcTensor, const LocalTensor<scaleT>& deqScale, const LocalTensor<uint8_t>& sharedTmpBuffer)
1
2
template <typename dstT, typename scaleT, DeQuantMode mode = DeQuantMode::DEQUANT_WITH_SINGLE_ROW>
__aicore__ inline void AscendDequant(const LocalTensor<dstT>& dstTensor, const LocalTensor<int32_t>& srcTensor, const LocalTensor<scaleT>& deqScale, const uint32_t calCount)
1
2
template <typename dstT, typename scaleT, DeQuantMode mode = DeQuantMode::DEQUANT_WITH_SINGLE_ROW>
__aicore__ inline void AscendDequant(const LocalTensor<dstT>& dstTensor, const LocalTensor<int32_t>& srcTensor, const LocalTensor<scaleT>& deqScale)

Parameters

Table 1 Template parameters

Parameter

Description

dstT

Data type of the destination operand.

scaleT

Data type of deqScale.

mode

Compute logic used when DequantParams is {1, n, calCount}, with enum DeQuantMode passed. The following configurations are supported:
  • DEQUANT_WITH_SINGLE_ROW: When DequantParams {m, n, calCount} meets the following conditions: m = 1, calCount being a multiple of 32/sizeof(dstT), and n % calCount = 0, {1, n, calCount} is computed as {n/calCount, calCount, calCount}.
  • DEQUANT_WITH_MULTI_ROW: Even if all the preceding conditions are met, {1, n, calCount} is still calculated as {1, n, calCount}. This means that the first calCount elements out of the total n elements are dequantized.
Table 2 Template parameters in the PER_TOKEN and PER_GROUP scenarios

Parameter

Description

srcT

Data type of the source operand.

config

Quantization API parameter, which is of the AscendDeQuantConfig type. The definition is as follows:

1
2
3
4
struct AscendDeQuantConfig {
        bool hasOffset;
        int32_t kDim = 1;
}
  • hasOffset: whether the quantization parameter offset is involved in the computation.
    • True: The offset parameter is involved in the computation.
    • False: The offset parameter is not involved in the computation.
  • kDim: compute direction of groups, that is, the k direction. This parameter is valid only in the PER_GROUP scenario. The following values are supported:
    • 0: The k axis is axis 0. That means the compute direction of groups is m.
    • 1: The k axis is axis 1. That means the compute direction of groups is n.

policy

Quantization policy parameter of the enumeration type. The following values are supported:

1
2
3
4
5
6
enum class AscendDeQuantPolicy : int32_t {
        PER_TOKEN // PER_TOKEN mode
        PER_GROUP // PER_GROUP mode
        PER_CHANNEL_PER_GROUP // Reserved.
        PER_TOKEN_PER_GROUP // Reserved.
}
Table 3 API parameters

Parameter

Input/Output

Description

dstTensor

Output

Destination operand. The type is LocalTensor, and the supported TPosition is VECIN, VECCALC, or VECOUT.

For the Atlas 350 Accelerator Card, the supported data types are half, bfloat16_t, and float.

For the Atlas A3 training product / Atlas A3 inference product , the supported data types are half, bfloat16_t, and float.

For the Atlas A2 training product / Atlas A2 inference product , the supported data types are half, bfloat16_t, and float.

For the Atlas inference product AI Core, the supported data types are half and float.

  • The number of rows of dstTensor must be the same as that of srcTensor.
  • If n x sizeof(dstT) does not meet the 32-byte alignment requirement, it needs to be padded to 32 bytes. n_dst indicates the number of columns after the padding. For example, if srcTensor has a data type of int32_t and a shape of (4, 8), and dstTensor has a data type of bfloat16_t, n_dst must be padded from 8 to 16, and the dstTensor shape should be (4, 16). The padding process is as follows: n_dst = (8 x sizeof(bfloat16_t) + 32 –1)/32 x 32/sizeof(bfloat16_t)

srcTensor

Input

Source operand. The type is LocalTensor, and the supported TPosition is VECIN, VECCALC, or VECOUT.

For the Atlas 350 Accelerator Card, the supported data type is int32_t.

For the Atlas A3 training product / Atlas A3 inference product , the supported data type is int32_t.

For the Atlas A2 training product / Atlas A2 inference product , the supported data type is int32_t.

For the Atlas inference product AI Core, the supported data type is int32_t.

The shape is [m, n], and the number of bytes occupied by n pieces of input data must be 32-byte aligned.

deqScale

Input

Source operand. The type is scalar or LocalTensor. When the type is LocalTensor, the supported TPosition is VECIN, VECCALC, or VECOUT.

For the Atlas 350 Accelerator Card, when deqScale is a vector, the supported data types are uint64_t, float, and bfloat16_t. When deqScale is a scalar, the supported data types are bfloat16_t and float.

For the Atlas A3 training product / Atlas A3 inference product , when deqScale is a vector, the supported data types are uint64_t, float, and bfloat16_t. When deqScale is a scalar, the supported data types are bfloat16_t and float.

For the Atlas A2 training product / Atlas A2 inference product , when deqScale is a vector, the supported data types are uint64_t, float, and bfloat16_t. When deqScale is a scalar, the supported data types are bfloat16_t and float.

For the Atlas inference product AI Core, when deqScale is a vector, the supported data types are uint64_t and float. When deqScale is a scalar, the supported data type is float.

For details about the data type combinations supported by dstTensor, srcTensor, and deqScale, see Table 5 and Table 6.

sharedTmpBuffer

Input

Temporary buffer. The type is LocalTensor, and the supported TPosition is VECIN, VECCALC, or VECOUT.

For details about how to obtain the temporary space size (BufferSize), see GetAscendDequantMaxMinTmpSize.

For the Atlas 350 Accelerator Card, the supported data type is uint8_t.

For the Atlas A3 training product / Atlas A3 inference product , the supported data type is uint8_t.

For the Atlas A2 training product / Atlas A2 inference product , the supported data type is uint8_t.

For the Atlas inference product AI Core, the supported data type is uint8_t.

params

Input

Shape of srcTensor, DequantParams type. The definition is as follows:

1
2
3
4
5
6
struct DequantParams
{
    uint32_t m;             // number of rows of srcTensor
    uint32_t n;             // number of columns of srcTensor
    uint32_t calCount;      // For each row of srcTensor, the first calCount elements are valid data, and they are multiplied by the first calCount elements of deqScale or by the deqScale scalar.
};
  • DequantParams.n x sizeof(T) must be an integer multiple of 32 bytes. T is the data type of the elements in srcTensor.
  • Since the multiplication operation is performed on the first calCount elements among every n elements, DequantParams.n and calCount must meet the following relationship:

    1 ≤ DequantParams.calCount ≤ DequantParams.n

  • When deqScale is a vector, DequantParams.calCount is less than or equal to the number of elements in deqScale.
Table 4 API parameters in the PER_TOKEN and PER_GROUP scenarios

Parameter

Input/Output

Description

dstTensor

Output

Destination operand.

The type is LocalTensor, and TPosition can be VECIN, VECCALC, or VECOUT.

For the Atlas 350 Accelerator Card, the supported data types are half, bfloat16_t, and float.

srcTensor

Input

Source operand.

The type is LocalTensor, and TPosition can be VECIN, VECCALC, or VECOUT.

For the Atlas 350 Accelerator Card, the supported data types are int32_t and float.

sharedTmpBuffer

Input

Temporary buffer.

The type is LocalTensor, and TPosition can be VECIN, VECCALC, or VECOUT.

For details about how to obtain the temporary space size (BufferSize), see GetAscendQuantMaxMinTmpSize.

For the Atlas 350 Accelerator Card, the supported data type is uint8_t.

scaleTensor

Input

Quantization parameter scale.

The type is LocalTensor, and TPosition can be VECIN, VECCALC, or VECOUT.

For the Atlas 350 Accelerator Card, the supported data types are half, bfloat16_t, and float.

offsetTensor

Input

Quantization parameter offset, which is reserved.

The type is LocalTensor, and TPosition can be VECIN, VECCALC, or VECOUT.

For the Atlas 350 Accelerator Card, the data type is the same as that of scaleTensor.

para

Input

Dequantization API parameter. The definition is as follows:

1
2
3
4
5
6
struct AscendDeQuantParam {
        uint32_t m;
        uint32_t n;
        uint32_t calCount;   
        uint32_t groupSize = 0;
}
  • m: number of elements in the m direction.
  • n: number of elements in the n direction. The data size corresponding to the value of n must be 32-byte aligned, indicating that the input and output whose last dimension of the shape is n must be 32-byte aligned.
  • calCount: number of elements involved in the computation. The value of calCount must be an integer multiple of n.
  • groupSize: The parameter is valid in the PER_GROUP scenario. It indicates that data in the groupSize row or column shares scale or offset. The value of groupSize must be greater than 0 and an integer multiple of 32.
Table 5 Supported data type combinations (deqScale is LocalTensor)

dstTensor

srcTensor

deqScale

half

int32_t

uint64_t

Note: When the data type of deqScale is uint64_t, the lower 32 bits of the value are used for computation. When the data type is float, the upper 32 bits of the value are some control parameters which are not used by this API.

float

int32_t

float

float

int32_t

bfloat16_t

bfloat16_t

int32_t

bfloat16_t

bfloat16_t

int32_t

float

Table 6 Supported data type combinations (deqScale is a scalar)

dstTensor

srcTensor

deqScale

bfloat16_t

int32_t

bfloat16_t

bfloat16_t

int32_t

float

float

int32_t

bfloat16_t

float

int32_t

float

Table 7 Data type combinations supported in the PER_TOKEN and PER_GROUP scenarios

srcDtype

scaleDtype

dstDtype

int32_t

half

half

bfloat16_t

bfloat16_t

float

float

float

half

float

bfloat16_t

float

half

half

bfloat16_t

bfloat16_t

float

float

float

half

float

bfloat16_t

Returns

None

Constraints

  • The source operand address must not overlap the destination operand address.
  • For details about the operand address alignment requirements, see General Address Alignment Restrictions.
  • Currently, only the Atlas 350 Accelerator Card supports the PER_TOKEN and PER_GROUP scenarios.
  • In the PER_TOKEN and PER_GROUP scenarios, the size of data in the continuous compute direction (n direction) must be 32-byte aligned.

Examples

For a complete operator sample, see dequant operator sample.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// dstLocal: tensor for storing the dequantization computation result
// srcLocal: tensor for storing the dequantization computation input
// deqScaleLocal: tensor for storing the input dequantization coefficient for dequantization computation
// sharedTmpBuffer: tensor for storing the temporary buffer during dequantization computation

uint32_t m = 4; // number of rows of srcTensor
uint32_t n = 8; // number of columns of srcTensor
uint32_t calCount = 6; // the first calCount elements in each row of srcTensor involved in dequantization computation

// deqScale is a vector, whose temporary space is passed through the sharedTmpBuffer input parameter.
AscendC::AscendDequant(dstLocal, srcLocal, deqScaleLocal, sharedTmpBuffer, {m, n, calCount});

// deqScale is a vector, whose temporary space is allocated through the API framework.
AscendC::AscendDequant(dstLocal, srcLocal, deqScaleLocal, {m, n, calCount});

// deqScale is a scalar, whose temporary space is passed through the sharedTmpBuffer input parameter.
AscendC::AscendDequant(dstLocal, srcLocal, static_cast<float>(2.2), sharedTmpBuffer, {m, n, calCount});
// deqScale is a scalar, whose temporary space is allocated through the API framework.
AscendC::AscendDequant(dstLocal, srcLocal, static_cast<float>(2.2), {m, n, calCount});

Result example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Input (srcLocal) of the int32_t data type:
[[-16 -15 -14 -13 -12 -11 -10  -9]
 [ -8  -7  -6  -5  -4  -3  -2  -1]
 [  0   1   2   3   4   5   6   7]
 [  8   9  10  11  12  13  14  15]]

deqScaleLocal of the float data type:
[2.2  -2.2  2.2  -2.2  2.2  -2.2  0.  0.]

Output (dstLocal) of the float data type:
[[-35.2  33.  -30.8  28.6 -26.4  24.2 -10.   -9. ]
 [-17.6  15.4 -13.2  11.   -8.8   6.6  -2.   -1. ]
 [  0.   -2.2   4.4  -6.6   8.8 -11.    6.    7. ]
 [ 17.6 -19.8  22.  -24.2  26.4 -28.6  14.   15. ]]

The following is an example of calling the API in the PER_TOKEN and PER_GROUP scenarios:

1
2
3
4
5
6
7
8
9
// Note that m and n must be passed from an external system.
constexpr static bool isReuseSource = false;
constexpr static AscendDeQuantConfig config = {has_offset, -1};
constexpr static AscendDeQuantPolicy policy = AscendDeQuantPolicy::PER_TOKEN; // The enumerated value can be modified to enable PER_GROUP.
AscendDeQuantParam para;
para.m = m;
para.n = n;
para.calCount = calCount;
AscendDequant<dstType, srcType, scaleType, config, policy>(dstLocal, srcLocal, scaleLocal, offsetLocal, para);