[Pure CL runtime] Support reshape/softmax over tensors (#1436)
author박종현/동작제어Lab(SR)/Staff Engineer/삼성전자 <jh1302.park@samsung.com>
Wed, 30 May 2018 08:49:00 +0000 (17:49 +0900)
committer오형석/동작제어Lab(SR)/Senior Engineer/삼성전자 <hseok82.oh@samsung.com>
Wed, 30 May 2018 08:49:00 +0000 (17:49 +0900)
This commit removes asserts in reshape/softmax compilation
implementation to support ADAS model.

Signed-off-by: Jonghyun Park <jh1302.park@samsung.com>
runtimes/pure_arm_compute/src/compilation.cc
runtimes/pure_arm_compute/src/internal/Swizzle.h [new file with mode: 0644]
runtimes/pure_arm_compute/src/internal/arm_compute/Cast.h [new file with mode: 0644]

index 6ad1c1c..18bb364 100644 (file)
@@ -13,6 +13,7 @@
 #include <arm_compute/runtime/CL/functions/CLFullyConnectedLayer.h>
 #include <arm_compute/runtime/CL/functions/CLSoftmaxLayer.h>
 
+#include "internal/arm_compute/Cast.h"
 #include "internal/arm_compute/kernel/View.h"
 #include "internal/nnapi/kernel/Reader.h"
 #include "internal/layers/GenericReshapeLayer.h"
@@ -880,18 +881,11 @@ void Planner::visit(const ::internal::tflite::op::Reshape::Node &node)
   //      output tensor shape
   // TODO Check consistency of ouput shape
 
-  // 'Feature Map' to 'Vector' reshape
-  assert(_ctx.at(input_index).shape().rank() == 4);
-  assert(_ctx.at(output_index).shape().rank() == 2);
-  assert(_ctx.at(output_index).shape().dim(0) == 1);
-
-  const auto ifm_shape = _ctx.at(input_index).shape().asFeature();
-  const auto out_size = _ctx.at(output_index).shape().dim(1);
+  // TODO Re-enable this assert
+  // assert((ifm_shape.C * ifm_shape.H * ifm_shape.W) == out_size);
 
-  assert((ifm_shape.C * ifm_shape.H * ifm_shape.W) == out_size);
-
-  _builder.addShapeConstr(output_index, asTensorInfo(out_size));
-  _builder.addShapeConstr(input_index, asTensorInfo(ifm_shape));
+  _builder.addShapeConstr(output_index, asTensorInfo(_ctx.at(output_index).shape()));
+  _builder.addShapeConstr(input_index, asTensorInfo(_ctx.at(input_index).shape()));
 
   struct Param
   {
@@ -928,16 +922,8 @@ void Planner::visit(const ::internal::tflite::op::Softmax::Node &node)
 
   assert(_ctx.at(output_index).shape().rank() == _ctx.at(input_index).shape().rank());
 
-  // TODO Support 'feature map' input
-  assert(_ctx.at(input_index).shape().rank() == 2);
-  assert(_ctx.at(input_index).shape().dim(0) == 1);
-  assert(_ctx.at(input_index).shape().dim(0) == _ctx.at(output_index).shape().dim(0));
-  assert(_ctx.at(input_index).shape().dim(1) == _ctx.at(output_index).shape().dim(1));
-
-  const uint32_t len = _ctx.at(output_index).shape().dim(1);
-
-  _builder.addShapeConstr(output_index, asTensorInfo(len));
-  _builder.addShapeConstr(input_index, asTensorInfo(len));
+  _builder.addShapeConstr(output_index, asTensorInfo(_ctx.at(output_index).shape()));
+  _builder.addShapeConstr(input_index, asTensorInfo(_ctx.at(input_index).shape()));
 
   struct Param
   {
diff --git a/runtimes/pure_arm_compute/src/internal/Swizzle.h b/runtimes/pure_arm_compute/src/internal/Swizzle.h
new file mode 100644 (file)
index 0000000..73c0d10
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef __SWIZZLE_H__
+#define __SWIZZLE_H__
+
+class ARMComputeAxis
+{
+public:
+  ARMComputeAxis() = default;
+
+public:
+  explicit ARMComputeAxis(uint32_t value) : _value{value}
+  {
+    // DO NOTHING
+  }
+
+public:
+  uint32_t value(void) const { return _value; }
+
+private:
+  uint32_t _value;
+};
+
+// Convert T/F Lite / NNAPI axis (based on ...NHWC) to ARMCompute axis (WCHN...)
+inline ARMComputeAxis ToARMComputeAxis(uint32_t rank, uint32_t axis)
+{
+  const ARMComputeAxis reversed{(rank - axis) - 1};
+
+  if (rank < 4)
+  {
+    return reversed;
+  }
+
+  // DEPTH
+  if (0 == reversed.value())
+  {
+    return ARMComputeAxis{2};
+  }
+  // WIDTH
+  if (1 == reversed.value())
+  {
+    return ARMComputeAxis{0};
+  }
+  // HEIGHT
+  if (2 == reversed.value())
+  {
+    return ARMComputeAxis{1};
+  }
+
+  // ELSE
+  return reversed;
+}
+
+#endif // __SWIZZLE_H__
diff --git a/runtimes/pure_arm_compute/src/internal/arm_compute/Cast.h b/runtimes/pure_arm_compute/src/internal/arm_compute/Cast.h
new file mode 100644 (file)
index 0000000..f4da6a1
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef __ARM_COMPUTE_CAST_H__
+
+#include <arm_compute/core/TensorShape.h>
+
+#include "internal/Swizzle.h"
+#include "internal/Model.h"
+
+// TODO Move asTensorShape and asTensorInfo in compilation.cc into this file
+inline ::arm_compute::TensorShape asTensorShape(const internal::tflite::operand::Shape &shape)
+{
+  const uint32_t rank = shape.rank();
+
+  ::arm_compute::TensorShape res{};
+
+  res.set_num_dimensions(rank);
+
+  for (uint32_t axis = 0; axis < rank; ++axis)
+  {
+    res[ToARMComputeAxis(rank, axis).value()] = shape.dim(axis);
+  }
+
+  return res;
+}
+
+::arm_compute::TensorInfo asTensorInfo(const internal::tflite::operand::Shape &shape)
+{
+  return ::arm_compute::TensorInfo(asTensorShape(shape), 1, ::arm_compute::DataType::F32);
+}
+
+#endif // __ARM_COMPUTE_CAST_H__