Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
飞翔的比温特
Mace
提交
1bf8032a
Mace
项目概览
飞翔的比温特
/
Mace
与 Fork 源项目一致
Fork自
Xiaomi / Mace
通知
3
Star
0
Fork
0
代码
文件
提交
分支
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看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
1bf8032a
编写于
8月 27, 2020
作者:
Z
Zhang Zhimin
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add micro concat op
上级
2eca3a0f
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
451 addition
and
0 deletion
+451
-0
micro/ops/concat.h
micro/ops/concat.h
+85
-0
micro/test/ccunit/micro/ops/concat_test.cc
micro/test/ccunit/micro/ops/concat_test.cc
+359
-0
tools/python/micro/micro_support_ops.py
tools/python/micro/micro_support_ops.py
+2
-0
tools/python/micro/scratch_computer.py
tools/python/micro/scratch_computer.py
+5
-0
未找到文件。
micro/ops/concat.h
0 → 100644
浏览文件 @
1bf8032a
// Copyright 2020 The MACE Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef MICRO_OPS_CONCAT_H_
#define MICRO_OPS_CONCAT_H_
#include "micro/base/utils.h"
#include "micro/framework/operator.h"
#include "micro/framework/scratch_buffer.h"
namespace
micro
{
namespace
ops
{
template
<
typename
T
>
class
ConcatOp
:
public
framework
::
Operator
{
public:
MaceStatus
OnInit
()
{
return
MACE_SUCCESS
;
}
MaceStatus
Run
()
{
const
int32_t
*
output_dims
=
GetOutputShapeDims
(
0
);
int32_t
output_dim_size
=
GetOutputShapeDimSize
(
0
);
int32_t
inputs_count
=
GetInputSize
();
MACE_ASSERT
(
inputs_count
>=
1
);
int32_t
axis
=
GetArgByName
(
"axis"
,
static_cast
<
int32_t
>
(
0
));
axis
=
axis
<
0
?
axis
+
output_dim_size
:
axis
;
MACE_ASSERT
(
0
<=
axis
&&
axis
<
output_dim_size
);
int32_t
inner_size
=
1
;
for
(
int
i
=
0
;
i
<
axis
;
++
i
)
{
inner_size
*=
output_dims
[
i
];
}
ScratchBuffer
scratch_buffer
(
engine_config_
);
int32_t
*
outer_sizes
=
scratch_buffer
.
GetBuffer
<
int32_t
>
(
inputs_count
);
for
(
int32_t
i
=
0
;
i
<
inputs_count
;
++
i
)
{
const
int32_t
*
input_dims
=
GetInputShapeDims
(
i
);
int32_t
input_dim_size
=
GetInputShapeDimSize
(
i
);
MACE_ASSERT
(
output_dim_size
==
input_dim_size
);
for
(
int
j
=
0
;
j
<
output_dim_size
;
++
j
)
{
if
(
j
==
axis
)
continue
;
MACE_ASSERT
(
input_dims
[
j
]
==
output_dims
[
j
]);
}
outer_sizes
[
i
]
=
1
;
for
(
int32_t
j
=
axis
;
j
<
input_dim_size
;
++
j
)
{
outer_sizes
[
i
]
*=
input_dims
[
j
];
}
}
const
T
**
input_ptrs
=
scratch_buffer
.
GetBuffer
<
const
T
*>
(
inputs_count
);
for
(
int32_t
i
=
0
;
i
<
inputs_count
;
++
i
)
{
input_ptrs
[
i
]
=
GetInputData
<
T
>
(
i
);
}
T
*
output
=
GetOutputData
<
T
>
(
0
);
for
(
int32_t
inner_idx
=
0
;
inner_idx
<
inner_size
;
++
inner_idx
)
{
for
(
int32_t
i
=
0
;
i
<
inputs_count
;
++
i
)
{
for
(
int32_t
k
=
0
;
k
<
outer_sizes
[
i
];
++
k
)
{
*
output
++
=
*
input_ptrs
[
i
]
++
;
}
}
}
return
MaceStatus
::
MACE_SUCCESS
;
}
};
}
// namespace ops
}
// namespace micro
#endif // MICRO_OPS_CONCAT_H_
micro/test/ccunit/micro/ops/concat_test.cc
0 → 100644
浏览文件 @
1bf8032a
// Copyright 2018 The MACE Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "micro/ops/concat.h"
#include "gtest/gtest.h"
#include "micro/ops/gtest_utils.h"
#include "micro/ops/substitute_op.h"
#include "micro/ops/test_utils.h"
namespace
micro
{
namespace
ops
{
namespace
test
{
class
ConcatOpTest
:
public
::
testing
::
Test
{};
TEST_F
(
ConcatOpTest
,
TestValueTypeDouble
)
{
// clang-format off
double
x0
[
2
*
3
]
=
{
0
,
1
,
2
,
3
,
4
,
5
};
int32_t
x0_dims
[
2
]
=
{
2
,
3
};
int32_t
x0_dim_size
=
2
;
double
x1
[
2
*
2
]
=
{
6
,
7
,
8
,
9
};
int32_t
x1_dims
[
2
]
=
{
2
,
2
};
int32_t
x1_dim_size
=
2
;
double
y
[
2
*
5
]
=
{};
int32_t
y_dims
[
2
]
=
{
2
,
5
};
int32_t
y_dim_size
=
2
;
double
y_g
[
2
*
5
]
=
{
0
,
1
,
2
,
6
,
7
,
3
,
4
,
5
,
8
,
9
};
int32_t
y_g_dims
[
2
]
=
{
2
,
5
};
int32_t
y_g_dim_size
=
2
;
// clang-format on
ConcatOp
<
double
>
Concat_op
;
framework
::
SubstituteOp
substitude_op
;
substitude_op
.
AddInput
(
x0
,
x0_dims
,
x0_dim_size
)
.
AddInput
(
x1
,
x1_dims
,
x1_dim_size
)
.
AddArg
(
"axis"
,
1
)
.
AddOutput
(
y
,
y_dims
,
y_dim_size
);
Concat_op
.
Init
(
NULL
,
reinterpret_cast
<
framework
::
OpContext
*>
(
&
substitude_op
),
NULL
);
Concat_op
.
Run
();
ExpectTensorNear
<
double
>
(
y
,
y_dims
,
y_dim_size
,
y_g
,
y_g_dims
,
y_g_dim_size
);
}
TEST_F
(
ConcatOpTest
,
TestValueTypeFloat
)
{
// clang-format off
float
x0
[
2
*
3
]
=
{
0
,
1
,
2
,
3
,
4
,
5
};
int32_t
x0_dims
[
2
]
=
{
2
,
3
};
int32_t
x0_dim_size
=
2
;
float
x1
[
2
*
2
]
=
{
6
,
7
,
8
,
9
};
int32_t
x1_dims
[
2
]
=
{
2
,
2
};
int32_t
x1_dim_size
=
2
;
float
y
[
2
*
5
]
=
{};
int32_t
y_dims
[
2
]
=
{
2
,
5
};
int32_t
y_dim_size
=
2
;
float
y_g
[
2
*
5
]
=
{
0
,
1
,
2
,
6
,
7
,
3
,
4
,
5
,
8
,
9
};
int32_t
y_g_dims
[
2
]
=
{
2
,
5
};
int32_t
y_g_dim_size
=
2
;
// clang-format on
ConcatOp
<
float
>
Concat_op
;
framework
::
SubstituteOp
substitude_op
;
substitude_op
.
AddInput
(
x0
,
x0_dims
,
x0_dim_size
)
.
AddInput
(
x1
,
x1_dims
,
x1_dim_size
)
.
AddArg
(
"axis"
,
1
)
.
AddOutput
(
y
,
y_dims
,
y_dim_size
);
Concat_op
.
Init
(
NULL
,
reinterpret_cast
<
framework
::
OpContext
*>
(
&
substitude_op
),
NULL
);
Concat_op
.
Run
();
ExpectTensorNear
<
float
>
(
y
,
y_dims
,
y_dim_size
,
y_g
,
y_g_dims
,
y_g_dim_size
);
}
TEST_F
(
ConcatOpTest
,
TestInputOrder
)
{
// clang-format off
int32_t
x0
[
2
*
3
]
=
{
0
,
1
,
2
,
3
,
4
,
5
};
int32_t
x0_dims
[
2
]
=
{
2
,
3
};
int32_t
x0_dim_size
=
2
;
int32_t
x1
[
2
*
2
]
=
{
6
,
7
,
8
,
9
};
int32_t
x1_dims
[
2
]
=
{
2
,
2
};
int32_t
x1_dim_size
=
2
;
int32_t
y
[
2
*
5
]
=
{};
int32_t
y_dims
[
2
]
=
{
2
,
5
};
int32_t
y_dim_size
=
2
;
int32_t
y_g
[
2
*
5
]
=
{
6
,
7
,
0
,
1
,
2
,
8
,
9
,
3
,
4
,
5
};
int32_t
y_g_dims
[
2
]
=
{
2
,
5
};
int32_t
y_g_dim_size
=
2
;
// clang-format on
ConcatOp
<
int32_t
>
Concat_op
;
framework
::
SubstituteOp
substitude_op
;
substitude_op
.
AddInput
(
x1
,
x1_dims
,
x1_dim_size
)
.
AddInput
(
x0
,
x0_dims
,
x0_dim_size
)
.
AddArg
(
"axis"
,
1
)
.
AddOutput
(
y
,
y_dims
,
y_dim_size
);
Concat_op
.
Init
(
NULL
,
reinterpret_cast
<
framework
::
OpContext
*>
(
&
substitude_op
),
NULL
);
Concat_op
.
Run
();
ExpectTensorNear
<
int32_t
>
(
y
,
y_dims
,
y_dim_size
,
y_g
,
y_g_dims
,
y_g_dim_size
);
}
TEST_F
(
ConcatOpTest
,
TestAxis1
)
{
// clang-format off
int32_t
x0
[
2
*
3
]
=
{
0
,
1
,
2
,
3
,
4
,
5
};
int32_t
x0_dims
[
2
]
=
{
2
,
3
};
int32_t
x0_dim_size
=
2
;
int32_t
x1
[
2
*
2
]
=
{
6
,
7
,
8
,
9
};
int32_t
x1_dims
[
2
]
=
{
2
,
2
};
int32_t
x1_dim_size
=
2
;
int32_t
y
[
2
*
5
]
=
{};
int32_t
y_dims
[
2
]
=
{
2
,
5
};
int32_t
y_dim_size
=
2
;
int32_t
y_g
[
2
*
5
]
=
{
0
,
1
,
2
,
6
,
7
,
3
,
4
,
5
,
8
,
9
};
int32_t
y_g_dims
[
2
]
=
{
2
,
5
};
int32_t
y_g_dim_size
=
2
;
// clang-format on
ConcatOp
<
int32_t
>
Concat_op
;
framework
::
SubstituteOp
substitude_op
;
substitude_op
.
AddInput
(
x0
,
x0_dims
,
x0_dim_size
)
.
AddInput
(
x1
,
x1_dims
,
x1_dim_size
)
.
AddArg
(
"axis"
,
1
)
.
AddOutput
(
y
,
y_dims
,
y_dim_size
);
Concat_op
.
Init
(
NULL
,
reinterpret_cast
<
framework
::
OpContext
*>
(
&
substitude_op
),
NULL
);
Concat_op
.
Run
();
ExpectTensorNear
<
int32_t
>
(
y
,
y_dims
,
y_dim_size
,
y_g
,
y_g_dims
,
y_g_dim_size
);
}
TEST_F
(
ConcatOpTest
,
TestAxis0
)
{
// clang-format off
int32_t
x0
[
3
*
2
]
=
{
0
,
1
,
2
,
3
,
4
,
5
};
int32_t
x0_dims
[
2
]
=
{
3
,
2
};
int32_t
x0_dim_size
=
2
;
int32_t
x1
[
2
*
2
]
=
{
6
,
7
,
8
,
9
};
int32_t
x1_dims
[
2
]
=
{
2
,
2
};
int32_t
x1_dim_size
=
2
;
int32_t
y
[
5
*
2
]
=
{};
int32_t
y_dims
[
2
]
=
{
5
,
2
};
int32_t
y_dim_size
=
2
;
int32_t
y_g
[
5
*
2
]
=
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
};
int32_t
y_g_dims
[
2
]
=
{
5
,
2
};
int32_t
y_g_dim_size
=
2
;
// clang-format on
ConcatOp
<
int32_t
>
Concat_op
;
framework
::
SubstituteOp
substitude_op
;
substitude_op
.
AddInput
(
x0
,
x0_dims
,
x0_dim_size
)
.
AddInput
(
x1
,
x1_dims
,
x1_dim_size
)
.
AddArg
(
"axis"
,
0
)
.
AddOutput
(
y
,
y_dims
,
y_dim_size
);
Concat_op
.
Init
(
NULL
,
reinterpret_cast
<
framework
::
OpContext
*>
(
&
substitude_op
),
NULL
);
Concat_op
.
Run
();
ExpectTensorNear
<
int32_t
>
(
y
,
y_dims
,
y_dim_size
,
y_g
,
y_g_dims
,
y_g_dim_size
);
}
TEST_F
(
ConcatOpTest
,
TestInputNumber1
)
{
// clang-format off
int32_t
x0
[
2
*
3
]
=
{
0
,
1
,
2
,
3
,
4
,
5
};
int32_t
x0_dims
[
2
]
=
{
2
,
3
};
int32_t
x0_dim_size
=
2
;
int32_t
y
[
2
*
3
]
=
{};
int32_t
y_dims
[
2
]
=
{
2
,
3
};
int32_t
y_dim_size
=
2
;
int32_t
y_g
[
2
*
3
]
=
{
0
,
1
,
2
,
3
,
4
,
5
};
int32_t
y_g_dims
[
2
]
=
{
2
,
3
};
int32_t
y_g_dim_size
=
2
;
// clang-format on
ConcatOp
<
int32_t
>
Concat_op
;
framework
::
SubstituteOp
substitude_op
;
substitude_op
.
AddInput
(
x0
,
x0_dims
,
x0_dim_size
)
.
AddArg
(
"axis"
,
1
)
.
AddOutput
(
y
,
y_dims
,
y_dim_size
);
Concat_op
.
Init
(
NULL
,
reinterpret_cast
<
framework
::
OpContext
*>
(
&
substitude_op
),
NULL
);
Concat_op
.
Run
();
ExpectTensorNear
<
int32_t
>
(
y
,
y_dims
,
y_dim_size
,
y_g
,
y_g_dims
,
y_g_dim_size
);
}
TEST_F
(
ConcatOpTest
,
TestInputNumber2
)
{
// clang-format off
int32_t
x0
[
2
*
3
]
=
{
0
,
1
,
2
,
3
,
4
,
5
};
int32_t
x0_dims
[
2
]
=
{
2
,
3
};
int32_t
x0_dim_size
=
2
;
int32_t
x1
[
2
*
2
]
=
{
6
,
7
,
8
,
9
};
int32_t
x1_dims
[
2
]
=
{
2
,
2
};
int32_t
x1_dim_size
=
2
;
int32_t
y
[
2
*
5
]
=
{};
int32_t
y_dims
[
2
]
=
{
2
,
5
};
int32_t
y_dim_size
=
2
;
int32_t
y_g
[
2
*
5
]
=
{
0
,
1
,
2
,
6
,
7
,
3
,
4
,
5
,
8
,
9
};
int32_t
y_g_dims
[
2
]
=
{
2
,
5
};
int32_t
y_g_dim_size
=
2
;
// clang-format on
ConcatOp
<
int32_t
>
Concat_op
;
framework
::
SubstituteOp
substitude_op
;
substitude_op
.
AddInput
(
x0
,
x0_dims
,
x0_dim_size
)
.
AddInput
(
x1
,
x1_dims
,
x1_dim_size
)
.
AddArg
(
"axis"
,
1
)
.
AddOutput
(
y
,
y_dims
,
y_dim_size
);
Concat_op
.
Init
(
NULL
,
reinterpret_cast
<
framework
::
OpContext
*>
(
&
substitude_op
),
NULL
);
Concat_op
.
Run
();
ExpectTensorNear
<
int32_t
>
(
y
,
y_dims
,
y_dim_size
,
y_g
,
y_g_dims
,
y_g_dim_size
);
}
TEST_F
(
ConcatOpTest
,
TestInputNumber3
)
{
// clang-format off
int32_t
x0
[
2
*
3
]
=
{
0
,
1
,
2
,
3
,
4
,
5
};
int32_t
x0_dims
[
2
]
=
{
2
,
3
};
int32_t
x0_dim_size
=
2
;
int32_t
x1
[
2
*
2
]
=
{
6
,
7
,
8
,
9
};
int32_t
x1_dims
[
2
]
=
{
2
,
2
};
int32_t
x1_dim_size
=
2
;
int32_t
y
[
2
*
7
]
=
{};
int32_t
y_dims
[
2
]
=
{
2
,
7
};
int32_t
y_dim_size
=
2
;
int32_t
y_g
[
2
*
7
]
=
{
0
,
1
,
2
,
6
,
7
,
6
,
7
,
3
,
4
,
5
,
8
,
9
,
8
,
9
};
int32_t
y_g_dims
[
2
]
=
{
2
,
7
};
int32_t
y_g_dim_size
=
2
;
// clang-format on
ConcatOp
<
int32_t
>
Concat_op
;
framework
::
SubstituteOp
substitude_op
;
substitude_op
.
AddInput
(
x0
,
x0_dims
,
x0_dim_size
)
.
AddInput
(
x1
,
x1_dims
,
x1_dim_size
)
.
AddInput
(
x1
,
x1_dims
,
x1_dim_size
)
.
AddArg
(
"axis"
,
1
)
.
AddOutput
(
y
,
y_dims
,
y_dim_size
);
Concat_op
.
Init
(
NULL
,
reinterpret_cast
<
framework
::
OpContext
*>
(
&
substitude_op
),
NULL
);
Concat_op
.
Run
();
ExpectTensorNear
<
int32_t
>
(
y
,
y_dims
,
y_dim_size
,
y_g
,
y_g_dims
,
y_g_dim_size
);
}
}
// namespace test
}
// namespace ops
}
// namespace micro
tools/python/micro/micro_support_ops.py
浏览文件 @
1bf8032a
...
...
@@ -96,6 +96,8 @@ McSupportedOps = [
mace_pb2
.
DT_FLOAT
,
DataFormat
.
NHWC
),
OpDescriptor
(
'micro/ops/expand_dims.h'
,
'ExpandDimsOp'
,
MaceOp
.
ExpandDims
.
name
,
mace_pb2
.
DT_FLOAT
,
DataFormat
.
NHWC
),
OpDescriptor
(
'micro/ops/concat.h'
,
'ConcatOp<mifloat>'
,
MaceOp
.
Concat
.
name
,
mace_pb2
.
DT_FLOAT
,
DataFormat
.
NHWC
),
OpDescriptor
(
'micro/ops/nhwc/depthwise_conv_2d_ref.h'
,
'DepthwiseConv2dRefOp'
,
MaceOp
.
DepthwiseConv2d
.
name
,
mace_pb2
.
DT_FLOAT
,
...
...
tools/python/micro/scratch_computer.py
浏览文件 @
1bf8032a
...
...
@@ -41,6 +41,7 @@ class ScratchComputer:
MaceOp
.
Shape
:
self
.
scratch_size_no_need
,
MaceOp
.
Reshape
:
self
.
scratch_size_no_need
,
MaceOp
.
ExpandDims
:
self
.
scratch_size_of_expand_dims
,
MaceOp
.
Concat
:
self
.
scratch_size_of_concat
,
MaceOp
.
MatMul
:
self
.
scratch_size_of_matmul
,
MaceOp
.
Pooling
:
self
.
scratch_size_of_pooling
,
MaceOp
.
DepthwiseConv2d
:
self
.
scratch_size_of_depthwise_conv
,
...
...
@@ -131,3 +132,7 @@ class ScratchComputer:
def
scratch_size_eltwise
(
self
,
op_def
):
input0_dims
=
self
.
get_op_input_dims
(
op_def
,
0
)
return
len
(
input0_dims
)
*
self
.
get_data_bytes
(
mace_pb2
.
DT_INT32
)
*
3
def
scratch_size_of_concat
(
self
,
op_def
):
# On a 64bit operating system, one pointer data need 8 bytes
return
len
(
op_def
.
input
)
*
self
.
get_data_bytes
(
mace_pb2
.
DT_INT32
)
*
3
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录