support rank 4 feature in pacl runtime (#2183)
author이춘석/동작제어Lab(SR)/Staff Engineer/삼성전자 <chunseok.lee@samsung.com>
Wed, 8 Aug 2018 09:37:03 +0000 (18:37 +0900)
committer오형석/동작제어Lab(SR)/Staff Engineer/삼성전자 <hseok82.oh@samsung.com>
Wed, 8 Aug 2018 09:37:03 +0000 (18:37 +0900)
* support rank 4 feature in pacl runtime

This commit enables rank 4 feature

Signed-off-by: Chunseok Lee <chunseok.lee@samsung.com>
* rank4 feature for neurun

Signed-off-by: Chunseok Lee <chunseok.lee@samsung.com>
22 files changed:
include/util/feature/Index.h
include/util/feature/IndexIterator.h
include/util/feature/Reader.h
include/util/feature/Shape.h
runtimes/neurun/src/backend/acl_cl/feature/View.h
runtimes/neurun/src/internal/Sink.h
runtimes/neurun/src/internal/Source.h
runtimes/neurun/src/internal/nnapi/feature/Reader.h
runtimes/neurun/src/internal/nnapi/feature/Utils.h
runtimes/neurun/src/internal/nnapi/feature/View.h
runtimes/neurun/src/kernel/acl_cl/TensorConvertFromCommonLayer.cc
runtimes/neurun/src/kernel/acl_cl/TensorConvertToCommonLayer.cc
runtimes/neurun/src/kernel/cpufallback/TensorConvertFromCommonLayer.cc
runtimes/neurun/src/kernel/cpufallback/TensorConvertToCommonLayer.cc
runtimes/pure_arm_compute/src/compilation.cc
runtimes/pure_arm_compute/src/internal/FeatureSink.h
runtimes/pure_arm_compute/src/internal/FeatureSource.h
runtimes/pure_arm_compute/src/internal/Model.cc
runtimes/pure_arm_compute/src/internal/arm_compute/feature/View.h
runtimes/pure_arm_compute/src/internal/nnapi/feature/Reader.h
runtimes/pure_arm_compute/src/internal/nnapi/feature/Utils.h
runtimes/pure_arm_compute/src/internal/nnapi/feature/View.h

index d8ac32a..83b51f8 100644 (file)
@@ -32,22 +32,29 @@ public:
   Index() = default;
 
 public:
-  Index(int32_t ch, int32_t row, int32_t col) : _ch{ch}, _row{row}, _col{col}
+  Index(int32_t ch, int32_t row, int32_t col) : _batch{1}, _ch{ch}, _row{row}, _col{col}
+  {
+    // DO NOTHING
+  }
+  Index(int32_t batch, int32_t ch, int32_t row, int32_t col) : _batch{batch}, _ch{ch}, _row{row}, _col{col}
   {
     // DO NOTHING
   }
 
 public:
+  int32_t batch(void) const { return _batch; }
   int32_t ch(void) const { return _ch; }
   int32_t row(void) const { return _row; }
   int32_t col(void) const { return _col; }
 
 public:
+  int32_t &batch(void) { return _batch; }
   int32_t &ch(void) { return _ch; }
   int32_t &row(void) { return _row; }
   int32_t &col(void) { return _col; }
 
 private:
+  int32_t _batch;
   int32_t _ch;
   int32_t _row;
   int32_t _col;
index 084d29f..f076b38 100644 (file)
@@ -37,13 +37,16 @@ public:
 public:
   template <typename Callable> IndexIterator &iter(Callable cb)
   {
-    for (uint32_t ch = 0; ch < _shape.C; ++ch)
+    for (uint32_t batch = 0; batch < _shape.N; ++batch)
     {
-      for (uint32_t row = 0; row < _shape.H; ++row)
+      for (uint32_t ch = 0; ch < _shape.C; ++ch)
       {
-        for (uint32_t col = 0; col < _shape.W; ++col)
+        for (uint32_t row = 0; row < _shape.H; ++row)
         {
-          cb(ch, row, col);
+          for (uint32_t col = 0; col < _shape.W; ++col)
+          {
+            cb(batch, ch, row, col);
+          }
         }
       }
     }
index 112503d..f870f7d 100644 (file)
@@ -31,6 +31,7 @@ template <typename T> struct Reader
   virtual ~Reader() = default;
 
   virtual T at(uint32_t ch, uint32_t row, uint32_t col) const = 0;
+  virtual T at(uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) const = 0;
 };
 
 } // namespace feature
