From 9eed07c3e317d54cdb60223dfdcb3029d573d98e Mon Sep 17 00:00:00 2001 From: =?utf8?q?=EC=9C=A4=ED=98=84=EC=8B=9D/On-Device=20Lab=28SR=29/Princip?= =?utf8?q?al=20Engineer/=EC=82=BC=EC=84=B1=EC=A0=84=EC=9E=90?= Date: Tue, 26 Feb 2019 19:25:53 +0900 Subject: [PATCH] [neurun] Sub operation (#4476) * [neurun] sub operator support Files for model and compilation were added. Test-skip file was modified. Signed-off-by: Hyun Sik Yoon * frameworktest was added * fix format checker error * add TODO comment for const_cast issue * renaming SubstractNode to SubNode --- .../neurun/src/backend/acl_cl/StageGenerator.cc | 62 ++++++++++++++++++++++ runtimes/neurun/src/backend/cpu/StageGenerator.cc | 2 + runtimes/neurun/src/compiler/OperationValidator.cc | 5 ++ .../src/frontend/wrapper/OperationFactory.cc | 19 +++++++ runtimes/neurun/src/frontend/wrapper/model.cc | 1 + runtimes/neurun/src/model/operation/Node.Include.h | 1 + runtimes/neurun/src/model/operation/Op.lst | 1 + runtimes/neurun/src/model/operation/SubNode.cc | 40 ++++++++++++++ runtimes/neurun/src/model/operation/SubNode.h | 61 +++++++++++++++++++++ tests/nnapi/nnapi_gtest.skip.armv7l-linux.neurun | 1 - .../neurun_frameworktest_list.armv7l.acl_cl.txt | 1 + 11 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 runtimes/neurun/src/model/operation/SubNode.cc create mode 100644 runtimes/neurun/src/model/operation/SubNode.h diff --git a/runtimes/neurun/src/backend/acl_cl/StageGenerator.cc b/runtimes/neurun/src/backend/acl_cl/StageGenerator.cc index 683ae59..31ee3c6 100644 --- a/runtimes/neurun/src/backend/acl_cl/StageGenerator.cc +++ b/runtimes/neurun/src/backend/acl_cl/StageGenerator.cc @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -1114,6 +1115,67 @@ void StageGenerator::visit(const model::operation::AddNode &node) }); } +void StageGenerator::visit(const model::operation::SubNode &node) +{ + const auto output_index{node.getOutputs().at(0)}; + const auto lhs_index{node.getInputs().at(model::operation::SubNode::Input::LHS)}; + const auto rhs_index{node.getInputs().at(model::operation::SubNode::Input::RHS)}; + const auto activation_index{node.param().activation_index}; + + if (!(_ctx.at(lhs_index).shape() == _ctx.at(rhs_index).shape())) + { + const auto broadcast_rank = + std::max(_ctx.at(lhs_index).shape().rank(), _ctx.at(rhs_index).shape().rank()); + + // TODO remove const_cast later. For example, _ctx may need to be a non const variable or + // a node to extend shape may be inserted in front of this operation + const_cast<::neurun::model::operand::Shape &>(_ctx.at(lhs_index).shape()) + .extendRank(broadcast_rank); + const_cast<::neurun::model::operand::Shape &>(_ctx.at(rhs_index).shape()) + .extendRank(broadcast_rank); + } + + struct Param + { + model::operand::Index ofm_index; + model::operand::Index lhs_index; + model::operand::Index rhs_index; + + FuseCode activation; + }; + + Param param; + + param.ofm_index = output_index; + param.lhs_index = lhs_index; + param.rhs_index = rhs_index; + + param.activation = static_cast(_ctx.at(activation_index).asScalar()); + + auto tensors = _tensor_builder; + + returnStage([tensors, param](IExecutionBuilder &builder) { + auto ofm_alloc = tensors->at(param.ofm_index).get(); + auto lhs_alloc = tensors->at(param.lhs_index).get(); + auto rhs_alloc = tensors->at(param.rhs_index).get(); + + std::unique_ptr<::arm_compute::IFunction> fn; + + auto l = make_layer<::arm_compute::CLArithmeticSubtraction>(); + + l->configure(lhs_alloc->handle(), rhs_alloc->handle(), ofm_alloc->handle(), + arm_compute::ConvertPolicy::SATURATE); + + fn = std::move(l); + + auto acl_fn = make_cl_function(std::move(fn)); + + builder.append(std::move(acl_fn)); + + ActivationBuilder{builder}.append(param.activation, ofm_alloc->handle()); + }); +} + } // namespace acl_cl } // namespace backend } // namespace neurun diff --git a/runtimes/neurun/src/backend/cpu/StageGenerator.cc b/runtimes/neurun/src/backend/cpu/StageGenerator.cc index da21c45..ae75ead 100644 --- a/runtimes/neurun/src/backend/cpu/StageGenerator.cc +++ b/runtimes/neurun/src/backend/cpu/StageGenerator.cc @@ -698,6 +698,8 @@ void StageGenerator::visit(const model::operation::PermuteNode &node) void StageGenerator::visit(const model::operation::AddNode &) { throw std::runtime_error("NYI"); } +void StageGenerator::visit(const model::operation::SubNode &) { throw std::runtime_error("NYI"); } + } // namespace neurun } // namespace backend } // namespace cpu diff --git a/runtimes/neurun/src/compiler/OperationValidator.cc b/runtimes/neurun/src/compiler/OperationValidator.cc index 5271dd2..e05d2e8 100644 --- a/runtimes/neurun/src/compiler/OperationValidator.cc +++ b/runtimes/neurun/src/compiler/OperationValidator.cc @@ -112,5 +112,10 @@ void OperationValidator::visit(const model::operation::AddNode &) // DO NOTHING } +void OperationValidator::visit(const model::operation::SubNode &) +{ + // DO NOTHING +} + } // namespace compiler } // namespace neurun diff --git a/runtimes/neurun/src/frontend/wrapper/OperationFactory.cc b/runtimes/neurun/src/frontend/wrapper/OperationFactory.cc index d1d15a2..9f5fc9e 100644 --- a/runtimes/neurun/src/frontend/wrapper/OperationFactory.cc +++ b/runtimes/neurun/src/frontend/wrapper/OperationFactory.cc @@ -109,6 +109,25 @@ OperationFactory::OperationFactory() return new operation::AddNode{inputs, outputs, param}; }; + _map[ANEURALNETWORKS_SUB] = [](const OperationFactory::Param &init_param) { + assert(init_param.input_count == 3); + assert(init_param.output_count == 1); + + // Each input should be interpreted as follows: + // + // 0 -> Lefthand side operand + // 1 -> Righthand side operand + + operand::IndexSet inputs{init_param.inputs[0], init_param.inputs[1]}; + operand::IndexSet outputs{init_param.outputs[0]}; + + operation::SubNode::Param param; + + param.activation_index = operand::Index{init_param.inputs[2]}; + + return new operation::SubNode{inputs, outputs, param}; + }; + _map[ANEURALNETWORKS_STRIDED_SLICE] = [](const OperationFactory::Param &init_param) { assert(init_param.input_count == 7 && init_param.output_count == 1); diff --git a/runtimes/neurun/src/frontend/wrapper/model.cc b/runtimes/neurun/src/frontend/wrapper/model.cc index d3e80bf..aff611a 100644 --- a/runtimes/neurun/src/frontend/wrapper/model.cc +++ b/runtimes/neurun/src/frontend/wrapper/model.cc @@ -110,6 +110,7 @@ bool ANeuralNetworksModel::addOperation(ANeuralNetworksOperationType type, uint3 switch (type) { case ANEURALNETWORKS_ADD: + case ANEURALNETWORKS_SUB: case ANEURALNETWORKS_CONV_2D: case ANEURALNETWORKS_MUL: case ANEURALNETWORKS_TANH: diff --git a/runtimes/neurun/src/model/operation/Node.Include.h b/runtimes/neurun/src/model/operation/Node.Include.h index 5e44c4d..1407d6d 100644 --- a/runtimes/neurun/src/model/operation/Node.Include.h +++ b/runtimes/neurun/src/model/operation/Node.Include.h @@ -25,6 +25,7 @@ #include "SoftmaxNode.h" #include "PermuteNode.h" #include "AddNode.h" +#include "SubNode.h" #include "DepthwiseConv2DNode.h" #include "StridedSliceNode.h" #include "MulNode.h" diff --git a/runtimes/neurun/src/model/operation/Op.lst b/runtimes/neurun/src/model/operation/Op.lst index 7ae5adc..7c8630d 100644 --- a/runtimes/neurun/src/model/operation/Op.lst +++ b/runtimes/neurun/src/model/operation/Op.lst @@ -22,6 +22,7 @@ // Internal Name | NN API? | NN API Name OP(AddNode , true , ADD) +OP(SubNode , true , SUB) OP(Conv2DNode , true , CONV_2D) OP(DepthwiseConv2DNode , true , DEPTHWISECONV_2D) OP(AvgPool2DNode , true , AVERAGE_POOL_2D) diff --git a/runtimes/neurun/src/model/operation/SubNode.cc b/runtimes/neurun/src/model/operation/SubNode.cc new file mode 100644 index 0000000..94a6551 --- /dev/null +++ b/runtimes/neurun/src/model/operation/SubNode.cc @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018 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 "SubNode.h" + +#include + +#include "NodeVisitor.h" + +namespace neurun +{ +namespace model +{ +namespace operation +{ + +void SubNode::accept(NodeVisitor &&v) const { v.visit(*this); } + +SubNode::SubNode(const operand::IndexSet &inputs, const operand::IndexSet &outputs, + const Param ¶m) + : model::operation::Node{OperandConstraint::createExact(2u), inputs, outputs}, _param{param} +{ +} + +} // namespace operation +} // namespace model +} // namespace neurun diff --git a/runtimes/neurun/src/model/operation/SubNode.h b/runtimes/neurun/src/model/operation/SubNode.h new file mode 100644 index 0000000..e60beb5 --- /dev/null +++ b/runtimes/neurun/src/model/operation/SubNode.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018 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_SUB_NODE_H__ +#define __NEURUN_MODEL_OPERATION_SUB_NODE_H__ + +#include "model/operation/Node.h" + +namespace neurun +{ +namespace model +{ +namespace operation +{ + +class SubNode : public model::operation::Node +{ +public: + enum Input + { + LHS = 0, + RHS + }; + + struct Param + { + operand::Index activation_index; + }; + +public: + SubNode(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 "Sub"; } + +public: + const Param ¶m() const { return _param; } + +private: + Param _param; +}; + +} // namespace operation +} // namespace model +} // namespace neurun + +#endif // __NEURUN_MODEL_OPERATION_SUB_H__ diff --git a/tests/nnapi/nnapi_gtest.skip.armv7l-linux.neurun b/tests/nnapi/nnapi_gtest.skip.armv7l-linux.neurun index 1864273..a3ce557 100644 --- a/tests/nnapi/nnapi_gtest.skip.armv7l-linux.neurun +++ b/tests/nnapi/nnapi_gtest.skip.armv7l-linux.neurun @@ -51,7 +51,6 @@ GeneratedTests.batch_to_space* GeneratedTests.div_* GeneratedTests.space_to_batch* GeneratedTests.squeeze* -GeneratedTests.sub* GeneratedTests.transpose* GeneratedTests.cast_ex* GeneratedTests.gather_ex* diff --git a/tests/scripts/neurun_frameworktest_list.armv7l.acl_cl.txt b/tests/scripts/neurun_frameworktest_list.armv7l.acl_cl.txt index b3b900d..cc29336 100644 --- a/tests/scripts/neurun_frameworktest_list.armv7l.acl_cl.txt +++ b/tests/scripts/neurun_frameworktest_list.armv7l.acl_cl.txt @@ -9,5 +9,6 @@ mul/broadcast softmax reshape/reshape1 strided_slice +sub/broadcast tanh MODELS/inception_module -- 2.7.4