news 2026/10/16 2:01:01

AscendC 算子属性定义指南:OpAttrDef 接口全解析(asc-devkit)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AscendC 算子属性定义指南:OpAttrDef 接口全解析(asc-devkit)
  • 人工智能
  • 深度学习
  • 算子库
  • CANN
  • Ascend

【免费下载链接】asc-devkit

本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C++标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。

项目地址:https://gitcode.com/cann/asc-devkit
点击查看免费下载

OpAttrDef 是 CANN asc-devkit 中用于定义算子属性的核心类,它在算子原型注册流程中承担"属性声明"职责:开发者通过OpDef::Attr()进入属性注册后,由 OpAttrDef 的链式接口逐一指定属性的类型(必选/可选)、数据类型、默认值、版本号与注释。本文以docs/zh/api/Utils-API/prototype_register_management/OpAttrDef/OpAttrDef_functions.md为主线,结合仓库内的真实算子示例与单测用例,完整讲解每个成员函数的用法、约束与底层影响,帮助你在自定义算子工程中正确、稳定地注册属性。

一、功能定位:OpAttrDef 在算子原型注册中的角色

在 asc-devkit 的原型注册体系中,一个算子的"长相"由 OpDef 描述,其中输入、输出通过 Input/Output 注册,而不参与核函数(Kernel)侧计算、仅在构图/编译期使用的参数则应注册为算子属性参数,入口即OpDef::Attr():

OpAttrDef &Attr(const char *name);

Attr()返回的正是OpAttrDef引用,因此所有属性描述动作都以this->Attr("属性名").xxx()链式调用展开。OpAttrDef 的职责可概括为四点:

  1. 记录属性名称(构造时传入);
  2. 声明属性类型(AttrType,OPTIONAL 可选 / REQUIRED 必选);
  3. 声明属性数据类型并可选地设置默认值(Bool/Float/Int/String/ListBool/ListFloat/ListInt/ListListInt);
  4. 为 aclnn 接口版本兼容(Version)与注释生成(Comment,见 Comment)提供支撑。

基于 OpDef 算子原型定义,自定义算子工程可以自动生成图模式场景使用的算子原型头文件,开发者可使用生成的算子原型进行构图、图编译、图执行等操作;属性注释也会同步生成到原型头文件中。

二、类原型总览

OpAttrDef 的完整函数原型如下(OpAttrDef_functions.md原文):

class OpAttrDef { public: explicit OpAttrDef(const char *name); OpAttrDef(const OpAttrDef &attr_def); ~OpAttrDef(); OpAttrDef &operator=(const OpAttrDef &attr_def); OpAttrDef &AttrType(Option attr_type); OpAttrDef &Bool(void); OpAttrDef &Bool(bool value); OpAttrDef &Float(void); OpAttrDef &Float(float value); OpAttrDef &Int(void); OpAttrDef &Int(int64_t value); OpAttrDef &String(void); OpAttrDef &String(const char *value); OpAttrDef &ListBool(void); OpAttrDef &ListBool(std::vector<bool> value); OpAttrDef &ListFloat(void); OpAttrDef &ListFloat(std::vector<float> value); OpAttrDef &ListInt(void); OpAttrDef &ListInt(std::vector<int64_t> value); OpAttrDef &ListListInt(void); OpAttrDef &ListListInt(std::vector<std::vector<int64_t>> value); OpAttrDef &Version(uint32_t version); ge::AscendString &GetName(void) const; bool IsRequired(void); private: ... };

设计要点:除构造函数外,绝大多数成员函数返回OpAttrDef &,这是支持this->Attr("name").AttrType(...).Float(...)连续链式调用的关键;explicit修饰的构造函数禁止隐式转换,强制显式传入属性名称。

三、成员函数逐项详解

下表完整列出 OpAttrDef 全部公开成员函数的入参与功能(继承自原文档"表1 OpAttrDef类成员函数说明")。

