[mir] Add AvgPool2D and MaxPool2D operations (#6996)
authorСергей Баранников/AI Tools Lab /SRR/Engineer/삼성전자 <s.barannikov@samsung.com>
Thu, 29 Aug 2019 05:55:26 +0000 (14:55 +0900)
committer오형석/On-Device Lab(SR)/Staff Engineer/삼성전자 <hseok82.oh@samsung.com>
Thu, 29 Aug 2019 05:55:26 +0000 (14:55 +0900)
These are the future replacement of the `Pool` operation.

Signed-off-by: Sergei Barannikov <s.barannikov@samsung.com>
compiler/mir/CMakeLists.txt
compiler/mir/include/mir/IrDotDumper.h
compiler/mir/include/mir/OpDefs.h
compiler/mir/include/mir/Operations.inc
compiler/mir/include/mir/ops/AvgPool2DOp.h [new file with mode: 0644]
compiler/mir/include/mir/ops/MaxPool2DOp.h [new file with mode: 0644]
compiler/mir/src/IrDotDumper.cpp
compiler/mir/src/ops/AvgPool2DOp.cpp [new file with mode: 0644]
compiler/mir/src/ops/MaxPool2DOp.cpp [new file with mode: 0644]

index bc265e5..7b27ee0 100644 (file)
@@ -1,4 +1,5 @@
 set(MIR_SOURCES
+    src/ops/AvgPool2DOp.cpp
     src/ops/BinaryElementwiseOp.cpp
     src/ops/ConcatOp.cpp
     src/ops/Conv2DOp.cpp
@@ -6,6 +7,7 @@ set(MIR_SOURCES
     src/ops/DepthwiseConv2DOp.cpp
     src/ops/FullyConnectedOp.cpp
     src/ops/GatherOp.cpp
+    src/ops/MaxPool2DOp.cpp
     src/ops/PadOp.cpp
     src/ops/PoolOp.cpp
     src/ops/ReduceMeanOp.cpp
index 653f453..17334c3 100644 (file)
@@ -30,6 +30,7 @@ namespace mir
 class IrDotDumper : public IVisitor
 {
 public:
+  void visit(ops::AvgPool2DOp &op) override;
   void visit(ops::CappedReluOp &op) override;
   void visit(ops::ConcatOp &op) override;
   void visit(ops::ConstantOp &op) override;
@@ -41,6 +42,7 @@ public:
   void visit(ops::GatherOp &op) override;
   void visit(ops::InputOp &op) override;
   void visit(ops::LeakyReluOp &op) override;
+  void visit(ops::MaxPool2DOp &op) override;
   void visit(ops::OutputOp &op) override;
   void visit(ops::PadOp &op) override;
   void visit(ops::PoolOp &op) override;
index 5da3050..e115ee2 100644 (file)
@@ -18,6 +18,7 @@
 #define _MIR_OPDEFS_H_
 
 #include "mir/ops/AddOp.h"
+#include "mir/ops/AvgPool2DOp.h"
 #include "mir/ops/CappedReluOp.h"
 #include "mir/ops/CommonProps.h"
 #include "mir/ops/ConcatOp.h"
@@ -32,6 +33,7 @@
 #include "mir/ops/InputOp.h"
 #include "mir/ops/LeakyReluOp.h"
 #include "mir/ops/MaxOp.h"
+#include "mir/ops/MaxPool2DOp.h"
 #include "mir/ops/MulOp.h"
 #include "mir/ops/OutputOp.h"
 #include "mir/ops/PadOp.h"
index 9867c6b..0967759 100644 (file)
@@ -19,6 +19,7 @@
 #endif // HANDLE_OP
 
 HANDLE_OP(add, AddOp)
+HANDLE_OP(avgPool2D, AvgPool2DOp)
 HANDLE_OP(cappedReLU, CappedReluOp)
 HANDLE_OP(concat, ConcatOp)
 HANDLE_OP(constant, ConstantOp)
@@ -32,6 +33,7 @@ HANDLE_OP(gather, GatherOp)
 HANDLE_OP(input, InputOp)
 HANDLE_OP(leakyReLU, LeakyReluOp)
 HANDLE_OP(max, MaxOp)
+HANDLE_OP(maxPool2D, MaxPool2DOp)
 HANDLE_OP(mul, MulOp)
 HANDLE_OP(output, OutputOp)
 HANDLE_OP(pad, PadOp)
diff --git a/compiler/mir/include/mir/ops/AvgPool2DOp.h b/compiler/mir/include/mir/ops/AvgPool2DOp.h
new file mode 100644 (file)
index 0000000..394e537
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2019 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 _MIR_OPS_AVG_POOL_OP_H_
+#define _MIR_OPS_AVG_POOL_OP_H_
+
+#include "mir/Operation.h"
+#include "mir/DataFormat.h"
+
+#include <cstdint>
+#include <vector>
+
+namespace mir
+{
+namespace ops
+{
+
+class AvgPool2DOp : public Operation
+{
+public:
+  AvgPool2DOp(Output *arg, std::vector<std::int32_t> window_size, std::vector<std::int32_t> strides,
+              std::vector<std::int32_t> padding_before, std::vector<std::int32_t> padding_after,
+              bool include_pad, DataFormat data_format)
+      : Operation(Type::avgPool2D, {arg}), _window_size(std::move(window_size)),
+        _strides(std::move(strides)), _padding_before(std::move(padding_before)),
+        _padding_after(std::move(padding_after)), _include_pad(include_pad),
+        _data_format(data_format)
+  {
+    inferOutputShapes();
+  }
+
+  Operation *copyWithInputs(const std::vector<Output *> &inputs) override
+  {
+    return new AvgPool2DOp(inputs[0], _window_size, _strides, _padding_before, _padding_after,
+                           _include_pad, _data_format);
+  };
+
+  const std::vector<std::int32_t> &getWindowSize() const { return _window_size; }
+
+  const std::vector<std::int32_t> &getStrides() const { return _strides; }
+
+  const std::vector<std::int32_t> &getPaddingBefore() const { return _padding_before; }
+
+  const std::vector<std::int32_t> &getPaddingAfter() const { return _padding_after; }
+
+  bool getIncludePad() const { return _include_pad; }
+
+  DataFormat getDataFormat() const { return _data_format; }
+
+private:
+  void inferOutputShapes();
+
+  std::vector<std::int32_t> _window_size;
+  std::vector<std::int32_t> _strides;
+  std::vector<std::int32_t> _padding_before;
+  std::vector<std::int32_t> _padding_after;
+  bool _include_pad;
+  DataFormat _data_format;
+};
+
+} // namespace ops
+} // namespace mir
+
+#endif //_MIR_OPS_AVG_POOL_OP_H_
diff --git a/compiler/mir/include/mir/ops/MaxPool2DOp.h b/compiler/mir/include/mir/ops/MaxPool2DOp.h
new file mode 100644 (file)
index 0000000..691fad4
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2019 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 _MIR_OPS_MAX_POOL_OP_H_
+#define _MIR_OPS_MAX_POOL_OP_H_
+
+#include "mir/Operation.h"
+#include "mir/DataFormat.h"
+
+#include <cstdint>
+#include <vector>
+
+namespace mir
+{
+namespace ops
+{
+
+class MaxPool2DOp : public Operation
+{
+public:
+  MaxPool2DOp(Output *arg, std::vector<std::int32_t> window_size, std::vector<std::int32_t> strides,
+              std::vector<std::int32_t> padding_before, std::vector<std::int32_t> padding_after,
+              DataFormat data_format)
+      : Operation(Type::maxPool2D, {arg}), _window_size(std::move(window_size)),
+        _strides(std::move(strides)), _padding_before(std::move(padding_before)),
+        _padding_after(std::move(padding_after)), _data_format(data_format)
+  {
+    inferOutputShapes();
+  }
+
+  Operation *copyWithInputs(const std::vector<Output *> &inputs) override
+  {
+    return new MaxPool2DOp(inputs[0], _window_size, _strides, _padding_before, _padding_after,
+                           _data_format);
+  };
+
+  const std::vector<std::int32_t> &getWindowSize() const { return _window_size; }
+
+  const std::vector<std::int32_t> &getStrides() const { return _strides; }
+
+  const std::vector<std::int32_t> &getPaddingBefore() const { return _padding_before; }
+
+  const std::vector<std::int32_t> &getPaddingAfter() const { return _padding_after; }
+
+  DataFormat getDataFormat() const { return _data_format; }
+
+private:
+  void inferOutputShapes();
+
+  std::vector<std::int32_t> _window_size;
+  std::vector<std::int32_t> _strides;
+  std::vector<std::int32_t> _padding_before;
+  std::vector<std::int32_t> _padding_after;
+  DataFormat _data_format;
+};
+
+} // namespace ops
+} // namespace mir
+
+#endif //_MIR_OPS_MAX_POOL_OP_H_
index 7cf234b..4c50a5a 100644 (file)
@@ -42,6 +42,20 @@ static std::vector<Shape> getOutputShapes(const Operation &op)
   return shapes;
 }
 
+void IrDotDumper::visit(ops::AvgPool2DOp &op)
+{
+  auto nodeInfo = DotIrNodeInfo()
+                      .withType("AvgPool2D", op.getName())
+                      .withInShapes(getInputShapes(op))
+                      .withOutShapes(getOutputShapes(op))
+                      .withShape("Window size", Shape(op.getWindowSize()))
+                      .withStride(Shape(op.getStrides()))
+                      .withShape("Padding before", Shape(op.getPaddingBefore()))
+                      .withShape("Padding after", Shape(op.getPaddingAfter()));
+
+  _dot_builder.updateWithOp(&op, nodeInfo);
+}
+
 void IrDotDumper::visit(ops::CappedReluOp &op)
 {
   auto nodeInfo = DotIrNodeInfo()
@@ -100,6 +114,20 @@ void IrDotDumper::visit(ops::FullyConnectedOp &op)
   _dot_builder.updateWithOp(&op, nodeInfo);
 }
 
+void IrDotDumper::visit(ops::MaxPool2DOp &op)
+{
+  auto nodeInfo = DotIrNodeInfo()
+                      .withType("MaxPool2D", op.getName())
+                      .withInShapes(getInputShapes(op))
+                      .withOutShapes(getOutputShapes(op))
+                      .withShape("Window size", Shape(op.getWindowSize()))
+                      .withStride(Shape(op.getStrides()))
+                      .withShape("Padding before", Shape(op.getPaddingBefore()))
+                      .withShape("Padding after", Shape(op.getPaddingAfter()));
+
+  _dot_builder.updateWithOp(&op, nodeInfo);
+}
+
 void IrDotDumper::visit(ops::SoftmaxOp &op)
 {
   auto nodeInfo = DotIrNodeInfo()
diff --git a/compiler/mir/src/ops/AvgPool2DOp.cpp b/compiler/mir/src/ops/AvgPool2DOp.cpp
new file mode 100644 (file)
index 0000000..5a16e3a
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2019 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 "mir/ops/AvgPool2DOp.h"
+
+namespace mir
+{
+namespace ops
+{
+
+void AvgPool2DOp::inferOutputShapes()
+{
+  const auto &input_shape = getInputShape(0);
+  const int batch_dim_index = getDataBatchDimIndex(_data_format);
+  const int channel_dim_index = getDataChannelDimIndex(_data_format);
+
+  constexpr int num_spatial_dims = 2;
+
+  assert(input_shape.rank() == 4);
+  assert(_window_size.size() == num_spatial_dims);
+  assert(_strides.size() == num_spatial_dims);
+  assert(_padding_before.size() == num_spatial_dims);
+  assert(_padding_after.size() == num_spatial_dims);
+
+  Shape output_shape(4);
+
+  output_shape.dim(batch_dim_index) = input_shape.dim(batch_dim_index);
+  output_shape.dim(channel_dim_index) = input_shape.dim(channel_dim_index);
+
+  for (int i = 0; i < num_spatial_dims; i++)
+  {
+    const int spatial_dim_index = getDataSpatialDimIndex(_data_format, i);
+    const std::int32_t padded_input =
+        input_shape.dim(spatial_dim_index) + _padding_before.at(i) + _padding_after.at(i);
+    // out_size = ceil((in_size - window_size + 1) / stride) =
+    //   (in_size - window_size + 1 + stride - 1) / stride =
+    //   (in_size - window_size) / stride + 1
+    output_shape.dim(spatial_dim_index) = (padded_input - _window_size[i]) / _strides[i] + 1;
+  }
+
+  setOutputShape(0, output_shape);
+}
+
+} // namespace ops
+} // namespace mir
diff --git a/compiler/mir/src/ops/MaxPool2DOp.cpp b/compiler/mir/src/ops/MaxPool2DOp.cpp
new file mode 100644 (file)
index 0000000..df7e538
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2019 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 "mir/ops/MaxPool2DOp.h"
+
+namespace mir
+{
+namespace ops
+{
+
+void MaxPool2DOp::inferOutputShapes()
+{
+  const auto &input_shape = getInputShape(0);
+  const int batch_dim_index = getDataBatchDimIndex(_data_format);
+  const int channel_dim_index = getDataChannelDimIndex(_data_format);
+
+  constexpr int num_spatial_dims = 2;
+
+  assert(input_shape.rank() == 4);
+  assert(_window_size.size() == num_spatial_dims);
+  assert(_strides.size() == num_spatial_dims);
+  assert(_padding_before.size() == num_spatial_dims);
+  assert(_padding_after.size() == num_spatial_dims);
+
+  Shape output_shape(4);
+
+  output_shape.dim(batch_dim_index) = input_shape.dim(batch_dim_index);
+  output_shape.dim(channel_dim_index) = input_shape.dim(channel_dim_index);
+
+  for (int i = 0; i < num_spatial_dims; i++)
+  {
+    const int spatial_dim_index = getDataSpatialDimIndex(_data_format, i);
+    const std::int32_t padded_input =
+        input_shape.dim(spatial_dim_index) + _padding_before.at(i) + _padding_after.at(i);
+    // out_size = ceil((in_size - window_size + 1) / stride) =
+    //   (in_size - window_size + 1 + stride - 1) / stride =
+    //   (in_size - window_size) / stride + 1
+    output_shape.dim(spatial_dim_index) = (padded_input - _window_size[i]) / _strides[i] + 1;
+  }
+
+  setOutputShape(0, output_shape);
+}
+
+} // namespace ops
+} // namespace mir