Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
机器未来
Paddle
提交
3757e068
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看板
未验证
提交
3757e068
编写于
3月 13, 2020
作者:
W
wangchaochaohu
提交者:
GitHub
3月 13, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add Unittest for backward of fusion group (#22932)
* add fusion group test for backward and refine code
上级
8fdcb43f
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
65 addition
and
25 deletion
+65
-25
paddle/fluid/framework/ir/fusion_group/code_generator.cc
paddle/fluid/framework/ir/fusion_group/code_generator.cc
+12
-9
paddle/fluid/framework/ir/fusion_group/code_generator.h
paddle/fluid/framework/ir/fusion_group/code_generator.h
+5
-4
paddle/fluid/operators/fused/fusion_group_op.h
paddle/fluid/operators/fused/fusion_group_op.h
+1
-1
python/paddle/fluid/tests/unittests/ir/pass_test.py
python/paddle/fluid/tests/unittests/ir/pass_test.py
+7
-1
python/paddle/fluid/tests/unittests/ir/test_ir_fusion_group_pass.py
...dle/fluid/tests/unittests/ir/test_ir_fusion_group_pass.py
+40
-10
未找到文件。
paddle/fluid/framework/ir/fusion_group/code_generator.cc
浏览文件 @
3757e068
...
...
@@ -24,7 +24,7 @@ namespace framework {
namespace
ir
{
namespace
fusion_group
{
std
::
string
ExtractDataType
(
const
std
::
vector
<
Node
*>
nodes
)
{
std
::
string
ExtractDataType
(
const
std
::
vector
<
Node
*>
&
nodes
)
{
std
::
string
dtype_str
=
"float"
;
auto
data_type
=
nodes
.
back
()
->
Var
()
->
GetDataType
();
...
...
@@ -98,6 +98,7 @@ std::vector<OperationExpression> CodeGenerator::ConvertToExpressions(
std
::
vector
<
int
>
output_ids
;
std
::
vector
<
std
::
string
>
output_names
=
OperationMap
::
Instance
().
Get
(
op
->
Type
()).
output_names
;
for
(
auto
&
name
:
output_names
)
{
PADDLE_ENFORCE_EQ
(
op
->
Output
(
name
).
size
(),
1U
,
...
...
@@ -125,9 +126,10 @@ std::string CodeGenerator::Generate(
std
::
string
func_name
,
const
std
::
vector
<
OperationExpression
>&
expressions
)
{
// TODO(liuyiqun): Check whether all expressions are elementwise operations.
std
::
set
<
int
>
input_ids
=
DistilInputIds
(
expressions
);
std
::
set
<
int
>
output_ids
=
DistilOutputIds
(
expressions
);
std
::
unordered_map
<
int
,
std
::
string
>
dtypes
=
DistilDtypes
(
expressions
);
std
::
set
<
int
>
input_ids
=
std
::
move
(
DistilInputIds
(
expressions
));
std
::
set
<
int
>
output_ids
=
std
::
move
(
DistilOutputIds
(
expressions
));
std
::
unordered_map
<
int
,
std
::
string
>
dtypes
=
std
::
move
(
DistilDtypes
(
expressions
));
TemplateVariable
template_var
;
template_var
.
Add
(
"func_name"
,
func_name
);
template_var
.
Add
(
"parameters"
,
EmitParameters
(
input_ids
,
output_ids
,
dtypes
));
...
...
@@ -211,7 +213,7 @@ std::unordered_map<int, std::string> CodeGenerator::DistilDtypes(
// we get the parameter list code for the expression information
std
::
string
CodeGenerator
::
EmitParameters
(
const
std
::
set
<
int
>&
input_ids
,
const
std
::
set
<
int
>&
output_ids
,
std
::
unordered_map
<
int
,
std
::
string
>
dtypes
)
{
const
std
::
unordered_map
<
int
,
std
::
string
>&
dtypes
)
const
{
std
::
stringstream
ret
;
ret
<<
"int N, "
;
...
...
@@ -219,13 +221,13 @@ std::string CodeGenerator::EmitParameters(
// from the input list.
for
(
auto
id
:
input_ids
)
{
if
(
output_ids
.
find
(
id
)
==
output_ids
.
end
())
{
ret
<<
dtypes
[
id
]
<<
"* "
<<
ArgName
(
id
)
<<
", "
;
ret
<<
dtypes
.
at
(
id
)
<<
"* "
<<
ArgName
(
id
)
<<
", "
;
}
}
size_t
index
=
0
;
for
(
auto
id
:
output_ids
)
{
ret
<<
dtypes
[
id
]
<<
"* "
<<
ArgName
(
id
);
ret
<<
dtypes
.
at
(
id
)
<<
"* "
<<
ArgName
(
id
);
if
(
index
!=
output_ids
.
size
()
-
1
)
{
ret
<<
", "
;
}
...
...
@@ -238,7 +240,7 @@ std::string CodeGenerator::EmitParameters(
std
::
string
CodeGenerator
::
EmitComputeBody
(
const
std
::
vector
<
OperationExpression
>&
expressions
,
const
std
::
set
<
int
>&
input_ids
,
const
std
::
set
<
int
>&
output_ids
,
std
::
unordered_map
<
int
,
std
::
string
>
dtypes
)
{
const
std
::
unordered_map
<
int
,
std
::
string
>&
dtypes
)
const
{
std
::
ostringstream
compute
;
std
::
unordered_set
<
int
>
used
;
for
(
size_t
i
=
0
;
i
<
expressions
.
size
();
i
++
)
{
...
...
@@ -251,7 +253,8 @@ std::string CodeGenerator::EmitComputeBody(
for
(
auto
id
:
input_ids
)
{
if
(
output_ids
.
find
(
id
)
==
output_ids
.
end
()
&&
used
.
find
(
id
)
!=
used
.
end
())
{
load
<<
dtypes
[
id
]
<<
" "
<<
TmpName
(
id
)
<<
" = "
<<
VarName
(
id
)
<<
";"
;
load
<<
dtypes
.
at
(
id
)
<<
" "
<<
TmpName
(
id
)
<<
" = "
<<
VarName
(
id
)
<<
";"
;
}
}
// Store temporal variables to memory.
...
...
paddle/fluid/framework/ir/fusion_group/code_generator.h
浏览文件 @
3757e068
...
...
@@ -17,6 +17,7 @@ limitations under the License. */
#include <set>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include "paddle/fluid/framework/ir/fusion_group/code_generator_helper.h"
#include "paddle/fluid/framework/ir/fusion_group/subgraph.h"
...
...
@@ -46,14 +47,14 @@ class CodeGenerator {
const
std
::
vector
<
OperationExpression
>&
expressions
);
// we get the parameter list code for the expression information
std
::
string
EmitParameters
(
const
std
::
set
<
int
>&
input_ids
,
const
std
::
set
<
int
>&
output_ids
,
std
::
unordered_map
<
int
,
std
::
string
>
dtypes
)
;
std
::
string
EmitParameters
(
const
std
::
set
<
int
>&
input_ids
,
const
std
::
set
<
int
>&
output_ids
,
const
std
::
unordered_map
<
int
,
std
::
string
>&
dtypes
)
const
;
std
::
string
EmitComputeBody
(
const
std
::
vector
<
OperationExpression
>&
expressions
,
const
std
::
set
<
int
>&
input_ids
,
const
std
::
set
<
int
>&
output_ids
,
std
::
unordered_map
<
int
,
std
::
string
>
dtypes
)
;
const
std
::
unordered_map
<
int
,
std
::
string
>&
dtypes
)
const
;
// Encode all var nodes in the subgraph with an unique number.
std
::
unordered_map
<
std
::
string
,
int
>
EncodeVarNodes
(
SubGraph
*
subgraph
);
...
...
paddle/fluid/operators/fused/fusion_group_op.h
浏览文件 @
3757e068
...
...
@@ -25,7 +25,7 @@ namespace operators {
static
void
MutableMultiTypeData
(
std
::
vector
<
paddle
::
framework
::
LoDTensor
*>*
var
,
const
std
::
vector
<
std
::
string
>&
data_type
,
const
platform
::
Place
&
place
)
{
for
(
size_t
i
=
0
;
i
<
(
*
var
).
size
();
i
++
)
{
for
(
size_t
i
=
0
;
i
<
var
->
size
();
i
++
)
{
if
(
data_type
[
i
]
==
"float"
)
{
(
*
var
)[
i
]
->
mutable_data
<
float
>
(
place
);
}
else
if
(
data_type
[
i
]
==
"double"
)
{
...
...
python/paddle/fluid/tests/unittests/ir/pass_test.py
浏览文件 @
3757e068
...
...
@@ -38,6 +38,7 @@ class PassTest(unittest.TestCase):
self
.
pass_attrs
=
{}
self
.
fused_op_type
=
None
self
.
num_fused_ops
=
-
1
self
.
backward
=
True
np
.
random
.
seed
(
123
)
random
.
seed
(
124
)
...
...
@@ -48,6 +49,11 @@ class PassTest(unittest.TestCase):
places
.
append
(
fluid
.
CUDAPlace
(
0
))
return
places
def
append_gradinets
(
self
,
outs
):
with
fluid
.
program_guard
(
self
.
main_program
,
self
.
startup_program
):
loss
=
fluid
.
layers
.
mean
(
outs
)
fluid
.
backward
.
append_backward
(
loss
)
def
check_output
(
self
,
startup_on_cpu
=
False
,
atol
=
1e-5
):
'''
Check whether the fetched outputs of the origin program and the
...
...
@@ -143,7 +149,7 @@ class PassTest(unittest.TestCase):
np
.
allclose
(
outs_opt
[
i
],
outs
[
i
],
atol
=
atol
),
"Output < {} > has diff at {}, expected {} but got {}"
.
format
(
self
.
fetch_list
[
i
]
.
name
,
str
(
place
),
outs_opt
[
i
],
outs
[
i
]))
self
.
fetch_list
[
i
],
str
(
place
),
outs_opt
[
i
],
outs
[
i
]))
def
_check_fused_ops
(
self
,
program
):
'''
...
...
python/paddle/fluid/tests/unittests/ir/test_ir_fusion_group_pass.py
浏览文件 @
3757e068
...
...
@@ -35,10 +35,15 @@ class FusionGroupPassTest(PassTest):
# subgraph with 2 op nodes
tmp_2
=
layers
.
relu
(
tmp_0
+
tmp_1
)
self
.
fetch_list
=
[
tmp_2
]
self
.
num_fused_ops
=
1
self
.
fetch_list
=
[
tmp_2
.
name
,
tmp_1
.
name
+
"@GRAD"
]
if
self
.
backward
:
self
.
append_gradinets
(
tmp_2
)
self
.
num_fused_ops
=
2
def
setUp
(
self
):
self
.
backward
=
True
self
.
build_program
(
"float32"
)
self
.
feeds
=
self
.
_feed_random_data
(
self
.
feed_vars
)
self
.
pass_names
=
"fusion_group_pass"
...
...
@@ -86,8 +91,13 @@ class FusionGroupPassTest1(FusionGroupPassTest):
self
.
feed_vars
[
2
])
*
layers
.
tanh
(
self
.
feed_vars
[
3
])
tmp_2
=
layers
.
tanh
(
tmp_1
)
+
layers
.
sigmoid
(
self
.
feed_vars
[
4
])
self
.
fetch_list
=
[
tmp_1
,
tmp_2
]
self
.
num_fused_ops
=
1
if
self
.
backward
:
self
.
append_gradinets
(
tmp_2
)
self
.
num_fused_ops
=
2
else
:
self
.
num_fused_ops
=
1
self
.
fetch_list
=
[
tmp_2
.
name
,
tmp_0
.
name
+
"@GRAD"
]
class
FusionGroupPassTest2
(
FusionGroupPassTest
):
...
...
@@ -98,15 +108,27 @@ class FusionGroupPassTest2(FusionGroupPassTest):
fluid
.
data
(
name
=
"data3"
,
shape
=
[
128
,
32
],
dtype
=
dtype
))
# subgraph with 3 op node
s
tmp_
1
=
layers
.
relu
(
(
self
.
feed_vars
[
0
]
-
self
.
feed_vars
[
1
])
*
self
.
feed_vars
[
2
]
)
# subgraph with 3 op node
tmp_
0
=
self
.
feed_vars
[
0
]
+
self
.
feed_vars
[
1
]
tmp_1
=
layers
.
relu
(
self
.
feed_vars
[
2
]
*
tmp_0
)
# subgraph with 2 op nodes
tmp_2
=
layers
.
relu
(
layers
.
sigmoid
(
self
.
feed_vars
[
3
]))
tmp_3
=
layers
.
mul
(
tmp_1
,
tmp_2
)
self
.
fetch_list
=
[
tmp_1
,
tmp_2
,
tmp_3
]
self
.
num_fused_ops
=
2
self
.
fetch_list
=
[
tmp_3
.
name
]
#TODO(wangchaochaohu): we need to deal with the condition of stop gradient
if
self
.
backward
:
self
.
append_gradinets
(
tmp_3
)
self
.
num_fused_ops
=
3
def
setUp
(
self
):
self
.
backward
=
False
self
.
build_program
(
"float32"
)
self
.
feeds
=
self
.
_feed_random_data
(
self
.
feed_vars
)
self
.
pass_names
=
"fusion_group_pass"
self
.
fused_op_type
=
"fusion_group"
class
FusionGroupPassTestFP64
(
FusionGroupPassTest
):
...
...
@@ -132,8 +154,12 @@ class FusionGroupPassTestFP16(FusionGroupPassTest):
tmp_4
=
layers
.
relu
(
tmp_2
+
tmp_3
)
tmp_5
=
layers
.
cast
(
tmp_4
,
dtype
=
dtype
)
self
.
fetch_list
=
[
tmp_0
,
tmp_1
,
tmp_2
,
tmp_3
,
tmp_4
,
tmp_5
]
self
.
num_fused_ops
=
2
self
.
num_fused_ops
=
1
self
.
fetch_list
=
[
tmp_5
.
name
]
if
self
.
backward
:
self
.
num_fused_ops
=
4
self
.
append_gradinets
(
tmp_5
)
class
FusionGroupPassSumTest
(
FusionGroupPassTest
):
...
...
@@ -158,9 +184,13 @@ class FusionGroupPassCastTest(FusionGroupPassTest):
tmp_1
=
layers
.
cast
(
tmp_0
,
dtype
=
"double"
)
tmp_2
=
layers
.
cast
(
tmp_1
,
dtype
=
"float32"
)
self
.
fetch_list
=
[
tmp_
0
,
tmp_1
,
tmp_2
]
self
.
fetch_list
=
[
tmp_
2
.
name
,
tmp_1
.
name
+
"@GRAD"
]
self
.
num_fused_ops
=
1
if
self
.
backward
:
self
.
num_fused_ops
=
2
self
.
append_gradinets
(
tmp_2
)
def
setUp
(
self
):
self
.
build_program
(
"float64"
)
self
.
feeds
=
self
.
_feed_random_data
(
self
.
feed_vars
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录