ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CANN opbase aclTensor 接口详解:SetOriginalShape 设置 OriginShape 的原理与实战

CANN opbase aclTensor 接口详解:SetOriginalShape 设置 OriginShape 的原理与实战 CANN opbase aclTensor 接口详解SetOriginalShape 设置 OriginShape 的原理与实战【免费下载链接】opbase本项目是CANN算子库的基础框架库为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase导读SetOriginalShape是 CANN opbase 框架库中aclTensor提供的核心元数据设置接口用于显式设置张量的 OriginShape原始形状。OriginShape 描述了 tensor 在经历 transdata 数据转换节点之前如果存在该节点的数学形状是算子开发与推理引擎理解张量语义的关键信息。读完本文你将掌握SetOriginalShape的函数原型、参数约束、与 StorageShape / ViewShape 的区别以及它在底层源码中的实现机制和实际调用场景。功能说明SetOriginalShape用于设置aclTensor的 OriginShape 属性。OriginShape 表示 aclTensor 在经历 transdata 节点前如果存在该节点的原始 shape 信息即 tensor 的 shape 数学描述。在 CANN 图编译与算子执行链路中张量可能因内存排布优化如转为 FRACTAL_NZ 等专用格式而插入 transdata 转换节点此时内存上的实际排布StorageShape与逻辑上的数学形状OriginShape会发生分离。OriginShape 保留的是数学上的形状是上层算子描述、shape 推导与用户感知所依赖的视图。函数原型void SetOriginalShape(const op::Shape shape)从源码声明看aclTensor::SetOriginalShape是一个 const 成员方法修改的是内部 tensor 对象的属性而非 aclTensor 外壳本身完整声明位于 include/nnopbase/opdev/common_types.hconst op::Shape GetOriginalShape() const; void SetOriginalShape(const op::Shape shape) const;参数说明参数输入/输出说明shape输入数据类型为op::Shape即gert::Shape记录了一组 shape 信息例如一个三维 shape[10, 20, 30]。关于参数类型可以在 include/nnopbase/opdev/common_types.h 中找到类型别名定义namespace op { constexpr uint64_t MAX_DIM_NUM 25; using ShapeVector FVectorint64_t, MAX_DIM_NUM; using Shape gert::Shape;要点如下op::Shape是gert::Shape的别名二者可直接互换使用op::Shape内部基于FVectorint64_t, MAX_DIM_NUM实现其中MAX_DIM_NUM 25即单次设置时 shape 的维数上限为 25 维框架内的公共约束shape 的每个维度取值为int64_t类型可通过AppendDim逐个追加维度也可直接使用op::Shape{...}初始化列表构造测试代码中广泛使用后一种写法例如op::Shape{32}。返回值说明无返回值void。约束说明原文档声明无约束。从实现层面补充两点可以推断的说明SetOriginalShape仅更新张量的 OriginShape 元数据不会触发底层内存分配或数据拷贝与SetStorageShape不同——后者在修改内存排布描述后会调用tensor_-SetSize(...)同步调整 tensor 大小见下文源码对比传入的 shape 维数不应超过框架约定的MAX_DIM_NUM25否则建议在调用前进行必要的合法性校验。源码实现与原理分析SetOriginalShape的底层实现位于 src/nnopbase/common/utils/common_types.cppvoid aclTensor::SetOriginalShape(const op::Shape shape) const { tensor_-MutableOriginShape() shape; }实现非常简洁通过tensor_内部持有的op::Tensor即gert::TensorV2的MutableOriginShape()返回 OriginShape 的可变引用再整体赋值为传入的 shape。与 GetOriginalShape 的对应关系读取方向由 GetOriginalShape 完成其实现同样位于 src/nnopbase/common/utils/common_types.cppconst op::Shape aclTensor::GetOriginalShape() const { return tensor_-GetShape().GetOriginShape(); }即 OriginShape 最终保存在底层gert::Tensor的GetShape()所返回的 Shape 描述结构中SetOriginalShape与GetOriginalShape读写的是同一份数据构成一对完整的设置/读取原语。与 SetStorageShape 的关键差异对比 SetStorageShape 的实现src/nnopbase/common/utils/common_types.cppvoid aclTensor::SetStorageShape(const op::Shape shape) const { tensor_-MutableStorageShape() shape; // tensor size need to resize when storage shape update tensor_-SetSize(op::CalcShapeBytes(tensor_-GetShapeSize(), tensor_-GetDataType())); }可以看到SetStorageShape修改 StorageShape 后会通过SetSize重新计算并更新 tensor 占用的字节数因为内存排布变化直接决定存储大小SetOriginalShape只修改数学形状描述不触碰size 计算——这正体现了OriginShape 是数学描述、不影响内存布局的设计语义。与 ViewShape 的区分除了 OriginShape / StorageShapeaclTensor还维护 ViewShape 与 ViewStrides见 include/nnopbase/opdev/common_types.h 的完整接口族。三者的定位可以概括为属性语义代表问题OriginShape数学形状描述transdata 节点之前的原始 shape这个张量逻辑上是几乘几StorageShape内存上的实际排布数据在内存里怎么摆ViewShape视图视角的形状配合 ViewStrides 描述切片/非连续视图以某个 stride 看待这个张量是什么形状SetOriginalShape只负责第一项是三者中语义最上层、最贴近数学描述的一环。调用示例原文档示例将input的 OriginShape 设置为[1, 2, 3, 4, 5]// 将input的OriginShape设置为[1, 2, 3, 4, 5] void Func(aclTensor *input) { gert::Shape newShape; for (int64_t i 1; i 5; i) { newShape.AppendDim(i); } input-SetOriginalShape(newShape); }结合源码可以给出两种等价写法写法一通过 AppendDim 逐个追加维度与示例一致gert::Shape shape; shape.AppendDim(1); shape.AppendDim(2); shape.AppendDim(3); shape.AppendDim(4); shape.AppendDim(5); input-SetOriginalShape(shape);写法二使用初始化列表直接构造测试代码中的常见风格input-SetOriginalShape(op::Shape({1, 2, 3, 4, 5}));读写配对示例void Func(const aclTensor *input) { auto shape input-GetOriginalShape(); // 读取当前 OriginShape input-SetOriginalShape(shape); // 原样写回或修改后再写回 }测试验证OriginShape 与 StorageShape 的独立性仓库测试用例验证了 OriginShape 可以与 StorageShape 不同这正是SetOriginalShape存在意义的直接证据。在 tests/nnopbase/ut/composite_op/test_common_types.cpp 中CHECK_WS_TENSOR_DIFF_FORMAT宏创建了不同格式的张量并分别断言三类 shape#define CHECK_WS_TENSOR_DIFF_FORMAT(tensorName, storageShape, originShape, dataType, storageFormat, originFormat, \ tensorData) \ aclTensor tensorName(storageShape, originShape, dataType, storageFormat, originFormat, tensorData); \ EXPECT_EQ(tensorName.GetViewShape(), originShape); \ EXPECT_EQ(tensorName.GetOriginalShape(), originShape); \ EXPECT_EQ(tensorName.GetStorageShape(), storageShape); \ ... TEST_F(CommonTypesTest, CreateWorkspaceTensorDiffFormat) { CHECK_WS_TENSOR_DIFF_FORMAT(c, Shape({16, 16}), Shape({16 * 16}), DataType::DT_FLOAT, Format::FORMAT_FRACTAL_NZ, Format::FORMAT_ND, nullptr); }该用例中同一个 aclTensor 的 StorageShape 为{16, 16}FRACTAL_NZ 格式的内存排布而 OriginShape 为{256}ND 格式的数学描述——二者并存且互不干扰印证了OriginShape 是 transdata 前的数学描述、StorageShape 是实际内存排布的核心语义。实际调用场景动态 shape 输出刷新在算子执行完成后刷新输出张量 shape 的场景中SetOriginalShape会与SetStorageShape、SetViewShape一起被调用。见 src/nnopbase/individual_op/executor/indv_executor.cppit-second-SetStorageShape(newShape); it-second-SetOriginalShape(newShape); it-second-SetViewShape(newShape); OP_LOGI(Refresh output[%u] shape successfully, shape is %s, it-first, op::ToString(newShape).GetString());这里在执行器读取到设备侧返回的动态输出 shape 后将三份 shape 描述同步刷新为最新值保证后续算子与框架侧拿到的 OriginShape / StorageShape / ViewShape 保持一致。由此可以看出SetOriginalShape在动态 shape 推理、workspace 张量管理等运行时路径中承担着关键的元数据同步职责。小结SetOriginalShape(const op::Shape shape)是aclTensor设置 OriginShape 的入口参数类型op::Shape即gert::Shape的别名支持AppendDim逐维构建与初始化列表两种构造方式底层实现一行完成tensor_-MutableOriginShape() shape;仅更新数学形状元数据不影响内存布局与 tensor sizeOriginShape / StorageShape / ViewShape 三套 shape 各有分工其中 OriginShape 专指 transdata 节点之前的数学描述相关接口完整清单见 common_types 接口列表测试用例tests/nnopbase/ut/composite_op/test_common_types.cpp与执行器源码src/nnopbase/individual_op/executor/indv_executor.cpp共同验证了该接口在非连续格式张量、动态 shape 输出刷新等真实场景下的行为可作为算子开发时参考的调用范式。【免费下载链接】opbase本项目是CANN算子库的基础框架库为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表