From dc3d298c4184c304ff3a3ac5e7ae2e7dd87c4dbd Mon Sep 17 00:00:00 2001 From: =?utf8?q?=EB=B0=95=EC=84=B8=ED=9D=AC/=EB=8F=99=EC=9E=91=EC=A0=9C?= =?utf8?q?=EC=96=B4Lab=28SR=29/Principal=20Engineer/=EC=82=BC=EC=84=B1?= =?utf8?q?=EC=A0=84=EC=9E=90?= Date: Fri, 7 Dec 2018 16:37:09 +0900 Subject: [PATCH] [enco] frontend/caffe: separate pooling (#2560) This will move Pooling layer handler to separate file. Signed-off-by: SaeHie Park --- contrib/enco/frontend/caffe/src/Frontend.cpp | 99 --------------- .../frontend/caffe/src/GraphBuilderRegistry.cpp | 2 + contrib/enco/frontend/caffe/src/Op/Pooling.cpp | 138 +++++++++++++++++++++ contrib/enco/frontend/caffe/src/Op/Pooling.h | 35 ++++++ 4 files changed, 175 insertions(+), 99 deletions(-) create mode 100644 contrib/enco/frontend/caffe/src/Op/Pooling.cpp create mode 100644 contrib/enco/frontend/caffe/src/Op/Pooling.h diff --git a/contrib/enco/frontend/caffe/src/Frontend.cpp b/contrib/enco/frontend/caffe/src/Frontend.cpp index 4d24b97..6a34dd0 100644 --- a/contrib/enco/frontend/caffe/src/Frontend.cpp +++ b/contrib/enco/frontend/caffe/src/Frontend.cpp @@ -130,105 +130,6 @@ enco::Bundle Frontend::load(void) const graph_builder->build(layer, &opbuilder_context); } // TODO move type handlers to separate builder - else if (layer.type() == "Pooling") - { - assert(layer.bottom().size() == 1); - assert(layer.top().size() == 1); - - assert(layer.has_pooling_param()); - const auto ¶m = layer.pooling_param(); - - PoolingSpec spec{param}; - { - const auto ifm_name = layer.bottom(0); - const auto ifm_shape = shape_ctx.at(ifm_name); - spec.ifm_shape(ifm_shape); - } - - // Create an object for an input feature map - const auto ifm_name = layer.bottom(0); - const auto ifm_shape = shape_ctx.at(ifm_name); - auto ifm_bag = bag_ctx.at(ifm_name); - auto ifm_obj = module->entity()->object()->create(); - - ifm_obj->bag(ifm_bag); - ifm_obj->layout(coco::FeatureLayouts::BCHW::create(as_feature_shape(ifm_shape))); - - // Create an object for an output feature map - const auto ofm_name = layer.top(0); - const auto ofm_shape = spec.ofm_shape(); - auto ofm_bag = module->entity()->bag()->create(num_elements(ofm_shape)); - auto ofm_obj = module->entity()->object()->create(); - - ofm_obj->bag(ofm_bag); - ofm_obj->layout(coco::FeatureLayouts::BCHW::create(as_feature_shape(ofm_shape))); - - using PoolingOpBuilder = std::function; - - std::map builders; - - // MaxPool2D op builder - builders[PoolingMethod::Max] = [ifm_obj](coco::Module *module, const PoolingSpec &spec) { - auto load = op_builder(module).load(ifm_obj).pop(); - - auto op = module->entity()->op()->create(); - - op->arg(load); - - op->window()->height(spec.window_height()); - op->window()->width(spec.window_width()); - - op->stride()->vertical(spec.vertical_stride()); - op->stride()->horizontal(spec.horizontal_stride()); - - op->pad()->top(spec.vertical_pad()); - op->pad()->bottom(spec.vertical_pad()); - op->pad()->left(spec.horizontal_pad()); - op->pad()->right(spec.horizontal_pad()); - - return op; - }; - - // AvgPool2D op builder - builders[PoolingMethod::Avg] = [ifm_obj](coco::Module *module, const PoolingSpec &spec) { - auto load = op_builder(module).load(ifm_obj).pop(); - - auto op = module->entity()->op()->create(); - - op->arg(load); - - // NOTE Caffe use static divisor on average pooling - op->divisor(coco::AvgPool2D::Divisor::Static); - - op->window()->height(spec.window_height()); - // TODO FIX THIS BUG AND ADD TEST - op->window()->width(spec.window_height()); - - op->stride()->vertical(spec.vertical_stride()); - op->stride()->horizontal(spec.horizontal_stride()); - - op->pad()->top(spec.vertical_pad()); - op->pad()->bottom(spec.vertical_pad()); - op->pad()->left(spec.horizontal_pad()); - op->pad()->right(spec.horizontal_pad()); - - return op; - }; - - // Create a pooling op - auto builder = builders.at(spec.method()); - auto op = builder(module.get(), spec); - - // Create a UnitF instruction - auto ins = instr_builder(module).eval(ofm_obj, op); - - // Append the instruction to the block - blk->instr()->append(ins); - - // Update bag and shape context - bag_ctx[ofm_name] = ofm_bag; - shape_ctx[ofm_name] = ofm_shape; - } else if (layer.type() == "ReLU") { assert(layer.bottom().size() == 1); diff --git a/contrib/enco/frontend/caffe/src/GraphBuilderRegistry.cpp b/contrib/enco/frontend/caffe/src/GraphBuilderRegistry.cpp index 6934e84..c2fee6b 100644 --- a/contrib/enco/frontend/caffe/src/GraphBuilderRegistry.cpp +++ b/contrib/enco/frontend/caffe/src/GraphBuilderRegistry.cpp @@ -18,6 +18,7 @@ #include "Op/Convolution.h" #include "Op/Input.h" +#include "Op/Pooling.h" #include @@ -31,6 +32,7 @@ GraphBuilderRegistry::GraphBuilderRegistry() // TODO add GraphBuilder for each caffe layer. _builder_map["Convolution"] = make_unique(); _builder_map["Input"] = make_unique(); + _builder_map["Pooling"] = make_unique(); } } // namespace caffeimport diff --git a/contrib/enco/frontend/caffe/src/Op/Pooling.cpp b/contrib/enco/frontend/caffe/src/Op/Pooling.cpp new file mode 100644 index 0000000..5b4e3cf --- /dev/null +++ b/contrib/enco/frontend/caffe/src/Op/Pooling.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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 "Pooling.h" +#include "PoolingSpec.h" +#include "IRBuilder.h" + +#include + +#include + +#include + +using namespace nncc::core::ADT; +using namespace morph::caffe; + +namespace caffeimport +{ + +void PoolingBuilder::build(const ::caffe::LayerParameter &layer, GraphBuilderContext *context) const +{ + coco::Module *module = context->module(); + coco::Block *blk = context->block(); + std::map &shape_ctx = context->shape_ctx(); + std::map &bag_ctx = context->bag_ctx(); + + assert(layer.bottom().size() == 1); + assert(layer.top().size() == 1); + + assert(layer.has_pooling_param()); + const auto ¶m = layer.pooling_param(); + + PoolingSpec spec{param}; + { + const auto ifm_name = layer.bottom(0); + const auto ifm_shape = shape_ctx.at(ifm_name); + spec.ifm_shape(ifm_shape); + } + + // Create an object for an input feature map + const auto ifm_name = layer.bottom(0); + const auto ifm_shape = shape_ctx.at(ifm_name); + auto ifm_bag = bag_ctx.at(ifm_name); + auto ifm_obj = module->entity()->object()->create(); + + ifm_obj->bag(ifm_bag); + ifm_obj->layout(coco::FeatureLayouts::BCHW::create(as_feature_shape(ifm_shape))); + + // Create an object for an output feature map + const auto ofm_name = layer.top(0); + const auto ofm_shape = spec.ofm_shape(); + auto ofm_bag = module->entity()->bag()->create(num_elements(ofm_shape)); + auto ofm_obj = module->entity()->object()->create(); + + ofm_obj->bag(ofm_bag); + ofm_obj->layout(coco::FeatureLayouts::BCHW::create(as_feature_shape(ofm_shape))); + + using PoolingOpBuilder = std::function; + + std::map builders; + + // MaxPool2D op builder + builders[PoolingMethod::Max] = [ifm_obj](coco::Module *module, const PoolingSpec &spec) { + auto load = op_builder(module).load(ifm_obj).pop(); + + auto op = module->entity()->op()->create(); + + op->arg(load); + + op->window()->height(spec.window_height()); + op->window()->width(spec.window_width()); + + op->stride()->vertical(spec.vertical_stride()); + op->stride()->horizontal(spec.horizontal_stride()); + + op->pad()->top(spec.vertical_pad()); + op->pad()->bottom(spec.vertical_pad()); + op->pad()->left(spec.horizontal_pad()); + op->pad()->right(spec.horizontal_pad()); + + return op; + }; + + // AvgPool2D op builder + builders[PoolingMethod::Avg] = [ifm_obj](coco::Module *module, const PoolingSpec &spec) { + auto load = op_builder(module).load(ifm_obj).pop(); + + auto op = module->entity()->op()->create(); + + op->arg(load); + + // NOTE Caffe use static divisor on average pooling + op->divisor(coco::AvgPool2D::Divisor::Static); + + op->window()->height(spec.window_height()); + // TODO FIX THIS BUG AND ADD TEST + op->window()->width(spec.window_height()); + + op->stride()->vertical(spec.vertical_stride()); + op->stride()->horizontal(spec.horizontal_stride()); + + op->pad()->top(spec.vertical_pad()); + op->pad()->bottom(spec.vertical_pad()); + op->pad()->left(spec.horizontal_pad()); + op->pad()->right(spec.horizontal_pad()); + + return op; + }; + + // Create a pooling op + auto builder = builders.at(spec.method()); + auto op = builder(module, spec); + + // Create a UnitF instruction + auto ins = instr_builder(module).eval(ofm_obj, op); + + // Append the instruction to the block + blk->instr()->append(ins); + + // Update bag and shape context + bag_ctx[ofm_name] = ofm_bag; + shape_ctx[ofm_name] = ofm_shape; +} + +} // namespace caffeimport diff --git a/contrib/enco/frontend/caffe/src/Op/Pooling.h b/contrib/enco/frontend/caffe/src/Op/Pooling.h new file mode 100644 index 0000000..e72fd7a --- /dev/null +++ b/contrib/enco/frontend/caffe/src/Op/Pooling.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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 __POOLING_BUILDER_H__ +#define __POOLING_BUILDER_H__ + +#include "GraphBuilder.h" + +#include "Context.h" + +namespace caffeimport +{ + +class PoolingBuilder final : public GraphBuilder +{ +public: + void build(const ::caffe::LayerParameter &layer, GraphBuilderContext *context) const override; +}; + +} // namespace caffeimport + +#endif // __POOLING_BUILDER_H__ -- 2.7.4