Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
机器未来
Paddle
提交
2a98cba2
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,发现更多精彩内容 >>
提交
2a98cba2
编写于
9月 15, 2017
作者:
T
tensor-tang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
enable mkldnn_pool forward and backward
上级
d3a86c67
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
216 addition
and
12 deletion
+216
-12
paddle/gserver/layers/MKLDNNPoolLayer.cpp
paddle/gserver/layers/MKLDNNPoolLayer.cpp
+171
-12
paddle/gserver/layers/MKLDNNPoolLayer.h
paddle/gserver/layers/MKLDNNPoolLayer.h
+45
-0
未找到文件。
paddle/gserver/layers/MKLDNNPoolLayer.cpp
浏览文件 @
2a98cba2
...
...
@@ -13,6 +13,7 @@ See the License for the specific language governing permissions and
limitations under the License. */
#include "MKLDNNPoolLayer.h"
#include "paddle/math/MathUtils.h"
#include "paddle/utils/Logging.h"
using
namespace
mkldnn
;
// NOLINT
...
...
@@ -28,17 +29,49 @@ bool MKLDNNPoolLayer::init(const LayerMap& layerMap,
return
false
;
}
/* the size of inputs for pool-layer is 1 */
CHECK_EQ
(
config_
.
inputs_size
(),
1
);
const
PoolConfig
&
conf
=
config_
.
inputs
(
0
).
pool_conf
();
ic_
=
conf
.
channels
();
ih_
=
conf
.
img_size_y
();
iw_
=
conf
.
img_size
();
oc_
=
ic_
;
oh_
=
conf
.
output_y
();
ow_
=
conf
.
output_x
();
fh_
=
conf
.
size_y
();
fw_
=
conf
.
size_x
();
ph_
=
conf
.
padding_y
();
pw_
=
conf
.
padding
();
sh_
=
conf
.
stride_y
();
sw_
=
conf
.
stride
();
const
std
::
string
&
type
=
conf
.
pool_type
();
if
(
type
==
"max-projection"
)
{
poolAlgo_
=
algorithm
::
pooling_max
;
}
else
if
(
type
==
"avg-projection"
)
{
// TODO(TJ): support choosing exclude or include when paddle support it
// paddle only support pooling_avg_exclude_padding yet
poolAlgo_
=
algorithm
::
pooling_avg_exclude_padding
;
}
else
{
LOG
(
FATAL
)
<<
"unknow pooling type!"
;
}
return
true
;
}
void
MKLDNNPoolLayer
::
reshape
(
int
&
bs
,
int
&
ic
,
int
&
ih
,
int
&
iw
,
int
oc
,
int
&
oh
,
int
&
ow
)
{
reshapeInput
(
bs
,
ih
,
iw
);
// ic_ and oc can not be changed
CHECK_EQ
(
inputElemenCnt_
/
bs
/
ih
/
iw
,
(
size_t
)
ic
)
<<
"Input channel can not be changed"
;
// cal output sizes
// oc can not be changed
// paddle used false caffeMode for pooling
oh
=
outputSize
(
ih
,
fh_
,
ph_
,
sh_
,
false
);
ow
=
outputSize
(
iw
,
fw_
,
pw_
,
sw_
,
false
);
reshapeOutput
(
oh
,
ow
);
resizeOutput
(
bs
,
oc
*
oh
*
ow
);
printSizeInfo
();
...
...
@@ -81,40 +114,166 @@ void MKLDNNPoolLayer::updateInputData() {
void
MKLDNNPoolLayer
::
resetFwdBuffers
(
MKLDNNMatrixPtr
&
in
,
MKLDNNMatrixPtr
&
out
)
{
resetInValue
(
in
);
resetOutValue
(
out
);
}
void
MKLDNNPoolLayer
::
resetInValue
(
MKLDNNMatrixPtr
&
in
)
{}
void
MKLDNNPoolLayer
::
resetInValue
(
MKLDNNMatrixPtr
&
in
)
{
if
(
inputIsOnlyMKLDNN
())
{
const
MatrixPtr
&
dnnIn
=
getInputValue
(
0
);
in
=
std
::
dynamic_pointer_cast
<
MKLDNNMatrix
>
(
dnnIn
);
CHECK
(
in
)
<<
"Input should be MKLDNNMatrix"
;
}
else
{
CHECK_EQ
(
getPrev
(
0
)
->
getDeviceId
(),
CPU_DEVICE
)
<<
"Only support CPU yet"
;
const
MatrixPtr
&
cpuIn
=
getInputValue
(
0
,
CPU_DEVICE
);
in
=
MKLDNNMatrix
::
create
(
cpuIn
,
{
bs_
,
ic_
,
ih_
,
iw_
},
format
::
nchw
,
engine_
);
}
}
void
MKLDNNPoolLayer
::
resetOutValue
(
MKLDNNMatrixPtr
&
out
)
{}
void
MKLDNNPoolLayer
::
resetOutValue
(
MKLDNNMatrixPtr
&
out
)
{
CHECK
(
inVal_
)
<<
"Should reset input value first"
;
memory
::
dims
outDims
=
memory
::
dims
{
bs_
,
oc_
,
oh_
,
ow_
};
out
=
MKLDNNMatrix
::
create
(
output_
.
value
,
outDims
,
inVal_
->
getFormat
(),
engine_
);
output_
.
value
=
std
::
dynamic_pointer_cast
<
Matrix
>
(
out
);
// create reorder if output value has cpu device and pd do not match
cpuOutVal_
=
nullptr
;
cvtOutVal_
=
nullptr
;
if
(
!
outputIsOnlyMKLDNN
())
{
const
MatrixPtr
&
cpuOut
=
getOutput
(
CPU_DEVICE
).
value
;
cpuOutVal_
=
MKLDNNMatrix
::
create
(
cpuOut
,
outDims
,
format
::
nchw
,
engine_
);
if
(
cpuOutVal_
->
getPrimitiveDesc
()
!=
out
->
getPrimitiveDesc
())
{
cvtOutVal_
=
MKLDNNMatrix
::
createReorder
(
out
,
cpuOutVal_
);
CHECK
(
cvtOutVal_
)
<<
"should not be emptry"
;
}
else
{
// CPU output share the same data of MKLDNN output
cpuOut
->
setData
(
out
->
getData
());
cpuOutVal_
=
out
;
}
}
}
void
MKLDNNPoolLayer
::
resetFwdPD
(
std
::
shared_ptr
<
pool_fwd
::
primitive_desc
>&
pd
,
MKLDNNMatrixPtr
in
,
MKLDNNMatrixPtr
out
)
{}
MKLDNNMatrixPtr
out
)
{
memory
::
dims
inDims
=
memory
::
dims
{
bs_
,
ic_
,
ih_
,
iw_
};
memory
::
dims
outDims
=
memory
::
dims
{
bs_
,
oc_
,
oh_
,
ow_
};
memory
::
dims
kernels
=
memory
::
dims
{
fh_
,
fw_
};
memory
::
dims
strides
=
memory
::
dims
{
sh_
,
sw_
};
memory
::
dims
padL
=
memory
::
dims
{
ph_
,
pw_
};
memory
::
dims
padR
=
getPaddingR
();
padding_kind
padKind
=
padding_kind
::
zero
;
prop_kind
pk
=
passType_
==
PASS_TEST
?
prop_kind
::
forward_scoring
:
prop_kind
::
forward_training
;
auto
fwdDesc
=
pool_fwd
::
desc
(
pk
,
poolAlgo_
,
in
->
getMemoryDesc
(),
out
->
getMemoryDesc
(),
strides
,
kernels
,
padL
,
padR
,
padKind
);
pd
.
reset
(
new
pool_fwd
::
primitive_desc
(
fwdDesc
,
engine_
));
// prepare workspace if necessary
workspace_
=
(
passType_
!=
PASS_TEST
&&
poolAlgo_
==
algorithm
::
pooling_max
)
?
std
::
make_shared
<
memory
>
(
memory
(
pd
->
workspace_primitive_desc
()))
:
nullptr
;
}
void
MKLDNNPoolLayer
::
resetFwdPipeline
(
std
::
vector
<
mkldnn
::
primitive
>&
pipeline
,
std
::
vector
<
primitive
>&
pipeline
,
std
::
shared_ptr
<
pool_fwd
::
primitive_desc
>&
pd
,
MKLDNNMatrixPtr
&
in
,
MKLDNNMatrixPtr
&
out
)
{}
MKLDNNMatrixPtr
&
out
)
{
pipeline
.
clear
();
fwd_
=
workspace_
?
std
::
make_shared
<
pool_fwd
>
(
pool_fwd
(
*
pd
,
*
in
,
*
out
,
*
workspace_
))
:
std
::
make_shared
<
pool_fwd
>
(
pool_fwd
(
*
pd
,
*
in
,
*
out
));
pipeline
.
push_back
(
*
fwd_
);
if
(
cvtOutVal_
)
{
pipeline
.
push_back
(
*
cvtOutVal_
);
}
}
void
MKLDNNPoolLayer
::
resetBwdBuffers
(
MKLDNNMatrixPtr
&
in
,
MKLDNNMatrixPtr
&
out
)
{
resetOutGrad
(
out
);
resetInGrad
(
in
);
}
void
MKLDNNPoolLayer
::
resetOutGrad
(
MKLDNNMatrixPtr
&
out
)
{}
void
MKLDNNPoolLayer
::
resetOutGrad
(
MKLDNNMatrixPtr
&
out
)
{
CHECK
(
outVal_
)
<<
"Should have output value"
;
out
=
MKLDNNMatrix
::
create
(
output_
.
grad
,
outVal_
->
getPrimitiveDesc
());
// create reorder if output value has cpu device and pd do not match
cpuOutGrad_
=
nullptr
;
cvtOutGrad_
=
nullptr
;
if
(
!
outputIsOnlyMKLDNN
())
{
const
MatrixPtr
&
cpuOut
=
getOutput
(
CPU_DEVICE
).
grad
;
cpuOutGrad_
=
MKLDNNMatrix
::
create
(
cpuOut
,
memory
::
dims
{
bs_
,
oc_
,
oh_
,
ow_
},
format
::
nchw
,
engine_
);
if
(
cpuOutGrad_
->
getPrimitiveDesc
()
!=
out
->
getPrimitiveDesc
())
{
cvtOutGrad_
=
MKLDNNMatrix
::
createReorder
(
cpuOutGrad_
,
out
);
CHECK
(
cvtOutGrad_
)
<<
"should not be emptry"
;
}
else
{
// share the same data of CPU output
output_
.
grad
->
setData
(
cpuOut
->
getData
());
out
=
cpuOutGrad_
;
}
}
}
void
MKLDNNPoolLayer
::
resetInGrad
(
MKLDNNMatrixPtr
&
in
)
{}
void
MKLDNNPoolLayer
::
resetInGrad
(
MKLDNNMatrixPtr
&
in
)
{
in
=
nullptr
;
const
MatrixPtr
&
inGrad
=
inputLayers_
[
0
]
->
getOutput
().
grad
;
if
(
inGrad
==
nullptr
)
{
return
;
}
CHECK
(
inVal_
);
in
=
MKLDNNMatrix
::
create
(
inGrad
,
inVal_
->
getPrimitiveDesc
());
}
void
MKLDNNPoolLayer
::
resetBwdPD
(
std
::
shared_ptr
<
pool_bwd
::
primitive_desc
>&
pd
,
MKLDNNMatrixPtr
&
in
,
MKLDNNMatrixPtr
&
out
)
{}
MKLDNNMatrixPtr
&
out
)
{
memory
::
dims
kernels
=
memory
::
dims
{
fh_
,
fw_
};
memory
::
dims
strides
=
memory
::
dims
{
sh_
,
sw_
};
memory
::
dims
padL
=
memory
::
dims
{
ph_
,
pw_
};
memory
::
dims
padR
=
getPaddingR
();
CHECK
(
in
);
CHECK
(
out
);
auto
bwdDesc
=
pool_bwd
::
desc
(
poolAlgo_
,
in
->
getMemoryDesc
(),
out
->
getMemoryDesc
(),
strides
,
kernels
,
padL
,
padR
,
padding_kind
::
zero
);
pd
.
reset
(
new
pool_bwd
::
primitive_desc
(
bwdDesc
,
engine_
,
*
fwdPD_
));
}
void
MKLDNNPoolLayer
::
resetBwdPipeline
(
std
::
vector
<
mkldnn
::
primitive
>&
pipeline
,
std
::
vector
<
primitive
>&
pipeline
,
std
::
shared_ptr
<
pool_bwd
::
primitive_desc
>&
pd
,
MKLDNNMatrixPtr
&
in
,
MKLDNNMatrixPtr
&
out
)
{}
MKLDNNMatrixPtr
&
out
)
{
pipeline
.
clear
();
if
(
cvtOutGrad_
)
{
pipeline
.
push_back
(
*
cvtOutGrad_
);
}
bwdData_
=
workspace_
?
std
::
make_shared
<
pool_bwd
>
(
pool_bwd
(
*
pd
,
*
out
,
*
workspace_
,
*
in
))
:
std
::
make_shared
<
pool_bwd
>
(
pool_bwd
(
*
pd
,
*
out
,
*
in
));
pipeline
.
push_back
(
*
bwdData_
);
}
}
// namespace paddle
paddle/gserver/layers/MKLDNNPoolLayer.h
浏览文件 @
2a98cba2
...
...
@@ -28,8 +28,28 @@ typedef mkldnn::pooling_backward pool_bwd;
*/
class
MKLDNNPoolLayer
:
public
MKLDNNLayer
{
protected:
// padding height and width
int
ph_
,
pw_
;
// stride height and width
int
sh_
,
sw_
;
// filter(kenerl) height and width
int
fh_
,
fw_
;
// pooling_avg or pooling_max
mkldnn
::
algorithm
poolAlgo_
;
// MKLDNNMatrixPtr which should be created from CPU Device
MKLDNNMatrixPtr
cpuOutVal_
;
MKLDNNMatrixPtr
cpuOutGrad_
;
// convert handle between CPU device and MKLDNN device
std
::
shared_ptr
<
mkldnn
::
reorder
>
cvtOutVal_
;
std
::
shared_ptr
<
mkldnn
::
reorder
>
cvtOutGrad_
;
// save forward primitive_desc, which can be used backward
std
::
shared_ptr
<
pool_fwd
::
primitive_desc
>
fwdPD_
;
// according to https://github.com/01org/mkl-dnn/blob/master/tests/gtests/
// test_pooling_forward.cpp, pool need workspace for backward
std
::
shared_ptr
<
mkldnn
::
memory
>
workspace_
;
public:
explicit
MKLDNNPoolLayer
(
const
LayerConfig
&
config
)
:
MKLDNNLayer
(
config
)
{}
...
...
@@ -56,6 +76,13 @@ public:
void
updateInputData
()
override
;
void
printSizeInfo
()
override
{
MKLDNNLayer
::
printSizeInfo
();
VLOG
(
MKLDNN_SIZES
)
<<
getName
()
<<
": fh: "
<<
fh_
<<
", fw: "
<<
fw_
<<
": ph: "
<<
ph_
<<
", pw: "
<<
pw_
<<
", sh: "
<<
sh_
<<
", sw: "
<<
sw_
;
}
protected:
/**
* Forward functions: reset buffers(input, output),
...
...
@@ -88,6 +115,24 @@ protected:
std
::
shared_ptr
<
pool_bwd
::
primitive_desc
>&
pd
,
MKLDNNMatrixPtr
&
in
,
MKLDNNMatrixPtr
&
out
);
/**
* get padding_r according to
* https://github.com/01org/mkl-dnn/blob/master/tests/gtests/
* test_pooling_forward.cpp
*/
mkldnn
::
memory
::
dims
getPaddingR
()
const
{
mkldnn
::
memory
::
dims
padR
=
{
ph_
,
pw_
};
for
(
int
i
=
0
;
i
<
2
;
++
i
)
{
if
((
ih_
+
ph_
+
padR
[
0
]
-
fh_
)
/
sh_
+
1
<
oh_
)
{
++
padR
[
0
];
}
if
((
iw_
+
pw_
+
padR
[
1
]
-
fw_
)
/
sw_
+
1
<
ow_
)
{
++
padR
[
1
];
}
}
return
padR
;
}
};
}
// namespace paddle
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录