From 8ff9ade04beb660a13e74547cbcccfa065fe3e75 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=EC=9D=B4=EC=83=81=EA=B7=9C/On-Device=20Lab=28SR=29/Princip?= =?utf8?q?al=20Engineer/=EC=82=BC=EC=84=B1=EC=A0=84=EC=9E=90?= Date: Tue, 12 Mar 2019 16:17:42 +0900 Subject: [PATCH] [neurun] Add Squeeze Operation (#4678) Add squeeze operation. The implementation comes from pure arm compute runtime. Signed-off-by: Sanggyu Lee --- .../neurun/src/backend/acl_cl/StageGenerator.cc | 31 ++++++++++++ .../neurun/src/backend/acl_cl/StageGenerator.h | 1 + .../src/frontend/wrapper/OperationFactory.cc | 27 ++++++++++ runtimes/neurun/src/model/operation/Node.Include.h | 1 + runtimes/neurun/src/model/operation/Op.lst | 1 + runtimes/neurun/src/model/operation/SqueezeNode.cc | 37 ++++++++++++++ runtimes/neurun/src/model/operation/SqueezeNode.h | 59 ++++++++++++++++++++++ tests/nnapi/nnapi_gtest.skip.armv7l-linux.neurun | 1 - .../neurun_frameworktest_list.armv7l.acl_cl.txt | 1 + 9 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 runtimes/neurun/src/model/operation/SqueezeNode.cc create mode 100644 runtimes/neurun/src/model/operation/SqueezeNode.h diff --git a/runtimes/neurun/src/backend/acl_cl/StageGenerator.cc b/runtimes/neurun/src/backend/acl_cl/StageGenerator.cc index c09120d..d828e96 100644 --- a/runtimes/neurun/src/backend/acl_cl/StageGenerator.cc +++ b/runtimes/neurun/src/backend/acl_cl/StageGenerator.cc @@ -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(); + 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)}; diff --git a/runtimes/neurun/src/backend/acl_cl/StageGenerator.h b/runtimes/neurun/src/backend/acl_cl/StageGenerator.h index e4862c3..850694a 100644 --- a/runtimes/neurun/src/backend/acl_cl/StageGenerator.h +++ b/runtimes/neurun/src/backend/acl_cl/StageGenerator.h @@ -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; diff --git a/runtimes/neurun/src/frontend/wrapper/OperationFactory.cc b/runtimes/neurun/src/frontend/wrapper/OperationFactory.cc index f9e8397..980d859 100644 --- a/runtimes/neurun/src/frontend/wrapper/OperationFactory.cc +++ b/runtimes/neurun/src/frontend/wrapper/OperationFactory.cc @@ -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); diff --git a/runtimes/neurun/src/model/operation/Node.Include.h b/runtimes/neurun/src/model/operation/Node.Include.h index 9e1656a..56f4499 100644 --- a/runtimes/neurun/src/model/operation/Node.Include.h +++ b/runtimes/neurun/src/model/operation/Node.Include.h @@ -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" diff --git a/runtimes/neurun/src/model/operation/Op.lst b/runtimes/neurun/src/model/operation/Op.lst index 50e3a85..12dea54 100644 --- a/runtimes/neurun/src/model/operation/Op.lst +++ b/runtimes/neurun/src/model/operation/Op.lst @@ -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 index 0000000..04769f5 --- /dev/null +++ b/runtimes/neurun/src/model/operation/SqueezeNode.cc @@ -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 ¶m) + : 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 index 0000000..f0abf82 --- /dev/null +++ b/runtimes/neurun/src/model/operation/SqueezeNode.h @@ -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 ¶m); + +public: + virtual void accept(NodeVisitor &&) const override; + virtual std::string getName() const override { return "Squeeze"; } + const Param ¶m() const { return _param; } + +private: + Param _param; +}; + +} // namespace operation +} // namespace model +} // namespace neurun + +#endif // __NEURUN_MODEL_OPERATION_SQUEEZE_H__ diff --git a/tests/nnapi/nnapi_gtest.skip.armv7l-linux.neurun b/tests/nnapi/nnapi_gtest.skip.armv7l-linux.neurun index d06f7ea..5904043 100644 --- a/tests/nnapi/nnapi_gtest.skip.armv7l-linux.neurun +++ b/tests/nnapi/nnapi_gtest.skip.armv7l-linux.neurun @@ -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 diff --git a/tests/scripts/neurun_frameworktest_list.armv7l.acl_cl.txt b/tests/scripts/neurun_frameworktest_list.armv7l.acl_cl.txt index 9bb8ecf..71542eb 100644 --- a/tests/scripts/neurun_frameworktest_list.armv7l.acl_cl.txt +++ b/tests/scripts/neurun_frameworktest_list.armv7l.acl_cl.txt @@ -20,3 +20,4 @@ sub/broadcast tanh transpose MODELS/inception_module +squeeze \ No newline at end of file -- 2.7.4