CANN opbase aclGetIntArraySize 接口详解:aclIntArray 大小获取与生命周期管理
【免费下载链接】opbase本项目是CANN算子库的基础框架库,为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase
导读
aclGetIntArraySize是 CANN 算子库基础框架 opbase 中 aclnn 公共接口(meta API)的一员,用于获取由 aclCreateIntArray 创建的aclIntArray整型数组的元素个数。本文以该接口为核心,结合其姊妹接口(创建、销毁)与仓库源码实现,讲解 aclnn 整型数组对象的完整使用链路——从创建、查询到销毁——并给出可直接复用的调用模式与异常处理要点。阅读完本文,你将掌握aclIntArray在单算子 API(aclnn)调用中的正确用法,理解其底层存储结构与空指针校验逻辑,并能结合仓库单测用例验证接口行为。
接口概览:功能、原型与参数
aclIntArray是 opbase 框架定义的一种用于管理和存储整型数据的数组结构,主要作为单算子 API 执行接口(形如aclxxXxx、aclxxXxxGetWorkspaceSize)的入参使用,例如用于传递算子的 shape、axes、dims 等整型参数集合。开发者无需关注其内部实现,直接通过公共接口使用即可。
函数原型
aclnnStatus aclGetIntArraySize(const aclIntArray *array, uint64_t *size)该接口声明位于 include/nnopbase/aclnn/acl_meta.h,属于对外导出的公共接口(ACL_FUNC_VISIBILITY修饰),其实际实现在 src/nnopbase/common/api/acl_op_api.cpp。
参数说明
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| array | 输入 | 输入的 aclIntArray,即通过aclCreateIntArray创建的对象。 |
| size | 输出 | 输出参数,返回 aclIntArray 中整型元素的个数(大小)。 |
两个参数均不可为空:array若为空指针则无对象可取;size若为空指针则结果无处可写,二者任一为空都会触发参数校验失败。
返回值与错误码分析
接口返回aclnnStatus类型状态码:
- 返回
0(ACLNN_SUCCESS)表示成功,size中即为获取到的数组大小。 - 返回其他值表示失败,常见失败原因为返回 161001:参数
array或size为空指针。
161001 对应公共返回码ACLNN_ERR_PARAM_NULLPTR(参数校验错误,参数中存在非法的 nullptr),完整返回码列表参见公共接口返回码。
源码级校验逻辑
在 src/nnopbase/common/api/acl_op_api.cpp 中,实现非常直观:
aclnnStatus aclGetIntArraySize(const aclIntArray* array, uint64_t* size) { if (array == nullptr || size == nullptr) { return ACLNN_ERR_PARAM_NULLPTR; } *size = array->Size(); return OK; }从源码可以看出两点实现事实:
- 先校验、后取值:入口处对两个指针同时做空指针检查,任一为空立即返回
ACLNN_ERR_PARAM_NULLPTR(161001),这与文档中"返回 161001"的说明完全一致,且不会发生空指针解引用。 - 大小即元素个数:
size的取值来自array->Size(),返回的是数组内 int64 元素的数量,而非字节数。例如创建时传入{1, 1, 2, 3}四个元素,查询得到的 size 即为 4。
配套接口:完整的 aclIntArray 生命周期
aclGetIntArraySize单独使用没有意义,它必须与aclCreateIntArray、aclDestroyIntArray配合,构成"创建 → 使用/查询 → 销毁"的完整生命周期。三个接口的原型声明集中定义在 include/nnopbase/aclnn/acl_meta.h。
创建:aclCreateIntArray
aclIntArray *aclCreateIntArray(const int64_t *value, uint64_t size)value:Host 侧的int64_t类型指针,其指向的数据会被拷贝给 aclIntArray(因此创建后原数组可安全复用或释放);size:整型数组的长度,取值为正整数。
成功返回创建好的aclIntArray,失败返回nullptr。其实现位于 src/nnopbase/common/api/acl_op_api.cpp,通过new aclIntArray(value, size)构造对象;若构造过程抛出异常,则记录ACLNN_ERR_INNER错误并释放已分配内存后返回空指针。
销毁:aclDestroyIntArray
aclnnStatus aclDestroyIntArray(const aclIntArray *array)- 成功返回
0,失败返回其他值(返回码列表参见公共接口返回码)。 - 实现上对空指针做了防御:若
array为nullptr直接返回成功(见 src/nnopbase/common/api/acl_op_api.cpp),避免重复销毁空对象。 - 当开启 aclnn 调试(
op::internal::IsAclnnDebugEnabled())时,销毁前会调用CheckDoubleFree检测双重释放(double-free),命中则打印告警日志"Possible double-free at addr %p."。这说明框架在调试模式下主动帮助开发者发现悬垂指针/二次释放问题,生产代码中仍需自行保证"一创一销、不重复销毁"。
重要约束:aclCreateIntArray与aclDestroyIntArray必须配套使用,分别完成 aclIntArray 的创建与销毁;调用aclGetIntArraySize可以获取该数组的大小(详见 aclCreateIntArray 与 aclDestroyIntArray 的约束说明)。
调用示例:完整可运行的调用模式
以下关键代码示例仅供参考,演示 aclIntArray 从创建到查询再到销毁的完整链路,注意其中...处需按实际场景补充(如将valueArray作为单算子 API 入参):
// 1. 创建 aclIntArray:数据被拷贝进对象内部 std::vector<int64_t> valueData = {1, 1, 2, 3}; aclIntArray *valueArray = aclCreateIntArray(valueData.data(), valueData.size()); if (valueArray == nullptr) { // 创建失败,处理异常,例如返回错误码或记录日志 return ACLNN_ERR_INNER; } // 2. 使用 aclGetIntArraySize 接口获取 valueArray 的大小 uint64_t size = 0; auto ret = aclGetIntArraySize(valueArray, &size); // 获取到的 valueArray 的 size 为 4 if (ret != 0) { // 返回 161001 表示 array 或 size 为空指针,需检查入参 return ret; } // 3. valueArray 可作为单算子 API 执行接口的入参,例如: // auto ret = aclxxXxxGetWorkspaceSize(srcTensor, valueArray, ..., outTensor, ..., // &workspaceSize, &executor); // ret = aclxxXxx(...); // 4. 销毁 aclIntArray(与创建配套使用,避免重复销毁) ret = aclDestroyIntArray(valueArray); if (ret != 0) { // 处理销毁失败 }示例要点总结:
- 创建后立即判空:
aclCreateIntArray可能返回nullptr,使用前必须检查; - size 先清零再接收:查询前将
size初始化为 0,防止误用未初始化值; - 返回值逐段检查:
aclGetIntArraySize与aclDestroyIntArray均需检查返回码,其中 161001(ACLNN_ERR_PARAM_NULLPTR)是aclGetIntArraySize最常见失败原因; - 生命周期对称:创建、销毁严格配对,销毁后不再访问
valueArray。
单元测试验证:接口行为可被仓库用例复现
opbase 仓库在 tests/nnopbase/ut/composite_op/test_acl_op_api.cpp 中提供了针对该接口的单元测试AclOpApiTest.aclGetIntArraySize,完整复现了本文描述的三种行为:
TEST_F(AclOpApiTest, aclGetIntArraySize) { EXPECT_NE(aclGetIntArraySize(nullptr, nullptr), OK); // 空指针入参 → 返回非 OK(161001) int64_t values[] = {3, 4, 5}; auto* value = aclCreateIntArray(values, sizeof(values) / sizeof(values[0])); uint64_t size = 0; EXPECT_EQ(aclGetIntArraySize(value, &size), OK); // 正常查询 → OK EXPECT_EQ(size, 3); // 元素个数为 3 EXPECT_EQ(aclDestroyIntArray(value), OK); // 销毁 → OK }该用例验证了三项关键行为,可作为开发者自行验证接口时的参照:
- 空指针防御:
aclGetIntArraySize(nullptr, nullptr)返回非OK,对应错误码 161001; - 大小语义正确:创建
{3, 4, 5}三个元素后查询,size为3,确认返回的是元素个数而非字节数; - 全链路可销毁:查询后调用
aclDestroyIntArray返回OK,完成生命周期闭环。
与其他数组类公共接口的关系
aclGetIntArraySize并非孤立接口。在 opbase 的 aclnn 公共接口族(0_aclnn_meta_api.md)中,还存在语义完全对称的一组"创建/销毁/查大小"接口,实现均集中在 src/nnopbase/common/api/acl_op_api.cpp,包括:
| 数据类型 | 创建接口 | 销毁接口 | 查询大小接口 |
|---|---|---|---|
| 整型数组 | aclCreateIntArray | aclDestroyIntArray | aclGetIntArraySize |
| 浮点数组 | aclCreateFloatArray | aclDestroyFloatArray | aclGetFloatArraySize |
| 布尔数组 | aclCreateBoolArray | aclDestroyBoolArray | aclGetBoolArraySize |
| Tensor 列表 | aclCreateTensorList | aclDestroyTensorList | aclGetTensorListSize |
| Scalar 列表 | aclCreateScalarList | aclDestroyScalarList | aclGetScalarListSize |
这些接口遵循完全相同的设计范式:创建接口返回对象指针、销毁接口防御空指针、查询大小接口校验空指针后返回Size()。其中aclGetFloatArraySize、aclGetBoolArraySize等的实现与aclGetIntArraySize逐行同构(见 src/nnopbase/common/api/acl_op_api.cpp),单元测试也采用了相同的断言结构(tests/nnopbase/ut/composite_op/test_acl_op_api.cpp)。掌握了本文的aclGetIntArraySize,即可举一反三掌握整个 aclnn 数组类公共接口族。
常见问题与使用建议
Q1:为什么查询到的 size 与我创建时传入的 size 不一致?
aclGetIntArraySize返回的是aclCreateIntArray创建时拷贝进对象内部的元素个数。只要创建时size参数正确(正整数)且对象未被意外修改,查询结果必然等于创建时的元素个数。若发现不一致,请检查是否在创建后误用了该指针(如二次创建覆盖、提前销毁后再查询)。
Q2:查询接口在什么场景下会返回 161001?
当array或size任一为空指针时返回ACLNN_ERR_PARAM_NULLPTR(161001)。典型场景包括:创建失败后未判空直接传入、size地址未正确传递(如传入nullptr)。建议在调用前对array判空,并确保size指向有效的栈上变量。
Q3:aclIntArray 需要手动释放内存吗?
需要。aclIntArray由aclCreateIntArray在 Host 侧堆上创建,必须由aclDestroyIntArray配套销毁,否则会造成内存泄漏。销毁后不要再访问该指针,避免产生悬垂指针。
Q4:如何排查双重释放问题?
框架已在销毁路径内置调试检测(CheckDoubleFree),开启 aclnn 调试时若触发二次释放会打印"Possible double-free at addr %p."告警。开发阶段建议开启该调试能力辅助定位,同时从代码规范上保证每个aclCreateIntArray仅对应一次aclDestroyIntArray。
【免费下载链接】opbase本项目是CANN算子库的基础框架库,为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考