index 64c926e..2a2c59e 100644 (file)
@@ -28,12 +28,17 @@ namespace feature
 
 struct Shape
 {
+  int32_t N; // Batch
   int32_t C; // Depth
   int32_t H; // Height
   int32_t W; // Width
 
   Shape() = default;
-  Shape(int32_t depth, int32_t height, int32_t width) : C{depth}, H{height}, W{width}
+  Shape(int32_t depth, int32_t height, int32_t width) : N{1}, C{depth}, H{height}, W{width}
+  {
+    // DO NOTHING
+  }
+  Shape(int32_t batch, int32_t depth, int32_t height, int32_t width) : N{batch}, C{depth}, H{height}, W{width}
   {
     // DO NOTHING
   }
index a3857da..8c59ce8 100644 (file)
@@ -42,6 +42,14 @@ public:
 
     return *ptr;
   }
+  float at(uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) const override
+  {
+    const auto offset = feature_index_to_byte_offset(batch, ch, row, col);
+
+    float *ptr = reinterpret_cast<float *>(_tensor->buffer() + offset);
+
+    return *ptr;
+  }
 
 public:
   float &at(uint32_t ch, uint32_t row, uint32_t col)
@@ -52,6 +60,14 @@ public:
 
     return *ptr;
   }
+  float &at(uint32_t batch, uint32_t ch, uint32_t row, uint32_t col)
+  {
+    const auto offset = feature_index_to_byte_offset(batch, ch, row, col);
+
+    float *ptr = reinterpret_cast<float *>(_tensor->buffer() + offset);
+
+    return *ptr;
+  }
 
 private:
   size_t feature_index_to_byte_offset(uint32_t ch, uint32_t row, uint32_t col) const
@@ -59,6 +75,12 @@ private:
     // ARM Compute uses CHW ordering
     return _tensor->info()->offset_element_in_bytes(::arm_compute::Coordinates{col, row, ch});
   }
+  size_t feature_index_to_byte_offset(uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) const
+  {
+    // ARM Compute uses CHW ordering
+    return _tensor->info()->offset_element_in_bytes(
+        ::arm_compute::Coordinates{col, row, ch, batch});
+  }
 
 private:
   ::nnfw::util::feature::Shape _shape;
index 0d5cd5e..cecf1e6 100644 (file)
@@ -76,10 +76,11 @@ public:
     const ::internal::nnapi::feature::Reader<float> from{_shape, tensor.buffer(), _size};
     ::internal::nnapi::feature::View<float> into{_shape, _base, _size};
 
-    ::nnfw::util::feature::iterate(_shape) << [&](uint32_t ch, uint32_t row, uint32_t col) {
-      const auto value = from.at(ch, row, col);
-      into.at(ch, row, col) = value;
-    };
+    ::nnfw::util::feature::iterate(_shape)
+        << [&](uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) {
+             const auto value = from.at(batch, ch, row, col);
+             into.at(batch, ch, row, col) = value;
+           };
   }
 
 private:
index 4b00285..8ca0203 100644 (file)
@@ -79,10 +79,11 @@ public:
     const ::internal::nnapi::feature::Reader<float> from{_shape, _base, _size};
     ::internal::nnapi::feature::View<float> into{_shape, tensor.buffer(), _size};
 
