diff --git a/docs/dev_guides/api_contributing_guides/api_contributing_guides_cn.rst b/docs/dev_guides/api_contributing_guides/api_contributing_guides_cn.rst index 7bd2a84a8b2..c027d16e4d2 100644 --- a/docs/dev_guides/api_contributing_guides/api_contributing_guides_cn.rst +++ b/docs/dev_guides/api_contributing_guides/api_contributing_guides_cn.rst @@ -105,6 +105,5 @@ API设计文档的目的是为了社区开发者更容易的参与开源项目 api_design_guidelines_standard_cn.md new_python_api_cn.md new_cpp_op_cn.md - new_cpp_op_notes_cn.md api_docs_guidelines_cn.md api_accpetance_criteria_cn.md diff --git a/docs/dev_guides/api_contributing_guides/code_gen_by_yaml.png b/docs/dev_guides/api_contributing_guides/code_gen_by_yaml.png new file mode 100644 index 00000000000..32dd779608f Binary files /dev/null and b/docs/dev_guides/api_contributing_guides/code_gen_by_yaml.png differ diff --git a/docs/dev_guides/api_contributing_guides/new_cpp_op_cn.md b/docs/dev_guides/api_contributing_guides/new_cpp_op_cn.md index 5215f6ed5ee..f2357428237 100644 --- a/docs/dev_guides/api_contributing_guides/new_cpp_op_cn.md +++ b/docs/dev_guides/api_contributing_guides/new_cpp_op_cn.md @@ -1,10 +1,10 @@ -# C++ OP 开发 +# C++ 算子开发指南 -> 注:飞桨原生算子的开发范式正在进行重构与升级,升级后算子开发方式会大幅简化,我们会及时更新本文档内容,升级后的算子开发范式预计会在2.3版本正式上线。 +> 注:飞桨算子的开发范式正处在重构升级后的上线初期,如果在开发过程中遇到问题欢迎通过[Issue](https://github.com/PaddlePaddle/Paddle/issues)向我们反馈。 ## 1. 概念简介 -本教程对新增原生算子的方法进行介绍,首先新增一个算子大概需要以下几个步骤: +本教程对新增算子的方法进行介绍,首先新增一个算子大概需要以下几个步骤: 1. 新增算子描述及定义:描述前反向算子的输入、输出、属性,实现InferMeta函数 2. 新增算子Kernel:实现算子在各种设备上的计算逻辑 @@ -23,7 +23,7 @@
配置项 | +配置内容及规则 | +
---|---|
api | +算子名称,与该算子Python API函数名相同(命名方式为:全小写+下划线),示例中为trace | +
args | +算子输入参数,与该算子Python API函数的输入参数对应(当前支持的输入数据类型包括:Tensor, Tensor[], float, double, bool, int, int64_t, int[], int64_t[], str, Place, DataType, DataLayout, IntArray, Scalar)。我们一般称这里Tensor类型的参数为Input(输入),非Tensor类型的参数为Attribute(属性) +注:Tensor[]表示Tensor数组;IntArray为int类型数组,主要用于表示shape,index和axes等类型数据,可以直接使用Tensor或者普通整型数组构造,目前仍在测试阶段,如非必要暂不建议使用;Scalar表示标量,可以支持不同的普通数据类型 + |
+
output | +算子输出类型(目前支持Tensor和Tensor[]类型),多个输出间用逗号“,”分隔开。可以使用”()”选择性标记输入的名字,如未标记默认为'out' +注:当返回类型为Tensor[]时,由于数组的size要在kernel执行前推导完成,所以需要在Tensor[]后的'{}'内通过表达式指定返回数组的size,如:Tensor[](out){input.size()} + |
+
infer_meta | +InferMeta函数负责根据输入变量推断返回Tensor的维度与类型,这里是对算子使用的InferMeta函数进行配置 | +
infer_meta:func | +调用的InferMeta函数,这里trace调用的是TraceInferMeta函数 | +
infer_meta:param | +InferMeta函数的输入参数,可以对args中的参数进行选择传入,未配置则默认传入args中的所有参数。示例中未配置本项,所以传入的参数为[x, offset, axis1, axis2]。output项中的参数作为输出无需配置会自动传入InferMeta函数中 | +
kernel | +算子的计算Kernel配置 | +
kernel:func | +算子对应kernel函数的注册名 | +
kernel:param | +kernel函数的输入参数,配置规则与InferMeta函数的param配置项相同 | +
kernel:data_type | +根据指定参数推导调用kernel的data_type(对应kernel函数的模板参数'T'),默认不进行配置,会根据输入Tensor自动进行推导。如果kernel的data_type类型由某个输入参数(Tensor或者DataType参数),需要将该参数的变量名填入该项。示例中未配置则kernel的data_type由输入变量'x'决定 | +kernel:backend | +根据指定参数来选择调用kernel的Backend(Kernel执行的具体设备,如CPU、GPU等),默认不进行配置,会根据输入Tensor自动进行推导。如果kernel执行的backend类型由某个输入参数(Tensor或者Backend参数)决定,需要将该参数的变量名填入该项。示例中未配置则kernel执行的Backend与输入变量'x'的Backend相同 | + +
backward | +算子对应的反向算子名称,如果没有反向则不需要配置,示例中trace算子的反向为trace_grad | +
特殊配置项(目前特殊配置项还处于不稳定阶段,后续可能会有调整更新) | +|
optional | +指定输入Tensor为可选输入,用法可参考dropout中seed_tensor(python/paddle/utils/code_gen/legacy_api.yaml中) | +
inplace | +算子对指定的输入做原位处理并作为输出结果返回,使用格式:(x -> out),具体用法可参考relu算子 +特殊规则:如果api中算子名称有'_'后缀则只生成支持inplace功能的接口,如果算子名称没有'_'后缀,则会同时生成支持inplace操作的接口(自动添加'_'后缀)和不支持inplace的普通接口共两套接口 + |
+
view | +与inplace机制类似,区别在于view模式返回的结果只是与输入共享内存,并不是输入Tensor变量本身,使用格式:(x -> out),具体用法可参考reshape算子 | +
intermediate | +标记前向计算中输出的用于反向计算的中间变量,不会出现在Python API的返回结果中,相关设计正在完善中,新增算子时不建议使用 | +
invoke | +复用已有的算子接口或实现自定义的C++ API,配置时以函数调用的形式配置即可,使用invoke时则不需要配置infer_meta和kernel。 +a. 如果是复用已有算子,需要被复用的算子为前向算子且两者的返回值类型相同,可参考zeros_like算子 +b. 如果是实现自定义的C++ API,需要在'paddle/phi/api/lib/api_custom_impl.h'声明自定义实现函数并在'paddle/phi/api/lib/api_custom_impl.cc'中进行实现,具体可参考embedding算子 |
+
配置项 | +配置内容及规则 | +
---|---|
backward_api | +反向算子名称,一般命名方式为:前向算子名称+'_grad',二阶算子则为前向算子名称+'_double_grad' | +
forward | +对应前向算子的名称、参数、返回值,需要与api.yaml中前向算子配置一致 | +
args | +反向算子输入参数, 示例中'x'表示将前向的'x'变量输入到反向,'out_grad'表示前向输出'out'对应的反向梯度 +约束条件1:所有参数需要在forward配置项的参数中(输入、输出以及输出对应的反向梯度)找到对应(根据变量名匹配) +约束条件2:反向输入参数需要以:a.前向输入Tensor b.前向输出Tensor c.前向输出Tensor的反向梯度 d.前向非Tensor类型属性变量(Attribute) 的顺序排列,反向计算中不需要使用的前向变量无须添加 + |
+
output | +反向算子输出,顺序需要与前向输入Tensor一致,比如前向输入(Tensor x, Tensor y),则反向输出必须为Tensor(x_grad), Tensor(y_grad) | +
infer_meta | +与前向配置规则相同 | +
kernel | +与前向配置规则相同 | +
backward | +反向算子对应的更高阶反向算子名称,如一阶反向算子的反向为二阶反向算子 | +
特殊配置项(目前特殊配置项还处于不稳定阶段,后续可能会有调整更新) | +|
no_need_buffer | +可选配置,标记的Tensor变量在前向运行完成后,持有的内存或显存会被释放,以减少训练过程中的内存使用。trace_grad由于反向算子只需要前向变量'x'的维度信息,不需要内存数据,所以可以标记为no_need_buffer提前释放内存 +注意:由于Tensor内存被释放后会影响dtype接口的使用,所以需要在kernel的data_type配置项中指定其他的Tensor来推导kernel的data_type |
+
optional | +与前向配置规则相同 | +
inplace | +与前向配置规则相同 | +
类型 | +特点 | +示例 | +
---|---|---|
LoD-Transparent | +计算过程不依赖 LoD,输入是否有 LoD 不会影响计算的结果,通常是 position-wise 的计算 | +conv2d_op、batch_norm_op、dropout_op 等 | +
LoD-Based | +计算以序列为单位, 计算过程依赖 LoD | +lstm_op、gru_op、sequence_ops 等 | +
注册项 | -类型 | -说明 | -调用 | -
---|---|---|---|
proto::OpProto | -Class | -存放Op的输入/输出/属性/Op类型 | -编译时调用 | -
GradOpMakerFN | -Functor | -返回当前Op对应的反向Op的一组OpDesc,因为正向Op的反向可能有多个Op构成 | -编译时调用 | -
OpAttrChecker | -Class | -对Op的attr进行check | -编译时调用 | -
InferVarTypeFN | -Functor | -用于推断输出Var的Type,比如是LoDTensor还是SelectedRows,或者其他 | -编译时调用 | -
InferShapeFN | -Functor | -用于推断Output的Shape | -分为编译时和运行时,编译时是在Python端调用;如果Op继承自OperatorWithKernel,运行时是在op.run中调用 | -
OpCreator | -Functor | -每次调用都会创建一个新的OperatorBase | -运行时调用 | -
类型 | -特点 | -示例 | -
---|---|---|
LoD-Transparent | -计算过程不依赖 LoD,输入是否有 LoD 不会影响计算的结果,通常是 position-wise 的计算 | -conv2d_op、batch_norm_op、dropout_op 等 | -
LoD-Based | -计算以序列为单位, 计算过程依赖 LoD | -lstm_op、gru_op、sequence_ops 等 | -