Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
机器未来
Paddle
提交
208dd503
P
Paddle
项目概览
机器未来
/
Paddle
与 Fork 源项目一致
Fork自
PaddlePaddle / Paddle
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
Paddle
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录