CANN opbase 算子开发指南:aclDestroyIntArray 接口的整型数组销毁机制与实践 📅 发布时间:2026/9/18 6:57:01 👁 浏览次数: CANN opbase 算子开发指南aclDestroyIntArray 接口的整型数组销毁机制与实践【免费下载链接】opbase本项目是CANN算子库的基础框架库为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase导读aclDestroyIntArray是 CANN opbase 基础框架库include/nnopbase/aclnn/acl_meta.h为单算子aclnnAPI 提供的元数据管理接口之一用于销毁由 aclCreateIntArray 创建的aclIntArray对象。aclIntArray是框架定义的一种用于管理和存储整型数据的数组结构常以shape/size 数组的形式作为单算子 API 执行的入参。读完本文你将掌握aclDestroyIntArray的函数签名、参数与返回值语义、底层销毁实现原理以及它与其他 aclnn 元数据接口配套使用的完整对象生命周期管理方法。aclIntArray 在 aclnn 单算子调用链中的定位在 CANN 的 aclnn 单算子编程模型中开发者需要先构造算子描述参数Tensor、Scalar、各种 Array、List再调用形如aclxxXxxGetWorkspaceSize与aclxxXxx的成对接口完成算子执行。其中aclIntArray是存放int64_t整型数据的数组结构由 aclCreateIntArray 创建它通常承载与算子输入 Tensor 相关的长度、轴、size等整型集合信息作为单算子 API 执行的入参该结构对开发者是黑盒无需关注其内部实现直接使用即可见 aclCreateIntArray.md 功能说明。从仓库源码看aclIntArray是模板类aclArrayT的特化实例通过宏ACL_ARRAY(Int, int64_t)生成定义位于 include/nnopbase/opdev/common_types.htemplate typename T class aclArray : public op::Object { public: ~aclArray() override; T operator[](uint64_t i); const T operator[](uint64_t i) const; uint64_t Size() const; const T* GetData() const; ge::AscendString ToString() const; protected: aclArray(const T* value, uint64_t size); private: T* value_{nullptr}; uint64_t size_{0}; uint8_t reserved_field_[8]; }; #define ACL_ARRAY(Type, T) \ class acl##Type##Array : public aclArrayT { \ friend struct aclOpExecutor; \ friend acl##Type##Array* aclCreate##Type##Array(const T* value, uint64_t size); \ friend aclnnStatus aclDestroy##Type##Array(const acl##Type##Array* array); \ private: \ acl##Type##Array(const T* value, uint64_t size) : aclArrayT(value, size) {} \ ~acl##Type##Array() override {} \ } ACL_ARRAY(Int, int64_t);可以看到aclIntArray的构造函数与析构函数均为私有成员只有aclCreateIntArray与aclDestroyIntArray两个友元函数能够触达这正是创建与销毁接口必须配套使用的源码级体现。函数原型与参数说明aclDestroyIntArray的声明位于 include/nnopbase/aclnn/acl_meta.h其函数原型如下aclnnStatus aclDestroyIntArray(const aclIntArray *array)参数说明参数名输入/输出说明array输入需要销毁的 aclIntArray即之前通过 aclCreateIntArray 返回的对象指针。在头文件中aclIntArray被声明为不透明结构体typedef struct aclIntArray aclIntArray;acl_meta.h外部调用者无法直接访问其内部成员只能通过框架提供的aclCreateIntArray/aclGetIntArraySize/aclDestroyIntArray三个配套接口进行创建、查询与销毁。返回值说明返回 0ACLNN_SUCCESS表示成功返回其他值表示失败。公共接口返回码的完整清单参见 公共接口返回码其中与本接口直接相关的常见返回码如下状态码名称状态码值状态码说明ACLNN_SUCCESS0成功。ACLNN_ERR_PARAM_NULLPTR161001参数校验错误参数中存在非法的 nullptr。ACLNN_ERR_PARAM_INVALID161002参数校验错误如输入的两个数据类型不满足输入类型推导关系。ACLNN_ERR_RUNTIME_ERROR361001API 内存调用 npu runtime 的接口异常。ACLNN_ERR_INNER_XXX561xxxAPI 发生内部异常。需要注意的是与 aclGetIntArraySize 不同该接口在array或size为空指针时会返回ACLNN_ERR_PARAM_NULLPTR即错误码 161001aclDestroyIntArray对空指针采取了宽容处理传入nullptr时直接返回成功不会报错详见下文源码剖析。异常详情可通过 Runtime 的aclGetRecentErrMsg接口获取。源码级实现剖析一次销毁调用发生了什么aclDestroyIntArray的实现位于 src/nnopbase/common/api/acl_op_api.cppaclnnStatus aclDestroyIntArray(const aclIntArray* array) { if (array nullptr) { return OK; } if (unlikely(op::internal::IsAclnnDebugEnabled()) op::internal::CheckDoubleFree(const_castaclIntArray*(array))) { OP_LOGW(Possible double-free at addr %p., static_castconst void*(array)); } delete array; return OK; }该实现包含三个关键环节空指针兜底array nullptr时直接返回OK允许调用方在不确定对象是否存在时安全调用不会触发空指针解引用。二次释放double-free检测当开启 aclnn 调试IsAclnnDebugEnabled()时通过op::internal::CheckDoubleFree对同一指针的重复销毁进行检测命中时打印警告日志OP_LOGW提示 Possible double-free at addr %p。仓库中还提供了对应的测试用例 test_check_double_free.cpp 来验证此类异常场景。触发对象析构与内存回收delete array会调用aclIntArray的析构函数进而调用基类aclArrayT::~aclArray()。该析构函数在 src/nnopbase/common/utils/common_types.cpp 中实现会通过op::internal::DeAllocate释放内部持有的数据缓冲区template typename T aclArrayT::~aclArray() { if (value_ ! nullptr) { op::internal::DeAllocate(value_); } }与创建过程对称来看aclCreateIntArray在构造aclArrayT时common_types.cpp会调用op::internal::Allocate申请size * sizeof(T)字节的内存并将入参value指向的数据深拷贝到新缓冲区对 trivial 类型使用memcpy_s而aclDestroyIntArray的delete则恰好完成逆操作——析构并回收这块缓冲区。这就是创建拷贝、销毁释放的完整内存闭环也是为什么 aclnn 文档要求二者必须配套使用。此外从调用链看单算子individual op路径下的NnopbaseDestroyIntArray正是对aclDestroyIntArray的直接封装src/nnopbase/individual_op/api/individual_op_fallback.cpp说明该接口同时服务于框架内部资源回收与开发者显式调用两条路径。与配套接口的完整生命周期aclDestroyIntArray不是孤立存在的接口它处于aclIntArray对象生命周期的收尾阶段与之配套的核心接口还有两个接口函数原型职责aclCreateIntArrayaclIntArray *aclCreateIntArray(const int64_t *value, uint64_t size)创建 aclIntArray将 Host 侧value指向的整型数据拷贝进对象size为数组长度正整数成功返回对象指针失败返回 nullptr。aclGetIntArraySizeaclnnStatus aclGetIntArraySize(const aclIntArray *array, uint64_t *size)查询 aclIntArray 的大小通过输出参数size返回array或size为空指针时返回 161001。aclDestroyIntArrayaclnnStatus aclDestroyIntArray(const aclIntArray *array)销毁 aclIntArray释放内部内存。约束与配套关系见 aclCreateIntArray.md 约束说明本接口需与 aclDestroyIntArray 配套使用分别完成 aclIntArray 的创建与销毁调用 aclGetIntArraySize 可以获取 aclIntArray 的大小。从 src/nnopbase/common/utils/op_cache.cpp 的实现还可以看到aclIntArray在作为算子参数时会参与算子缓存 key 的哈希计算AddParamToBuf将GetData()与Size()序列化进 hash 缓冲区因此整型数组的内容直接影响算子缓存命中。这解释了为什么销毁时机应当在单算子执行链路完成之后——在执行过程中该数组仍可能被用于缓存 key 的构建与算子参数描述。调用示例从创建到销毁的完整流程接口的完整调用流程请以 aclCreateIntArray 的调用示例为参考。典型的关键代码示例如下仅供参考不支持直接拷贝运行// 创建aclIntArray std::vectorint64_t sizeData {1, 1, 2, 3}; aclIntArray *size aclCreateIntArray(sizeData.data(), sizeData.size()); ... // aclIntArray作为单算子API执行接口的入参 auto ret aclxxXxxGetWorkspaceSize(srcTensor, size, ..., outTensor, ..., workspaceSize, executor); ret aclxxXxx(...); ... // 销毁aclIntArray ret aclDestroyIntArray(size);若需要在使用前确认数组长度可结合aclGetIntArraySize完成查询示例来源// 创建aclIntArray std::vectorint64_t valueData {1, 1, 2, 3}; aclIntArray *valueArray aclCreateIntArray(valueData.data(), valueData.size()); ... // 使用aclGetIntArraySize接口获取valueArray的大小 uint64_t size 0; auto ret aclGetIntArraySize(valueArray, size); // 获取到的valueArray的size为4 ... // 销毁aclIntArray ret aclDestroyIntArray(valueArray);在上述示例中需要注意的关键点aclCreateIntArray会深拷贝value指向的数据因此创建完成后原始的std::vector生命周期即可结束aclIntArray内部数据不受影响size取值为正整数0 或非法值应视为无效输入在aclxxXxxGetWorkspaceSize/aclxxXxx执行完成之前不应提前销毁作为入参的aclIntArray因为该对象仍被算子执行与缓存构建过程引用对象使用完毕后必须调用aclDestroyIntArray释放内存否则会造成内存泄漏。测试与验证仓库中的测试用例为接口行为提供了直接验证tests/nnopbase/st/composite_op/test_acl_op_api.cpp创建aclIntArray后立即销毁并断言aclDestroyIntArray(value)返回值等于OK即 0同文件 L348-L352 在更复杂的场景中再次覆盖创建-销毁配对流程tests/nnopbase/ut/composite_op/test_check_double_free.cpp 验证了调试模式下二次释放检测的逻辑对应aclDestroyIntArray实现中的CheckDoubleFree分支。这些测试用例表明正常路径下aclDestroyIntArray返回OK重复销毁在非调试模式下不会导致崩溃空指针兜底在调试模式下则会输出告警日志帮助开发者在测试阶段尽早暴露资源管理问题。使用建议与注意事项综合文档与源码使用aclDestroyIntArray时建议遵循以下实践严格配对为每个aclCreateIntArray调用匹配一次aclDestroyIntArray形成创建-使用-销毁的完整闭环先使用后销毁确保单算子执行接口aclxxXxxGetWorkspaceSize/aclxxXxx完成后再销毁相关aclIntArray避免执行期访问已释放内存善用调试开关开发与测试阶段可开启 aclnn 调试能力借助CheckDoubleFree的告警日志及时发现重复销毁问题无需担心空指针aclDestroyIntArray(nullptr)会安全返回成功可在不确定对象是否创建成功如aclCreateIntArray返回 nullptr时放心调用了解内存语义销毁操作会释放aclCreateIntArray创建时内部申请的数据缓冲区二者在内存分配与释放上严格对称无需也不应手动干预对象内部数据。该接口属于 aclnn 元数据管理 API 家族与其并列的还有aclDestroyTensor、aclDestroyScalar、aclDestroyFloatArray、aclDestroyBoolArray、aclDestroyTensorList、aclDestroyScalarList等成对接口声明见 acl_meta.h实现见 acl_op_api.cpp它们遵循完全一致的创建/销毁配套、空指针兜底、调试期二次释放检测设计范式掌握aclDestroyIntArray的使用模式即可举一反三。进一步阅读完整的 aclnn 元数据 API 列表见 0_aclnn_meta_api.md公共接口总览见 public_interface.md。【免费下载链接】opbase本项目是CANN算子库的基础框架库为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考