CANN opbase 中 aclTensor 的 SetOriginalFormat 接口:原始 Format 设置原理与实战解析
【免费下载链接】opbase本项目是CANN算子库的基础框架库,为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase
SetOriginalFormat是 CANN opbase 基础框架库中aclTensor公共类型的一个成员接口,用于设置张量在经历transdata节点之前的原始 Format(OriginFormat)。本文将以 SetOriginalFormat.md 为骨架,结合仓库源码与测试用例,讲解该接口的原型、参数、底层实现链路、Format 枚举体系及在算子开发与框架调度中的实际应用,帮助算子开发者准确理解并正确使用原始格式设置能力。
OriginFormat:先弄清"原始格式"到底是什么
在昇腾计算图的算子链路中,张量的数据排布格式(Format)并非一成不变。为满足昇腾 AI Core 对特定算子的高效计算要求,框架可能会在算子之间插入transdata节点,将张量从一种格式转换为另一种格式。例如,把 NCHW 布局的张量转换为适合昇腾硬件计算的 FRACTAL_NZ 分形格式。
OriginFormat描述的就是aclTensor 在经历 transdata 节点之前(如果存在该节点)的原始 Format 信息。它记录的是"这份数据最初以什么格式排布",而与之相对的StorageFormat则描述数据在当前存储中的实际排布。二者解耦的意义在于:即使张量在底层已经以某种硬件友好的格式存储,上层语义(如 shape 推导、算子语义判断、dump 信息还原)依然可以追溯到其原始格式。
SetOriginalFormat正是用于显式设置这一原始格式信息的接口,原型如下:
void SetOriginalFormat(op::Format format)参数说明
| 参数 | 输入/输出 | 说明 |
|---|---|---|
| format | 输入 | 数据类型为op::Format(即ge::Format),是一个枚举类型,定义了多种不同的数据排布格式,例如 NCHW、ND、NC1HWC0、FRACTAL_NZ 等。 |
- 返回值:无(
void)。 - 约束:无。接口为普通成员函数,直接写入张量的 Format 元信息,不涉及内存分配或设备侧操作。
源码级解析:接口的底层实现链路
SetOriginalFormat声明于公共类型头文件 common_types.h,位于aclTensor类中,与GetOriginalFormat、SetStorageFormat、SetViewFormat等接口并列,共同构成 aclTensor 的 Format 三视图管理能力:
op::Format GetStorageFormat() const; void SetStorageFormat(op::Format format); op::Format GetOriginalFormat() const; void SetOriginalFormat(op::Format format); op::Format GetViewFormat() const; void SetViewFormat(op::Format format);其实际实现位于 common_types.cpp,实现非常简洁——委托给内部的op::Tensor对象:
void aclTensor::SetOriginalFormat(op::Format format) { tensor_->SetOriginFormat(format); }对应的读取接口实现为(common_types.cpp):
op::Format aclTensor::GetOriginalFormat() const { return tensor_->GetFormat().GetOriginFormat(); }由此可见,aclTensor是对内部op::Tensor元数据的薄封装:Format 信息被聚合存储在 Tensor 的 Format 描述对象中,SetOriginalFormat/GetOriginalFormat只是把OriginFormat的读写能力暴露给算子开发者。从代码结构看,SetOriginalFormat与SetStorageFormat(common_types.cpp)、SetViewFormat(common_types.cpp)三者分别维护原始格式、存储格式与视图格式,对应 common_types.h 中GetStorageShape/GetOriginalShape/GetViewShape的"存储-原始-视图"三视图设计思想。
常用 Format 枚举值
op::Format即ge::Format,完整枚举定义可参考 AICPU 侧公共类型头文件 cpu_types.h,常用取值包括:
| 枚举值 | 含义 |
|---|---|
FORMAT_NCHW | 经典四维布局,通道维 C 在第二位(值为 0) |
FORMAT_NHWC | 通道维 C 在最后一位 |
FORMAT_ND | 通用多维张量布局,不限定维度数 |
FORMAT_NC1HWC0 | 昇腾特有的 5 维布局,C 维按 C0(通常为 16)切分 |
FORMAT_FRACTAL_NZ | 分形 NZ 格式,AI Core 计算友好的权重/激活布局 |
FORMAT_NDC1HWC0/FORMAT_FRACTAL_Z等 | 5D/3D 场景及更多专用布局 |
此外,format_utils.h 提供了一组格式辅助工具,可用于判断私有格式、字符串与枚举互转以及提取主格式/子格式/C0 信息,例如op::ToFormat(const std::string&)、op::ToString(Format)、op::GetPrimaryFormat、op::GetSubFormat、op::GetC0Format,实际排布还可能通过主格式+子格式组合编码的方式表达,设置原始格式时传入基础枚举值即可。
调用示例
将输入张量的 OriginFormat 显式设置为 ND 格式(即原文档示例):
// 将 input 的 OriginFormat 置为 ND 格式 void Func(const aclTensor *input) { input->SetOriginalFormat(ge::FORMAT_ND); }将张量原始格式设置为 FRACTAL_NZ 的完整读写示例:
#include "nnopbase/opdev/common_types.h" void SetAndQueryOriginalFormat(aclTensor *tensor) { // 设置原始格式为 FRACTAL_NZ tensor->SetOriginalFormat(op::Format::FORMAT_FRACTAL_NZ); // 读取并核对 op::Format fmt = tensor->GetOriginalFormat(); // fmt == op::Format::FORMAT_FRACTAL_NZ }注意示例中既可以使用ge::FORMAT_ND(ge命名空间别名),也可以使用op::Format::FORMAT_FRACTAL_NZ(op命名空间),二者指向同一枚举。
配套接口与三格式协同
aclTensor围绕 Format 提供了一组配套读写接口(common_types.h),实际开发中通常成组使用:
GetStorageFormat()/SetStorageFormat(Format):数据在内存中的实际存储格式;GetOriginalFormat()/SetOriginalFormat(Format):数据进入 transdata 之前的原始格式;GetViewFormat()/SetViewFormat(Format):视图(view)语义下的格式,配合SetViewShape使用。
三者的典型关系是:原始格式描述语义排布,存储格式描述物理排布,视图格式描述用户视角的切片排布。当张量经过transdata后,其 StorageFormat 发生变化而 OriginFormat 保持不变,这正是推理与调试场景中还原数据原始语义的关键。
在框架调度中的实际应用
从源码搜索可以看到OriginFormat被框架多个模块读取使用,这些调用点印证了该接口的实战价值:
- Tiling 上下文构建:在单算子执行器中,indv_tilingcontext_builder.cpp 等多处通过
storageFormat.GetOriginFormat()将原始格式写入 TilingData,供 AI Core 侧 Tiling 解析使用; - 编译描述生成:复合算子引擎在 kernel_context_holder.cpp 中通过
tensor->GetOriginalFormat()把原始格式写入编译描述(compileDesc)的 storage_format,参与算子二进制选择与缓存 key 构建; - Tiling 信息落盘:算子信息记录模块在 tiling_context_to_json.cpp 中将
origin_format序列化进 JSON,供离线分析工具还原 Tiling 现场; - 执行器张量维护:indv_executor_tensor.cpp 在运行期按实际存储格式对运行时张量调用
SetOriginFormat,保证运行时上下文与编译期描述一致。
测试验证
仓库测试用例对SetOriginalFormat与GetOriginalFormat的读写一致性做了直接验证,见 test_common_types.cpp(UT 用例,ST 侧用例见 test_common_types.cpp):
a.SetStorageFormat(Format::FORMAT_FRACTAL_NZ); EXPECT_EQ(a.GetStorageFormat(), Format::FORMAT_FRACTAL_NZ); a.SetOriginalFormat(Format::FORMAT_FRACTAL_NZ); EXPECT_EQ(a.GetOriginalFormat(), Format::FORMAT_FRACTAL_NZ); a.SetViewFormat(Format::FORMAT_FRACTAL_NZ); EXPECT_EQ(a.GetViewFormat(), Format::FORMAT_FRACTAL_NZ);该用例将 Storage/Original/View 三种格式分别设置并断言读取结果,直接验证了SetOriginalFormat的写入-读取闭环,也佐证了三格式互不干扰、独立存取的设计。
使用建议与注意事项
- 设置时机:建议在创建/构造 aclTensor 语义信息时同步设置原始格式,或在张量经过格式转换(transdata)之前记录下转换前的格式,避免语义信息丢失;
- 与 StorageFormat 的关系:
SetOriginalFormat只影响语义层面的原始格式记录,不会触发数据重排或内存搬运,真正的数据转换由transdata算子完成,本接口只是元数据标注; - 与视图语义配合:当通过
aclCreateTensor等接口创建带 view 语义的张量时,建议同时明确 Storage/Original/View 三套格式,保证 shape 推导、tiling 计算与 dump 信息完整一致; - 格式化调试:如需将 Format 转为可读字符串,可使用 format_utils.h 中的
op::ToString(Format),与 Tiling 落盘 JSON 中的origin_format字段对应,便于排查格式链路问题。
小结
SetOriginalFormat虽然是一个仅有几行实现的小接口,却是 aclTensor 三视图 Format 体系中承上启下的一环:它把"数据在 transdata 之前的原始格式"显式记录进张量元数据,并被 tiling 上下文构建、编译描述生成与信息落盘等框架模块广泛读取。掌握该接口及配套的GetOriginalFormat/SetStorageFormat/SetViewFormat,有助于在自定义算子开发中正确维护张量格式语义,确保 shape 推导、tiling 与 dump 全链路的信息一致性。相关接口的完整清单可参阅 common_types.md 与 opdev API 总览。
【免费下载链接】opbase本项目是CANN算子库的基础框架库,为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考