-    ::nnfw::util::feature::iterate(_shape) << [&](uint32_t ch, uint32_t row, uint32_t col) {
-      const auto value = from.at(ch, row, col);
-      into.at(ch, row, col) = value;
-    };
+    ::nnfw::util::feature::iterate(_shape)
+        << [&](uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) {
+             const auto value = from.at(batch, ch, row, col);
+             into.at(batch, ch, row, col) = value;
+           };
   }
 
 private:
index 46b3bcd..2e758ac 100644 (file)
@@ -35,6 +35,14 @@ public:
 
     return arr[index];
   }
+  float at(uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) const override
+  {
+    uint32_t index = index_of(_shape, batch, ch, row, col);
+
+    const auto arr = reinterpret_cast<const float *>(_ptr);
+
+    return arr[index];
+  }
 
 private:
   nnfw::util::feature::Shape _shape;
index b87c576..61a09bc 100644 (file)
@@ -23,6 +23,20 @@ inline uint32_t index_of(const ::nnfw::util::feature::Shape &shape, uint32_t ch,
   return res;
 }
 
+inline uint32_t index_of(const ::nnfw::util::feature::Shape &shape, uint32_t batch, uint32_t ch,
+                         uint32_t row, uint32_t col)
+{
+  uint32_t res = 0;
+
+  // NNAPI uses NHWC ordering
+  res += batch * shape.H * shape.W * shape.C;
+  res += row * shape.W * shape.C;
+  res += col * shape.C;
+  res += ch;
+
+  return res;
+}
+
 } // namespace feature
 } // namespace nnapi
 } // namespace internal
index b4cdb95..96a6c55 100644 (file)
@@ -34,6 +34,15 @@ public:
     return arr[index];
   }
 
+  T at(uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) const override
+  {
+    uint32_t index = index_of(_shape, batch, ch, row, col);
+
+    T *arr = reinterpret_cast<T *>(_ptr);
+
+    return arr[index];
+  }
+
   T &at(uint32_t ch, uint32_t row, uint32_t col)
   {
     uint32_t index = index_of(_shape, ch, row, col);
@@ -43,6 +52,15 @@ public:
     return arr[index];
   }
 
+  T &at(uint32_t batch, uint32_t ch, uint32_t row, uint32_t col)
+  {
+    uint32_t index = index_of(_shape, batch, ch, row, col);
+
+    T *arr = reinterpret_cast<T *>(_ptr);
+
+    return arr[index];
+  }
+
 private:
   nnfw::util::feature::Shape _shape;
 
index 27a0e86..0615526 100644 (file)
@@ -60,10 +60,11 @@ bool TensorConvertFromCommonLayer::convert()
     const ::internal::nnapi::feature::Reader<float> from{featureShape, inputBuffer, inputSize};
     ::internal::arm_compute::feature::View<float> into{_outputTensor};
 
-    ::nnfw::util::feature::iterate(featureShape) << [&](uint32_t ch, uint32_t row, uint32_t col) {
-      const auto value = from.at(ch, row, col);
-      into.at(ch, row, col) = value;
-    };
+    ::nnfw::util::feature::iterate(featureShape)
+        << [&](uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) {
+             const auto value = from.at(batch, ch, row, col);
+             into.at(batch, ch, row, col) = value;
+           };
   }
 
   _outputTensor->unmap(queue);
index aebab30..9f7ae08 100644 (file)
@@ -60,10 +60,11 @@ bool TensorConvertToCommonLayer::convert()
     const ::internal::arm_compute::feature::View<float> from{_inputTensor};
     ::internal::nnapi::feature::View<float> into{featureShape, outputBuffer, outputSize};
 
-    ::nnfw::util::feature::iterate(featureShape) << [&](uint32_t ch, uint32_t row, uint32_t col) {
-      const auto value = from.at(ch, row, col);
-      into.at(ch, row, col) = value;
-    };
+    ::nnfw::util::feature::iterate(featureShape)
+        << [&](uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) {
+             const auto value = from.at(batch, ch, row, col);
+             into.at(batch, ch, row, col) = value;
+           };
   }
 
   _inputTensor->unmap(queue);
