54
54
</table >
55
55
56
56
57
- 实现新的op都添加至目录[ paddle/operators] ( https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/operators ) 下,文件命名以` *_op.h ` (如有) 、 ` *_op.cc ` 、` *_op.cu ` (如有)结尾。** 系统会根据文件名自动构建op和其对应的Python扩展。**
57
+ 实现新的op都添加至目录[ paddle/fluid/ operators] ( https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/fluid /operators ) 下,文件命名以` *_op.h ` (如有) 、 ` *_op.cc ` 、` *_op.cu ` (如有)结尾。** 系统会根据文件名自动构建op和其对应的Python扩展。**
58
58
59
59
60
- 下面以矩阵乘操作,即[ MulOp] ( https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/mul_op.cc ) 为例来介绍如何写带Kernel的Operator。
60
+ 下面以矩阵乘操作,即[ MulOp] ( https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/fluid/ operators/mul_op.cc ) 为例来介绍如何写带Kernel的Operator。
61
61
62
62
63
63
## 实现C++类
@@ -85,39 +85,39 @@ The equation is: Out = X * Y
85
85
};
86
86
```
87
87
88
- [`MulOpMaker`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/mul_op.cc#L43 )继承自`framework::OpProtoAndCheckerMaker`,构造函数含有2个参数:
88
+ [`MulOpMaker`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/fluid/ operators/mul_op.cc#L76-L127 )继承自`framework::OpProtoAndCheckerMaker`,构造函数含有2个参数:
89
89
90
90
- `framework::OpProto` : 前者存储Op的输入输出和参数属性,将用于Python API接口的生成。
91
91
- `framework::OpAttrChecker` :后者用于检查参数属性的合法性。
92
92
93
93
构造函数里通过`AddInput`添加输入参数,通过`AddOutput`添加输出参数,通过`AddComment`添加Op的注释。这些函数会将对应内容添加到`OpProto`中。
94
94
95
- 上面的代码在`MulOp`中添加两个输入`X`和`Y`,添加了一个输出`Out`,并解释了各自含义,命名请遵守[命名规范](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators /name_convention.md)。
95
+ 上面的代码在`MulOp`中添加两个输入`X`和`Y`,添加了一个输出`Out`,并解释了各自含义,命名请遵守[命名规范](https://github.com/PaddlePaddle/Paddle/blob/develop/doc/fluid/dev /name_convention.md)。
96
96
97
97
98
- 再以[`ScaleOp`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/scale_op.cc#L37 )为例:
98
+ 再以[`ScaleOp`](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/fluid/ operators/scale_op.cc#L38-L55 )为例:
99
99
100
100
```cpp
101
101
template <typename AttrType>
102
102
class ScaleOpMaker : public framework::OpProtoAndCheckerMaker {
103
103
public:
104
104
ScaleOpMaker(OpProto *proto, OpAttrChecker *op_checker)
105
105
: OpProtoAndCheckerMaker(proto, op_checker) {
106
- AddInput(" X" , " The input tensor of scale operator ." ).NotInGradient();
107
- AddOutput(" Out" , " The output tensor of scale operator ." ).NotInGradient();
108
- AddComment(R" DOC(Scale operator
109
- The equation is: Out = scale*X
106
+ AddInput(" X" , " (Tensor) Input tensor of scale operator ." );
107
+ AddOutput(" Out" , " (Tensor) Output tensor of scale operator ." );
108
+ AddComment(R" DOC(
109
+ Scale operator
110
+ $$Out = scale*X$$
110
111
)DOC" );
111
- AddAttr<AttrType>(" scale" , " scale of scale operator ." ).SetDefault(1.0);
112
+ AddAttr<AttrType>(" scale" ,
113
+ " (float , default 1.0 )"
114
+ " The scaling factor of the scale operator ." )
115
+ .SetDefault(1.0);
112
116
}
113
117
};
114
118
```
115
119
116
- 这个例子有两处不同:
117
-
118
- - `AddInput(" X" ," ..." ).NotInGradient()` : 表示`X`这个输入不参与`ScaleOp`对应的梯度Op计算之中,如果Op的某个输入不参与反向梯度的计算,请显示地调用`.NotInGradient()`进行设置。
119
-
120
- - `AddAttr<AttrType>(" scale" , " ..." ).SetDefault(1.0);` : 增加`scale`系数,作为参数属性,并且设置默认值为1.0。
120
+ 这个例子有`AddAttr<AttrType>(" scale" , " ..." ).SetDefault(1.0);` : 增加`scale`系数,作为参数属性,并且设置默认值为1.0。
121
121
122
122
123
123
### 定义Operator类
@@ -205,7 +205,6 @@ MulOp(const std::string &type, const framework::VariableNameMap &inputs,
205
205
206
206
为了使` OpKernel ` 的计算过程书写更加简单,并且CPU、CUDA的代码可以复用,我们通常借助 Eigen unsupported Tensor模块来实现` Compute ` 接口。关于在PaddlePaddle中如何使用Eigen库,请参考[ 使用文档] ( https://github.com/PaddlePaddle/Paddle/blob/develop/doc/howto/dev/use_eigen_cn.md ) 。
207
207
208
-
209
208
到此,前向Op实现完成。接下来,需要在` .cc ` 文件中注册该op和kernel。
210
209
反向Op类的定义,反向OpKernel的定义与前向Op类似,这里不再赘述。** 但需注意反向Op没有` ProtoMaker ` ** 。
211
210
@@ -215,7 +214,9 @@ MulOp(const std::string &type, const framework::VariableNameMap &inputs,
215
214
216
215
``` cpp
217
216
namespace ops = paddle::operators;
218
- REGISTER_OP(mul, ops::MulOp, ops::MulOpMaker, mul_grad, ops::MulOpGrad);
217
+ REGISTER_OPERATOR(mul, ops::MulOp, ops::MulOpMaker,
218
+ paddle::framework::DefaultGradOpDescMaker<true >)
219
+ REGISTER_OPERATOR(mul_grad, ops::MulGradOp)
219
220
REGISTER_OP_CPU_KERNEL(mul, ops::MulKernel<paddle::platform::CPUDeviceContext, float>);
220
221
REGISTER_OP_CPU_KERNEL(mul_grad,
221
222
ops::MulGradKernel<paddle::platform::CPUDeviceContext, float>);
@@ -255,7 +256,7 @@ make mul_op
255
256
256
257
## 实现单元测试
257
258
258
- 单测包括对比前向Op不同设备(CPU、CUDA)的实现、对比反向OP不同设备(CPU、CUDA)的实现、反向Op的梯度测试。下面介绍介绍[ ` MulOp ` 的单元测试] ( https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/v2/framework/ tests/test_mul_op.py ) 。
259
+ 单测包括对比前向Op不同设备(CPU、CUDA)的实现、对比反向OP不同设备(CPU、CUDA)的实现、反向Op的梯度测试。下面介绍介绍[ ` MulOp ` 的单元测试] ( https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/fluid/ tests/unittests /test_mul_op.py ) 。
259
260
260
261
### 前向Operator单测
261
262
@@ -331,7 +332,6 @@ ctest -R test_mul_op
331
332
332
333
## 注意事项
333
334
334
- - 为每个Op创建单独的` *_op.h ` (如有)、` *_op.cc ` 和` *_op.cu ` (如有)。不允许一个文件中包含多个Op,这将会导致编译出错。
335
- - 注册Op时的类型名,需要和该Op的名字一样。即不允许在` A_op.cc ` 里面,注册` REGISTER_OP(B, ...) ` 等,这将会导致单元测试出错。
335
+ - 注册Op时的类型名,需要和该Op的名字一样。即不允许在` A_op.cc ` 里面,注册` REGISTER_OPERATOR(B, ...) ` 等,这将会导致单元测试出错。
336
336
- 如果Op没有实现CUDA Kernel,请不要创建空的` *_op.cu ` ,这将会导致单元测试出错。
337
337
- 如果多个Op依赖一些共用的函数,可以创建非` *_op.* ` 格式的文件来存放,如` gather.h ` 文件。
0 commit comments