Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Xiaomi
Mace
提交
97addf5a
Mace
项目概览
Xiaomi
/
Mace
通知
107
Star
40
Fork
27
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Mace
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
97addf5a
编写于
9月 06, 2017
作者:
W
wuchenghui
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add pooling op
上级
e1e25d7c
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
288 addition
and
4 deletion
+288
-4
mace/kernels/pooling.h
mace/kernels/pooling.h
+141
-0
mace/ops/BUILD
mace/ops/BUILD
+35
-4
mace/ops/pooling.cc
mace/ops/pooling.cc
+25
-0
mace/ops/pooling.h
mace/ops/pooling.h
+22
-0
mace/ops/pooling_test.cc
mace/ops/pooling_test.cc
+65
-0
未找到文件。
mace/kernels/pooling.h
0 → 100644
浏览文件 @
97addf5a
//
// Copyright (c) 2017 XiaoMi All rights reserved.
//
#ifndef MACE_KERNELS_POOLING_H
#define MACE_KERNELS_POOLING_H
#include "mace/core/tensor.h"
namespace
mace
{
namespace
kernels
{
enum
{
PoolMethod_MAX
=
0
,
PoolMethod_AVE
=
1
};
enum
{
PADDING_DROP
=
0
,
PADDING_ZERO
=
1
};
template
<
typename
T
>
void
PoolingFunction
(
const
Tensor
*
input_tensor
,
Tensor
*
output_tensor
,
int
pooling_type
,
int
kernel_size
,
int
stride
,
int
padding
)
{
// max value in NxN window
// avg value in NxN window
vector
<
int64
>
in_shape
=
input_tensor
->
shape
();
REQUIRE
(
in_shape
.
size
()
==
4
,
"The input tensor shape should specify 4 dimensions(NCHW)"
);
int64
batch_size
=
in_shape
[
0
];
int64
channels
=
in_shape
[
1
];
int64
h
=
in_shape
[
2
];
int64
w
=
in_shape
[
3
];
// calculate paddings and output tensor shape
int
outw
,
outh
,
pad_top
,
pad_bottom
,
pad_left
,
pad_right
;
if
(
padding
==
PADDING_ZERO
)
{
int
wpad
=
kernel_size
+
(
w
-
1
)
/
stride
*
stride
-
w
;
int
hpad
=
kernel_size
+
(
h
-
1
)
/
stride
*
stride
-
h
;
pad_top
=
hpad
/
2
;
pad_bottom
=
hpad
-
pad_top
;
pad_left
=
wpad
/
2
;
pad_right
=
wpad
-
pad_left
;
outw
=
(
w
+
wpad
-
kernel_size
)
/
stride
+
1
;
outh
=
(
h
+
hpad
-
kernel_size
)
/
stride
+
1
;
}
else
if
(
padding
==
PADDING_DROP
)
// Drop bottom-most rows and right-most columns
{
pad_top
=
pad_bottom
=
pad_left
=
pad_right
=
0
;
outw
=
(
w
-
kernel_size
)
/
stride
+
1
;
outh
=
(
h
-
kernel_size
)
/
stride
+
1
;
}
output_tensor
->
Resize
({
batch_size
,
channels
,
outh
,
outw
});
if
(
pooling_type
==
PoolMethod_MAX
)
{
#pragma omp parallel for
for
(
int
batch
=
0
;
batch
<
batch_size
;
batch
++
)
{
for
(
int
q
=
0
;
q
<
channels
;
q
++
)
{
float
*
outptr
=
output_tensor
->
mutable_data
<
float
>
()
+
(
batch
*
channels
+
q
)
*
outw
*
outh
;
for
(
int
i
=
0
;
i
<
outh
;
i
++
)
{
for
(
int
j
=
0
;
j
<
outw
;
j
++
)
{
float
val
;
float
max
;
if
(
padding
==
PADDING_ZERO
)
{
max
=
0.0
;
for
(
int
m
=
0
;
m
<
kernel_size
;
m
++
)
{
for
(
int
n
=
0
;
n
<
kernel_size
;
n
++
)
{
if
(
i
*
stride
-
pad_top
+
m
<
0
||
j
*
stride
-
pad_left
+
n
<
0
||
i
*
stride
-
pad_top
+
m
>=
h
||
j
*
stride
-
pad_left
+
n
>=
w
)
{
val
=
0.0
;
}
else
{
int
index
=
(
batch
*
channels
+
q
)
*
w
*
h
+
w
*
(
i
*
stride
-
pad_top
+
m
)
+
j
*
stride
-
pad_left
+
n
;
val
=
input_tensor
->
data
<
float
>
()[
index
];
}
max
=
std
::
max
(
max
,
val
);
}
}
}
else
{
const
float
*
sptr
=
input_tensor
->
data
<
float
>
()
+
(
batch
*
channels
+
q
)
*
w
*
h
+
w
*
i
*
stride
+
j
*
stride
;
max
=
sptr
[
0
];
for
(
int
m
=
0
;
m
<
kernel_size
;
m
++
)
{
for
(
int
n
=
0
;
n
<
kernel_size
;
n
++
)
{
val
=
sptr
[
w
*
m
+
n
];
max
=
std
::
max
(
max
,
val
);
}
}
}
outptr
[
j
]
=
max
;
}
outptr
+=
outw
;
}
}
}
}
else
if
(
pooling_type
==
PoolMethod_AVE
)
{
#pragma omp parallel for
for
(
int
batch
=
0
;
batch
<
batch_size
;
batch
++
)
{
for
(
int
q
=
0
;
q
<
channels
;
q
++
)
{
float
*
outptr
=
output_tensor
->
mutable_data
<
float
>
()
+
(
batch
*
channels
+
q
)
*
outw
*
outh
;
for
(
int
i
=
0
;
i
<
outh
;
i
++
)
{
for
(
int
j
=
0
;
j
<
outw
;
j
++
)
{
float
val
;
float
sum
=
0.0
;
if
(
padding
==
PADDING_ZERO
)
{
for
(
int
m
=
0
;
m
<
kernel_size
;
m
++
)
{
for
(
int
n
=
0
;
n
<
kernel_size
;
n
++
)
{
if
(
i
*
stride
-
pad_top
+
m
<
0
||
j
*
stride
-
pad_left
+
n
<
0
||
i
*
stride
-
pad_top
+
m
>=
h
||
j
*
stride
-
pad_left
+
n
>=
w
)
{
val
=
0.0
;
}
else
{
int
index
=
(
batch
*
channels
+
q
)
*
w
*
h
+
w
*
(
i
*
stride
-
pad_top
+
m
)
+
j
*
stride
-
pad_left
+
n
;
val
=
input_tensor
->
data
<
float
>
()[
index
];
}
sum
+=
val
;
}
}
}
else
{
const
float
*
sptr
=
input_tensor
->
data
<
float
>
()
+
(
batch
*
channels
+
q
)
*
w
*
h
+
w
*
i
*
stride
+
j
*
stride
;
for
(
int
m
=
0
;
m
<
kernel_size
;
m
++
)
{
for
(
int
n
=
0
;
n
<
kernel_size
;
n
++
)
{
val
=
sptr
[
w
*
m
+
n
];
sum
+=
val
;
}
}
}
outptr
[
j
]
=
sum
/
(
kernel_size
*
kernel_size
);
}
outptr
+=
outw
;
}
}
}
}
}
}
// namespace kernels
}
// namespace mace
#endif //MACE_KERNELS_POOLING_H
mace/ops/BUILD
浏览文件 @
97addf5a
...
@@ -5,7 +5,6 @@ package(
...
@@ -5,7 +5,6 @@ package(
default_visibility
=
[
"//visibility:public"
],
default_visibility
=
[
"//visibility:public"
],
)
)
licenses
([
"notice"
])
# Apache 2.0
licenses
([
"notice"
])
# Apache 2.0
load
(
"//mace:mace.bzl"
,
"if_android"
)
load
(
"//mace:mace.bzl"
,
"if_android"
)
...
@@ -14,11 +13,43 @@ cc_library(
...
@@ -14,11 +13,43 @@ cc_library(
name
=
"ops"
,
name
=
"ops"
,
srcs
=
glob
([
"*.cc"
]),
srcs
=
glob
([
"*.cc"
]),
hdrs
=
glob
([
"*.h"
]),
hdrs
=
glob
([
"*.h"
]),
copts
=
[
"-std=c++11"
],
deps
=
[
deps
=
[
"//mace/core"
,
"//mace/kernels"
,
"//mace/proto:cc_proto"
,
"//mace/proto:cc_proto"
,
"//mace/core:core"
,
"//mace/kernels:kernels"
,
],
],
copts
=
[
'-std=c++11'
],
alwayslink
=
1
,
alwayslink
=
1
,
)
)
cc_test
(
name
=
"relu_test"
,
srcs
=
[
"relu_test.cc"
],
copts
=
[
"-std=c++11"
],
linkopts
=
if_android
([
"-pie"
,
"-llog"
,
"-latomic"
,
]),
linkstatic
=
1
,
deps
=
[
":ops"
,
"@gtest//:gtest_main"
,
],
)
cc_test
(
name
=
"pooling_test"
,
srcs
=
[
"pooling_test.cc"
],
copts
=
[
"-std=c++11"
],
linkopts
=
if_android
([
"-pie"
,
"-llog"
,
"-latomic"
,
]),
linkstatic
=
1
,
deps
=
[
":ops"
,
"@gtest//:gtest_main"
,
],
)
mace/ops/pooling.cc
0 → 100644
浏览文件 @
97addf5a
//
// Copyright (c) 2017 XiaoMi All rights reserved.
//
#include "mace/ops/pooling.h"
#include "mace/proto/mace.pb.h"
#include "mace/kernels/pooling.h"
namespace
mace
{
template
<
>
bool
PoolingOp
<
DeviceType
::
CPU
,
float
>::
Run
()
{
const
Tensor
*
input_tensor
=
Input
(
0
);
Tensor
*
output_tensor
=
Output
(
0
);
int
pooling_type
=
this
->
GetSingleArgument
<
int
>
(
"pooling_type"
,
0
);
int
kernel_size
=
this
->
GetSingleArgument
<
int
>
(
"kernel_size"
,
1
);
int
stride
=
this
->
GetSingleArgument
<
int
>
(
"stride"
,
1
);
int
padding
=
this
->
GetSingleArgument
<
int
>
(
"padding"
,
0
);
kernels
::
PoolingFunction
<
float
>
(
input_tensor
,
output_tensor
,
pooling_type
,
kernel_size
,
stride
,
padding
);
return
true
;
}
REGISTER_CPU_OPERATOR
(
Pooling
,
PoolingOp
<
DeviceType
::
CPU
,
float
>
);
}
// namespace mace
mace/ops/pooling.h
0 → 100644
浏览文件 @
97addf5a
//
// Copyright (c) 2017 XiaoMi All rights reserved.
//
#ifndef MACE_OPS_POOLING_H_
#define MACE_OPS_POOLING_H_
#include "mace/core/operator.h"
namespace
mace
{
template
<
DeviceType
D
,
class
T
>
class
PoolingOp
:
public
Operator
<
D
,
T
>
{
public:
PoolingOp
(
const
OperatorDef
&
operator_def
,
Workspace
*
ws
)
:
Operator
<
D
,
T
>
(
operator_def
,
ws
)
{}
bool
Run
()
override
;
};
}
// namespace mace
#endif //MACE_OPS_POOLING_H_
mace/ops/pooling_test.cc
0 → 100644
浏览文件 @
97addf5a
//
// Copyright (c) 2017 XiaoMi All rights reserved.
//
#include "gtest/gtest.h"
#include "mace/core/operator.h"
#include "mace/core/net.h"
using
namespace
mace
;
TEST
(
PoolingTest
,
Pooling
)
{
OperatorRegistry
*
registry
=
gDeviceTypeRegistry
()
->
at
(
DeviceType
::
CPU
);
vector
<
string
>
registry_keys
=
registry
->
Keys
();
for
(
auto
&
key
:
registry_keys
)
{
VLOG
(
0
)
<<
"registry_op: "
<<
key
;
}
// Construct graph
OperatorDef
op_def
;
op_def
.
add_input
(
"Input0"
);
op_def
.
add_output
(
"Output0"
);
op_def
.
set_name
(
"PoolingTest"
);
op_def
.
set_type
(
"Pooling"
);
auto
pooling_type
=
op_def
.
add_arg
();
pooling_type
->
set_name
(
"pooling_type"
);
pooling_type
->
set_i
(
0
);
auto
kernel_size
=
op_def
.
add_arg
();
kernel_size
->
set_name
(
"kernel_size"
);
kernel_size
->
set_i
(
2
);
auto
stride
=
op_def
.
add_arg
();
stride
->
set_name
(
"stride"
);
stride
->
set_i
(
2
);
auto
padding
=
op_def
.
add_arg
();
padding
->
set_name
(
"padding"
);
padding
->
set_i
(
0
);
NetDef
net_def
;
net_def
.
set_name
(
"NetTest"
);
net_def
.
add_op
()
->
CopyFrom
(
op_def
);
VLOG
(
0
)
<<
net_def
.
DebugString
();
// Create workspace and input tensor
Workspace
ws
;
Tensor
*
input
=
ws
.
CreateTensor
(
"Input0"
,
cpu_allocator
(),
DataType
::
DT_FLOAT
);
Tensor
*
output
=
ws
.
CreateTensor
(
"Output0"
,
cpu_allocator
(),
DataType
::
DT_FLOAT
);
input
->
Resize
({
2
,
2
,
4
,
4
});
float
*
input_data
=
input
->
mutable_data
<
float
>
();
for
(
int
i
=
0
;
i
<
64
;
++
i
)
{
input_data
[
i
]
=
i
;
}
// Create Net & run
auto
net
=
CreateNet
(
net_def
,
&
ws
,
DeviceType
::
CPU
);
net
->
Run
();
for
(
int
d
:
output
->
shape
()){
ASSERT_EQ
(
d
,
2
);
}
ASSERT_FLOAT_EQ
(
output
->
data
<
float
>
()[
0
],
5
);
ASSERT_FLOAT_EQ
(
output
->
data
<
float
>
()[
3
],
15
);
ASSERT_FLOAT_EQ
(
output
->
data
<
float
>
()[
15
],
63
);
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录