index 20d620d..69978e7 100644 (file)
@@ -58,10 +58,11 @@ bool TensorConvertFromCommonLayer::convert()
     const ::internal::nnapi::feature::Reader<float> from{featureShape, inputBuffer, inputSize};
     ::internal::nnapi::feature::View<float> into{featureShape, outputBuffer, outputSize};
 
-    ::nnfw::util::feature::iterate(featureShape) << [&](uint32_t ch, uint32_t row, uint32_t col) {
-      const auto value = from.at(ch, row, col);
-      into.at(ch, row, col) = value;
-    };
+    ::nnfw::util::feature::iterate(featureShape)
+        << [&](uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) {
+             const auto value = from.at(batch, ch, row, col);
+             into.at(batch, ch, row, col) = value;
+           };
   }
 }
 
index cebb91a..7d0161d 100644 (file)
@@ -58,10 +58,11 @@ bool TensorConvertToCommonLayer::convert()
     const ::internal::nnapi::feature::Reader<float> from{featureShape, inputBuffer, inputSize};
     ::internal::nnapi::feature::View<float> into{featureShape, outputBuffer, outputSize};
 
-    ::nnfw::util::feature::iterate(featureShape) << [&](uint32_t ch, uint32_t row, uint32_t col) {
-      const auto value = from.at(ch, row, col);
-      into.at(ch, row, col) = value;
-    };
+    ::nnfw::util::feature::iterate(featureShape)
+        << [&](uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) {
+             const auto value = from.at(batch, ch, row, col);
+             into.at(batch, ch, row, col) = value;
+           };
   }
 }
 
index 72ec76c..1481096 100644 (file)
@@ -164,10 +164,11 @@ static void initFeatureTensor(::arm_compute::ITensor &tensor,
   const ::internal::nnapi::feature::Reader<T> from{feature_shape, feature_base, feature_size};
   ::internal::arm_compute::feature::View<T> into{&tensor};
 
-  ::nnfw::util::feature::iterate(feature_shape) << [&](uint32_t ch, uint32_t row, uint32_t col) {
-    const auto value = from.at(ch, row, col);
-    into.at(ch, row, col) = value;
-  };
+  ::nnfw::util::feature::iterate(feature_shape)
+      << [&](uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) {
+           const auto value = from.at(batch, ch, row, col);
+           into.at(batch, ch, row, col) = value;
+         };
 }
 
 template <typename T>
index 98bdadb..5586f1a 100644 (file)
@@ -28,10 +28,11 @@ public:
     // Inevitably casting must be done.
     ::internal::nnapi::feature::View<T> into{_shape, reinterpret_cast<uint8_t *>(_base), _size};
 
-    ::nnfw::util::feature::iterate(_shape) << [&](uint32_t ch, uint32_t row, uint32_t col) {
-      const auto value = from.at(ch, row, col);
-      into.at(ch, row, col) = value;
-    };
+    ::nnfw::util::feature::iterate(_shape)
+        << [&](uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) {
+             const auto value = from.at(batch, ch, row, col);
+             into.at(batch, ch, row, col) = value;
+           };
   }
 
 private:
index f2479be..50c0b19 100644 (file)
@@ -26,10 +26,11 @@ public:
         _shape, reinterpret_cast<const uint8_t *>(_base), _size};
     ::internal::arm_compute::feature::View<T> into{&tensor};
 
-    ::nnfw::util::feature::iterate(_shape) << [&](uint32_t ch, uint32_t row, uint32_t col) {
-      const auto value = from.at(ch, row, col);
-      into.at(ch, row, col) = value;
-    };
+    ::nnfw::util::feature::iterate(_shape)
+        << [&](uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) {
+             const auto value = from.at(batch, ch, row, col);
+             into.at(batch, ch, row, col) = value;
+           };
   }
 
 private:
index a063b27..d892eaf 100644 (file)
@@ -40,13 +40,13 @@ nnfw::util::feature::Shape Shape::asFeature(void) const
   //  - Dimension(1) -> Height
   //  - Dimension(2) -> Width
   //  - Dimension(3) -> Depth
