[neurun] Add Squeeze Operation (#4678)
author이상규/On-Device Lab(SR)/Principal Engineer/삼성전자 <sg5.lee@samsung.com>
Tue, 12 Mar 2019 07:17:42 +0000 (16:17 +0900)
committer박세희/On-Device Lab(SR)/Principal Engineer/삼성전자 <saehie.park@samsung.com>
Tue, 12 Mar 2019 07:17:42 +0000 (16:17 +0900)
Add squeeze operation.
The implementation comes from pure arm compute runtime.

Signed-off-by: Sanggyu Lee <sg5.lee@samsung.com>
runtimes/neurun/src/backend/acl_cl/StageGenerator.cc
runtimes/neurun/src/backend/acl_cl/StageGenerator.h
runtimes/neurun/src/frontend/wrapper/OperationFactory.cc
runtimes/neurun/src/model/operation/Node.Include.h
runtimes/neurun/src/model/operation/Op.lst
runtimes/neurun/src/model/operation/SqueezeNode.cc [new file with mode: 0644]
runtimes/neurun/src/model/operation/SqueezeNode.h [new file with mode: 0644]
tests/nnapi/nnapi_gtest.skip.armv7l-linux.neurun
tests/scripts/neurun_frameworktest_list.armv7l.acl_cl.txt

index c09120d..d828e96 100644 (file)
@@ -957,6 +957,37 @@ void StageGenerator::visit(const model::operation::ReshapeNode &node)
   });
 }
 
+void StageGenerator::visit(const model::operation::SqueezeNode &node)
+{
+  // Squeeze is identical to reshape except that it has an optional dimensions input.
+  // In addition, optional dims_index is ignored since output tensor already has squeezed shape
+  // by freezer and toco
+  const auto output_index{node.getOutputs().at(0)};
+  const auto input_index{node.getInputs().at(model::operation::SqueezeNode::Input::INPUT)};
+  const auto dims_index{node.param().dims};
+
+  struct Param
+  {
+    model::operand::Index output_index;
+    model::operand::Index input_index;
+  };
+
+  Param param{output_index, input_index};
+  auto tensors = _tensor_builder;
+
+  tensors->dimCorrection(input_index, false);
+  tensors->dimCorrection(output_index, false);
+
+  returnStage([tensors, param](IExecutionBuilder &builder) {
+    auto output_alloc = tensors->at(param.output_index).get();
+    auto input_alloc = tensors->at(param.input_index).get();
+    auto fn = make_layer<arm_compute::misc::GenericReshapeLayer>();
+    fn->configure(input_alloc->handle(), output_alloc->handle());
+    auto acl_fn = make_cl_function(std::move(fn));
+    builder.append(std::move(acl_fn));
+  });
+}
+
 void StageGenerator::visit(const model::operation::TanhNode &node)
 {
   const auto output_index{node.getOutputs().at(0)};
index e4862c3..850694a 100644 (file)
@@ -46,6 +46,7 @@ public:
   virtual void visit(const model::operation::MulNode &) override;
   virtual void visit(const model::operation::ReduceSumNode &) override;
   virtual void visit(const model::operation::ReshapeNode &) override;
+  virtual void visit(const model::operation::SqueezeNode &) override;
   virtual void visit(const model::operation::TanhNode &) override;
   virtual void visit(const model::operation::SoftmaxNode &) override;
   virtual void visit(const model::operation::StridedSliceNode &) override;
index f9e8397..980d859 100644 (file)
@@ -501,6 +501,33 @@ OperationFactory::OperationFactory()
     return new operation::MulNode{inputs, outputs, param};
   };
 
