CANN opbase 算子开发指南:GetOriginalShape() 接口获取 aclTensor 原始形状深度解析

发布时间:2026/9/18 20:08:19
CANN opbase 算子开发指南:GetOriginalShape() 接口获取 aclTensor 原始形状深度解析 CANN opbase 算子开发指南GetOriginalShape() 接口获取 aclTensor 原始形状深度解析【免费下载链接】opbase本项目是CANN算子库的基础框架库为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase导读本指南围绕 CANN 算子库基础框架opbase中 aclTensor 的核心只读接口GetOriginalShape()展开讲解其功能语义、函数原型、调用方式并结合仓库源码剖析 OriginShape 属性的存储结构与底层实现最后通过真实调用链与单元测试展示其在实际算子开发与框架调度中的用途。读完本文你将掌握 OriginShape 与 StorageShape、ViewShape 三者之间的关系能够在算子开发与调试中正确读取和校验张量的数学维度信息。GetOriginalShape()是 common_types 接口族 中用于获取 aclTensor 原始形状OriginShape的成员方法对应文档为 GetOriginalShape.md与之配套的写入接口见 SetOriginalShape.md。功能说明什么是 OriginShapeGetOriginalShape()用于获取 aclTensor 的OriginShape原始形状属性。OriginShape 表示 aclTensor 在经历transdata 节点之前如果存在该节点的原始 shape 信息即 tensor 的 shape 数学描述。换言之它是张量在逻辑/数学层面上的维度定义不随底层内存排布方式format 转换的变化而改变。理解这一点需要先区分 aclTensor 上并存的三套 shape 语义仓库文档中与之一一对应的接口可参见 common_types.mdShape 概念语义获取接口设置接口OriginShape原始形状transdata 节点前的 shape 数学描述逻辑维度GetOriginalShapeSetOriginalShapeStorageShape存储形状张量在内存上的实际排布运行时实际 shapeGetStorageShapeSetStorageShapeViewShape视图形状视图view视角下观察到的形状GetViewShapeSetViewShape例如一个三维 tensor其 OriginShape 记录为[10, 20, 30]当它经过 format 转换如转为 5D 的 FRACTAL_NZ 排布后StorageShape 可能变为带 format 特有维度的形状而 OriginShape 依然保持[10, 20, 30]这一数学描述不变。这正对应测试 test_infer_shape.cpp 中注释给出的典型场景TransData 后GetOriginalShape()保持输入形状而GetStorageShape()变为类似{33, 1, 14, 48, 16}的存储形态。函数原型与参数说明接口声明位于 aclTensor 类中函数原型如下gert::Shape GetOriginalShape()参数说明无。返回值说明返回值为gert::Shape记录了一组 shape 信息。例如一个三维 shape[10, 20, 30]。说明gert::Shape是框架公共的 shape 数据结构。在本仓库中op::Shape即gert::Shape参见 SetOriginalShape.md 中参数类型描述其详细成员方法如维度个数、维度取值、形状元素总数等定义于 gert 命名空间的 Shape 数据结构对应《基础数据结构和接口参考》中gert 命名空间 Shape。约束说明无。调用示例接口为无参只读方法最简调用方式如下void Func(const aclTensor *input) { auto shape input-GetOriginalShape(); }获取到的gert::Shape可以进一步遍历维度。从仓库实际使用代码可以确认gert::Shape提供GetDimNum()维度个数与GetDim(i)第 i 维取值等访问方法例如在 aicpu_args_handler.cpp 中有如下模式auto shape aclTensor.GetOriginalShape(); for (size_t i 0; i shape.GetDimNum(); i) { AICPU_ASSERT_TRUE_RETVAL(shape.GetDim(i) 0); tensorDataInfo.add_dim(shape.GetDim(i)); }源码级实现原理底层实现从源码结构看GetOriginalShape()并非独立存储一份数据而是直接透传底层op::Tensor内封装的op::StorageShape结构中的 OriginShape 字段实现位于 common_types.cppconst op::Shape aclTensor::GetStorageShape() const { return tensor_-GetShape().GetStorageShape(); } const op::Shape aclTensor::GetOriginalShape() const { return tensor_-GetShape().GetOriginShape(); } const op::Shape aclTensor::GetViewShape() const { return viewShape_; }即GetOriginalShape()等价于tensor_-GetShape().GetOriginShape()。注意实现返回的是const op::Shape引用头文件声明中返回值写作gert::Shape避免了拷贝开销因此调用方读取后不应修改其内容。OriginShape 在构造阶段如何被记录在 aclTensor 的构造过程中OriginShape 被显式写入op::StorageShape。以存储格式与原始格式可区分的构造重载为例common_types.cppaclTensor::aclTensor(const op::Shape storageShape, const op::Shape originShape, op::DataType dataType, op::Format storageFormat, op::Format originFormat, void* tensorDataAddr) : storage_(new(std::nothrow) aclStorage(tensorDataAddr, true)), viewOffset_(0), viewStrides_(), viewShape_(originShape), viewFormat_(originFormat) { ... op::StorageShape gertShape; op::StorageFormat gertFormat; gertShape.MutableStorageShape() storageShape; gertShape.MutableOriginShape() originShape; ... }从源码可以推断以下要点当仅传入单一shape构造 aclTensor 时common_types.cpp内部会以shape, shape同时作为 storageShape 与 originShape 构造即三种 shape 在初始时保持一致aclTensor::aclTensor(const op::Shape shape, op::DataType dataType, op::Format format, void* tensorDataAddr) : aclTensor(shape, shape, dataType, format, format, tensorDataAddr) {}测试 test_common_types.cpp 验证了这一行为单一 shape 构造后GetOriginalShape()、GetStorageShape()、GetViewShape()三者相等。当 storageShape 与 originShape 分别传入时GetOriginalShape()返回构造时给定的 originShapeGetStorageShape()返回 storageShape测试见 test_common_types.cpp。通过视图view构造的 aclTensor 会继承源张量的 shape 语义test_common_types.cpp且CreateView创建的视图张量其GetOriginalShape()为视图形状test_common_types.cpp。与 SetOriginalShape 的对应关系OriginShape 属性可读可写写入接口为SetOriginalShape(const op::Shape shape)其实现同样直接操作底层 tensorvoid aclTensor::SetOriginalShape(const op::Shape shape) const { tensor_-MutableOriginShape() shape; }典型用法见 SetOriginalShape.md 调用示例先构造gert::Shape并通过AppendDim逐维追加再写入void Func(aclTensor *input) { gert::Shape newShape; for (int64_t i 1; i 5; i) { newShape.AppendDim(i); } input-SetOriginalShape(newShape); // 将 input 的 OriginShape 设置为 [1, 2, 3, 4, 5] }在仓库中的真实调用链与使用场景GetOriginalShape()在 opbase 框架内被多处核心链路调用可作为理解其用途的最佳佐证。1. AICPU 任务扩展信息ExtInfo下发在 aicpu_ext_info_handle.cpp 中构建 AICPU 输入信息时直接取tensors[index]-GetOriginalShape()写入扩展信息并做形状更新auto shape tensors[index]-GetOriginalShape(); AICPU_ASSERT_OK_RETVAL(UpdateShape(shape, inputs[index]));输出侧同样会同时打印 ViewShape、StorageShape、OriginalShape 三套形状aicpu_ext_info_handle.cpp便于算子侧核对逻辑形状与实际存储形状的差异OP_LOGI(output[%zu], ViewShape is %s, StorageShape is %s, OriginalShape is %s., i, op::ToString(outputs[i]-GetViewShape()).GetString(), op::ToString(outputs[i]-GetStorageShape()).GetString(), op::ToString(outputs[i]-GetOriginalShape()).GetString());2. AICPU 参数序列化在 aicpu_args_handler.cpp 中张量 shape 信息以GetOriginalShape()为来源逐维写入 protobuf 的 TensorShape作为算子参数的一部分下发auto shape aclTensor-GetOriginalShape(); const auto dimNum shape.GetDimNum(); for (size_t index 0U; index dimNum; index) { aicpuops::TensorShape_Dim* aicpuDims aicpuShape-add_dim(); ... }同时Host 侧张量的内存大小也是基于GetOriginalShape().GetShapeSize()结合数据类型计算的aicpu_args_handler.cppauto hostTensorSize GetSizeInBytes(inputs[i]-GetOriginalShape().GetShapeSize(), inputs[i]-GetDataType());3. 输出形状推导infershape在 shape_inference.cpp 中默认的UpdateOutputShape以输入张量的 OriginalShape 作为输出 StorageShape 的基准aclnnStatus UpdateOutputShape(aclTensor* tensor) { auto originalShape tensor-GetOriginalShape(); tensor-SetStorageShape(originalShape); ... }4. 数据搬移与张量复用在 z_framework_op.cpp 中张量拷贝/复用操作通过同时读取GetStorageShape()与GetOriginalShape()以及对应的 format 信息完整重建目标张量保证逻辑形状与存储形状都不丢失auto dst executor-AllocTensor(src-GetStorageShape(), src-GetOriginalShape(), src-GetDataType(), src-GetStorageFormat(), src-GetOriginalFormat());5. 诊断信息与序列化输出op_dfx.cpp 在转储算子输入输出信息时同时收集 storageShape 与 originShapeinfo.originShape.push_back(originShape.GetDim(jj))用于问题定位。tiling_context_to_json.cpp 将opShape-GetOriginShape()各维写入 JSON 的origin_shape字段。aclTensor 的ToString()调试输出也会带上ori_shapecommon_types.cpp。单元测试验证仓库单元测试对GetOriginalShape()的行为有系统验证可据此理解接口的精确语义test_common_types.cpp构造后校验GetOriginalShape()等于构造传入的 storageShape单 shape 构造场景同时GetOriginalFormat()为FORMAT_ND。test_common_types.cpp分别传入 storageShape 与 originShape 时GetOriginalShape()精确返回 originShape与GetViewShape()一致。test_common_types.cpp对CreateView产生的视图张量GetOriginalShape()为视图形状{16, 16, 16}而GetStorageShape()保持源张量的存储形状{4913}——直观展示了 OriginShape 与 StorageShape 解耦的语义。test_kernel_workspace.cpp 与 test_binary_resuse.cpp验证 workspace 张量的GetOriginalShape()与预期形状一致。使用建议与注意事项只读语义GetOriginalShape()用于读取逻辑形状不要通过返回值修改底层数据需要改写时应使用 SetOriginalShape。与 StorageShape 的区分算子侧做维度循环、广播等逻辑运算时应以 OriginShape数学形状为准涉及内存排布、步长计算时需结合GetStorageShape()与 format 信息参见 GetStorageShape。默认一致性未显式区分构造时OriginShape 与 StorageShape、ViewShape 初始保持一致经过 transdata、视图切片等操作后三者才可能出现差异。跨接口配合OriginShape 与 OriginFormat 描述同一逻辑层面的属性判断张量的原始形态时建议同时读取GetOriginalFormat()参见 GetOriginalFormat.md以获得完整的逻辑描述。【免费下载链接】opbase本项目是CANN算子库的基础框架库为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询