-  assert(dim(0) == 1);
 
+  const auto batch = dim(0);
   const auto depth = dim(3);
   const auto height = dim(1);
   const auto width = dim(2);
 
-  return nnfw::util::feature::Shape(depth, height, width);
+  return nnfw::util::feature::Shape(batch, depth, height, width);
 }
 
 nnfw::util::tensor::Shape Shape::asTensor(void) const
index 59f4139..7ecea1d 100644 (file)
@@ -30,6 +30,15 @@ public:
     return *ptr;
   }
 
+  T at(uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) const override
+  {
+    const auto offset = feature_index_to_byte_offset(batch, ch, row, col);
+
+    T *ptr = reinterpret_cast<T *>(_tensor->buffer() + offset);
+
+    return *ptr;
+  }
+
 public:
   T &at(uint32_t ch, uint32_t row, uint32_t col)
   {
@@ -40,6 +49,15 @@ public:
     return *ptr;
   }
 
+  T &at(uint32_t batch, uint32_t ch, uint32_t row, uint32_t col)
+  {
+    const auto offset = feature_index_to_byte_offset(batch, ch, row, col);
+
+    T *ptr = reinterpret_cast<T *>(_tensor->buffer() + offset);
+
+    return *ptr;
+  }
+
 private:
   size_t feature_index_to_byte_offset(uint32_t ch, uint32_t row, uint32_t col) const
   {
@@ -47,6 +65,13 @@ private:
     return _tensor->info()->offset_element_in_bytes(::arm_compute::Coordinates{col, row, ch});
   }
 
+  size_t feature_index_to_byte_offset(uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) const
+  {
+    // ARM Compute uses CHW ordering
+    return _tensor->info()->offset_element_in_bytes(
+        ::arm_compute::Coordinates{col, row, ch, batch});
+  }
+
 private:
   ::arm_compute::ITensor *_tensor;
 };
index d617d3c..c026271 100644 (file)
@@ -34,6 +34,15 @@ public:
     return arr[index];
   }
 
+  T at(uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) const override
+  {
+    uint32_t index = index_of(_shape, batch, ch, row, col);
+
+    const auto arr = reinterpret_cast<const T *>(_ptr);
+
+    return arr[index];
+  }
+
 private:
   nnfw::util::feature::Shape _shape;
 
index b87c576..61a09bc 100644 (file)
@@ -23,6 +23,20 @@ inline uint32_t index_of(const ::nnfw::util::feature::Shape &shape, uint32_t ch,
   return res;
 }
 
+inline uint32_t index_of(const ::nnfw::util::feature::Shape &shape, uint32_t batch, uint32_t ch,
+                         uint32_t row, uint32_t col)
+{
+  uint32_t res = 0;
+
+  // NNAPI uses NHWC ordering
+  res += batch * shape.H * shape.W * shape.C;
+  res += row * shape.W * shape.C;
+  res += col * shape.C;
+  res += ch;
+
+  return res;
+}
+
 } // namespace feature
 } // namespace nnapi
 } // namespace internal
index 1039818..93695e8 100644 (file)
@@ -33,6 +33,14 @@ public:
 
     return arr[index];
   }
+  T at(uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) const override
+  {
+    uint32_t index = index_of(_shape, batch, ch, row, col);
+
+    T *arr = reinterpret_cast<T *>(_ptr);
+
+    return arr[index];
+  }
 
   T &at(uint32_t ch, uint32_t row, uint32_t col)
   {
@@ -42,6 +50,14 @@ public:
 
     return arr[index];
   }
+  T &at(uint32_t batch, uint32_t ch, uint32_t row, uint32_t col)
+  {
+    uint32_t index = index_of(_shape, batch, ch, row, col);
+
+    T *arr = reinterpret_cast<T *>(_ptr);
+
+    return arr[index];
+  }
 
 private:
   nnfw::util::feature::Shape _shape;