ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

CANN opbase 算子库 aclnn Common API 全览:张量/标量/数组元对象管理与 aclOpExecutor 复用实战

CANN opbase 算子库 aclnn Common API 全览:张量/标量/数组元对象管理与 aclOpExecutor 复用实战 CANN opbase 算子库 aclnn Common API 全览张量/标量/数组元对象管理与 aclOpExecutor 复用实战【免费下载链接】opbase本项目是CANN算子库的基础框架库为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase本篇技术指南围绕 CANN opbase 算子库中 aclnn 单算子 API 执行框架的 Common API通用元 API展开系统梳理从参数对象aclTensor、aclScalar、aclIntArray 等的创建、查询、销毁到 aclnn 资源初始化/去初始化再到 aclOpExecutor 复用与动态地址更新的完整 API 家族。读完本文你将掌握编写 aclnn 单算子调用程序所需的全部元对象操作能力并能基于 aclOpExecutor 复用机制写出高效、低开销的算子执行代码。一、Common API List 概述docs/en/api/nnopbase/aclnn/common_api_list.md是 aclnn 单算子 API 执行框架中通用元 API 的完整清单。所谓通用元 API是指调用 CANN 算子 API 之前必须准备的基础设施类接口例如创建与销毁aclTensor、aclScalar、aclIntArray等框架定义的数据结构。这些 API 不直接完成算子计算而是为算子执行提供参数载体是所有 aclnnXxx 单算子调用的公共前置。完整清单如下每个 API 的详细说明见其对应文档页Common APIs通用 API 总览表创建类aclCreateBoolArray、aclCreateFloatArray、aclCreateIntArray、aclCreateScalar、aclCreateScalarList、aclCreateTensor、aclCreateTensorList销毁类aclDestroyAclOpExecutor、aclDestroyBoolArray、aclDestroyFloatArray、aclDestroyIntArray、aclDestroyScalar、aclDestroyScalarList、aclDestroyTensor、aclDestroyTensorList查询类aclGetBoolArraySize、aclGetDataType、aclGetFloatArraySize、aclGetFormat、aclGetIntArraySize、aclGetRawTensorAddr、aclGetScalarListSize、aclGetStorageShape、aclGetTensorListSize、aclGetViewOffset、aclGetViewShape、aclGetViewStrides初始化/复用/地址更新类aclInitTensor、aclSetAclOpExecutorRepeatable、aclSetDynamicInputTensorAddr、aclSetDynamicOutputTensorAddr、aclSetDynamicTensorAddr、aclSetInputTensorAddr、aclSetOutputTensorAddr、aclSetRawTensorAddr、aclSetTensorAddr生命周期类aclnnInit、aclnnFinalize其他Reserved APIs、Common API Return Codes二、头文件与安装环境调用本文所述 API 时需要根据实际站点site需求包含依赖头文件。头文件存放在$\{INSTALL_DIR\}/include目录其中$\{INSTALL_DIR\}为 CANN 软件安装路径。例如以root用户安装Ascend-cann-toolkit软件包后文件存储路径为/usr/local/Ascend/cann。在 opbase 仓库中这些头文件的源码位于 include/nnopbase/aclnn 目录其中acl_meta.h声明全部参数对象类 API包括创建、查询、销毁、地址更新系列如aclCreateTensor、aclGetRawTensorAddr等aclnn_base.h声明aclnnInit与aclnnFinalize两个生命周期函数。从源码可以看到API 均带ACL_FUNC_VISIBILITY导出属性例如 aclnn_base.h 中的ACL_FUNC_VISIBILITY aclnnStatus aclnnInit(const char* configPath);保证函数从动态库中正确导出供上层框架链接调用。三、API 全景总览下表汇总了 Common APIs 文档common_apis.md中全部通用 API 的功能与头文件归属API功能描述头文件aclCreateBoolArray创建 aclBoolArrayaclnn/acl_meta.haclCreateFloatArray创建 aclFloatArrayaclnn/acl_meta.haclCreateIntArray创建 aclIntArrayaclnn/acl_meta.haclCreateScalar创建 aclScalaraclnn/acl_meta.haclCreateScalarList创建 aclScalarListaclnn/acl_meta.haclCreateTensor创建 aclTensoraclnn/acl_meta.haclCreateTensorList创建 aclTensorListaclnn/acl_meta.haclDestroyAclOpExecutor销毁可复用的 aclOpExecutoraclnn/acl_meta.haclDestroyBoolArray销毁已创建的 aclBoolArrayaclnn/acl_meta.haclDestroyFloatArray销毁已创建的 aclFloatArrayaclnn/acl_meta.haclDestroyIntArray销毁已创建的 aclIntArrayaclnn/acl_meta.haclDestroyScalar销毁已创建的 aclScalaraclnn/acl_meta.haclDestroyScalarList销毁已创建的 aclScalarList其中标量无需再单独销毁aclnn/acl_meta.haclDestroyTensor销毁已创建的 aclTensoraclnn/acl_meta.haclDestroyTensorList销毁已创建的 aclTensorList其中张量无需再单独销毁aclnn/acl_meta.haclGetBoolArraySize获取 aclBoolArray 大小aclnn/acl_meta.haclGetDataType获取 aclTensor 数据类型aclnn/acl_meta.haclGetFloatArraySize获取 aclFloatArray 大小aclnn/acl_meta.haclGetFormat获取 aclTensor 数据格式aclnn/acl_meta.haclGetIntArraySize获取 aclIntArray 大小aclnn/acl_meta.haclGetRawTensorAddr获取 aclTensor 中记录的设备内存地址aclnn/acl_meta.haclGetScalarListSize获取 aclScalarList 大小aclnn/acl_meta.haclGetStorageShape获取 aclTensor 的 StorageShapeaclnn/acl_meta.haclGetTensorListSize获取 aclTensorList 大小aclnn/acl_meta.haclGetViewOffset获取 aclTensor 的 ViewOffset即 ViewShape 对应的偏移aclnn/acl_meta.haclGetViewShape获取 aclTensor 的 ViewShapeaclnn/acl_meta.haclGetViewStrides获取 aclTensor 的 ViewStrides即 ViewShape 对应的 strideaclnn/acl_meta.haclInitTensor初始化指定张量的参数aclnn/acl_meta.haclSetAclOpExecutorRepeatable使 aclOpExecutor 可复用aclnn/acl_meta.haclSetDynamicInputTensorAddr启用复用后输入设备内存地址变化时更新输入 aclTensorList 中记录的地址aclnn/acl_meta.haclSetDynamicOutputTensorAddr启用复用后输出设备内存地址变化时更新输出 aclTensorList 中记录的地址aclnn/acl_meta.haclSetDynamicTensorAddr启用复用后输入或输出设备内存地址变化时更新对应 aclTensorList 中记录的地址aclnn/acl_meta.haclSetInputTensorAddr启用复用后输入设备内存地址变化时更新输入 aclTensor 中记录的地址aclnn/acl_meta.haclSetOutputTensorAddr启用复用后输出设备内存地址变化时更新输出 aclTensor 中记录的地址aclnn/acl_meta.haclSetRawTensorAddr更新 aclTensor 中原始记录的设备内存地址aclnn/acl_meta.haclSetTensorAddr启用复用后输入或输出设备内存地址变化时更新对应 aclTensor 中记录的地址aclnn/acl_meta.haclnnInitaclnn API 初始化函数aclnn/aclnn_base.haclnnFinalizeaclnn API 去初始化函数aclnn/aclnn_base.h四、aclnn 资源生命周期aclnnInit 与 aclnnFinalize在调用任何aclnnXxx单算子 API 之前必须先初始化 aclnn 资源如读取环境变量、解析配置文件、加载资源库否则会出现内部系统错误影响业务运行。4.1 aclnnInit轻量级初始化aclnnStatus aclnnInit(const char *configPath)参数configPath为 aclnn 初始化配置文件路径含文件名可通过该配置开启 aclnn API 的调试能力默认值为NULL。配置文件必须为 JSON 格式例如值为/home/acl.json时配置示例{ op_debug_config:{ enable_debug_kernel:on } }enable_debug_kernel取值说明on开启 aclnn API 调试能力。算子执行过程中系统会检查全局内存是否溢出、内部流水线是否同步off关闭调试能力为默认值。重要说明aclnnInit与aclInit均可用于初始化资源区别在于aclnnInit只初始化 aclnn 相关资源aclInit会同时初始化 aclnn 及 acl API 中其他资源因此aclnnInit更轻量。若两者都被调用不会返回失败信息。4.2 aclnnFinalize轻量级去初始化aclnnStatus aclnnFinalize()进程退出前必须释放进程内 aclnn 相关资源否则会导致内部系统错误。aclnnFinalize与aclFinalize的关系与初始化侧对称aclnnFinalize仅释放 aclnn 相关资源更轻量两者同时调用不会报错。约束aclnnInit与aclnnFinalize必须配对使用且各自在一个进程中只能调用一次。4.3 典型生命周期代码// 初始化资源。 auto ret aclnnInit(/home/acl.json); ... // 创建算子 API 参数对象。 ret aclCreate***(...); ... // 调用两阶段算子 API。 ret aclnnXxxGetWorkspaceSize(...); ret aclnnXxx(...); ... // 销毁算子 API 参数对象。 ret aclDestroy***(); ... // 去初始化资源。 ret aclnnFinalize();以上代码仅为参考示例不保证可直接复制运行。五、参数对象创建从 aclTensor 到各类数组5.1 核心概念ViewShape 与 StorageShape理解aclTensor的关键是区分两个形状概念详见 aclCreateTensorViewShape张量的逻辑形状即实际使用时所需的张量大小StorageShape张量的实际物理布局形状即张量在内存中的实际大小。例如若 StorageShape 为[10, 20]则张量按[10, 20]在内存中排布若 ViewShape 为[2, 5, 20]则算子使用时可将该张量视为一个[2, 5, 20]的数据块。下图展示了张量的逻辑结构aclTensor 由连续或非连续的内存地址加一系列描述信息stride、offset 等组成基于 shape、stride 与 offset 信息张量可以从内存中取数或得到非连续内存如下图中 y 所示。aclTensor 逻辑结构图5.2 aclCreateTensor创建张量元对象aclTensor *aclCreateTensor(const int64_t *viewDims, uint64_t viewDimsNum, aclDataType dataType, const int64_t *stride, int64_t offset, aclFormat format, const int64_t *storageDims, uint64_t storageDimsNum, void *tensorData)参数说明参数输入/输出说明viewDims输入张量 ViewShape 维度值非负整数viewDimsNum输入张量 ViewShape 维度数dataType输入张量数据类型stride输入张量各维元素访问步长非负整数offset输入张量首元素相对 storage 的偏移非负整数format输入张量格式storageDims输入张量 StorageShape 维度值非负整数storageDimsNum输入张量 StorageShape 维度数tensorData输入张量在设备上的存储地址必须 32 字节对齐否则可能发生未定义错误成功返回创建的 aclTensor失败返回nullptr。以图中的 x 张量为例创建普通张量aclTensor *CreateXTensor() { std::vectorint64_t viewDims {2, 4}; std::vectorint64_t stride {4, 1}; // 第一维 stride 为 4第二维为 1 std::vectorint64_t storageDims {2, 4}; return aclCreateTensor(viewDims.data(), 2, ACL_FLOAT16, stride.data(), 0, ACL_FORMAT_ND, storageDims.data(), 2, nullptr); }创建 x 的转置张量 x^T通过交换 stride 实现aclTensor *CreateXTransposedTensor() { std::vectorint64_t viewDims {4, 2}; std::vectorint64_t stride {1, 4}; // 转置 stride std::vectorint64_t storageDims {2, 4}; return aclCreateTensor(viewDims.data(), 2, ACL_FLOAT16, stride.data(), 0, ACL_FORMAT_ND, storageDims.data(), 2, nullptr); }完整调用与销毁流程// 创建 aclTensor。 aclTensor *xTensor CreateXTensor(); aclTensor *xTransposedTensor CreateXTransposedTensor(); // 将 aclTensor 作为单算子 API 执行的输入参数。 auto ret aclxxXxxGetWorkspaceSize(xTensor, xTransposedTensor, ..., outTensor, ..., workspaceSize, executor); ret aclxxXxx(...); ... // 销毁 aclTensor。 ret aclDestroyTensor(xTensor); ret aclDestroyTensor(xTransposedTensor);从源码看aclCreateTensor在 acl_op_api.cpp 中实现内部创建张量对象失败时会记录OP_LOGE(ACLNN_ERR_INNER, aclCreateTensor error.)并返回空指针这解释了失败返回 nullptr的行为。5.3 aclInitTensor重置已有张量的参数若想复用已有 aclTensor可调用aclInitTensor重置其属性aclnnStatus aclInitTensor(aclTensor *tensor, const int64_t *viewDims, uint64_t viewDimsNum, aclDataType dataType, const int64_t *stride, int64_t offset, aclFormat format, const int64_t *storageDims, uint64_t storageDimsNum, void *tensorDataAddr)其参数语义与aclCreateTensor完全一致区别在于目标对象是已创建的tensor各维度值、stride、offset 均为非负整数tensorDataAddr同样要求 32 字节对齐。5.4 标量与数组对象创建aclCreateScalar创建标量对象用于算子中的alpha、beta等标量参数。aclScalar *aclCreateScalar(void *value, aclDataType dataType) // 示例 float alphaValue 1.2f; aclScalar* alpha aclCreateScalar(alphaValue, aclDataType::ACL_FLOAT); ... ret aclDestroyScalar(alpha);aclCreateIntArray创建整数数组对象常用于size、shape等整型属性参数。aclIntArray *aclCreateIntArray(const int64_t *value, uint64_t size) // 示例value 为主机端 int64_t 指针其值会被拷贝进 aclIntArray std::vectorint64_t sizeData {1, 1, 2, 3}; aclIntArray *size aclCreateIntArray(sizeData.data(), sizeData.size());aclCreateFloatArray创建浮点数组对象常用于scales等浮点属性参数。aclFloatArray *aclCreateFloatArray(const float *value, uint64_t size) // 示例 std::vectorfloat scalesData {1.0, 1.0, 2.0, 2.0}; aclFloatArray *scales aclCreateFloatArray(scalesData.data(), scalesData.size());aclCreateBoolArray创建布尔数组对象常用于mask等布尔属性参数。aclBoolArray *aclCreateBoolArray(const bool *value, uint64_t size) // 示例 std::vectorbool maskData {true, false}; aclBoolArray *mask aclCreateBoolArray(maskData.data(), maskData.size());三种数组的size参数均表示数组长度要求为正整数主机端数据会被拷贝到框架对象中因此调用后原主机缓冲区可安全复用。5.5 列表对象创建aclTensorList 与 aclScalarList当算子需要接收多个张量或标量时使用列表对象承载。aclCreateTensorListaclTensorList *aclCreateTensorList(const aclTensor *const *value, uint64_t size) // 示例创建 input1、input2 两个张量后打包为列表 std::vectorint64_t shape {1, 2, 3}; aclTensor *input1 aclCreateTensor(shape.data(), shape.size(), aclDataType::ACL_FLOAT, nullptr, 0, aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), nullptr); aclTensor *input2 aclCreateTensor(shape.data(), shape.size(), aclDataType::ACL_FLOAT, nullptr, 0, aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), nullptr); std::vectoraclTensor * tmp{input1, input2}; aclTensorList* tensorList aclCreateTensorList(tmp.data(), tmp.size()); ... ret aclDestroyTensorList(tensorList);aclCreateScalarListaclScalarList *aclCreateScalarList(const aclScalar *const *value, uint64_t size) // 示例 float alpha1Value 1.2f; aclScalar *alpha1 aclCreateScalar(alpha1Value, aclDataType::ACL_FLOAT); float alpha2Value 2.2f; aclScalar *alpha2 aclCreateScalar(alpha2Value, aclDataType::ACL_FLOAT); std::vectoraclScalar * tempscalar{alpha1, alpha2}; aclScalarList *scalarlist aclCreateScalarList(tempscalar.data(), tempscalar.size()); ... ret aclDestroyScalarList(scalarlist);六、属性查询反向获取张量元信息查询类 API 用于从已创建的元对象中取回其描述信息是先查属性、再按属性创建新张量等复用场景的核心工具。它们的原型与要点如下API原型输出要点aclGetDataTypeaclnnStatus aclGetDataType(const aclTensor *tensor, aclDataType *dataType)张量数据类型tensor/dataType为空指针时返回 161001aclGetFormataclnnStatus aclGetFormat(const aclTensor *tensor, aclFormat *format)张量数据格式空指针返回 161001aclGetStorageShapeaclnnStatus aclGetStorageShape(const aclTensor *tensor, int64_t **storageDims, uint64_t *storageDimsNum)StorageShape 维度值与维数storageDims内存由 API 内部分配使用后需手动释放aclGetViewShapeaclnnStatus aclGetViewShape(const aclTensor *tensor, int64_t **viewDims, uint64_t *viewDimsNum)ViewShape 维度值与维数viewDims内存由 API 内部分配使用后需手动释放aclGetViewStridesaclnnStatus aclGetViewStrides(const aclTensor *tensor, int64_t **stridesValue, uint64_t *stridesNum)ViewShape 对应 stride 值stridesValue内存由 API 内部分配使用后需手动释放aclGetViewOffsetaclnnStatus aclGetViewOffset(const aclTensor *tensor, int64_t *offset)ViewShape 对应偏移无内存释放要求aclGetRawTensorAddraclnnStatus aclGetRawTensorAddr(const aclTensor *tensor, void **addr)aclTensor 中记录的设备内存地址返回的指针指向的地址与创建时传入的地址一致此外还有四个取大小 API签名模式统一为aclnnStatus aclGetXxxSize(const aclXxx *obj, uint64_t *size)分别获取 aclGetIntArraySize、aclGetFloatArraySize、aclGetBoolArraySize、aclGetScalarListSize、aclGetTensorListSize 对应对象的元素个数对象或输出指针为空时均返回 161001。一个典型的读取属性并重建张量场景文档示例// 假设已有 aclTensor 对象 xTensor读取其数据类型、格式、维度、stride、offset 等属性 // 并基于这些属性创建新对象 yTensor。 aclDataType dataType; aclFormat format; int64_t *viewDims nullptr, *storageDims nullptr, *strides nullptr; uint64_t viewDimsNum 0, storageDimsNum 0, stridesNum 0; int64_t offset 0; aclGetDataType(xTensor, dataType); aclGetFormat(xTensor, format); aclGetViewShape(xTensor, viewDims, viewDimsNum); aclGetStorageShape(xTensor, storageDims, storageDimsNum); aclGetViewStrides(xTensor, strides, stridesNum); aclGetViewOffset(xTensor, offset); // 使用获得的属性创建 yTensor ... // 注意viewDims、storageDims、strides 使用后需手动释放七、销毁语义成对使用与列表所有权所有创建类 API 都必须与对应的销毁 API 成对使用否则会造成资源泄漏。销毁类 API 统一签名为aclnnStatus aclDestroyXxx(Xxx *obj)成功返回 0失败返回非 0详见 Common API Return Codes。需要特别注意的是列表销毁的所有权语义aclDestroyTensorList销毁 aclTensorList 时列表中包含的张量不需要再单独销毁列表销毁会一并处理其中张量aclDestroyScalarList销毁 aclScalarList 时列表中的标量不需要再单独销毁。八、aclOpExecutor 复用机制性能优化的核心手段8.1 两阶段 API 与 executor 的默认生命周期aclnn 单算子 API 采用两阶段调用模型第一阶段aclnnXxxGetWorkspaceSize(...)完成 shape 推导、tiling 计算等准备工作输出workspaceSize与aclOpExecutor *executor第二阶段aclnnXxx(workspace, workspaceSize, executor, stream)真正下发算子执行。aclOpExecutor是框架定义的算子执行器是执行算子计算的容器。对于未启用复用的 executor框架会在第一阶段自动创建、第二阶段自动销毁用户无需手动管理。但这也意味着每轮算子调用都会伴随 executor 的创建与销毁开销。8.2 aclSetAclOpExecutorRepeatable开启复用若希望复用已有的 aclOpExecutor必须在第一阶段 API 执行后立即调用aclSetAclOpExecutorRepeatable开启复用之后可以多次调用第二阶段 API 执行算子aclnnStatus aclSetAclOpExecutorRepeatable(aclOpExecutor *executor)开启复用后executor 资源在第二阶段执行完毕后不会自动释放必须配合 aclDestroyAclOpExecutor 手动销毁。若executor为空指针返回 561103。复用适用性限制目前使用 AI CPU 与 AI Core 计算单元的算子支持 aclOpExecutor 复用以下场景不支持复用使用 L0 主机到设备、设备到设备拷贝相关 API如CopyToNpu、CopyNpuToNpu、CopyToNpuSync使用 L0 ViewCopy API 且源地址与目的地址相同算子 API 内部创建设备张量只允许使用外部张量。8.3 复用模式下的地址更新 API 族复用 executor 后若每次执行的输入/输出设备内存地址发生变化需要更新张量中记录的地址。地址更新 API 分为两类对应两种参数形态面向单个 aclTensor 的地址更新aclSetInputTensorAddr、aclSetOutputTensorAddr、aclSetTensorAddraclnnStatus aclSetInputTensorAddr(aclOpExecutor *executor, const size_t index, aclTensor *tensor, void *addr) aclnnStatus aclSetOutputTensorAddr(aclOpExecutor *executor, const size_t index, aclTensor *tensor, void *addr) aclnnStatus aclSetTensorAddr(aclOpExecutor *executor, const size_t index, aclTensor *tensor, void *addr)其中index为待更新张量的序号取值区间为[0, 输入/输出张量总数 - 1]。面向 aclTensorList 的地址更新aclSetDynamicInputTensorAddr、aclSetDynamicOutputTensorAddr、aclSetDynamicTensorAddraclnnStatus aclSetDynamicInputTensorAddr(aclOpExecutor *executor, size_t irIndex, const size_t relativeIndex, aclTensorList *tensors, void *addr) aclnnStatus aclSetDynamicOutputTensorAddr(aclOpExecutor *executor, size_t irIndex, const size_t relativeIndex, aclTensorList *tensors, void *addr) aclnnStatus aclSetDynamicTensorAddr(aclOpExecutor *executor, size_t irIndex, const size_t relativeIndex, aclTensorList *tensors, void *addr)其中irIndex待更新的 aclTensorList 在算子 IR 原型定义中的序号从 0 开始relativeIndex待更新的 aclTensor 在 aclTensorList 中的序号若列表含 N 个张量取值区间为[0, N-1]tensors待更新的 aclTensorList 指针addr更新到指定 aclTensor 上的设备存储地址必须 32 字节对齐否则可能发生未定义错误。地址更新失败的可能原因返回值详见第八节executor或tensors为空指针时返回 561103relativeIndex大于等于tensors中张量数时返回 161002irIndex大于等于算子原型输入/输出参数个数时返回 161002。8.4 复用模式完整示例以下示例展示了开启复用、更新输入输出地址、循环执行与销毁的完整流程算子原型为两个输入——aclTensorList 与 aclTensor一个输出——aclTensor// 创建输入输出aclTensor 与 aclTensorList。 std::vectorint64_t shape {1, 2, 3}; aclTensor tensor1 aclCreateTensor(shape.data(), shape.size(), aclDataType::ACL_FLOAT, nullptr, 0, aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), nullptr); aclTensor tensor2 aclCreateTensor(shape.data(), shape.size(), aclDataType::ACL_FLOAT, nullptr, 0, aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), nullptr); aclTensor tensor3 aclCreateTensor(shape.data(), shape.size(), aclDataType::ACL_FLOAT, nullptr, 0, aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), nullptr); aclTensor output aclCreateTensor(shape.data(), shape.size(), aclDataType::ACL_FLOAT, nullptr, 0, aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), nullptr); aclTensor *list[] {tensor1, tensor2}; auto tensorList aclCreateTensorList(list, 2); uint64_t workspaceSize 0; aclOpExecutor *executor; // 第一阶段 APIAddCustom 算子两个输入 aclTensorList、aclTensor一个输出 aclTensor。 aclnnAddCustomGetWorkspaceSize(tensorList, tensor3, output, workspaceSize, executor); // 开启 executor 复用。 aclSetAclOpExecutorRepeatable(executor); // 每轮执行前更新输入输出设备地址。 void *addr; aclSetDynamicInputTensorAddr(executor, 0, 0, tensorList, addr); // 更新输入列表第一个 aclTensor 地址 aclSetDynamicInputTensorAddr(executor, 0, 1, tensorList, addr); // 更新输入列表第二个 aclTensor 地址 // 多次调用第二阶段 API 执行算子。 aclnnAddCustom(workspace, workspaceSize, executor, stream); ... // 复用结束后销毁 executor。 aclDestroyAclOpExecutor(executor);若输入输出为独立的 aclTensor非列表则改用aclSetInputTensorAddr/aclSetOutputTensorAddr/aclSetTensorAddrindex按算子原型中张量的全局顺序取值若同时存在输入输出列表可用aclSetDynamicTensorAddr统一处理。8.5 非复用场景的地址更新aclSetRawTensorAddr 与 aclGetRawTensorAddr当网络需要频繁复用 aclTensor 本身shape、format 等属性不变而非复用 executor 时可使用 aclSetRawTensorAddr 直接更新 aclTensor 中记录的设备内存地址aclnnStatus aclSetRawTensorAddr(aclTensor *tensor, void *addr)并用 aclGetRawTensorAddr 校验更新结果aclnnStatus aclGetRawTensorAddr(const aclTensor *tensor, void **addr)关键时序约束这两个 API 必须在第一阶段 APIaclxxXxxGetWorkspaceSize调用之前或第二阶段 APIaclxxXxx调用之后使用不能在两阶段调用之间使用。aclSetRawTensorAddr在tensor为空指针时返回 161001aclGetRawTensorAddr在tensor或addr为空指针时返回 161001。典型用法是跨算子复用张量地址// 创建输入输出张量。 std::vectorint64_t shape {1, 2, 3}; aclTensor inputTensor aclCreateTensor(shape.data(), shape.size(), aclDataType::ACL_FLOAT, nullptr, 0, aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), nullptr); aclTensor outputTensor aclCreateTensor(shape.data(), shape.size(), aclDataType::ACL_FLOAT, nullptr, 0, aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), nullptr); // 调用 Xxx 算子的两阶段 API。 auto ret aclxxXxxGetWorkspaceSize(inputTensor, outputTensor, workspaceSize, executor); ret aclxxXxx(workspace, workspaceSize, executor, stream); ... // 重新分配设备内存并更新张量地址。 void *addr1; void *addr2; ... // 分配设备内存地址 addr1 和 addr2 ret aclSetRawTensorAddr(inputTensor, addr1); // 更新 inputTensor 设备地址 ret aclSetRawTensorAddr(outputTensor, addr2); // 更新 outputTensor 设备地址 ... // 复用更新后的张量调用另一个算子 Yyy。 auto ret aclnnYyyGetWorkspaceSize(inputTensor, outputTensor, workspaceSize, executor); ret aclnnYyy(workspace, workspaceSize, executor, stream); ...九、返回值与错误码速查所有 Common API 统一返回aclnnStatus类型常用返回码common_api_return_codes.md如下错误码值说明ACLNN_SUCCESS0成功ACLNN_ERR_PARAM_NULLPTR161001参数校验错误参数含无效nullptrACLNN_ERR_PARAM_INVALID161002参数校验错误例如两个输入数据类型不满足数据类型推导要求ACLNN_ERR_RUNTIME_ERROR361001调用 NPU Runtime API 时发生异常ACLNN_ERR_INNER_XXX561xxx内部 API 异常常见场景- 561101ACLNN_ERR_INNER_CREATE_EXECUTOR创建aclOpExecutor失败可能原因OS 异常- 561102ACLNN_ERR_INNER_NOT_TRANS_EXECUTORAPI 内部未调用uniqueExecutor ReleaseTo- 561103ACLNN_ERR_INNER_NULLPTRaclnn API 内部发生空指针错误获取错误信息可调用 Runtime API 中的aclGetRecentErrMsg依据错误信息排障或联系技术支持。十、保留 APIReserved APIsreserved_apis.md 列出了部分保留的通用 API。这些 API 可能在后续版本中变更或废弃不建议关注或使用应使用其对应的正式 API保留 API对应正式 APIAclSetInputTensorAddraclSetInputTensorAddrAclSetOutputTensorAddraclSetOutputTensorAddrAclSetDynamicInputTensorAddraclSetDynamicInputTensorAddrAclSetDynamicOutputTensorAddraclSetDynamicOutputTensorAddrAclSetTensorAddraclSetTensorAddrAclSetDynamicTensorAddraclSetDynamicTensorAddr十一、源码实现印证与扩展阅读上述 Common API 并非仅停留在文档层面在 opbase 仓库中均有真实实现可对照阅读参数对象与地址更新实现src/nnopbase/common/api/acl_op_api.cpp 实现了aclCreateTensor第 56 行、aclCreateTensorList第 100 行、aclSetDynamicTensorAddr第 472 行、aclSetAclOpExecutorRepeatable第 505 行等核心函数其中aclSetDynamicInputTensorAddr等变体内部会转发到aclSetDynamicTensorAddr统一处理印证了文档所述三类 Dynamic API 语义一致、仅输入/输出方向不同的设计。对外声明include/nnopbase/aclnn/acl_meta.h 与 include/nnopbase/aclnn/aclnn_base.h 给出了全部 API 的声明是核对函数签名的一手依据。其他相关文档仓库 docs 目录下的 中文版通用 API 文档 与英文版内容对应可交叉参考aclnn API 列表 收录了全部单算子 API 入口。结语Common API 是 CANN aclnn 单算子编程模型的地基aclnnInit/aclnnFinalize管理资源生命周期aclCreate*系列构造参数载体aclGet*系列反向读取元信息aclDestroy*系列回收资源而aclSetAclOpExecutorRepeatable配合地址更新 API 族则构成高性能推理场景下最关键的 executor 复用能力。掌握这些 API 的语义、时序约束尤其是 32 字节对齐、两阶段调用之间的限制、列表所有权规则即可写出正确且高效的单算子调用程序。【免费下载链接】opbase本项目是CANN算子库的基础框架库为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表