Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
Paddle
提交
208dd503
P
Paddle
项目概览
PaddlePaddle
/
Paddle
1 年多 前同步成功
通知
2302
Star
20931
Fork
5422
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1423
列表
看板
标记
里程碑
合并请求
543
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
Paddle
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1,423
Issue
1,423
列表
看板
标记
里程碑
合并请求
543
合并请求
543
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
208dd503
编写于
4月 18, 2018
作者:
Y
Yang Yang(Tony)
提交者:
GitHub
4月 18, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Update new_op_cn.md
上级
9ca578d4
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
20 addition
and
20 deletion
+20
-20
doc/fluid/dev/new_op_cn.md
doc/fluid/dev/new_op_cn.md
+20
-20
未找到文件。
doc/fluid/dev/new_op_cn.md
浏览文件 @
208dd503
...
...
@@ -54,10 +54,10 @@
</table>
实现新的op都添加至目录
[
paddle/
operators
](
https://github.com/PaddlePaddle/Paddle/tree/develop/paddle
/operators
)
下,文件命名以
`*_op.h`
(如有) 、
`*_op.cc`
、
`*_op.cu`
(如有)结尾。
**系统会根据文件名自动构建op和其对应的Python扩展。**
实现新的op都添加至目录
[
paddle/
fluid/operators
](
https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/fluid
/operators
)
下,文件命名以
`*_op.h`
(如有) 、
`*_op.cc`
、
`*_op.cu`
(如有)结尾。
**系统会根据文件名自动构建op和其对应的Python扩展。**
下面以矩阵乘操作,即
[
MulOp
](
https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/mul_op.cc
)
为例来介绍如何写带Kernel的Operator。
下面以矩阵乘操作,即
[
MulOp
](
https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/
fluid/
operators/mul_op.cc
)
为例来介绍如何写带Kernel的Operator。
## 实现C++类
...
...
@@ -85,17 +85,17 @@ The equation is: Out = X * Y
};
```
[
`MulOpMaker`
](
https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/
operators/mul_op.cc#L43
)
继承自
`framework::OpProtoAndCheckerMaker`
,构造函数含有2个参数:
[
`MulOpMaker`
](
https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/
fluid/operators/mul_op.cc#L76-L127
)
继承自
`framework::OpProtoAndCheckerMaker`
,构造函数含有2个参数:
-
`framework::OpProto`
: 前者存储Op的输入输出和参数属性,将用于Python API接口的生成。
-
`framework::OpAttrChecker`
:后者用于检查参数属性的合法性。
构造函数里通过
`AddInput`
添加输入参数,通过
`AddOutput`
添加输出参数,通过
`AddComment`
添加Op的注释。这些函数会将对应内容添加到
`OpProto`
中。
上面的代码在
`MulOp`
中添加两个输入
`X`
和
`Y`
,添加了一个输出
`Out`
,并解释了各自含义,命名请遵守
[
命名规范
](
https://github.com/PaddlePaddle/Paddle/blob/develop/
paddle/operators
/name_convention.md
)
。
上面的代码在
`MulOp`
中添加两个输入
`X`
和
`Y`
,添加了一个输出
`Out`
,并解释了各自含义,命名请遵守
[
命名规范
](
https://github.com/PaddlePaddle/Paddle/blob/develop/
doc/fluid/dev
/name_convention.md
)
。
再以
[
`ScaleOp`
](
https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/
operators/scale_op.cc#L37
)
为例:
再以
[
`ScaleOp`
](
https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/
fluid/operators/scale_op.cc#L38-L55
)
为例:
```
cpp
template
<
typename
AttrType
>
...
...
@@ -103,21 +103,21 @@ class ScaleOpMaker : public framework::OpProtoAndCheckerMaker {
public:
ScaleOpMaker
(
OpProto
*
proto
,
OpAttrChecker
*
op_checker
)
:
OpProtoAndCheckerMaker
(
proto
,
op_checker
)
{
AddInput
(
"X"
,
"The input tensor of scale operator."
).
NotInGradient
();
AddOutput
(
"Out"
,
"The output tensor of scale operator."
).
NotInGradient
();
AddComment
(
R"DOC(Scale operator
The equation is: Out = scale*X
AddInput
(
"X"
,
"(Tensor) Input tensor of scale operator."
);
AddOutput
(
"Out"
,
"(Tensor) Output tensor of scale operator."
);
AddComment
(
R"DOC(
Scale operator
$$Out = scale*X$$
)DOC"
);
AddAttr
<
AttrType
>
(
"scale"
,
"scale of scale operator."
).
SetDefault
(
1.0
);
AddAttr
<
AttrType
>
(
"scale"
,
"(float, default 1.0)"
"The scaling factor of the scale operator."
)
.
SetDefault
(
1.0
);
}
};
```
这个例子有两处不同:
-
`AddInput("X","...").NotInGradient()`
: 表示
`X`
这个输入不参与
`ScaleOp`
对应的梯度Op计算之中,如果Op的某个输入不参与反向梯度的计算,请显示地调用
`.NotInGradient()`
进行设置。
-
`AddAttr<AttrType>("scale", "...").SetDefault(1.0);`
: 增加
`scale`
系数,作为参数属性,并且设置默认值为1.0。
这个例子有
`AddAttr<AttrType>("scale", "...").SetDefault(1.0);`
: 增加
`scale`
系数,作为参数属性,并且设置默认值为1.0。
### 定义Operator类
...
...
@@ -205,7 +205,6 @@ MulOp(const std::string &type, const framework::VariableNameMap &inputs,
为了使
`OpKernel`
的计算过程书写更加简单,并且CPU、CUDA的代码可以复用,我们通常借助 Eigen unsupported Tensor模块来实现
`Compute`
接口。关于在PaddlePaddle中如何使用Eigen库,请参考
[
使用文档
](
https://github.com/PaddlePaddle/Paddle/blob/develop/doc/howto/dev/use_eigen_cn.md
)
。
到此,前向Op实现完成。接下来,需要在
`.cc`
文件中注册该op和kernel。
反向Op类的定义,反向OpKernel的定义与前向Op类似,这里不再赘述。
**但需注意反向Op没有`ProtoMaker`**
。
...
...
@@ -215,7 +214,9 @@ MulOp(const std::string &type, const framework::VariableNameMap &inputs,
```cpp
namespace ops = paddle::operators;
REGISTER_OP(mul, ops::MulOp, ops::MulOpMaker, mul_grad, ops::MulOpGrad);
REGISTER_OPERATOR(mul, ops::MulOp, ops::MulOpMaker,
paddle::framework::DefaultGradOpDescMaker<true>)
REGISTER_OPERATOR(mul_grad, ops::MulGradOp)
REGISTER_OP_CPU_KERNEL(mul, ops::MulKernel<paddle::platform::CPUDeviceContext, float>);
REGISTER_OP_CPU_KERNEL(mul_grad,
ops::MulGradKernel<paddle::platform::CPUDeviceContext, float>);
...
...
@@ -255,7 +256,7 @@ make mul_op
## 实现单元测试
单测包括对比前向Op不同设备(CPU、CUDA)的实现、对比反向OP不同设备(CPU、CUDA)的实现、反向Op的梯度测试。下面介绍介绍
[
`MulOp`的单元测试
](
https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/
v2/framework/
tests/test_mul_op.py
)
。
单测包括对比前向Op不同设备(CPU、CUDA)的实现、对比反向OP不同设备(CPU、CUDA)的实现、反向Op的梯度测试。下面介绍介绍
[
`MulOp`的单元测试
](
https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/
fluid/tests/unit
tests/test_mul_op.py
)
。
### 前向Operator单测
...
...
@@ -331,7 +332,6 @@ ctest -R test_mul_op
## 注意事项
-
为每个Op创建单独的
`*_op.h`
(如有)、
`*_op.cc`
和
`*_op.cu`
(如有)。不允许一个文件中包含多个Op,这将会导致编译出错。
-
注册Op时的类型名,需要和该Op的名字一样。即不允许在
`A_op.cc`
里面,注册
`REGISTER_OP(B, ...)`
等,这将会导致单元测试出错。
-
注册Op时的类型名,需要和该Op的名字一样。即不允许在
`A_op.cc`
里面,注册
`REGISTER_OPERATOR(B, ...)`
等,这将会导致单元测试出错。
-
如果Op没有实现CUDA Kernel,请不要创建空的
`*_op.cu`
,这将会导致单元测试出错。
-
如果多个Op依赖一些共用的函数,可以创建非
`*_op.*`
格式的文件来存放,如
`gather.h`
文件。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录