diff --git a/doc/fluid/dev/op_notes.md b/doc/fluid/dev/op_notes.md index 636589ef913a700600082bfd6aeae7d7d8a65558..f612054cb2a94c89160cdb46bafdb28b0d59c2c2 100644 --- a/doc/fluid/dev/op_notes.md +++ b/doc/fluid/dev/op_notes.md @@ -30,7 +30,7 @@ Fluid中所有的Op都继承自`OperatorBase`,且所有的Op都是无状态的 Op的核心方法是Run,Run方法需要两方面的资源:数据资源和计算资源,这两个资源分别通过`Scope`和`Place`获取。框架内部有一个全局的`DeviceContextPool`,用来记录`Place`和`DeviceContext`之间的对应的关系,即每个`Place`有且仅有一个`DeviceContext`与之对应,`DeviceContext`中存放了当前设备的计算资源,比如对于GPU,这些资源包括`cudnn_handle`、`cublas_handle`、`stream`等,Op内部所有的计算(数据拷贝和CUDA Kernel等)都必须在在`DeviceContext`中进行。 -Fluid框架的设计理念是可以在多种设备及第三方库上运行,有些Op的实现可能会因为设备或者第三方库的不同而不同,为此Fluid引入了OpKernel的方式,即一个Op可以有多个OpKernel,这类Op继承自`OperatorWithKernel`,这类Op的代表是conv,conv_op的OpKerne有:`GemmConvKernel`、`CUDNNConvOpKernel`、`ConvMKLDNNOpKernel`,且每个OpKernel都有double和float两种数据类型。不需要OpKernel的代表有`WhileOp`等。 +Fluid框架的设计理念是可以在多种设备及第三方库上运行,有些Op的实现可能会因为设备或者第三方库的不同而不同。为此,Fluid引入了OpKernel的方式,即一个Op可以有多个OpKernel,这类Op继承自`OperatorWithKernel`,这类Op的代表是conv,conv_op的OpKerne有:`GemmConvKernel`、`CUDNNConvOpKernel`、`ConvMKLDNNOpKernel`,且每个OpKernel都有double和float两种数据类型。不需要OpKernel的代表有`WhileOp`等。 Operator继承关系图:
@@ -115,15 +115,15 @@ Operator继承关系图:
注意:
-1. 对于一般的Op,前三个参数是必须的,op_type指明op的名字,OperatorBase是该Op的对象,op_maker_and_checker_maker是op的maker和op中attr的checker。
+1. 对于所有Op,前三个参数是必须的,op_type指明op的名字,OperatorBase是该Op的对象,op_maker_and_checker_maker是op的maker和op中attr的checker。
2. 如果该Op有反向,则必须要有op_grad_opmaker,因为在backward会根据正向的Op中获取反向Op的Maker。
-3. 框架提供了一个默认的op_grad_opmaker:`DefaultGradOpDescMaker`,这个Maker会将前向Op的输入和输出都做为反向Op的输入,将前向Op的输入的梯度作为反向Op的输出,并将前向Op的属性拷贝过来。注意:DefaultGradOpDescMaker会将前向Op的所有输入输出都做反向Op的输入,即使这个输入是没有必要的,这将会导致无法对没有用到的变量做内存优化。
+3. 框架提供了一个默认的op_grad_opmaker:`DefaultGradOpDescMaker`,这个Maker会将前向Op的输入和输出都做为反向Op的输入,将前向Op的输入的梯度作为反向Op的输出,并将前向Op的属性拷贝过来。**注意:**DefaultGradOpDescMaker会将前向Op的所有输入输出都做反向Op的输入,即使这个输入是没有必要的,这将会导致无法对没有用到的变量做内存优化。
-4. 框架没有提供默认的op_infer_var_shape方法。如果该Op是无OpKernel的,通常需要需要用户添加对应的op_infer_var_shape方法;如果该Op是有OpKernel的,需要实现`OperatorWithKernel`中的`InferShape`方法,此时不需要提供op_infer_var_shape方法。具体实现可参考while_op.cc,conv_op.cc。
+4. 框架没有提供默认的op_infer_var_shape方法。如果该Op是无OpKernel的,通常需要用户添加对应的op_infer_var_shape方法;如果该Op是有OpKernel的,需要实现`OperatorWithKernel`中的`InferShape`方法,此时不需要提供op_infer_var_shape方法。具体实现可参考[while_op.cc](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/fluid/operators/controlflow/while_op.cc),[conv_op.cc](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/fluid/operators/conv_op.cc)。
-5. 框架没有提供默认的op_infer_var_type方法,用户需要根据实际情况添加op_infer_var_shape。严格来说每个Op都应该注册一个InferVarType,op_infer_var_type根据输入的Var的type和dtype推断输出Var的type和dtype。注意:在python端的LayerHelper中create_variable_for_type_inference操作返回的Variable里面是LoDTensor,并且C++端的InferVarType可能会对这个type和dtype进行修改。
+5. 框架没有提供默认的op_infer_var_type方法,用户需要根据实际情况添加op_infer_var_shape。严格来说每个Op都应该注册一个InferVarType,op_infer_var_type根据输入的Var的type和dtype推断输出Var的type和dtype。**注意:**在Python端的LayerHelper中create_variable_for_type_inference操作返回的Variable里面是LoDTensor,C++端的InferVarType可以修改`Variable`的type和dtype。
更多内容请参考:
@@ -131,9 +131,9 @@ Operator继承关系图:
## 写Op注意事项
### 3.关于Op可以支持输入输出类型
-Fluid的Op的输入输出都是Variable,从设计上讲,Variable中可以存放任意类型,Op的输入输出Variable可能是是任意类型,通常情况下Variable中存放的是LoDTensor、SlelecteRows。
+Fluid的Op的输入输出都是`Variable`,从设计上讲,`Variable`中可以存放任意类型,Op的输入输出`Variable`可能是是任意类型,通常情况下`Variable`中存放的是`LoDTensor`、`SlelecteRows`。
-注意:
+**注意:**
- 代码中经常出现`context.Input