+  _map[ANEURALNETWORKS_SQUEEZE] = [](const OperationFactory::Param &init_param) {
+    assert(init_param.input_count == 1 || init_param.input_count == 2);
+    assert(init_param.output_count == 1);
+
+    operand::IndexSet outputs{init_param.outputs[0]};
+
+    // Each input should be interpreted as follows:
+    //
+    // 0 -> An n-D tensor, the tensor to be squeezed.
+    // 1 -> An optional 1-D tensor of ANEURALNETWORKS_TENSOR_INT32. The dimensions to squeeze.
+    //      If specified only squeezes the dimensions listed. Otherwise, squeezes all dimensions.
+    //      The dimension index starts at 0. An error must be reported if squeezing a dimension that
+    //      is not 1.
+
+    // Add mandatory input index
+    operand::IndexSet inputs{init_param.inputs[0]};
+
+    // Add dims index if specified
+    operation::SqueezeNode::Param param;
+    if (init_param.input_count == 2)
+    {
+      param.dims = operand::Index{init_param.inputs[1]};
+    }
+
+    return new operation::SqueezeNode{inputs, outputs, param};
+  };
+
   _map[ANEURALNETWORKS_TANH] = [](const OperationFactory::Param &init_param) {
     assert(init_param.input_count == 1 && init_param.output_count == 1);
 
index 9e1656a..56f4499 100644 (file)
@@ -31,6 +31,7 @@
 #include "DepthwiseConv2DNode.h"
 #include "StridedSliceNode.h"
 #include "MulNode.h"
+#include "SqueezeNode.h"
 #include "TanhNode.h"
 #include "LogisticNode.h"
 #include "CastNode.h"
index 50e3a85..12dea54 100644 (file)
@@ -34,6 +34,7 @@ OP(ReduceSumNode           , true    , REDUCE_SUM_EX)
 OP(ReshapeNode             , true    , RESHAPE)
 OP(MulNode                 , true    , MUL)
 OP(SoftmaxNode             , true    , SOFTMAX)
+OP(SqueezeNode             , true    , SQUEEZE)
 OP(StridedSliceNode        , true    , STRIDED_SLICE)
 OP(TanhNode                , true    , TANH)
 OP(LogisticNode            , true    , LOGISTIC)
diff --git a/runtimes/neurun/src/model/operation/SqueezeNode.cc b/runtimes/neurun/src/model/operation/SqueezeNode.cc
new file mode 100644 (file)
index 0000000..04769f5
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SqueezeNode.h"
+#include "NodeVisitor.h"
+
+namespace neurun
+{
+namespace model
+{
+namespace operation
+{
+
+void SqueezeNode::accept(NodeVisitor &&v) const { v.visit(*this); }
+
+SqueezeNode::SqueezeNode(const operand::IndexSet &inputs, const operand::IndexSet &outputs,
+                         const Param &param)
+    : model::operation::Node{OperandConstraint::createExact(1u), inputs, outputs}, _param(param)
+{
+}
+
+} // namespace operation
+} // namespace model
+} // namespace neurun
diff --git a/runtimes/neurun/src/model/operation/SqueezeNode.h b/runtimes/neurun/src/model/operation/SqueezeNode.h
new file mode 100644 (file)
index 0000000..f0abf82
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __NEURUN_MODEL_OPERATION_SQUEEZE_NODE_H__
+#define __NEURUN_MODEL_OPERATION_SQUEEZE_NODE_H__
+
+#include "model/operation/Node.h"
+
+namespace neurun
+{
+namespace model
+{
+namespace operation
+{
+
+class SqueezeNode : public model::operation::Node
+{
+public:
+  enum Input
+  {
+    INPUT = 0
+  };
+
+  struct Param
+  {
+    operand::Index dims;
+  };
+
+public:
+  SqueezeNode(const operand::IndexSet &inputs, const operand::IndexSet &outputs,
+              const Param &param);
+
+public:
+  virtual void accept(NodeVisitor &&) const override;
+  virtual std::string getName() const override { return "Squeeze"; }
+  const Param &param() const { return _param; }
+
+private:
+  Param _param;
+};
+
+} // namespace operation
+} // namespace model
+} // namespace neurun
+
+#endif // __NEURUN_MODEL_OPERATION_SQUEEZE_H__
index d06f7ea..5904043 100644 (file)
@@ -44,7 +44,6 @@ GeneratedTests.squared_difference_ex*
 GeneratedTests.svdf*
 GeneratedTests.batch_to_space*
 GeneratedTests.space_to_batch*
-GeneratedTests.squeeze*
 GeneratedTests.gather_ex*
 GeneratedTests.topk_v2*
 # Unexpected result