函数名称入参说明功能说明
OpAttrDefname: 算子属性名称构造算子属性定义 OpAttrDef,并设置属性名称。
OpAttrDefattr_def: 已构造完成的算子属性 OpAttrDef拷贝构造 OpAttrDef,复制被拷贝对象的属性名称、属性数据类型、属性类型、默认值、版本号和注释等配置。
AttrTypeattr_type: 属性类型设置算子属性类型,取值为:OPTIONAL(可选)、REQUIRED(必选)。
Bool无设置算子属性数据类型为 Bool。
Boolvalue设置算子属性数据类型为 Bool,并设置属性默认值为 value。属性类型设置为 OPTIONAL 时必须调用该类接口设置默认值。
Float无设置算子属性数据类型为 Float。
Floatvalue设置算子属性数据类型为 Float,并设置属性默认值为 value。属性类型设置为 OPTIONAL 时必须调用该类接口设置默认值。
Int无设置算子属性数据类型为 Int。
Intvalue设置算子属性数据类型为 Int,并设置属性默认值为 value。属性类型设置为 OPTIONAL 时必须调用该类接口设置默认值。
String无设置算子属性数据类型为 String。
Stringvalue设置算子属性数据类型为 String,并设置属性默认值为 value。属性类型设置为 OPTIONAL 时必须调用该类接口设置默认值。
ListBool无设置算子属性数据类型为 ListBool。
ListBoolvalue设置算子属性数据类型为 ListBool,并设置属性默认值为 value。属性类型设置为 OPTIONAL 时必须调用该类接口设置默认值。
ListFloat无设置算子属性数据类型为 ListFloat。
ListFloatvalue设置算子属性数据类型为 ListFloat,并设置属性默认值为 value。属性类型设置为 OPTIONAL 时必须调用该类接口设置默认值。
ListInt无设置算子属性数据类型为 ListInt。
ListIntvalue设置算子属性数据类型为 ListInt,并设置属性默认值为 value。属性类型设置为 OPTIONAL 时必须调用该类接口设置默认值。
ListListInt无设置算子属性数据类型为 ListListInt。
ListListIntvalue设置算子属性数据类型为 ListListInt,并设置属性默认值为 value。属性类型设置为 OPTIONAL 时必须调用该类接口设置默认值。
Versionversion:配置的版本号新增可选属性时,为了保持原有单算子 API(aclnnxxx)接口的兼容性,可以通过 Version 接口配置 aclnn 接口的版本号。版本号需要从 1 开始配,且应该连续配置(和可选输入统一编号)。配置后,自动生成的 aclnn 接口会携带版本号,高版本号的接口会包含低版本号接口的所有参数。
GetName无获取属性名称。
IsRequired无判断算子属性是否为必选,必选返回 true,可选返回 false。

3.1 构造函数与拷贝构造

  • explicit OpAttrDef(const char *name):唯一必需的入参是属性名称。属性名将作为该属性的唯一标识,后续GetName()返回的名称即构造时传入的 name,其类型为ge::AscendString。
  • OpAttrDef(const OpAttrDef &attr_def):拷贝构造会完整复制源对象的全部配置,包括属性名称、属性数据类型、属性类型(OPTIONAL/REQUIRED)、默认值、版本号和注释,适合在需要复用同一套属性描述时使用。
  • 赋值运算符operator=与拷贝构造语义一致,配合类内部的资源管理(析构函数~OpAttrDef())保证复制安全。

3.2 属性类型:AttrType

OpAttrDef &AttrType(Option attr_type);
  • OPTIONAL:可选属性,调用方可以不传;此时必须通过带默认值的接口(如Float(0.0f))设置默认值;
  • REQUIRED:必选属性,调用方必须显式提供该属性值。

从仓库测试可见,必选/可选属性在同一算子中可以混用,例如 test_ops.cpp 中的FallBackTest原型同时声明了bias1(REQUIRED)与bias0(OPTIONAL)。此外,IsRequired()即返回该属性的必选性,供生成器判断 aclnn 接口参数是否需要携带默认值。

3.3 数据类型设置接口

OpAttrDef 支持 8 种属性数据类型,每个类型都提供"无参(仅声明类型)"与"带值(声明类型 + 默认值)"两个重载:

数据类型无参接口带默认值接口C++ 对应类型
BoolBool()Bool(bool value)bool
FloatFloat()Float(float value)float
IntInt()Int(int64_t value)int64_t
StringString()String(const char *value)const char *
ListBoolListBool()ListBool(std::vector<bool> value)std::vector<bool>
ListFloatListFloat()ListFloat(std::vector<float> value)std::vector<float>
ListIntListInt()ListInt(std::vector<int64_t> value)std::vector<int64_t>
ListListIntListListInt()ListListInt(std::vector<std::vector<int64_t>> value)std::vector<std::vector<int64_t>>

使用要点:

  1. 必选属性可以只调用无参版本声明类型,如this->Attr("bias1").AttrType(REQUIRED).Float(0.0);(test_opbuild.cpp),此时该默认值仅作类型声明占位;
  2. 可选属性必须设置默认值:this->Attr("bias0").AttrType(OPTIONAL).Int(0);(test_opbuild.cpp)。若不设置默认值,构图期未显式传参时属性取值不确定,可能导致构图失败或行为异常;
  3. 列表类属性支持用初始化列表直接构造,如ListBool({true, false})、ListFloat({0.1, 0.2})、ListInt({1, 2}),在仓库测试用例 test_ops.cpp 中均有覆盖。

