From 68b4e6dd18e368e1f78c6a5bea76417c35f72196 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=EB=B0=95=EC=A2=85=ED=98=84/=EB=8F=99=EC=9E=91=EC=A0=9C?= =?utf8?q?=EC=96=B4Lab=28SR=29/Staff=20Engineer/=EC=82=BC=EC=84=B1?= =?utf8?q?=EC=A0=84=EC=9E=90?= Date: Thu, 6 Sep 2018 19:40:56 +0900 Subject: [PATCH] [enco] Implement AvgPool2D decomposition (#1388) With this commit, enco backend now decomposes Static AvgPool2D with padding into PadF and PaddingExcluded AvgPool2D without padding. Signed-off-by: Jonghyun Park --- contrib/enco/core/src/Transforms/Rewrite.cpp | 81 ++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/contrib/enco/core/src/Transforms/Rewrite.cpp b/contrib/enco/core/src/Transforms/Rewrite.cpp index ec01ad1..69383d2 100644 --- a/contrib/enco/core/src/Transforms/Rewrite.cpp +++ b/contrib/enco/core/src/Transforms/Rewrite.cpp @@ -1,7 +1,13 @@ #include "Rewrite.h" +#include +#include + #include +using namespace nncc::core::ADT; +using nncc::core::ADT::feature::num_elements; + namespace { @@ -12,6 +18,40 @@ bool empty(coco::Padding2D *pad) } // namespace +namespace +{ +namespace ShapeTransform +{ + +class Pad +{ +public: + Pad(const coco::Padding2D *pad) : _pad{pad} + { + // DO NOTHING + } + +public: + // @brief Return the expected OFM shape for a given IFM shape + feature::Shape forward(const feature::Shape &ifm_shape) const + { + const uint32_t OFM_C = ifm_shape.depth(); + const uint32_t OFM_H = ifm_shape.height() + _pad->top() + _pad->bottom(); + const uint32_t OFM_W = ifm_shape.width() + _pad->left() + _pad->right(); + + return feature::Shape{OFM_C, OFM_H, OFM_W}; + } + +private: + const coco::Padding2D *_pad; +}; + +} // namespace ShapeTransform + +ShapeTransform::Pad shape_xform(const coco::Padding2D *pad) { return ShapeTransform::Pad{pad}; } + +} // namespace + namespace enco { @@ -33,6 +73,47 @@ void AvgPoolRewritePass::runOnModule(coco::Module *m) const // NOTE If there is no padding, Static and PaddingExcluded schemes are equivalent avgpool->divisor(coco::AvgPool2D::Divisor::PaddingExcluded); } + else + { + // Before: Static AvgPool2D with Padding + // After: PadF; PaddingExcluded AvgPool2D without Padding + + // Create PadF + auto ifm_obj = unit->ifm(); + assert(ifm_obj != nullptr); + + auto pad_shape = shape_xform(avgpool->pad()).forward(ifm_obj->shape()); + auto pad_bag = m->entity()->bag()->create(num_elements(pad_shape)); + auto pad_obj = m->entity()->object()->create(pad_shape); + + pad_obj->bag(pad_bag); + pad_obj->reorder(); + + auto pad_op = m->entity()->op()->create(); + + pad_op->pad()->top(avgpool->pad()->top()); + pad_op->pad()->bottom(avgpool->pad()->bottom()); + pad_op->pad()->left(avgpool->pad()->left()); + pad_op->pad()->right(avgpool->pad()->right()); + + auto pad_instr = m->entity()->instr()->create(); + + pad_instr->ifm(ifm_obj); + pad_instr->ofm(pad_obj); + pad_instr->op(pad_op); + + // Insert PadF before AvgPool2D + pad_instr->insertBefore(unit); + + // Rewrite AvgPool2D as PaddingExcluded AvgPool2D without Padding + unit->ifm(pad_obj); + + avgpool->divisor(coco::AvgPool2D::Divisor::PaddingExcluded); + avgpool->pad()->top(0); + avgpool->pad()->bottom(0); + avgpool->pad()->left(0); + avgpool->pad()->right(0); + } } } } -- 2.7.4