ONE - On-device Neural Engine
Loading...
Searching...
No Matches
Pooling.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "Pooling.h"
18#include "PoolingSpec.h"
19#include "IRBuilder.h"
20
22
23#include <morph/caffe.h>
24
25#include <cassert>
26#include <functional>
27
28using namespace nncc::core::ADT;
29using namespace morph::caffe;
30
31namespace caffeimport
32{
33
34void PoolingBuilder::build(const ::caffe::LayerParameter &layer, GraphBuilderContext *context) const
35{
36 coco::Module *module = context->module();
37 coco::Block *blk = context->block();
38 std::map<std::string, tensor::Shape> &shape_ctx = context->shape_ctx();
39 std::map<std::string, coco::Bag *> &bag_ctx = context->bag_ctx();
40
41 assert(layer.bottom().size() == 1);
42 assert(layer.top().size() == 1);
43
44 assert(layer.has_pooling_param());
45 const auto &param = layer.pooling_param();
46
47 PoolingSpec spec{param};
48 {
49 const auto ifm_name = layer.bottom(0);
50 const auto ifm_shape = shape_ctx.at(ifm_name);
51 spec.ifm_shape(ifm_shape);
52 }
53
54 // Create an object for an input feature map
55 const auto ifm_name = layer.bottom(0);
56 const auto ifm_shape = shape_ctx.at(ifm_name);
57 auto ifm_bag = bag_ctx.at(ifm_name);
58 auto ifm_obj = module->entity()->object()->create<coco::FeatureObject>();
59
60 ifm_obj->bag(ifm_bag);
61 ifm_obj->layout(coco::FeatureLayouts::BCHW::create(as_feature_shape(ifm_shape)));
62
63 // Create an object for an output feature map
64 const auto ofm_name = layer.top(0);
65 const auto ofm_shape = spec.ofm_shape();
66 auto ofm_bag = module->entity()->bag()->create(num_elements(ofm_shape));
67 auto ofm_obj = module->entity()->object()->create<coco::FeatureObject>();
68
69 ofm_obj->bag(ofm_bag);
70 ofm_obj->layout(coco::FeatureLayouts::BCHW::create(as_feature_shape(ofm_shape)));
71
72 using PoolingOpBuilder = std::function<coco::Op *(coco::Module * m, const PoolingSpec &spec)>;
73
74 std::map<PoolingMethod, PoolingOpBuilder> builders;
75
76 // MaxPool2D op builder
77 builders[PoolingMethod::Max] = [ifm_obj](coco::Module *module, const PoolingSpec &spec) {
78 auto load = op_builder(module).load(ifm_obj).pop();
79
80 auto op = module->entity()->op()->create<coco::MaxPool2D>();
81
82 op->arg(load);
83
84 op->window()->height(spec.window_height());
85 op->window()->width(spec.window_width());
86
87 op->stride()->vertical(spec.vertical_stride());
88 op->stride()->horizontal(spec.horizontal_stride());
89
90 op->pad()->top(spec.vertical_pad());
91 op->pad()->bottom(spec.vertical_pad());
92 op->pad()->left(spec.horizontal_pad());
93 op->pad()->right(spec.horizontal_pad());
94
95 return op;
96 };
97
98 // AvgPool2D op builder
99 builders[PoolingMethod::Avg] = [ifm_obj](coco::Module *module, const PoolingSpec &spec) {
100 auto load = op_builder(module).load(ifm_obj).pop();
101
102 auto op = module->entity()->op()->create<coco::AvgPool2D>();
103
104 op->arg(load);
105
106 // NOTE Caffe use static divisor on average pooling
108
109 op->window()->height(spec.window_height());
110 op->window()->width(spec.window_width());
111
112 op->stride()->vertical(spec.vertical_stride());
113 op->stride()->horizontal(spec.horizontal_stride());
114
115 op->pad()->top(spec.vertical_pad());
116 op->pad()->bottom(spec.vertical_pad());
117 op->pad()->left(spec.horizontal_pad());
118 op->pad()->right(spec.horizontal_pad());
119
120 return op;
121 };
122
123 // Create a pooling op
124 auto builder = builders.at(spec.method());
125 auto op = builder(module, spec);
126
127 // Create a UnitF instruction
128 auto ins = instr_builder(module).eval(ofm_obj, op);
129
130 // Append the instruction to the block
131 blk->instr()->append(ins);
132
133 // Update bag and shape context
134 bag_ctx[ofm_name] = ofm_bag;
135 shape_ctx[ofm_name] = ofm_shape;
136}
137
138} // namespace caffeimport
OpBuilder op_builder(coco::Module *m)
Definition IRBuilder.h:144
InstrBuilder instr_builder(coco::Module *m)
Definition IRBuilder.h:174
coco::Eval * eval(coco::Object *out, coco::Op *op) const
Create "Eval" instruction with a given "Object" and "Op".
Definition IRBuilder.h:162
OpBuilder & load(coco::Object *obj)
Create "Load" op and push it onto the internal stack.
Definition IRBuilder.h:70
coco::Op * pop(void)
Pop op from the internal stack.
Definition IRBuilder.h:116
const nncc::core::ADT::tensor::Shape & ifm_shape(void) const
Definition PoolingSpec.h:36
ShapeContext & shape_ctx()
Definition Context.h:97
void build(const ::caffe::LayerParameter &layer, GraphBuilderContext *context) const override
Definition Pooling.cpp:34
A unit of (grouped) instructions.
Definition Block.h:40
static std::unique_ptr< BCHW > create(const nncc::core::ADT::feature::Shape &shape)
Top-level element of coco IR which represents a neural network.
Definition Module.h:34
nncc::core::ADT::feature::Shape as_feature_shape(const nncc::core::ADT::tensor::Shape &)
Definition caffe.cpp:54
Base interface on all supported NN operations.
Definition Op.h:45
virtual Op * arg(uint32_t n) const =0
Return N-th argument.