十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CANN ops-nn 量化矩阵乘接口 aclnnQuantMatmul 完全指南:INT8 量化 Matmul 的原理、调用与迁移

CANN ops-nn 量化矩阵乘接口 aclnnQuantMatmul 完全指南:INT8 量化 Matmul 的原理、调用与迁移 CANN ops-nn 量化矩阵乘接口 aclnnQuantMatmul 完全指南INT8 量化 Matmul 的原理、调用与迁移【免费下载链接】ops-nn本项目是CANN提供的神经网络类计算算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-nn本文以 CANN ops-nn 算子库中的aclnnQuantMatmul接口为对象系统讲解其完成 INT8 量化矩阵乘的数学原理、两段式调用范式、全参数约束与错误码、完整可编译的调用示例并结合仓库源码matmul/quant_matmul/op_host/op_api/aclnn_quant_matmul.cpp剖析其内部实现与校验流程同时给出该接口向新版aclnnQuantMatmulV4的迁移路径。读者读完后可以在 Atlas A2/A3 系列产品上独立完成 INT8 量化矩阵乘的算子 API 开发、调试与版本升级。一、接口定位与产品支持情况aclnnQuantMatmul是 CANN ops-nn 算子库cann/ops-nn中面向量化矩阵乘Quantized Matmul场景的 aclnn 单算子 API其功能是完成带 bias 与反量化系数deqScale的 INT8 量化矩阵乘计算最小支持 2 维输入最大支持 3 维输入第一维为 Batch 维度。须知该接口后续版本会废弃请使用最新aclnnQuantMatmulV5接口在当前仓库中官方给出的中间迁移目标是aclnnQuantMatmulV4详见下文“迁移到 aclnnQuantMatmulV4”一节。各产品对aclnnQuantMatmul的支持情况如下产品是否支持Ascend 950PR/Ascend 950DT不支持Atlas A3 训练系列产品 / Atlas A3 推理系列产品支持Atlas A2 训练系列产品 / Atlas A2 推理系列产品支持Atlas 200I/500 A2 推理产品不支持Atlas 推理系列产品不支持Atlas 训练系列产品不支持这与仓库源码中的 SoC 版本检查逻辑一致aclnn_quant_matmul.cpp中的CheckSupportSocVersion()仅对ASCEND910B对应 Atlas A2 训练/推理系列与ASCEND910_93对应 Atlas A3 训练/推理系列返回ACLNN_SUCCESS其余平台返回ACLNN_ERR_RUNTIME_ERROR见 aclnn_quant_matmul.cpp。二、功能说明与计算公式接口功能完成量化的矩阵乘计算最小支持维度为 2 维最大支持输入维度为 3 维。计算公式$$ out (x1x2 bias) * deqScale $$其中表示矩阵乘Matmul运算。从量化视角看该公式对应「INT8 低比特矩阵乘 bias 累加 反量化dequant到 FLOAT16」的完整链路deqScale即反量化系数用于将 INT8 域计算结果还原到浮点域属于典型的静态量化场景量化参数预先确定详见 量化介绍。相似接口aclnnMm仅支持 2 维 Tensor 作为输入的矩阵乘aclnnBatchMatMul仅支持 3 维的矩阵乘其中第一维是 Batch 维度。而aclnnQuantMatmul同时覆盖 2~3 维并额外承担了量化参数的转换与反量化计算。三、两段式接口架构与函数原型每个 aclnn 算子分为两段式接口参见 两段式接口必须先调用aclnnQuantMatmulGetWorkspaceSize获取计算所需 workspace 大小以及包含了算子计算流程的执行器executor再调用aclnnQuantMatmul执行计算。两段接口的函数原型如下aclnnStatus aclnnQuantMatmulGetWorkspaceSize( const aclTensor *x1, const aclTensor *x2, const aclTensor *bias, float deqScale, aclTensor *out, uint64_t *workspaceSize, aclOpExecutor **executor)aclnnStatus aclnnQuantMatmul( void *workspace, uint64_t workspaceSize, aclOpExecutor *executor, const aclrtStream stream)工作机制第一段接口完成入参校验与计算图构建并返回workspaceSize算子在 NPU 上完成计算所需的临时内存大小与executor封装了算子计算流程的执行器调用方按workspaceSize在 Device 侧申请内存后调用第二段接口执行计算第二段接口不能重复调用即GetWorkspaceSize → 执行 → 执行的调用方式是异常的每个 executor 只能执行一次。从源码看第二段接口aclnnQuantMatmul的实现非常简洁直接委托给框架的统一运行入口CommonOpExecutorRun(workspace, workspaceSize, executor, stream)完成计算见 aclnn_quant_matmul.cpp。四、第一段接口 aclnnQuantMatmulGetWorkspaceSize 参数说明第一段接口的参数说明如下表参数名输入/输出描述使用说明数据类型数据格式维度(shape)非连续tensorx1输入公式中的输入 x1维度与 x2 一致不支持 broadcast数据类型需要与 x2 满足互推导关系INT8ND2-3-x2输入公式中的输入 x2维度与 x1 一致不支持 broadcast数据类型需要与 x1 满足互推导关系INT8ND2-3-bias输入公式中的输入 biasshape 支持一维 (n, )n 与 x2 的 n 一致。量化特殊处理过程biasINT32 round(round(biasFLOAT16/deqScale) - offsetX * wINT8)INT32ND1-deqScale输入公式中的输入 deqScale量化参数-float---out输出公式中的输出 out-FLOAT16ND--workspaceSize出参返回需要在 Device 侧申请的 workspace 大小-----executor出参返回 op 执行器包含了算子计算流程-----要点解读x1/x2 为 INT8、bias 为 INT32、out 为 FLOAT16、deqScale 为 float 标量。这是aclnnQuantMatmul与 V2 版本的重要差异V1 的 deqScale 是裸的float数值而 V2 版本将其升级为 UINT64 的 aclTensor见 aclnnQuantMatmulV2.md。从源码看第一段接口会调用TransDequantScaleToM1(deqScale)将 float 型反量化系数转成硬件 FixPipe 需要的 M1 定点表示fixpipeDeqScale再包装成 UINT64 标量 Tensor 参与计算见 aclnn_quant_matmul.cpp。互推导关系x1 与 x2 的数据类型必须满足互推导关系表中可推导的组合当两个输入均为 INT8 时推导结果仍为 INT8因此正常满足约束。bias 的量化特殊处理bias 在送入硬件前会被转换为 INT32 定点表示转换公式为biasINT32 round(round(biasFLOAT16/deqScale) - offsetX * wINT8)其中offsetX为 x1 的量化零点偏移wINT8为 x2 的 INT8 权重。这也是该接口在量化域完成「乘加 bias」的关键一步。五、返回值与错误码两段接口均返回aclnnStatus状态码具体取值参见 aclnn返回码。第一段接口完成入参校验出现以下场景时报错返回值错误码描述ACLNN_ERR_PARAM_NULLPTR161001传入的 x1、x2 或 out 是空指针ACLNN_ERR_PARAM_INVALID161002x1、x2、bias 或 out 的数据类型/数据格式/维度不在支持的范围之内ACLNN_ERR_PARAM_INVALID161002x1 和 x2 的数据类型无法做数据类型推导ACLNN_ERR_PARAM_INVALID161002x1 和 x2 的输入 shape 不满足矩阵乘关系ACLNN_ERR_PARAM_INVALID161002x2 与 bias 的 shape 不一致ACLNN_ERR_PARAM_INVALID161002bias 存在且 m 和 n 均不为 0 但 k 为 0 的空 tensor源码级校验流程印证见 aclnn_quant_matmul.cpp 的CheckParams空指针检查x1、x2、deqScale、out 任一为空即返回空指针类错误数据类型检查CheckDtypeValid校验 x1/x2 必须为DT_INT8、bias 为DT_INT32、deqScale 为DT_UINT64、out 为DT_FLOAT16数据格式检查CheckFormatVaild要求所有输入输出为FORMAT_NDFORMAT_FRACTAL_NZ会被拒绝维度检查x1/x2 维度必须在 [2, 3] 区间bias 必须为 1 维Shape 关系检查x1 与 x2 的维度数必须一致、Batch 维必须一致、K 维reduce 轴必须相等、bias 的第一维必须等于 x2 的 n、输出 shape 必须与推导结果完全匹配含 Batch 广播语义SoC 版本检查仅支持 Atlas A2/A3 系列产品。仓库测试用例 test_aclnn_quant_matmul.cpp 对这些异常路径做了全覆盖验证例如 4 维 x1、1 维 x2、2 维 bias、deqScale 长度非 16 对齐、FRACTAL_NZ 格式、batch 不一致、K 不一致、输出 shape 与推导不一致等场景均断言返回ACLNN_ERR_PARAM_INVALID。六、第二段接口 aclnnQuantMatmul 参数说明参数名输入/输出描述workspace输入在 Device 侧申请的 workspace 内存地址workspaceSize输入在 Device 侧申请的 workspace 大小由第一段接口 aclnnQuantMatmulGetWorkspaceSize 获取executor输入op 执行器包含了算子计算流程stream输入指定执行任务的 Stream返回值为aclnnStatus具体参见 aclnn返回码。七、约束说明与确定性确定性说明Atlas A3 训练系列产品/Atlas A3 推理系列产品、Atlas A2 训练系列产品/Atlas A2 推理系列产品上aclnnQuantMatmul为默认确定性实现即相同输入多次运行结果可复现相关背景可参考 确定性计算。空 tensor 处理当 x1 或 x2 为空 tensor 时接口走空 tensor 快速路径——若 bias 存在且 kreduce 轴为 0则直接报错否则用Fill算子生成全 0 输出此时第一段接口返回的workspaceSize为 0见 aclnn_quant_matmul.cpp。测试用例ascend910B2_test_empty即覆盖了x1{16,0}、x2{0,16}的空 tensor 场景。非连续 tensor接口内部通过TensorContiguousProcess对 x1、x2、bias 做连续化处理见 aclnn_quant_matmul.cpp。测试用例ascend910B2_test_non_contiguous_x1、ascend910B2_test_non_contiguous_bias分别验证了转置步长{1, 16}的 x1 与步长为 2 的切片 bias 均可正常返回ACLNN_SUCCESS非连续 tensor 相关概念可参考 非连续tensor。八、该接口迁移到 aclnnQuantMatmulV4 的方法由于aclnnQuantMatmul即将废弃官方在当前仓库中给出了迁移到aclnnQuantMatmulV4的明确步骤V4 接口文档见 aclnnQuantMatmulV4.md输入 x1、x2、bias 可以直接转为aclnnQuantMatmulV4接口中的 x1、x2、bias。输入 deqScale 为 FLOAT 型将该 FLOAT 数构造成 shape 为1的 FLOAT 型 aclTensor参考下文调用示例中的CreateAclTensor再利用aclnnTransQuantParamV2转为 shape 为1的 uint64_t 的 aclTensor参考 aclnnQuantMatmulV4 调用示例 中关于aclnnTransQuantParamV2的使用方式记为scale对标 V4 接口中的 scale 参数。aclnnQuantMatmulV4接口中的可选输入offset/pertokenScaleOptional设置为nullptrtransposeX1和transposeX2均设置为false。最终调用形式为aclnnQuantMatmulV4GetWorkspaceSize(x1, x2, scale, nullptr, nullptr, bias, false, false, out, workspaceSize, executor)与 V2 版本迁移的差异aclnnQuantMatmulV2的 deqScale 本身就是 UINT64 的 aclTensor迁移到 V4 时仅需注意 V2 的 deqScale shape 为(t, )且t align(n, 16)而 V4 的 scale shape 为(t, )且t 1或n因此直接使用原始 FLOAT 型量化参数经aclnnTransQuantParam转换即可详见 aclnnQuantMatmulV2.md 的迁移章节。九、调用示例完整可编译代码示例代码如下仅供参考具体编译和执行过程请参考编译与运行样例。仓库中的完整样例文件还有 test_aclnn_quant_matmul_v2.cpp。#include iostream #include vector #include memory #include acl/acl.h #include aclnnop/aclnn_quant_matmul.h #define CHECK_RET(cond, return_expr) \ do { \ if (!(cond)) { \ return_expr; \ } \ } while (0) #define CHECK_FREE_RET(cond, return_expr) \ do { \ if (!(cond)) { \ Finalize(deviceId, stream);\ return_expr; \ } \ } while (0) #define LOG_PRINT(message, ...) \ do { \ printf(message, ##__VA_ARGS__); \ } while (0) int64_t GetShapeSize(const std::vectorint64_t shape) { int64_t shapeSize 1; for (auto i : shape) { shapeSize * i; } return shapeSize; } int Init(int32_t deviceId, aclrtStream* stream) { // 固定写法资源初始化 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(const std::vectorT hostData, const std::vectorint64_t shape, void** deviceAddr, aclDataType dataType, aclTensor** tensor) { auto size GetShapeSize(shape) * sizeof(T); // 调用aclrtMalloc申请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); // 调用aclrtMemcpy将host侧数据拷贝到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); // 计算连续tensor的strides std::vectorint64_t strides(shape.size(), 1); for (int64_t i shape.size() - 2; i 0; i--) { strides[i] shape[i 1] * strides[i 1]; } // 调用aclCreateTensor接口创建aclTensor *tensor aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), *deviceAddr); return 0; } void Finalize(int32_t deviceId, aclrtStream stream) { aclrtDestroyStream(stream); aclrtResetDevice(deviceId); aclFinalize(); } int aclnnQuantMatmulTest(int32_t deviceId, aclrtStream stream) { auto ret Init(deviceId, stream); CHECK_FREE_RET(ret ACL_SUCCESS, LOG_PRINT(Init acl failed. ERROR: %d\n, ret); return ret); // 2. 构造输入与输出需要根据API的接口自定义构造 std::vectorint64_t x1Shape {2, 2}; std::vectorint64_t x2Shape {2, 2}; std::vectorint64_t biasShape {2}; std::vectorint64_t outShape {2, 2}; void* x1DeviceAddr nullptr; void* x2DeviceAddr nullptr; void* biasDeviceAddr nullptr; void* outDeviceAddr nullptr; aclTensor* x1 nullptr; aclTensor* x2 nullptr; aclTensor* bias nullptr; aclTensor* out nullptr; std::vectorint8_t x1HostData{1, 1, 1, 1}; std::vectorint8_t x2HostData{1, 1, 1, 1}; std::vectorint32_t biasHostData{1, 1}; std::vectoruint16_t outHostData{1, 1, 1, 1}; // 实际上是float16半精度方式 // 创建x1 aclTensor ret CreateAclTensor(x1HostData, x1Shape, x1DeviceAddr, aclDataType::ACL_INT8, x1); std::unique_ptraclTensor, aclnnStatus (*)(const aclTensor *) x1TensorPtr(x1, aclDestroyTensor); std::unique_ptrvoid, aclError (*)(void *) x1DeviceAddrPtr(x1DeviceAddr, aclrtFree); CHECK_FREE_RET(ret ACL_SUCCESS, return ret); // 创建x2 aclTensor ret CreateAclTensor(x2HostData, x2Shape, x2DeviceAddr, aclDataType::ACL_INT8, x2); std::unique_ptraclTensor, aclnnStatus (*)(const aclTensor *) x2TensorPtr(x2, aclDestroyTensor); std::unique_ptrvoid, aclError (*)(void *) x2DeviceAddrPtr(x2DeviceAddr, aclrtFree); CHECK_FREE_RET(ret ACL_SUCCESS, return ret); // 创建bias aclTensor ret CreateAclTensor(biasHostData, biasShape, biasDeviceAddr, aclDataType::ACL_INT32, bias); std::unique_ptraclTensor, aclnnStatus (*)(const aclTensor *) biasTensorPtr(bias, aclDestroyTensor); std::unique_ptrvoid, aclError (*)(void *) biasDeviceAddrPtr(biasDeviceAddr, aclrtFree); CHECK_FREE_RET(ret ACL_SUCCESS, return ret); // 创建out aclTensor ret CreateAclTensor(outHostData, outShape, outDeviceAddr, aclDataType::ACL_FLOAT16, out); std::unique_ptraclTensor, aclnnStatus (*)(const aclTensor *) outTensorPtr(out, aclDestroyTensor); std::unique_ptrvoid, aclError (*)(void *) outDeviceAddrPtr(outDeviceAddr, aclrtFree); CHECK_FREE_RET(ret ACL_SUCCESS, return ret); float deqScale 1.0f; // 3. 调用CANN算子库API需要修改为具体的API名称 uint64_t workspaceSize 0; aclOpExecutor* executor; // 调用aclnnQuantMatmul第一段接口 ret aclnnQuantMatmulGetWorkspaceSize(x1, x2, bias, deqScale, out, workspaceSize, executor); CHECK_FREE_RET(ret ACL_SUCCESS, LOG_PRINT(aclnnQuantMatmulGetWorkspaceSize failed. ERROR: %d\n, ret); return ret); // 根据第一段接口计算出的workspaceSize申请device内存 void* workspaceAddr nullptr; std::unique_ptrvoid, aclError (*)(void *) workspaceAddrPtr(nullptr, aclrtFree); if (workspaceSize 0) { ret aclrtMalloc(workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); CHECK_FREE_RET(ret ACL_SUCCESS, LOG_PRINT(allocate workspace failed. ERROR: %d\n, ret); return ret); workspaceAddrPtr.reset(workspaceAddr); } // 调用aclnnQuantMatmul第二段接口 ret aclnnQuantMatmul(workspaceAddr, workspaceSize, executor, stream); CHECK_FREE_RET(ret ACL_SUCCESS, LOG_PRINT(aclnnQuantMatmul failed. ERROR: %d\n, ret); return ret); // 4.固定写法同步等待任务执行结束 ret aclrtSynchronizeStream(stream); CHECK_FREE_RET(ret ACL_SUCCESS, LOG_PRINT(aclrtSynchronizeStream failed. ERROR: %d\n, ret); return ret); // 5. 获取输出的值将device侧内存上的结果拷贝至host侧需要根据具体API的接口定义修改 auto size GetShapeSize(outShape); std::vectorfloat resultData(size, 0); ret aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); CHECK_FREE_RET(ret ACL_SUCCESS, LOG_PRINT(copy result from device to host failed. ERROR: %d\n, ret); return ret); for (int64_t i 0; i size; i) { LOG_PRINT(result[%ld] is: %f\n, i, resultData[i]); } return ACL_SUCCESS; } int main() { // 1.固定写法device/stream初始化参考acl API手册 // 根据自己的实际device填写deviceId int32_t deviceId 0; aclrtStream stream; auto ret aclnnQuantMatmulTest(deviceId, stream); CHECK_FREE_RET(ret ACL_SUCCESS, LOG_PRINT(aclnnQuantMatmulTest failed. ERROR: %d\n, ret); return ret); Finalize(deviceId, stream); return 0; }示例要点CreateAclTensor模板函数封装了「申请 Device 内存 → Host 到 Device 拷贝 → 按连续 strides 创建 ND 格式 aclTensor」的标准流程可直接复用于 V2/V4 等其他接口的输入构造由于out是 FLOAT16Host 侧用uint16_t缓冲区承载实际取值需按 IEEE 754 半精度规则解析通过std::unique_ptr管理 aclTensor 与 Device 内存的 RAII 释放保证异常路径不泄漏若workspaceSize 0例如空 tensor 场景无需申请 workspace直接以nullptr调用第二段接口。十、编译与运行按照 编译与运行样例 的通用流程环境准备确保驱动、固件、CANN 软件包、ops 包等基础环境已搭建完成开发和运行环境合设场景并确保运行环境为支持列表内的 Atlas A2/A3 系列产品。准备文件将上述示例代码保存为test_aclnn_quant_matmul.cpp并准备 CMakeLists.txt仓库样例中编译配置可参考 compile_and_run_sample.md 中给出的模板链接libascendcl.so、libnnopbase.so、libopapi_math.so、libopapi_nn.so。配置环境变量source ${INSTALL_DIR}/set_env.sh其中${INSTALL_DIR}为 CANN 软件安装后的文件存储路径。编译并运行mkdir -p build cd build cmake ../ -DCMAKE_CXX_COMPILERg -DCMAKE_SKIP_RPATHTRUE make cd bin ./opapi_test异常排查若执行报错可使用aclGetRecentErrMsg接口获取具体错误信息例如入参为空指针时会输出形如aclnnQuantMatmulGetWorkspaceSize failed. ERROR: 161001的错误码与参数错误详情。十一、内部实现剖析从 API 到 NPU 计算图结合 aclnn_quant_matmul.cpp 与 quantBatchmatmul.cppaclnnQuantMatmul第一段接口的完整执行链路如下创建执行器调用CREATE_EXECUTOR()创建OpExecutor实例deqScale 定点化TransDequantScaleToM1(deqScale)将 float 型反量化系数转换为 FixPipe 的 M1 定点格式并包装为 shape{1,1,1,1}、view 格式FORMAT_NHWC、存储格式FORMAT_NC1HWC0的 UINT64 aclTensor入参校验CheckParams依次完成空指针、数据类型、数据格式仅 ND、维度x1/x2 为 2~3 维、bias 为 1 维、shape 关系Batch 一致、K 一致、bias 的 n 一致、输出推导一致以及 SoC 版本检查连续化处理TensorContiguousProcess将非连续输入统一为连续布局因此 V1 接口对外不承诺支持非连续 tensor参数表中标注为-构建计算图BuildQuantMatMulGraph调用 level0 算子l0op::QuantBatchMatmul见 quantBatchmatmul.cpp该算子通过INFER_SHAPE推导输出 shape、通过ADD_TO_LAUNCHER_LIST_AICORE挂载 AI Core 侧 kernel 启动器随后对结果执行Reshape对齐到用户输出 shape最后ViewCopy写回 out返回 workspaceexecutor-GetWorkspaceSize()汇总图中所有算子所需的临时内存大小ReleaseTo(executor)将执行器所有权移交调用方。这一链路也解释了为什么第一段接口会返回「包含算子计算流程的执行器」——它本质上是一张由 level0 算子QuantBatchMatmul、Reshape、ViewCopy、必要时 Fill构成的计算图第二段接口只是把这张图提交到指定 stream 上执行。十二、测试用例对行为边界的验证仓库单测 test_aclnn_quant_matmul.cpp 系统性地覆盖了该接口的行为边界可作为开发时的「约束清单」参考测试用例输入构造期望行为ascend910B2_test_normal_inputx1{16,32}、x2{32,16}、bias{16}、deqScale1.0GetWorkspaceSize 正常返回ascend910B2_test_emptyx1{16,0}、x2{0,16}空 tensor 路径正常处理ascend910B2_test_abnormal_input_x1x1 为 4 维ACLNN_ERR_PARAM_INVALIDascend910B2_test_abnormal_input_x2x2 为 1 维ACLNN_ERR_PARAM_INVALIDascend910B2_test_abnormal_input_biasbias 为 2 维ACLNN_ERR_PARAM_INVALIDascend910B2_test_abnormal_input_deqScaleV2 的 deqScale 长度 15非 16 对齐ACLNN_ERR_PARAM_INVALIDascend910B2_test_abnormal_input_formatFRACTAL_NZ 格式格式不支持ascend910B2_test_abnormal_input_sameDimx1 2 维、x2 3 维维度不一致报错ascend910B2_test_abnormal_input_sameKx1 的 k32、x2 的 k31K 不一致报错ascend910B2_test_abnormal_outMDim_x1MDimout 的 m 与 x1 的 m 不一致ACLNN_ERR_PARAM_INVALIDascend910B2_test_non_contiguous_x1转置步长 {1,16} 的 x1ACLNN_SUCCESS这些用例同时印证了本文第五节错误码表中各「ACLNN_ERR_PARAM_INVALID」子场景的真实触发条件开发者可将其作为自测用例的模板。十三、总结aclnnQuantMatmul是 CANN ops-nn 中面向 Atlas A2/A3 系列产品的 INT8 量化矩阵乘接口通过out (x1x2 bias) * deqScale一次完成低比特矩阵乘、bias 累加与反量化。其两段式调用范式GetWorkspaceSize 执行、严格的 ND 格式/数据类型/shape 关系约束、确定性实现保证以及完善的错误码体系使其易于集成与调试。由于该接口即将废弃新开发建议直接使用aclnnQuantMatmulV5存量代码可按照本文第八节给出的步骤平滑迁移到aclnnQuantMatmulV4将 float deqScale 经aclnnTransQuantParamV2转为 UINT64 scale tensor 即可。【免费下载链接】ops-nn本项目是CANN提供的神经网络类计算算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-nn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表