[PureCL] Initialize CLTensors having const data (#1472)
author서상민/동작제어Lab(SR)/Staff Engineer/삼성전자 <sangmin7.seo@samsung.com>
Thu, 31 May 2018 06:23:03 +0000 (15:23 +0900)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Thu, 31 May 2018 06:23:03 +0000 (15:23 +0900)
For issue #1366

In the current implementation of Pure CL runtime, CLTensors, which have
const data in their corresponding NNAPI operand, are not initialized.
This patch fixes this issue by initializing them in PlanBuilder's
finalize method.

Signed-off-by: Sangmin Seo <sangmin7.seo@samsung.com>
runtimes/pure_arm_compute/src/compilation.cc
runtimes/pure_arm_compute/src/internal/Model.h

index 18bb364..87fcac1 100644 (file)
 #include "internal/arm_compute/Cast.h"
 #include "internal/arm_compute/kernel/View.h"
 #include "internal/nnapi/kernel/Reader.h"
+#include "internal/nnapi/feature/Reader.h"
+#include "internal/nnapi/feature/View.h"
+#include "internal/arm_compute/feature/View.h"
 #include "internal/layers/GenericReshapeLayer.h"
 #include "internal/layers/SimpleArithmeticAdditionLayer.h"
 
 #include "util/kernel/IndexIterator.h"
+#include "util/feature/IndexIterator.h"
 
 #include "compilation.h"
 #include "model.h"
@@ -1073,6 +1077,35 @@ void PlanBuilder::addStage(const Stage &stage) { _stages.emplace_back(stage); }
 
 #include <stack>
 
+static void initFeatureTensor(::arm_compute::ITensor &tensor,
+                              const nnfw::util::feature::Shape &feature_shape,
+                              const uint8_t *feature_base, const size_t feature_size)
+{
+  const ::internal::nnapi::feature::Reader<float> from{feature_shape, feature_base, feature_size};
+  ::internal::arm_compute::feature::View<float> 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;
+  };
+}
+
+static void initVectorTensor(::arm_compute::ITensor &tensor, const uint8_t *vec_base,
+                             const size_t vec_size)
+{
+  for (uint32_t n = 0; n < vec_size; ++n)
+  {
+    const ::arm_compute::Coordinates coordinate{n};
+
+    float *into = reinterpret_cast<float *>(tensor.ptr_to_element(coordinate));
+
+    const float *from = reinterpret_cast<const float *>(vec_base) + n;
+    const auto value = *from;
+
+    *into = value;
+  }
+}
+
 void PlanBuilder::finalize(void) const
 {
   // CLTensor objects to be initialized later
@@ -1180,6 +1213,46 @@ void PlanBuilder::finalize(void) const
     const ::internal::tflite::operand::Index operand_index{it->first};
     _plan.operands().at(operand_index).access(it->second);
   }
+
+  // Initialize CLTensors that have data in their corresponding NNAPI operand but are not
+  // initialized yet
+  const auto &operands = _plan.model().operands();
+  for (int idx = 0; idx < operands.size(); ++idx)
+  {
+    const ::internal::tflite::operand::Index operand_idx{idx};
+    if (isAllocated(idx) && operands.at(operand_idx).hasData() &&
+        _initializer_ctx.find(idx) == _initializer_ctx.end())
+    {
+      const auto rank = operands.at(operand_idx).shape().rank();
+      auto base = operands.at(operand_idx).data().base();
+      ::arm_compute::ICLTensor &tensor = *(_plan.operands().at(operand_idx).ptr());
+
+      switch (rank)
+      {
+        case 0: // scalar
+        {
+          initVectorTensor(tensor, base, 1);
+          break;
+        }
+        case 1: // vector
+        {
+          auto size = operands.at(operand_idx).shape().asVector();
+          initVectorTensor(tensor, base, size);
+          break;
+        }
+        case 4: // feature
+        {
+          const auto feature_shape = operands.at(operand_idx).shape().asFeature();
+          auto size = operands.at(operand_idx).data().size();
+          initFeatureTensor(tensor, feature_shape, base, size);
+          break;
+        }
+        default:
+          throw std::runtime_error("Not supported, yet");
+          break;
+      }
+    }
+  }
 }
 
 //
index e51ebb1..69f2ac6 100644 (file)
@@ -194,6 +194,7 @@ public:
 public:
   const Object &at(const Index &) const;
   Object &at(const Index &);
+  size_t size(void) const { return _objects.size(); }
 
 private:
   std::vector<std::unique_ptr<Object>> _objects;