3.4 版本兼容:Version

OpAttrDef &Version(uint32_t version);

算子编译部署后,会自动生成单算子 API(aclnnxxx)接口,接口中的输入输出参数与算子原型定义保持一致。当算子演进需要新增可选属性时,直接新增会破坏已发布 aclnn 接口的二进制/源码兼容性,此时通过Version()为新增的可选属性(或可选输入,二者统一编号)配置版本号:

  • 版本号必须从 1 开始,且应连续配置;
  • 与可选输入的版本号统一编号(详见 Version 中的AddCustom示例:x1配.Version(1)、x2配.Version(2));
  • 配置后自动生成的 aclnn 接口会携带版本号(如aclnnAddCustomV1、aclnnAddCustomV2),高版本接口包含低版本接口的所有参数,实现向前兼容;
  • 约束:仅可选属性(AttrType 为 OPTIONAL)可以配置 Version。仓库单测 test_opbuild.cpp 验证了该约束:对 REQUIRED 属性调用.Version(1)会生成错误信息"VersionFail only optional attr can configured version."。

仓库中的完整多版本属性示例见 test_ops.cpp:

this->Attr("bias1").AttrType(OPTIONAL).Int(1).Version(1); this->Attr("bias2").AttrType(OPTIONAL).Float(0.0).Version(2); this->Attr("bias3").AttrType(OPTIONAL).Bool(true).Version(2); this->Attr("bias4").AttrType(OPTIONAL).ListBool({true, false}).Version(1); this->Attr("bias5").AttrType(OPTIONAL).ListFloat({0.1, 0.2}).Version(1); this->Attr("bias6").AttrType(OPTIONAL).ListInt({1, 2}).Version(2); this->Attr("bias7").AttrType(OPTIONAL).String("ssss").Version(2);

3.5 注释:Comment

OpAttrDef &Comment(const char *comment);

Comment()用于设置算子属性的注释:自动生成算子原型头文件时,会同步生成算子原型注释,这些注释有助于辅助理解算子原型,并可以基于注释自动生成算子原型的文档说明。调用方式为链式追加:

this->Attr("attrname").Comment("Attr cmt 1");

完整参数说明见 Comment:comment为输入参数,表示注释内容,返回值仍为算子属性定义 OpAttrDef。该能力通常以内置 CANN 算子使用较多,自定义算子可按需使用。

3.6 查询接口:GetName 与 IsRequired

  • GetName()返回属性名称(ge::AscendString),用于在生成或调试阶段识别属性;
  • IsRequired()判断属性是否为必选:必选返回true,可选返回false。

这两个接口常用于 aclnn 接口生成器内部对属性元信息的读取与校验。

四、属性命名约束(重要)

通过Attr()注册属性时,属性名不能与以下 Python 关键字及内置变量名相同,否则会导致未定义错误(来源:Attr.md):

  • 常见 Python 关键字:and、as、assert、break、class、continue、def、del、elif、else、except、finally、for、from、global、if、import、in、is、lambda、not、or、pass、raise、return、try、while、with、yield、False、None、True、nonlocal、arg;
  • 内置变量名:__inputs__、__outputs__、__attrs__、options、bisheng、bisheng_path、tikcpp_path、impl_mode、custom_compile_options、custom_all_compile_options、soc_version、soc_short、custom_compile_options_soc、custom_all_compile_options_soc、origin_func_name、ascendc_src_dir_ex、ascendc_src_dir、ascendc_src_file、src、op_type、code_channel、op_info、compile_op、get_code_channel、result、isinstance、attr、get_current_build_config、_build_args、get_dtype_fmt_options、shutil、os、get_kernel_source、ascendc_api_version_header_path、ascendc_api_version_file、ascendc_api_version、re。

命名时建议统一使用小写下划线风格(如negative_slope),避免与上述保留名冲突。

五、完整实战示例:LeakyReLU 自定义算子属性

仓库中的 leaky_relu_custom_host.cpp 是 OpAttrDef 的典型落地用法——为 LeakyReLU 注册可选属性negative_slope:

namespace ops { class LeakyReluCustom : public OpDef { public: LeakyReluCustom(const char* name) : OpDef(name) { this->Input("x").ParamType(REQUIRED).DataType({ge::DT_FLOAT}).Format({ge::FORMAT_ND}); this->Output("y").ParamType(REQUIRED).DataType({ge::DT_FLOAT}).Format({ge::FORMAT_ND}); this->Attr("negative_slope").AttrType(OPTIONAL).Float(0.0f); this->SetInferShape(ge::InferShape).SetInferDataType(ge::InferDataType); this->AICore().SetTiling(optiling::TilingFunc).AddConfig("ascend910b"); } }; OP_ADD(LeakyReluCustom); } // namespace ops

