[Pure ACL NN Runtime] Partailly implement addOperation (#501)
author박종현/동작제어Lab(SR)/Senior Engineer/삼성전자 <jh1302.park@samsung.com>
Mon, 9 Apr 2018 07:19:53 +0000 (16:19 +0900)
committer김정현/동작제어Lab(SR)/Senior Engineer/삼성전자 <jh0822.kim@samsung.com>
Mon, 9 Apr 2018 07:19:53 +0000 (16:19 +0900)
This commit implements ANeuralNetworksModel_addOperation partially for
Conv2D operation with implicit paddings.

Signed-off-by: Jonghyun Park <jh1302.park@samsung.com>
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 580c925..5658f81 100644 (file)
@@ -20,6 +20,25 @@ namespace internal
 {
 namespace tflite
 {
+namespace op
+{
+namespace Conv2D
+{
+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 operand
 {
 
index a593d17..6675d7a 100644 (file)
@@ -187,6 +187,136 @@ namespace internal
 {
 namespace tflite
 {
+namespace op
+{
+
+struct NodeVisitor;
+
+struct Node
+{
+  virtual ~Node() = default;
+
+  virtual void accept(NodeVisitor &&) const = 0;
+};
+
+} // namespace op
+} // namespace tflite
+} // namespace internal
+
+namespace internal
+{
+namespace tflite
+{
+namespace op
+{
+namespace Conv2D
+{
+namespace implicit
+{
+
+struct Param
+{
+  int32_t ofm_index;
+
+  int32_t ifm_index;
+  int32_t ker_index;
+  int32_t bias_index;
+
+  int32_t hstride;
+  int32_t vstride;
+
+  int32_t padding;
+  int32_t activation;
+};
+
+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 Conv2D
+} // 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;
+};
+
+} // namespace op
+} // namespace tflite
+} // namespace internal
+
+namespace internal
+{
+namespace tflite
+{
+namespace op
+{
+
+class Sequence
+{
+public:
+  Sequence() = default;
+
+public:
+  uint32_t size(void) const { return _ops.size(); }
+
+public:
+  op::Node &at(uint32_t nth) { return *(_ops.at(nth)); }
+  const op::Node &at(uint32_t nth) const { return *(_ops.at(nth)); }
+
+private:
+  Sequence &emplace_back(std::unique_ptr<op::Node> &&node)
+  {
+    _ops.emplace_back(std::move(node));
+    return (*this);
+  }
+public:
+  template <typename T, typename... Args> Sequence &emplace_back(Args&&... args)
+  {
+    emplace_back(std::unique_ptr<T>(new T{std::forward<Args>(args)...}));
+  }
+
+private:
+  std::vector<std::unique_ptr<op::Node>> _ops;
+};
+
+} // namespace op
+} // namespace tflite
+} // namespace internal
+
+namespace internal
+{
+namespace tflite
+{
 
 class Model
 {
@@ -194,8 +324,13 @@ public:
   operand::Set &operands(void) { return _operands; }
   const operand::Set &operands(void) const { return _operands; }
 
+public:
+  op::Sequence &operations(void) { return _operations; }
+  const op::Sequence &operations(void) const { return _operations; }
+
 private:
   operand::Set _operands;
+  op::Sequence _operations;
 };
 
 } // namespace tflite
index df587e4..1241d6b 100644 (file)
@@ -1,6 +1,7 @@
 #include <nnapi.h>
 
 #include <cassert>
+#include <stdexcept>
 
 #include "model.h"
 #include "memory.h"
@@ -80,6 +81,52 @@ ANeuralNetworksModel_addOperation(ANeuralNetworksModel* model,
                                   uint32_t inputCount, const uint32_t* inputs,
                                   uint32_t outputCount, const uint32_t* outputs)
 {
+  switch (type)
+  {
+    case ANEURALNETWORKS_CONV_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)
+      {
+        internal::tflite::op::Conv2D::implicit::Param param;
+
+        param.ofm_index = outputs[0];
+
+        // Each input should be interpreted as follows:
+        //
+        //  0 -> IFM Tensor Index
+        //  1 -> Kernel Tensor Index
+        //  2 -> Bias Tensor Index
+        //  3 -> Padding Code (ANEURALNETWORKS_PADDING_SAME or ANEURALNETWORKS_PADDING_VALID)
+        //  4 -> Stride (width)
+        //  5 -> Stride (height)
+        //  6 -> Activation
+        param.ifm_index = inputs[0];
+        param.ker_index = inputs[1];
+        param.bias_index = inputs[2];
+        // TODO Set hstride/vstride/padding/activation
+
+        // Add 'operations'
+        auto &operations = model->deref().operations();
+
+        operations.emplace_back<internal::tflite::op::Conv2D::implicit::Node>(param);
+      }
+      else
+      {
+        throw std::runtime_error{"Explicit padding in Conv2D is not supported, yet"};
+      }
+
+      break;
+    }
+    default:
+      throw std::runtime_error{"Not supported operation"};
+  };
+
   return ANEURALNETWORKS_NO_ERROR;
 }