- 人工智能
- 深度学习
- 算子库
- CANN
- Ascend
【免费下载链接】asc-devkit
本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C++标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。
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 的职责可概括为四点:
- 记录属性名称(构造时传入);
- 声明属性类型(
AttrType,OPTIONAL 可选 / REQUIRED 必选); - 声明属性数据类型并可选地设置默认值(
Bool/Float/Int/String/ListBool/ListFloat/ListInt/ListListInt); - 为 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类成员函数说明")。
| 函数名称 | 入参说明 | 功能说明 |
|---|---|---|
| OpAttrDef | name: 算子属性名称 | 构造算子属性定义 OpAttrDef,并设置属性名称。 |
| OpAttrDef | attr_def: 已构造完成的算子属性 OpAttrDef | 拷贝构造 OpAttrDef,复制被拷贝对象的属性名称、属性数据类型、属性类型、默认值、版本号和注释等配置。 |
| AttrType | attr_type: 属性类型 | 设置算子属性类型,取值为:OPTIONAL(可选)、REQUIRED(必选)。 |
| Bool | 无 | 设置算子属性数据类型为 Bool。 |
| Bool | value | 设置算子属性数据类型为 Bool,并设置属性默认值为 value。属性类型设置为 OPTIONAL 时必须调用该类接口设置默认值。 |
| Float | 无 | 设置算子属性数据类型为 Float。 |
| Float | value | 设置算子属性数据类型为 Float,并设置属性默认值为 value。属性类型设置为 OPTIONAL 时必须调用该类接口设置默认值。 |
| Int | 无 | 设置算子属性数据类型为 Int。 |
| Int | value | 设置算子属性数据类型为 Int,并设置属性默认值为 value。属性类型设置为 OPTIONAL 时必须调用该类接口设置默认值。 |
| String | 无 | 设置算子属性数据类型为 String。 |
| String | value | 设置算子属性数据类型为 String,并设置属性默认值为 value。属性类型设置为 OPTIONAL 时必须调用该类接口设置默认值。 |
| ListBool | 无 | 设置算子属性数据类型为 ListBool。 |
| ListBool | value | 设置算子属性数据类型为 ListBool,并设置属性默认值为 value。属性类型设置为 OPTIONAL 时必须调用该类接口设置默认值。 |
| ListFloat | 无 | 设置算子属性数据类型为 ListFloat。 |
| ListFloat | value | 设置算子属性数据类型为 ListFloat,并设置属性默认值为 value。属性类型设置为 OPTIONAL 时必须调用该类接口设置默认值。 |
| ListInt | 无 | 设置算子属性数据类型为 ListInt。 |
| ListInt | value | 设置算子属性数据类型为 ListInt,并设置属性默认值为 value。属性类型设置为 OPTIONAL 时必须调用该类接口设置默认值。 |
| ListListInt | 无 | 设置算子属性数据类型为 ListListInt。 |
| ListListInt | value | 设置算子属性数据类型为 ListListInt,并设置属性默认值为 value。属性类型设置为 OPTIONAL 时必须调用该类接口设置默认值。 |
| Version | version:配置的版本号 | 新增可选属性时,为了保持原有单算子 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++ 对应类型 |
|---|---|---|---|
| Bool | Bool() | Bool(bool value) | bool |
| Float | Float() | Float(float value) | float |
| Int | Int() | Int(int64_t value) | int64_t |
| String | String() | String(const char *value) | const char * |
| ListBool | ListBool() | ListBool(std::vector<bool> value) | std::vector<bool> |
| ListFloat | ListFloat() | ListFloat(std::vector<float> value) | std::vector<float> |
| ListInt | ListInt() | ListInt(std::vector<int64_t> value) | std::vector<int64_t> |
| ListListInt | ListListInt() | ListListInt(std::vector<std::vector<int64_t>> value) | std::vector<std::vector<int64_t>> |
使用要点:
- 必选属性可以只调用无参版本声明类型,如
this->Attr("bias1").AttrType(REQUIRED).Float(0.0);(test_opbuild.cpp),此时该默认值仅作类型声明占位; - 可选属性必须设置默认值:
this->Attr("bias0").AttrType(OPTIONAL).Int(0);(test_opbuild.cpp)。若不设置默认值,构图期未显式传参时属性取值不确定,可能导致构图失败或行为异常; - 列表类属性支持用初始化列表直接构造,如
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对照上文要点逐条解读:
- 属性声明:
this->Attr("negative_slope")注册属性名为negative_slope的属性; - 类型声明:
.AttrType(OPTIONAL)声明为可选属性; - 默认值:
.Float(0.0f)声明数据类型为 Float 并设置默认值 0.0f——可选属性必须设置默认值,这里满足约束; - 运行期读取:该属性的最终落地在 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,满足多维场景算子开发诉求。
相关推荐
asc-devkit 算子原型注册系列:OpAttrDef::Comment 接口详解——为算子属性添加注释并自动生成算子原型头文件
asc devkit 算子原型注册系列:OpAttrDef::Comment 接口详解——为算子属性添加注释并自动生成算子原型头文件 导读 OpAttrDef:
人工智能深度学习算子库CANNAscendasc-devkit OpAICoreDef 算子定义类全解析:AI Core 算子原型注册的 8 个核心接口
asc devkit OpAICoreDef 算子定义类全解析:AI Core 算子原型注册的 8 个核心接口 OpAICoreDef 是 CANN asc d
人工智能深度学习算子库CANNAscendasc-devkit 中 AICPU 自定义算子原型注册之 OpkernelLib 接口详解
asc devkit 中 AICPU 自定义算子原型注册之 OpkernelLib 接口详解 导读 本文围绕 asc devkit 算子原型注册框架中的 Opk
人工智能深度学习算子库CANNAscend
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考