对照上文要点逐条解读:

  1. 属性声明:this->Attr("negative_slope")注册属性名为negative_slope的属性;
  2. 类型声明:.AttrType(OPTIONAL)声明为可选属性;
  3. 默认值:.Float(0.0f)声明数据类型为 Float 并设置默认值 0.0f——可选属性必须设置默认值,这里满足约束;
  4. 运行期读取:该属性的最终落地在 tiling 阶段,通过gert::RuntimeAttrs读取:
static ge::graphStatus TilingFunc(gert::TilingContext* context) { ... const gert::RuntimeAttrs* attrs = context->GetAttrs(); const float* negativeSlope = attrs->GetAttrPointer<float>(0); ... tiling->negativeSlope = *negativeSlope; return ge::GRAPH_SUCCESS; }

可以看到:属性一旦注册,即可在 Tiling 函数中按声明顺序(此处为第 0 个属性)通过GetAttrPointer<float>(0)取回,参与算子编译与调度决策。整个调用链为"OpDef 构造 → Attr() 创建 OpAttrDef → 链式配置 → OP_ADD 注册 → 原型/头文件生成 → aclnn 接口与 Tiling 消费"。

六、测试验证与常见错误

仓库的 opbuild 工具单测覆盖了 OpAttrDef 的关键行为(test_ops.cpp、test_opbuild.cpp),可作为开发自测的对照:

  • 可选属性默认值覆盖:FallBackTest同时验证了Int(0)、Float(0.0)、ListBool({true, false})、ListFloat({0.1, 0.2})、ListInt({1, 2})、String("ssss")、Bool(true)等全部带默认值形式(test_opbuild.cpp);
  • 版本约束校验:仅 OPTIONAL 属性可配 Version,对 REQUIRED 属性配置会报错"only optional attr can configured version."(test_opbuild.cpp);
  • 版本号连续性:可选属性与可选输入统一编号,版本号从 1 开始连续递增(Version.md 中的AddCustom完整示例)。

常见开发错误与规避建议汇总:

错误场景后果正确做法
可选属性不设默认值构图期属性值不确定OPTIONAL 属性必须调用带 value 的接口设置默认值
属性名使用 Python 关键字/内置变量名生成阶段未定义错误参照第四节保留名清单规避
对 REQUIRED 属性配置 Version生成报错,接口版本错乱仅对 OPTIONAL 属性配置 Version
版本号不从 1 开始或跳号生成的 aclnn 接口版本不连续版本号从 1 开始、连续递增,与可选输入统一编号
必选属性只声明类型不传值调用方必须显式传参REQUIRED 属性由调用方在构图时提供实际值

七、小结

OpAttrDef 是 asc-devkit 算子原型注册体系(原型注册与管理)中描述算子属性的标准接口。掌握它需要记住三条主线:类型声明(AttrType 必选/可选 + 8 种数据类型)、默认值绑定(可选属性必设)、版本演进(Version 与 aclnn 接口兼容)。结合 leaky_relu_custom_host.cpp 等仓库示例与 opbuild 单测,开发者可以快速在自定义算子工程中落地健壮的属性定义,并为后续构图、图编译与 aclnn 单算子调用链路提供正确的属性元信息。

  • 人工智能
  • 深度学习
  • 算子库
  • CANN
  • Ascend

【免费下载链接】asc-devkit

本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C++标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。

项目地址:https://gitcode.com/cann/asc-devkit
点击查看免费下载

相关推荐

上一篇:如何使用OBS-Multi-RTMP插件实现多平台同步直播?超简单教程来了! 🚀
下一篇:如何快速下载全网资源?2025年超实用的res-downloader资源嗅探工具全指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/16 2:00:57

手写全连接神经网络:Numpy实现前向传播、反向传播与梯度下降

简介&#xff1a;这是用Python和NumPy从零实现的一个简单全连接神经网络代码包&#xff0c;面向希望理解深度学习底层原理的入门开发者。全连接神经网络&#xff08;多层感知器&#xff09;由输入层、隐藏层和输出层组成&#xff0c;信息逐层前向传递&#xff0c;代码不依赖Ten…

作者头像 李华
网站建设 2026/10/16 1:57:31

python中的浮点数运算、round()

0.1 &#xff0c;计算机会想“没前缀&#xff0c;是十进制&#xff0c;我要转成二进制存”&#xff1b;你写 0b0.00011 &#xff0c;它才会想“有 0b &#xff0c;是二进制&#xff0c;我直接按二进制存”。 计算机是以二进制来存储数据的&#xff0c;而像 0.1 、 0.2 这样的十…

作者头像 李华