[Pure ACL] Allow model to include MaxPool2D op (#606)
author박종현/동작제어Lab(SR)/Senior Engineer/삼성전자 <jh1302.park@samsung.com>
Thu, 12 Apr 2018 02:03:18 +0000 (11:03 +0900)
committer김정현/동작제어Lab(SR)/Senior Engineer/삼성전자 <jh0822.kim@samsung.com>
Thu, 12 Apr 2018 02:03:18 +0000 (11:03 +0900)
This commit revises Pure ACL NN Runtime to include MaxPool2D operation
while constructing a model.

Note that execution is not supported, yet.

Signed-off-by: Jonghyun Park <jh1302.park@samsung.com>
tools/nnapi_bindings/bindings/pure_arm_compute/src/compilation.cc
tools/nnapi_bindings/bindings/pure_arm_compute/src/internal/Model.cc
tools/nnapi_bindings/bindings/pure_arm_compute/src/internal/Model.h
tools/nnapi_bindings/bindings/pure_arm_compute/src/model.cc

index 3ff2040..0d75cd0 100644 (file)
@@ -72,6 +72,7 @@ public:
 
 public:
   void visit(const ::internal::tflite::op::Conv2D::implicit::Node &node) override;
+  void visit(const ::internal::tflite::op::MaxPool2D::implicit::Node &node) override;
 
 private:
   const ::internal::tflite::operand::Set &_ctx;
@@ -165,6 +166,11 @@ void Planner::visit(const ::internal::tflite::op::Conv2D::implicit::Node &node)
   _builder.addStage(stage);
 }
 
+void Planner::visit(const ::internal::tflite::op::MaxPool2D::implicit::Node &node)
+{
+  throw std::runtime_error{"Not supported, yet"};
+}
+
 class AllocationContext final : public IAllocationContext
 {
 public:
index 78cdf97..381d722 100644 (file)
@@ -126,6 +126,67 @@ namespace internal
 {
 namespace tflite
 {
+namespace op
+{
+namespace MaxPool2D
+{
+namespace implicit
+{
+
+void Node::accept(NodeVisitor &&v) const { v.visit(*this); }
+
+} // namespace implicit
+} // namespace Conv2D
+} // namespace op
+} // namespace tflite
+} // namespace internal
+
+namespace internal
+{
+namespace tflite
+{
+namespace op
+{
+namespace MaxPool2D
+{
+namespace implicit
+{
+
+Param::Param(uint32_t inputCount, const uint32_t* inputs,
+             uint32_t outputCount, const uint32_t* outputs)
+{
+  assert(inputCount == 7 && outputCount == 1);
+
+  ofm_index = outputs[0];
+
+  // Each input should be interpreted as follows:
+  //
+  //  0 -> IFM Tensor Index
+  //  1 -> Padding Code (ANEURALNETWORKS_PADDING_SAME or ANEURALNETWORKS_PADDING_VALID) Index
+  //  2 -> Horizontal (over width) Stride Index
+  //  3 -> Vertial (over height) Stride Index
+  //  4 -> Filter Width Index
+  //  5 -> Filter Height Index
+  //  6 -> FuseCode (activation) Index
+  ifm_index = inputs[0];
+  padding_index = inputs[1];
+  hstride_index = inputs[2];
+  vstride_index = inputs[3];
+  kw_index = inputs[4];
+  kh_index = inputs[5];
+  activation_index = inputs[6];
+}
+
+} // namespace implicit
+} // namespace Conv2D
+} // namespace op
+} // namespace tflite
+} // namespace internal
+
+namespace internal
+{
+namespace tflite
+{
 namespace operand
 {
 
index 04b7cc0..9378f2d 100644 (file)
@@ -274,12 +274,71 @@ namespace tflite
 {
 namespace op
 {
+namespace MaxPool2D
+{
+namespace implicit
+{
+
+struct Param
+{
+  int32_t ofm_index;
+
+  int32_t ifm_index;
+
+  int32_t kw_index;
+  int32_t kh_index;
+
+  int32_t hstride_index;
+  int32_t vstride_index;
+
+  int32_t padding_index;
+  int32_t activation_index;
+
+  Param() = default;
+  Param(uint32_t inputCount, const uint32_t* inputs,
+        uint32_t outputCount, const uint32_t* outputs);
+};
+
+class Node final : public op::Node
+{
+public:
+  Node(const Param &param) : _param(param)
+  {
+    // DO NOTHING
+  }
+
+public:
+  virtual ~Node() = default;
+
+public:
+  const Param &param(void) const { return _param; }
+
+public:
+  void accept(NodeVisitor &&) const override;
+
+private:
+  const Param _param;
+};
+
+} // namespace implicit
+} // namespace MaxPool2D
+} // namespace op
+} // namespace tflite
+} // namespace internal
+
+namespace internal
+{
+namespace tflite
+{
+namespace op
+{
 
 struct NodeVisitor
 {
   virtual ~NodeVisitor() = default;
 
   virtual void visit(const Conv2D::implicit::Node &) = 0;
+  virtual void visit(const MaxPool2D::implicit::Node &) = 0;
 };
 
 } // namespace op
index 63dbe9b..8793e27 100644 (file)
@@ -108,6 +108,29 @@ ANeuralNetworksModel_addOperation(ANeuralNetworksModel* model,
 
       break;
     }
+    case ANEURALNETWORKS_MAX_POOL_2D:
+    {
+      // inputCount is either 7 or 9 acccording to NN API specification.
+      //  - Padding is implicit when inputCount is 7
+      //  - Padding is explicit when inputCount is 9
+      assert(inputCount == 7 || inputCount == 9);
+      assert(outputCount == 1);
+
+      if (inputCount == 7)
+      {
+        using internal::tflite::op::MaxPool2D::implicit::Param;
+        using internal::tflite::op::MaxPool2D::implicit::Node;
+
+        // Add 'operations'
+        auto &operations = model->deref().operations();
+
+        operations.emplace_back<Node>(Param{inputCount, inputs, outputCount, outputs});
+      }
+      else
+      {
+        throw std::runtime_error{"Explicit padding in MaxPool2D is not supported, yet"};
+      }
+    }
     default:
       throw std::runtime_error{"Not supported operation"};
   };