资讯详情

资讯详情

CANN opbase 算子开发指南:aclGetFormat 接口详解与 aclTensor 数据格式获取实战

CANN opbase 算子开发指南aclGetFormat 接口详解与 aclTensor 数据格式获取实战【免费下载链接】opbase本项目是CANN算子库的基础框架库为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase导读aclGetFormat是 CANN opbase 基础框架库中用于查询aclTensor数据排布格式format的元数据访问接口。在单算子ACLNN开发中张量以aclTensor结构承载数据在 Device 内存上的排布方式ND、NCHW、NC1HWC0、FRACTAL_NZ 等直接影响算子的地址计算与 kernel 实现。本文以 docs/zh/api/nnopbase/aclnn/aclGetFormat.md 为骨架结合仓库内头文件声明、源码实现与单元测试完整讲解aclGetFormat的函数原型、参数与返回码、底层实现原理、与aclCreateTensor的配套用法并给出可复用的属性读取与张量重建实战示例帮助读者安全、正确地查询与传递张量格式信息。一、接口定位aclTensor 元数据访问家族中的一员aclGetFormat属于 ACLNN 元数据meta接口族负责从aclTensor中取出数据排布格式。aclTensor由 aclCreateTensor 接口创建是框架定义的一种用来管理和存储张量数据的结构开发者无需关注其内部实现直接使用即可。一个aclTensor内部记录了一组完整的张量描述信息包括ViewShape逻辑 shape与 StorageShape物理排布 shape各维度的访问步长stride与首元素偏移offset数据类型dataType与数据排布格式formatDevice 侧存储地址。围绕这些属性opbase 提供了一组一一对应的查询接口aclGetFormat是其中专门负责 format 的一个接口查询内容声明位置aclGetViewShape逻辑 shapeViewShapeinclude/nnopbase/aclnn/acl_meta.haclGetViewStrides各维度访问步长include/nnopbase/aclnn/acl_meta.haclGetViewOffset首元素相对 storage 的偏移include/nnopbase/aclnn/acl_meta.haclGetStorageShape实际物理排布 shapeStorageShapeinclude/nnopbase/aclnn/acl_meta.haclGetFormat数据排布格式formatinclude/nnopbase/aclnn/acl_meta.haclGetDataType数据类型dataTypeinclude/nnopbase/aclnn/acl_meta.h这组接口共同支撑了读取既有 aclTensor 的完整属性 → 基于这些属性重建新的 aclTensor的典型开发模式详见第四节实战示例。二、函数原型与参数说明aclGetFormat的接口声明位于 include/nnopbase/aclnn/acl_meta.h以ACL_FUNC_VISIBILITY修饰对外导出aclnnStatus aclGetFormat(const aclTensor *tensor, aclFormat *format)2.1 参数解析参数名输入/输出说明tensor输入输入的 aclTensor即待查询格式的张量对象。format输出返回的 aclTensor 的数据格式类型为aclFormat枚举。其中aclFormat与aclnnStatus等基础类型定义在acl/acl_base.hacl_meta.h通过#include acl/acl_base.h引入常见的 format 取值包括ACL_FORMAT_UNDEFINED未定义格式通常作为输出变量的初始化值ACL_FORMAT_ND按维度顺序连续存储是最常用的通用格式ACL_FORMAT_NCHW、ACL_FORMAT_NHWC、ACL_FORMAT_HWCN经典多维排布ACL_FORMAT_NC1HWC0、ACL_FORMAT_FRACTAL_Z、ACL_FORMAT_FRACTAL_NZ昇腾硬件算子常用的分形/分块格式。2.2 返回值说明返回0即OK表示成功返回其他值表示失败。公共返回码列表参见 公共接口返回码可能失败的原因返回161001ACLNN_ERR_PARAM_NULLPTR参数tensor或format为空指针即参数校验错误参数中存在非法的 nullptr。2.3 约束说明该接口无额外约束。但需要注意一个使用前提待查询的tensor必须是通过aclCreateTensor等接口合法创建的 aclTensor 对象且format必须指向有效的可写内存否则会触发参数空指针校验错误。三、源码级实现原理两次转换与一份白名单3.1 接口实现位置与调用链aclGetFormat的实现位于 src/nnopbase/common/api/acl_op_api.cppaclnnStatus aclGetFormat(const aclTensor* tensor, aclFormat* format) { if (tensor nullptr || format nullptr) { return ACLNN_ERR_PARAM_NULLPTR; } *format op::ToAclFormat(tensor-GetViewFormat()); return OK; }从实现可以看到完整的执行流程空指针校验tensor或format任一为nullptr时立即返回ACLNN_ERR_PARAM_NULLPTR对应公共返回码 161001与文档可能失败的原因完全一致读取内部格式调用tensor-GetViewFormat()取出 aclTensor 内部记录的格式。从源码结构看该内部格式以op::Format viewFormat_成员存储由SetViewFormat写入、GetViewFormat读取见 src/nnopbase/common/utils/common_types.cpp 与 L478格式转换通过op::ToAclFormat将内部op::Format转换为对外暴露的aclFormat枚举并写入输出参数。3.2 ToAclFormat 的可转换白名单op::ToAclFormat定义于 include/nnopbase/opdev/format_utils.h。该函数维护了一份可安全转换为 aclFormat 的格式白名单包括FORMAT_NCHW、FORMAT_NHWC、FORMAT_ND、FORMAT_NC1HWC0、FORMAT_FRACTAL_Z、FORMAT_FRACTAL_NZ、FORMAT_NDHWC、FORMAT_NC等 19 种常见格式若内部格式不在白名单中则返回aclFormat::ACL_FORMAT_UNDEFINED。这意味着常规张量ND、NCHW、NC1HWC0 等通过aclGetFormat可以无损取回原格式极少数算子内部使用的私有/特殊格式无法直接映射为公开的aclFormat枚举此时返回ACL_FORMAT_UNDEFINED开发者应将其视为内部格式不可直接用于外部枚举语义而非数据异常。3.3 与 aclCreateTensor 的格式写入路径对称在创建方向aclCreateTensor会把入参format经op::ToOpFormat转换后写入张量见 src/nnopbase/common/utils/common_types.cpp。ToOpFormat与ToAclFormat互为反向转换一写一读形成闭环创建时ACL_FORMAT_ND → FORMAT_ND存储查询时FORMAT_ND → ACL_FORMAT_ND返回保证开发者传入的格式在属性回读时保持一致。四、实战示例读取属性并重建 aclTensor原文档给出了一段完整的关键代码示例仅供参考不支持直接拷贝运行演示了先创建 xTensor → 读取其全部属性含 format→ 用属性重建 yTensor的标准流程本节在保留原示例全部细节的基础上补充逐段注释。4.1 创建 xTensor// 1.创建xTensor int64_t xViewDims[] {2, 4}; int64_t xStridesValue[] {4, 1}; // 第1维步长4第2维步长1 int64_t xStorageDims[] {2, 4}; aclTensor *xTensor aclCreateTensor(xViewDims, 2, ACL_FLOAT16, xStridesValue, 0, ACL_FORMAT_ND, xStorageDims, 2, nullptr);aclCreateTensor的完整原型为见 aclCreateTensoraclTensor *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/viewDimsNum是逻辑 shapestorageDims/storageDimsNum是物理排布 shapestride是各维度访问步长offset是首元素相对 storage 的偏移format是数据排布格式tensorData是 Device 侧存储地址需 32 字节对齐否则可能出现未定义错误。示例中 xTensor 为2×4的 FP16 张量连续存储、偏移为 0、格式为 ND。4.2 读取 xTensor 的全部属性// 2. 获取xTensor的各种属性值 // 获取xTensor的逻辑shapeviewDims为{2, 4}, viewDimsNum为2 int64_t *viewDims nullptr; uint64_t viewDimsNum 0; auto ret aclGetViewShape(xTensor, viewDims, viewDimsNum); // 获取xTensor的数据类型为ACL_FLOAT16 aclDataType dataType aclDataType::ACL_DT_UNDEFINED; ret aclGetDataType(xTensor, dataType); // 获取xTensor的步长信息stridesValue为{4, 1}, stridesNum为2 int64_t *stridesValue nullptr; uint64_t stridesNum 0; ret aclGetViewStrides(xTensor, stridesValue, stridesNum); // 获取xTensor的首元素对于storage的偏移值offset为0 int64_t offset 0; ret aclGetViewOffset(xTensor, offset); // 获取xTensor的数据排布格式为ACL_FORMAT_ND aclFormat format aclFormat::ACL_FORMAT_UNDEFINED; ret aclGetFormat(xTensor, format); // 获取xTensor的实际物理排布shapestorageDims为{2, 4}, storageDimsNum为2 int64_t *storageDims nullptr; uint64_t storageDimsNum 0; ret aclGetStorageShape(xTensor, storageDims, storageDimsNum); // device侧地址 void *deviceAddr;需要特别说明的是format和dataType这两个输出参数在调用前必须先初始化为ACL_FORMAT_UNDEFINED/ACL_DT_UNDEFINED即使调用失败也不会读到未初始化内存而viewDims、stridesValue、storageDims三个指针型输出由接口内部new分配使用完毕后必须手动delete[]否则会造成内存泄漏。4.3 根据属性重建 yTensor 并释放内存// 3.根据xTensor的属性创建新的tensor aclTensor *yTensor aclCreateTensor(viewDims, viewDimsNum, dataType, stridesValue, offset, format, storageDims, storageDimsNum, deviceAddr); // 4.手动释放内存 delete[] viewDims; delete[] stridesValue; delete[] storageDims;由于 xTensor 是连续存储的 ND 张量重建出的 yTensor 与 xTensor 属性完全一致。对于非连续张量如转置、切片产生的视图只需通过aclGetViewStrides/aclGetViewOffset读取到的步长与偏移配合aclCreateTensor的stride/offset参数即可无损重建同样的视图语义——这正是aclTensor以 shape、stride、offset、format 等描述信息刻画张量的价值所在。aclTensor的逻辑结构与 torch.Tensor 类似由一块连续或非连续的内存地址和一系列描述信息组成详见 aclCreateTensor 文档中的 tensor 逻辑结构图。五、单元测试佐证行为与边界可验证仓库在单元测试与系统测试中均对aclGetFormat的边界行为做了验证例如 tests/nnopbase/ut/composite_op/test_acl_op_api.cpp 中的用例TEST_F(AclOpApiTest, aclGetFormat) { EXPECT_NE(aclGetFormat(nullptr, nullptr), OK); // 空指针入参必须返回非OK std::vectorint64_t strides {8, 1}; CHECK_TENSOR(a, std::vectorint64_t({4, 2}), std::vectorint64_t({32}), aclDataType::ACL_FLOAT, strides.data(), 0, aclFormat::ACL_FORMAT_ND, nullptr); aclFormat formatRes aclFormat::ACL_FORMAT_UNDEFINED; EXPECT_EQ(aclGetFormat(a, formatRes), OK); // 正常查询返回OK EXPECT_EQ(formatRes, aclFormat::ACL_FORMAT_ND); // 与创建时传入的格式一致 }该用例验证了两个关键事实空指针校验aclGetFormat(nullptr, nullptr)必然返回非OK与文档中返回 161001参数 tensor 或 format 为空指针的描述一致格式回读一致性创建时以ACL_FORMAT_ND创建的张量查询后返回ACL_FORMAT_ND印证了 3.3 节所述的ToOpFormat/ToAclFormat双向转换闭环。同样的测试用例也存在于系统测试 tests/nnopbase/st/composite_op/test_acl_op_api.cpp 中开发者可对照阅读了解该接口在测试环境下的完整行为预期。六、常见问题与使用建议调用后 format 仍为ACL_FORMAT_UNDEFINED先检查返回值若返回非 0 则是入参为空指针或非法对象若返回 0 但格式为UNDEFINED从源码结构看是内部格式不在ToAclFormat白名单中见 3.2 节属于框架内部格式不建议直接依赖其枚举值。忘记释放指针型输出aclGetViewShape、aclGetViewStrides、aclGetStorageShape的输出数组由接口内部分配调用方需delete[]format、offset、dataType是值型输出无需释放。format 与 shape 的配套使用aclGetFormat仅返回格式枚举实际内存排布还需结合aclGetStorageShape理解——例如 NC1HWC0 格式下物理 shape 与逻辑 shape 并不相同二者配套查询才能正确计算地址偏移。与创建接口的配套format 在创建时通过aclCreateTensor的format参数写入读取时通过aclGetFormat取回若需修改既有张量的属性可使用 aclInitTensor 初始化给定 tensor 的参数。七、小结aclGetFormat虽是一个参数极简的查询接口却是 aclTensor 元数据读取链路中承上启下的一环向下它映射aclTensor内部以op::Format存储的格式字段向上它把格式转换为开发者可直接使用的aclFormat枚举。配合aclGetViewShape、aclGetViewStrides、aclGetViewOffset、aclGetStorageShape、aclGetDataType即可完整读取一个 aclTensor 的全部属性再经aclCreateTensor重建出新张量实现视图克隆、格式校验、算子入参构造等常见场景。理解其 161001 空指针返回码语义与ToAclFormat白名单行为有助于在实际算子开发中快速定位参数问题写出健壮的 ACLNN 单算子调用代码。【免费下载链接】opbase本项目是CANN算子库的基础框架库为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →