十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

CANN opbase Elewise 算子形状推导:InferShape4Elewise 接口解析与实战

CANN opbase Elewise 算子形状推导:InferShape4Elewise 接口解析与实战 CANN opbase Elewise 算子形状推导InferShape4Elewise 接口解析与实战【免费下载链接】opbase本项目是CANN算子库的基础框架库为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase导读InferShape4Elewise是 CANN opbase 基础框架库为 elewise逐元素运算类算子提供的标准 InferShape 推导函数。它解决图模式场景下输出张量形状推导这一核心问题对于满足单输入、单输出且输入输出形状一致这一规律的算子开发者无需重写形状推导逻辑直接复用该函数即可完成注册。本文将从功能语义、函数原型、参数与返回值约定出发结合 源码实现 剖析其内部处理流程含 UnknownRank 动态形状分支并通过 IsFinite 算子的注册示例给出可直接落地的接入方法帮助算子开发者快速完成 elewise 类算子的 InferShape 实现。功能说明Elewise 算子的形状推导语义在图模式Graph 模式下算子实现分为 Host 侧与 Device 侧其中 Host 侧的 InferShape 方法负责在构图或编译阶段推导输出张量的形状shape为后续的形状推导、内存分配和算子调度提供依据。InferShape4Elewise专门服务于 elewise逐元素类算子。此类算子的典型特征是对输入张量的每个元素独立执行相同的运算如取绝对值、取反、类型转换等因此输出张量的形状与输入张量逐位相同。opbase 将其抽象为一个可复用的公共推导函数声明位于 include/op_common/op_host/infershape_elewise_util.h头文件中的注释对该函数的适用前提做了精确定义Do infershape for OP which is single-input single-output and in-shape equal out-shape.即单输入、单输出且输入形状等于输出形状。这是决定能否复用一个算子的判断准则——凡是满足该条件的算子都可以直接或间接调用InferShape4Elewise完成推导无需编写重复代码。该函数位于Ops::Base命名空间并通过OPBASE_API导出宏对外暴露供算子工程链接使用。在 opbase 的整体 InferShape 公共能力体系中它属于逐元素类推导工具与 broadcast 类InferShape4Broadcast、reduce 类InferShape4Reduce共同构成覆盖主要算子族形状推导的公共函数集完整的接口清单可参见 infershape.md 与 0_op_common_list.md。函数原型ge::graphStatus InferShape4Elewise(gert::InferShapeContext *context)该函数只有一个context参数。gert::InferShapeContext是 GEGraph Engine侧提供的 InferShape 运行时上下文通过它可以读取输入张量信息并写入输出张量信息。值得注意的是源码实现 中实际使用的是gert::InferShapeContext* context星号紧贴参数名两种书写风格在 C 语法上完全等价。参数说明参数名输入/输出说明context输出GE 传入的 InferShape 上下文封装了节点的输入/输出张量形状信息。关于context的输入/输出属性需要结合源码做更准确的理解context本身是由 GE 传入的上下文对象对调用方而言是输入但函数内部既会从该上下文中读取输入形状context-GetInputShape(0)也会通过它写入输出形状context-GetOutputShape(0)因此文档中标注为输出是指该参数承载了推导结果的写回能力。返回值说明返回类型为ge::graphStatusge::GRAPH_SUCCESSInferShape 成功。ge::GRAPH_FAILInferShape 失败。需要说明的是从 当前源码实现 看函数在正常路径上始终返回ge::GRAPH_SUCCESSGRAPH_FAIL是接口契约中保留的失败返回语义供调用方如外层包装函数在发生错误时向上层 GE 传递失败状态。开发者自研推导函数时应遵循同样的返回值约定确保 GE 侧能正确识别推导是否成功。约束说明原接口文档声明无约束。从源码与头文件注释可以进一步明确其适用边界算子结构约束必须为单输入、单输出算子且输出形状与输入形状一致即in-shape equal out-shape否则不应复用本函数。动态形状约束输入为未知 rankUnknownRank场景同样受支持函数内部会对该分支做专门处理见下文实现原理无需调用方额外判断。实现原理从源码看内部处理流程InferShape4Elewise的实现非常精简完整逻辑位于 src/op_common/op_host/infershape_elewise_util.cpp整体可分为三个步骤ge::graphStatus InferShape4Elewise(gert::InferShapeContext* context) { auto inShape context-GetInputShape(0); OP_CHECK_NULL_WITH_CONTEXT(context, inShape); auto outShape context-GetOutputShape(0); OP_CHECK_NULL_WITH_CONTEXT(context, outShape); if (IsUnknownRank(*inShape)) { OP_LOGD(context-GetNodeName(), input shape is UnknownRank, set output shape to (-2, )); SetUnknownRank(*outShape); return ge::GRAPH_SUCCESS; } *outShape *inShape; return ge::GRAPH_SUCCESS; }步骤一获取并校验输入/输出 Shape 指针通过context-GetInputShape(0)与context-GetOutputShape(0)分别取得输入张量索引 0与输出张量索引 0的 shape 对象指针。随后使用OP_CHECK_NULL_WITH_CONTEXT宏对两个指针做空指针保护若任一指针为空宏会记录上下文日志并直接返回失败防止后续解引用空指针导致崩溃。这体现了 opbase 公共函数对 GE 异常输入的防御性设计。步骤二UnknownRank 动态形状分支调用IsUnknownRank(*inShape)判断输入形状是否为未知秩UnknownRank。在 opbase 的形状语义中UnknownRank 用特殊的-2标记表示其判定与设置逻辑实现在 src/op_common/op_host/util/shape_util.cpp常量约定UNKNOWN_RANK_DIM_VALUE -2LL未知秩标记UNKNOWN_DIM_VALUE -1LL未知维度标记SetUnknownRank(shape)先将 shape 的维数清零再追加一个值为-2的维度使形状呈现为(-2,)IsUnknownRank(shape)当 shape 的维数为 1 且唯一维度的值为-2时判定为 UnknownRank。因此当输入为动态形状且秩未知时输出形状被原样标记为(-2,)即 UnknownRank保证动态场景下推导结果同样具备未知语义不会误判为确定的静态形状。这与 IsUnknownRank / SetUnknownRank 等配套接口 的定义保持一致。步骤三静态形状直接拷贝当输入形状不是 UnknownRank 时直接执行*outShape *inShape将输入形状整体拷贝给输出形状。这正是 elewise 类算子输出形状等于输入形状语义的最直接体现。此外与同族的 InferShape4Broadcast支持多输入重载相比InferShape4Elewise只提供单输入接口因为逐元素运算天然只关心单一输入的形状无需广播规则参与。调用示例以 IsFinite 算子为模板当需要为满足上述约束的算子接入形状推导时典型做法是编写一个薄封装函数内部直接委托给InferShape4Elewise然后通过IMPL_OP_INFERSHAPE宏注册到 GE。原文档以 IsFinite 算子为例关键代码如下仅供参考不支持直接拷贝运行需结合自身算子工程适配// IsFinite算子进行inferShape推导其推导过程与Elewise算子推导过程一致可直接复用 ge::graphStatus InferShape4IsFinite(gert::InferShapeContext* context) { return Ops::Base::InferShape4Elewise(context); } // IsFinite算子及其推导函数注册到GE IMPL_OP_INFERSHAPE(IsFinite).InferShape(InferShape4IsFinite);接入步骤可归纳为包含头文件在算子 Host 侧实现文件中引入op_common/op_host/infershape_elewise_util.h以获得Ops::Base::InferShape4Elewise的声明编写包装函数定义形如InferShape4Xxx(gert::InferShapeContext* context)的函数函数体直接return Ops::Base::InferShape4Elewise(context);。这一层包装的存在使得算子名与推导函数解耦也便于后续在委托前后插入算子特有的处理逻辑注册到 GE通过IMPL_OP_INFERSHAPE(算子名).InferShape(包装函数)宏将推导函数绑定到对应算子使 GE 在构图阶段自动调用。IMPL_OP_INFERSHAPE宏是算子 Host 侧声明与注册 InferShape 的标准入口与 op_common 文档体系中的 op_common_api_introduction.md 所描述的注册机制一致。对于多输入或多输出的算子族则应评估是否改用 InferShape4Broadcast多输入广播或 InferShape4Reduce归约类等更匹配的公共函数。适用场景与使用建议结合文档与源码给出如下实践建议何时复用本函数算子满足单输入、单输出、逐元素运算三个条件时如 IsFinite、Abs、Neg、类型转换类算子应优先复用InferShape4Elewise避免重复实现推导逻辑也避免因手写推导遗漏 UnknownRank 分支而引入动态形状缺陷。何时不可复用存在多个输入参与形状运算如 Add 的广播语义、输出形状与输入不同如 reduce 类、reshape 类的算子不能直接复用本函数应选择对应族类的公共函数或自行实现推导。动态形状的正确性本函数对 UnknownRank 输入会透传(-2,)标记对秩已知但个别维度未知UnknownShape的情况则直接拷贝形状维度上的-1未知标记随拷贝自然保留动态形状语义不会丢失。总结InferShape4Elewise是 CANN opbase 框架面向 elewise 算子族提供的高复用形状推导原语对外以ge::graphStatus InferShape4Elewise(gert::InferShapeContext*)的简洁接口呈现对内通过空指针校验、UnknownRank 特判与形状拷贝三步完成输出形状等于输入形状的推导语义。理解其内部实现infershape_elewise_util.cpp与配套的形状工具shape_util.cpp是快速为自研逐元素算子接入图模式形状推导、保证静态与动态场景一致性的关键。【免费下载链接】opbase本项目是CANN算子库的基础框架库为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表