aclnnGroupedMatmulWeightNz
Supported Products
| Product | Supported |
|---|---|
| √ | |
| √ | |
| × | |
| √ | |
| × |
Function
Description: Implements grouped matrix multiplication, supporting non-uniform matrix dimension sizes across multiple groups. The basic function is matrix multiplication, for example, , where indicates the number of groups and , , and define the shapes for each group. Both inputs and outputs are of the aclTensorList type, with the following functions:
- K-axis grouping: varies across groups, while and remain the same for each group. In this case, and can be concatenated along the K-axis.
- M-axis grouping: remains the same for each group. In this case, and can be concatenated along the N-axis.
New features compared with GroupedMatmulV5:
- The input
weightdata supports the AI processor-affinity layout format (FRACTAL_NZ). - The
quantGroupSizeparameter is added. It is an integer that indicates the quantization group size in per-group mode. If per-group quantization is not involved, set this parameter to0.
Formulas:
- Non-quantization scenario:
Quantization scenario (without perTokenScaleOptional):
xin INT8 andbiasin INT32xin INT8 andbiasin BFLOAT16/FLOAT16/FLOAT32, without offset
Quantization scenario (with perTokenScaleOptional):
xin INT8 andbiasin INT32xin INT8 andbiasin BFLOAT16/FLOAT16/FLOAT32
Quantization scenario (MX quantization, without bias or activation layer):
- Dequantization scenario:
- Fake-quantization scenario:
Prototype
Each operator has two-phase API calls. First, aclnnGroupedMatmulWeightNzGetWorkspaceSize is called to obtain the input parameters and compute the required workspace size based on the process. Then, aclnnGroupedMatmulWeightNz is called to perform computation.
aclnnStatus aclnnGroupedMatmulWeightNzGetWorkspaceSize(
const aclTensorList *x,
const aclTensorList *weight,
const aclTensorList *biasOptional,
const aclTensorList *scaleOptional,
const aclTensorList *offsetOptional,
const aclTensorList *antiquantScaleOptional,
const aclTensorList *antiquantOffsetOptional,
const aclTensorList *perTokenScaleOptional,
const aclTensor *groupListOptional,
const aclTensorList *activationInputOptional,
const aclTensorList *activationQuantScaleOptional,
const aclTensorList *activationQuantOffsetOptional,
int64_t splitItem,
int64_t groupType,
int64_t groupListType,
int64_t actType,
aclIntArray *tuningConfigOptional,
int64_t quantGroupSize,
aclTensorList *out,
aclTensorList *activationFeatureOutOptional,
aclTensorList *dynQuantScaleOutOptional,
uint64_t *workspaceSize,
aclOpExecutor **executor)aclnnStatus aclnnGroupedMatmulWeightNz(
void *workspace,
uint64_t workspaceSize,
aclOpExecutor *executor,
aclrtStream stream)aclnnGroupedMatmulWeightNzGetWorkspaceSize
Parameters
Name Input/Output Description Usage Notes Data Type Data Format Dimension (Shape) Non-contiguous Tensor x Input Input x in the formula. The maximum length is 128. FLOAT16, BFLOAT16, INT8, INT41, INT321, FLOAT8_E4M3FN2 ND - - weight Input Weight in the formula. The maximum length is 128. The Ascend-affinity data layout format (NZ) is supported. FLOAT16, BFLOAT16, INT8, INT4, INT32, FLOAT32, FLOAT4_E2M12 ND, FRACTAL_NZ - - biasOptional Optional input Bias in the formula. Same length as weight. FLOAT16, FLOAT32, INT32, BFLOAT16 ND - - scaleOptional Optional input Scale in the formula, indicating the scale factor for quantization parameters. Generally, the length is the same as the weight length. For details about the constraints, see Constraints. UINT641, BFLOAT161, FLOAT32 ND - - offsetOptional Optional input Offset in the formula, indicating the offset for quantization parameters. Same length as weight. FLOAT32 ND - - antiquantScaleOptional Optional input antiquant_scale in the formula, indicating the scale factor for fake-quantization parameters. Same length as weight. For details about the constraints, see Constraints. FLOAT16, BFLOAT161, FLOAT8_E8M02 ND - - antiquantOffsetOptional Optional input antiquant_offset in the formula, indicating the offset for fake-quantization parameters. Same length as weight. For details about the constraints, see Constraints. FLOAT16, BFLOAT161 ND - - perTokenScaleOptional Optional input per_token_scale in the formula, indicating the scale factor (introduced by x quantization) for quantization parameters. It is valid in scenarios where x, weight, and out are all single-tensor. For details about the constraints, see Constraints. FLOAT32, FLOAT8_E8M02 ND - - groupListOptional Optional input Matmul size distribution along the grouping axis for inputs and outputs. Input data in different formats based on groupListType. Note that when the length of the output TensorList is 1, the last value of this parameter constrains the valid portion of the output. INT64 ND - - activationInputOptional Optional input Backward input of the activation function. Currently, only nullptr can be passed. - - - - activationQuantScaleOptional Optional input - Currently, only nullptr can be passed. - - - - activationQuantOffsetOptional Optional input - Currently, only nullptr can be passed. - - - - splitItem Input Specifies whether to perform tensor splitting on the output. 0/1 indicates that the output is multi-tensor; 2/3 indicates that the output is single-tensor. INT64 - - - groupType Input Axis to be grouped. -1: no grouping; 0: M-axis grouping; 1: N-axis grouping; 2: K-axis grouping. For details about the constraints, see Constraints. INT64 - - - groupListType Input Grouping mode of the groupList input. 0: Cumulative sum result; 1: size of each group; 2: [groupIdx, groupSize]. For details about the constraints, see Constraints. INT64 - - - actType Input Activation function type. The value ranges from 0 to 5. For details about the constraints, see Constraints. INT64 - - - tuningConfigOptional Optional input The first value indicates the expected number of tokens to be processed by each expert, which is used to optimize tiling. Compatible with earlier versions. If this parameter is not used, do not pass it (that is, pass nullptr). INT64 - - - quantGroupSize Input Group size for per-group quantization. If per-group quantization is not involved, set this parameter to `0`. INT64 - - - out Output Output y in the formula. The maximum length is 128. FLOAT16, BFLOAT16, INT8, FLOAT32, INT32 ND - - activationFeatureOutOptional Output Input data of the activation function. Currently, only nullptr can be passed. - - - - dynQuantScaleOutOptional Output - Currently, only nullptr can be passed. - - - - workspaceSize Output Size of the workspace required to be allocated on the device. - - - - - executor Output Operator executor, containing the operator computation process. - - - - - Atlas A2 training products/Atlas A2 inference products andAtlas A3 training products/Atlas A3 inference products :- The superscript "1" in the "Data Type" column of the table above indicates data types that are supported by the products, and the superscript "2" indicates data types that are not supported by the products.
- The
weightformat can be converted from ND to NZ by callingaclnnCalculateMatmulWeightSizeV2andaclnnTransMatmulWeight. When the input data type is INT32, each INT32 value is treated as eight INT4 values inside the API.
Atlas inference products :- Only FLOAT16 is supported.
weightsupports only the FRACTAL_NZ format, which needs to be converted through auxiliary APIs. - Quantization/asymmetric quantization parameters such as
scaleOptionalandoffsetOptionalare not supported, and need to be passed as null pointers. groupTypesupports only M-axis grouping (0). The value ofactTypecan only be0.tuningConfigOptionalis not supported.
- Only FLOAT16 is supported.
Return
aclnnStatusstatus code. For details, see aclnn Return Codes.The first-phase API implements input parameter validation. The following errors may be thrown:
Return Error Code Description ACLNN_ERR_PARAM_NULLPTR 161001 1. The required input, output, or attribute is passed as a null pointer. 2. The input weight contains elements that are null pointers. 3. The input x contains elements that are null pointers, while the corresponding elements in the output out are non-null pointers. 4. The input x contains elements that are non-null pointers, while the corresponding elements in the output out are null pointers. ACLNN_ERR_PARAM_INVALID 161002 1. The data type or data format of x, weight, biasOptional, scaleOptional, offsetOptional, antiquantScaleOptional, antiquantOffsetOptional, groupListOptional, or out is not supported. 2. The weight length is greater than 128; the bias is not null but its length is not equal to the weight length. 3. The dimension of groupListOptional is 1. 4. When splitItem is set to 2 or 3, the length of out is not 1. 5. When splitItem is set to 0 or 1, the length of out or groupListOptional is not equal to the weight length. 6. An element in the input parameter tuningConfigOptional is negative or exceeds the number of rows (M) in x.
aclnnGroupedMatmulWeightNz
Parameters
Parameter Input/Output Description workspace Input Address of the workspace to be allocated on the device. workspaceSize Input Size of the workspace to be allocated on the device, which is obtained by calling aclnnGroupedMatmulWeightNzGetWorkspaceSize.executor Input Operator executor, containing the operator computation process. stream Input Stream for executing the task. Return
aclnnStatusstatus code. For details, see aclnn Return Codes.
Constraints
- Deterministic computation:
aclnnGroupedMatmulWeightNzdefaults to deterministic implementation.
- Common constraints
- If
groupListOptionalis passed: whengroupListTypeis0,groupListOptionalmust be a non-negative, monotonically non-decreasing sequence; whengroupListTypeis1,groupListOptionalmust be a non-negative sequence and its length cannot be 1; whengroupListTypeis2, the second column ofgroupListOptionalmust be a non-negative sequence and its length cannot be 1. - The size of each dimension for every tensor in
xandweight, after 32-byte alignment, should be less than the maximum value of INT32 (2147483647).
- If
Atlas A2 training products/Atlas A2 inference products and Atlas A3 training products/Atlas A3 inference products
The following input types are supported in non-quantization scenarios:
x: FLOAT16;weight: FLOAT16;biasOptional: FLOAT16;scaleOptional: null;offsetOptional: null;antiquantScaleOptional: null;antiquantOffsetOptional: null;perTokenScaleOptional: null;activationInputOptional: null;out: FLOAT16x: BFLOAT16;weight: BFLOAT16;biasOptional: FLOAT32;scaleOptional: null;offsetOptional: null;antiquantScaleOptional: null;antiquantOffsetOptional: null;perTokenScaleOptional: null;activationInputOptional: null;out: BFLOAT16
The following input types are supported in quantization scenarios:
x: INT8;weight: INT8;biasOptional: INT32;scaleOptional: BFLOAT16;offsetOptional: null;antiquantScaleOptional: null;antiquantOffsetOptional: null;perTokenScaleOptional: null or FLOAT32;activationInputOptional: null;out: BFLOAT16x: INT8;weight: INT8;biasOptional: INT32;scaleOptional: FLOAT32;offsetOptional: null;antiquantScaleOptional: null;antiquantOffsetOptional: null;perTokenScaleOptional: null or FLOAT32;activationInputOptional: null;out: FLOAT16x: INT4;weight: INT4;biasOptional: null;scaleOptional: UINT64;offsetOptional: null;antiquantScaleOptional: null;antiquantOffsetOptional: null;perTokenScaleOptional: null or FLOAT32;activationInputOptional: null;out: FLOAT16 or BFLOAT16
The following input types are supported in fake-quantization scenarios:
The shapes of the fake-quantization parameters
antiquantScaleOptionalandantiquantOffsetOptionalmust meet the following requirements ( indicates the number of Matmul groups, indicates the number of quantization groups, and indicates the number of quantization groups of the i-th tensor).Application Scenario Sub-scenario Shape Restriction Fake-quantization (per-channel) Single-tensor weightFake-quantization (per-channel) Multi-tensor weightFake-quantization (per-group) Single-tensor weightFake-quantization (per-group) Multi-tensor weightx: INT8;weight: INT4;biasOptional: FLOAT32;scaleOptional: UINT64;antiquantScaleOptional: null;antiquantOffsetOptional: null;perTokenScaleOptional: FLOAT32;activationInputOptional: null This scenario supports symmetric quantization and asymmetric quantization:Symmetric quantization
- The data type of the output
outis BFLOAT16 or FLOAT16. offsetOptionalis null.- Only the count mode is supported (the operator does not validate
groupListType).kmust be an integer multiple ofquantGroupSizeandk≤ 18432.quantGroupSizeis the per-group quantization length in the K-axis. Currently,quantGroupSize=256is supported. - The scale is the result after per-group and per-channel offline fusion. The shape must be , where .
- The bias is the auxiliary result of offline computation during the computation process. Its value must be and is accumulated in the first dimension. The shape must be .
- N must be an integer multiple of 8.
- The data type of the output
Asymmetric quantization
- The data type of the output
outis FLOAT16. - Only the count mode is supported (the operator does not validate
groupListType). - {k, n} must be {7168, 4096} or {2048, 7168}.
- The scale is the result after per-group and per-channel offline fusion. The shape must be .
offsetOptionalis not null. For asymmetric quantization,offsetOptionalis the auxiliary result of offline computation during the computation process, that is, . The shape must be , and the data type must be FLOAT32.- The bias is the auxiliary result of offline computation during the computation process. Its value must be and is accumulated in the first dimension. The shape must be .
- N must be an integer multiple of 8.
- The data type of the output
In fake-quantization scenarios, if the
weighttype is INT8, only the per-channel mode is supported. If theweighttype is INT4, the per-channel and per-group modes are supported in symmetric quantization. If the per-group mode is used, the number of quantization groups ( or ) must be exactly divisible by the corresponding . For multi-tensorweight, the per-group length is defined as , and all values must be the same. Asymmetric quantization supports the per-channel mode.In fake-quantization scenarios, if the
weighttype is INT4, the last dimension of each group of tensors in weight must be an even number. The last dimension of refers to the N-axis whenweightis not transposed or the K-axis whenweightis transposed. In the per-group mode, whenweightis transposed, the per-group length must be an even number.
Supported scenarios for different
groupTypevalues:In quantization and fake-quantization scenarios,
groupTypecan be either-1or0."S" stands for single-tensor, and "M" stands for multi-tensor, expressed in the sequence of
x,weight,y. For example, "SMS" indicates single-tensorx, multi-tensorweight, and single-tensory.groupType Supported Scenario Scenario Restrictions -1 MMM (1) splitItemcan only be set to0or1.
(2) The tensors inxmust have the same dimensionality, which can be 2D to 6D. The tensors inweightmust be 2D. The dimensionality of tensors inymust match that ofx.
(3)groupListOptionalmust be passed as null.
(4)weightcan be transposed. The transposition status of each tensor within theweighttensorList must be consistent.
(5)xcannot be transposed.0 SSS (1) splitItemcan only be set to2or3.
(2) The tensor inweightmust be 3D, and the tensors inxandymust be 2D.
(3)groupListOptionalmust be passed. WhengroupListTypeis0, the last value must be equal to the first dimension of the tensor inx. WhengroupListTypeis1, the sum of the values must be equal to the first dimension of the tensor inx. WhengroupListTypeis2, the sum of the values in the second column must be equal to the first dimension of the tensor inx.
(4) The first dimension ofgroupListOptionalsupports a maximum of 1024 groups.
(5)weightcan be transposed.
(6)xcannot be transposed.0 SMS (1) splitItemcan only be set to2or3.
(2)groupListOptionalmust be passed. WhengroupListTypeis0, the last value must be equal to the first dimension of the tensor inx. WhengroupListTypeis1, the sum of the values must be equal to the first dimension of the tensor inxand the maximum length is 128. WhengroupListTypeis2, the sum of the values in the second column must be equal to the first dimension of the tensor inxand the maximum length is 128.
(3) Tensors inx,weight, andymust be 2D.
(4) The N-axis of each tensor inweightmust be the same.
(5)weightcan be transposed. The transposition status of each tensor within theweighttensorList must be consistent.
(6)xcannot be transposed.0 MMS (1) splitItemcan only be set to2or3.
(2) Tensors inx,weight, andymust be 2D.
(3) The N-axis of each tensor inweightmust be the same.
(4) IfgroupListOptionalis passed: whengroupListTypeis0, the differences ofgroupListOptionalvalues must be in one-to-one mapping with the first dimension of the tensors inx; whengroupListTypeis1, thegroupListOptionalvalues must be in one-to-one mapping with the first dimension of the tensors inx, and the maximum length is 128; whengroupListTypeis2, the values in the second column ofgroupListOptionalmust be in one-to-one mapping with the first dimension of the tensors inx, and the maximum length is 128.
(5)weightcan be transposed. The transposition status of each tensor within theweighttensorList must be consistent.
(6)xcannot be transposed.
Atlas inference products
The input and output support only the FLOAT16 type. The N-axis size of the output
ymust be a multiple of 16."S" stands for single-tensor and "M" stands for multi-tensor, expressed in the sequence of
x,weight,y. For example, "SMS" indicates single-tensorx, multi-tensorweight, and single-tensory.groupType Supported Scenario Scenario Restrictions 0 SSS (1) splitItemcan only be set to2or3.
(2) The tensor inweightmust be 3D, and the tensors inxandymust be 2D.
(3)groupListOptionalmust be passed. WhengroupListTypeis0, the last value must be equal to the first dimension of the tensor inx. WhengroupListTypeis1, the sum of the values must be equal to the first dimension of the tensor inx.
(4) The first dimension ofgroupListOptionalsupports a maximum of 1024 groups.
(5)weightcan be transposed, butxcannot.
Calling Example
The following example is for reference only. For details, see Compilation and Running Sample.
#include <iostream>
#include <vector>
#include "acl/acl.h"
#include "aclnnop/aclnn_grouped_matmul_weight_nz.h"
#define CHECK_RET(cond, return_expr) \
do { \
if (!(cond)) { \
return_expr; \
} \
} while (0)
#define LOG_PRINT(message, ...) \
do { \
printf(message, ##__VA_ARGS__); \
} while (0)
int64_t GetShapeSize(const std::vector<int64_t>& shape) {
int64_t shapeSize = 1;
for (auto i : shape) {
shapeSize *= i;
}
return shapeSize;
}
int Init(int32_t deviceId, aclrtStream* stream) {
// (Boilerplate) Initialize resources.
auto ret = aclInit(nullptr);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret);
ret = aclrtSetDevice(deviceId);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret);
ret = aclrtCreateStream(stream);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret);
return 0;
}
template <typename T>
int CreateAclTensor_New(const std::vector<int64_t>& hostData, const std::vector<int64_t>& shape, void** deviceAddr,
aclDataType dataType, aclTensor** tensor) {
auto size = GetShapeSize(shape) * sizeof(T);
// Call aclrtMalloc to allocate memory on the device.
auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret);
// Call aclrtMemcpy to copy the data on the host to the memory on the device.
ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret);
// Compute the strides of the contiguous tensor.
std::vector<int64_t> strides(shape.size(), 1);
for (int64_t i = shape.size() - 2; i >= 0; i--) {
strides[i] = shape[i + 1] * strides[i + 1];
}
// Call aclCreateTensor to create an aclTensor.
*tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND,
shape.data(), shape.size(), *deviceAddr);
return 0;
}
template <typename T>
int CreateAclTensor(const std::vector<int64_t>& shape, void** deviceAddr,
aclDataType dataType, aclTensor** tensor) {
auto size = GetShapeSize(shape) * sizeof(T);
// Call aclrtMalloc to allocate memory on the device.
auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret);
// Call aclrtMemcpy to copy the data on the host to the memory on the device.
std::vector<T> hostData(size, 0);
ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret);
// Compute the strides of the contiguous tensor.
std::vector<int64_t> strides(shape.size(), 1);
for (int64_t i = shape.size() - 2; i >= 0; i--) {
strides[i] = shape[i + 1] * strides[i + 1];
}
// Call aclCreateTensor to create an aclTensor.
*tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND,
shape.data(), shape.size(), *deviceAddr);
return 0;
}
int CreateAclTensorList(const std::vector<std::vector<int64_t>>& shapes, void** deviceAddr,
aclDataType dataType, aclTensorList** tensor) {
int size = shapes.size();
aclTensor* tensors[size];
for (int i = 0; i < size; i++) {
int ret = CreateAclTensor<uint16_t>(shapes[i], deviceAddr + i, dataType, tensors + i);
CHECK_RET(ret == ACL_SUCCESS, return ret);
}
*tensor = aclCreateTensorList(tensors, size);
return ACL_SUCCESS;
}
template <typename T>
int CreateAclTensorNz(const std::vector<T> &hostData, const std::vector<std::vector<int64_t>> &shapes, void **deviceAddr,
aclDataType dataType, aclTensor **tensor)
{
auto size = GetShapeSize(shape) * sizeof(T);
// Call aclrtMalloc to allocate device memory.
auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret);
// Call aclrtMemcpy to copy host data to the device memory.
ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret);
// Compute the strides of the contiguous tensor.
std::vector<int64_t> strides(shape.size(), 1);
for (int64_t i = shape.size() - 2; i >= 0; i--) {
strides[i] = shape[i + 1] * strides[i + 1];
}
int64_t E = shape[0];
int64_t K = shape[1];
int64_t N = shape[2];
std::vector<int64_t> shapeNz = {E, N/64, K/16, 16, 64};
// Call aclCreateTensor to create an aclTensor.
*tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_FRACTAL_NZ,
shapeNz.data(), shapeNz.size(), *deviceAddr);
return 0;
}
template <typename T>
int CreateAclTensorListNz(const std::vector<std::vector> &hostData, const std::vector<std::vector<int64_t>> &shapes, void **deviceAddr,
aclDataType dataType, aclTensorList **tensor)
{
int size = shapes.size();
aclTensor * tensors[size];
for (int i = 0; i < size; i++) {
int ret = CreateAclTensorNz<T>(hostData[i], shapes[i], deviceAddr + i, dataType, tensors + i);
CHECK_RET(ret == ACL_SUCCESS, return ret);
}
*tensor = aclCreateTensorList(tensors, size);
return ACL_SUCCESS;
}
int main() {
// 1. (Boilerplate) Initialize the device and stream. For details, see the ACL API manual.
// Set the device ID in use.
int32_t deviceId = 0;
aclrtStream stream;
auto ret = Init(deviceId, &stream);
// Customize error handling based on your requirements.
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret);
// 2. Construct inputs and outputs based on API definitions.
std::vector<std::vector<int64_t>> xShape = {{512, 256}};
std::vector<std::vector<int64_t>> weightShape= {{2, 256, 256}};
std::vector<std::vector<int64_t>> yShape = {{512, 256}};
std::vector<int64_t> groupListShape = {{2}};
std::vector<int64_t> groupListData = {256, 512};
void* xDeviceAddr[1];
void* weightDeviceAddr[1];
void* yDeviceAddr[1];
void* groupListDeviceAddr;
aclTensorList* x = nullptr;
aclTensorList* weight = nullptr;
aclTensorList* bias = nullptr;
aclTensor* groupedList = nullptr;
aclTensorList* scale = nullptr;
aclTensorList* offset = nullptr;
aclTensorList* antiquantScale = nullptr;
aclTensorList* antiquantOffset = nullptr;
aclTensorList* perTokenScale = nullptr;
aclTensorList* activationInput = nullptr;
aclTensorList* activationQuantScale = nullptr;
aclTensorList* activationQuantOffset = nullptr;
aclTensorList* out = nullptr;
aclTensorList* activationFeatureOut = nullptr;
aclTensorList* dynQuantScaleOut = nullptr;
int64_t splitItem = 3;
int64_t groupType = 0;
int64_t groupListType = 0;
int64_t actType = 0;
std::vector<int8_t> wHostData(GetShapeSize(weightShape));
// Create a tuningconfig aclIntArray.
std::vector<int64_t> tuningConfigData = {512};
aclIntArray *tuningConfig = aclCreateIntArray(tuningConfigData.data(), 1);
// Create an x aclTensorList.
ret = CreateAclTensorList(xShape, xDeviceAddr, aclDataType::ACL_BF16, &x);
CHECK_RET(ret == ACL_SUCCESS, return ret);
// Create a weight aclTensorList.
ret = CreateAclTensorListNz(wHostData, weightShape, weightDeviceAddr, aclDataType::ACL_BF16, &weight);
CHECK_RET(ret == ACL_SUCCESS, return ret);
// Create a y aclTensorList.
ret = CreateAclTensorList(yShape, yDeviceAddr, aclDataType::ACL_BF16, &out);
CHECK_RET(ret == ACL_SUCCESS, return ret);
// Create a group_list aclTensor.
ret = CreateAclTensor_New<int64_t>(groupListData, groupListShape, &groupListDeviceAddr, aclDataType::ACL_INT64, &groupedList);
CHECK_RET(ret == ACL_SUCCESS, return ret);
uint64_t workspaceSize = 0;
aclOpExecutor* executor;
// 3. Call the CANN operator library API.
// Call the first-phase API of aclnnGroupedMatmulWeightNz.
ret = aclnnGroupedMatmulWeightNzGetWorkspaceSize(x, weight, bias, scale, offset, antiquantScale, antiquantOffset, perTokenScale, groupedList, activationInput, activationQuantScale, activationQuantOffset, splitItem, groupType, groupListType, actType, tuningConfig, 0, out, activationFeatureOut, dynQuantScaleOut, &workspaceSize, &executor);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnGroupedMatmulWeightNzGetWorkspaceSize failed. ERROR: %d\n", ret); return ret);
// Allocate device memory based on workspaceSize computed by the first-phase API.
void* workspaceAddr = nullptr;
if (workspaceSize > 0) {
ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret);
}
// Call the second-phase API of aclnnGroupedMatmulWeightNz.
ret = aclnnGroupedMatmulWeightNz(workspaceAddr, workspaceSize, executor, stream);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnGroupedMatmulWeightNz failed. ERROR: %d\n", ret); return ret);
// 4. (Boilerplate) Wait until the task execution is complete.
ret = aclrtSynchronizeStream(stream);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret);
// 5. Obtain the output value and copy the result from the device memory to the host. Modify the code based on the API definition.
for (int i = 0; i < 1; i++) {
auto size = GetShapeSize(yShape[i]);
std::vector<uint16_t> resultData(size, 0);
ret = aclrtMemcpy(resultData.data(), size * sizeof(resultData[0]), yDeviceAddr[i],
size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST);
CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret);
for (int64_t j = 0; j < size; j++) {
LOG_PRINT("result[%ld] is: %d\n", j, resultData[j]);
}
}
// 6. Release aclTensors and aclScalars. Modify the code based on the API definition.
aclDestroyTensorList(x);
aclDestroyTensorList(weight);
aclDestroyTensorList(bias);
aclDestroyTensorList(out);
// 7. Release device resources. Modify the code based on the API definition.
for (int i = 0; i < 1; i++) {
aclrtFree(xDeviceAddr[i]);
aclrtFree(weightDeviceAddr[i]);
aclrtFree(biasDeviceAddr[i]);
aclrtFree(yDeviceAddr[i]);
}
if (workspaceSize > 0) {
aclrtFree(workspaceAddr);
}
aclrtDestroyStream(stream);
aclrtResetDevice(deviceId);
aclFinalize();
return 0;
}