diff options
Diffstat (limited to 'runtimes/neurun/backend/acl_cl/ShapeFixer.cc')
-rw-r--r-- | runtimes/neurun/backend/acl_cl/ShapeFixer.cc | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/runtimes/neurun/backend/acl_cl/ShapeFixer.cc b/runtimes/neurun/backend/acl_cl/ShapeFixer.cc new file mode 100644 index 000000000..e6744cc24 --- /dev/null +++ b/runtimes/neurun/backend/acl_cl/ShapeFixer.cc @@ -0,0 +1,361 @@ +/* + * 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 "ShapeFixer.h" + +#include <arm_compute/runtime/CL/CLFunctions.h> // Include all ARM Compute CL functions +#include <arm_compute/runtime/CL/CLFunctionsEx.h> // Include all ARM Compute EX CL functions +#include <arm_compute/runtime/misc/functions/GenericGather.h> +#include <arm_compute/runtime/misc/functions/GenericReshapeLayer.h> + +#include <AclFunction.h> +#include <Convert.h> +#include <Swizzle.h> + +#include "kernel/ConcatLayer.h" +#include "model/Index.h" +#include "model/DataType.h" +#include "model/InternalType.h" +#include "compiler/IExecutionBuilder.h" +#include "exec/NopFunction.h" +#include "util/logging.h" +#include "util/Utils.h" +#include "util/Padding.h" + +using ::neurun::compiler::IExecutionBuilder; + +namespace neurun +{ +namespace backend +{ +namespace acl_cl +{ + +using ::neurun::backend::acl_common::asAclFunction; + +ShapeFixer::ShapeFixer(const neurun::model::Operands &ctx, + const std::shared_ptr<TensorBuilder> &tensor_builder) + : _ctx(ctx), _tensor_builder(tensor_builder) +{ + assert(tensor_builder); +} + +void ShapeFixer::visit(const model::operation::CastNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::Conv2DNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::DepthwiseConv2DNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::MaxPool2DNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::AvgPool2DNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::ConcatNode &node) +{ + const auto ofm_index{node.getOutputs().at(0)}; + _tensor_builder->dimCorrection(ofm_index, false); + for (const auto &input : node.getInputs()) + _tensor_builder->dimCorrection(input, false); +} + +void ShapeFixer::visit(const model::operation::FullyConnectedNode &node) +{ + using model::operation::FullyConnectedNode; + const auto input_index{node.getInputs().at(FullyConnectedNode::Input::INPUT)}; + const auto input_rank = _ctx.at(input_index).shape().rank(); + if (input_rank == 4) + _tensor_builder->dimCorrection(input_index, false); +} + +void ShapeFixer::visit(const model::operation::MulNode &node) +{ + const auto lhs_index{node.getInputs().at(model::operation::MulNode::Input::LHS)}; + const auto rhs_index{node.getInputs().at(model::operation::MulNode::Input::RHS)}; + + 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::Shape &>(_ctx.at(lhs_index).shape()).extendRank(broadcast_rank); + const_cast<::neurun::model::Shape &>(_ctx.at(rhs_index).shape()).extendRank(broadcast_rank); + } +} + +void ShapeFixer::visit(const model::operation::ReduceSumNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::ReshapeNode &node) +{ + const auto output_index{node.getOutputs().at(0)}; + const auto input_index{node.getInputs().at(model::operation::ReshapeNode::Input::INPUT)}; + _tensor_builder->dimCorrection(input_index, false); + _tensor_builder->dimCorrection(output_index, false); +} + +void ShapeFixer::visit(const model::operation::SqueezeNode &node) +{ + const auto output_index{node.getOutputs().at(0)}; + const auto input_index{node.getInputs().at(model::operation::SqueezeNode::Input::INPUT)}; + _tensor_builder->dimCorrection(input_index, false); + _tensor_builder->dimCorrection(output_index, false); +} + +void ShapeFixer::visit(const model::operation::TanhNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::SoftmaxNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::StridedSliceNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::TransposeNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::AddNode &node) +{ + const auto lhs_index{node.getInputs().at(model::operation::AddNode::Input::LHS)}; + const auto rhs_index{node.getInputs().at(model::operation::AddNode::Input::RHS)}; + + 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()); + const_cast<::neurun::model::Shape &>(_ctx.at(lhs_index).shape()).extendRank(broadcast_rank); + const_cast<::neurun::model::Shape &>(_ctx.at(rhs_index).shape()).extendRank(broadcast_rank); + } +} + +void ShapeFixer::visit(const model::operation::SubNode &node) +{ + const auto lhs_index{node.getInputs().at(model::operation::SubNode::Input::LHS)}; + const auto rhs_index{node.getInputs().at(model::operation::SubNode::Input::RHS)}; + + 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::Shape &>(_ctx.at(lhs_index).shape()).extendRank(broadcast_rank); + const_cast<::neurun::model::Shape &>(_ctx.at(rhs_index).shape()).extendRank(broadcast_rank); + } +} + +void ShapeFixer::visit(const model::operation::DivNode &node) +{ + const auto lhs_index{node.getInputs().at(model::operation::DivNode::Input::LHS)}; + const auto rhs_index{node.getInputs().at(model::operation::DivNode::Input::RHS)}; + + 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::Shape &>(_ctx.at(lhs_index).shape()).extendRank(broadcast_rank); + const_cast<::neurun::model::Shape &>(_ctx.at(rhs_index).shape()).extendRank(broadcast_rank); + } +} + +void ShapeFixer::visit(const model::operation::ExpNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::LogisticNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::LogicalAndNode &node) +{ + const auto input0_index{node.getInputs().at(model::operation::LogicalAndNode::Input::INPUT0)}; + const auto input1_index{node.getInputs().at(model::operation::LogicalAndNode::Input::INPUT1)}; + + if (!(_ctx.at(input0_index).shape() == _ctx.at(input1_index).shape())) + { + const auto broadcast_rank = + std::max(_ctx.at(input0_index).shape().rank(), _ctx.at(input1_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::Shape &>(_ctx.at(input0_index).shape()).extendRank(broadcast_rank); + const_cast<::neurun::model::Shape &>(_ctx.at(input1_index).shape()).extendRank(broadcast_rank); + } +} + +void ShapeFixer::visit(const model::operation::LSTMNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::ReduceMaxNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::ComparisonNode &node) +{ + const auto input0_index{node.getInputs().at(model::operation::ComparisonNode::Input::INPUT0)}; + const auto input1_index{node.getInputs().at(model::operation::ComparisonNode::Input::INPUT1)}; + + if (!(_ctx.at(input0_index).shape() == _ctx.at(input1_index).shape())) + { + const auto broadcast_rank = + std::max(_ctx.at(input0_index).shape().rank(), _ctx.at(input1_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::Shape &>(_ctx.at(input0_index).shape()).extendRank(broadcast_rank); + const_cast<::neurun::model::Shape &>(_ctx.at(input1_index).shape()).extendRank(broadcast_rank); + } +} + +void ShapeFixer::visit(const model::operation::RSQRTNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::ReLUNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::ResizeBilinearNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::ReLU1Node &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::ReLU6Node &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::RNNNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::FloorNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::SpaceToDepthNode &node) +{ + const auto ofm_index{node.getOutputs().at(0)}; + const auto ifm_index{node.getInputs().at(model::operation::SpaceToDepthNode::Input::INPUT)}; + _tensor_builder->dimCorrection(ofm_index, false); + _tensor_builder->dimCorrection(ifm_index, false); +} + +void ShapeFixer::visit(const model::operation::L2Pool2DNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::EmbeddingLookupNode &node) +{ + const auto output_index{node.getOutputs().at(0)}; + const auto values_index{ + node.getInputs().at(model::operation::EmbeddingLookupNode::Input::VALUES)}; + _tensor_builder->dimCorrection(values_index, false); + _tensor_builder->dimCorrection(output_index, false); +} + +void ShapeFixer::visit(const model::operation::L2NormalizationNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::HashtableLookupNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::PReLUNode &node) +{ + const auto ifm_index{node.getInputs().at(model::operation::PReLUNode::Input::INPUT)}; + const auto alpha_index{node.getInputs().at(model::operation::PReLUNode::Input::ALPHA)}; + + if (!(_ctx.at(ifm_index).shape() == _ctx.at(alpha_index).shape())) + { + const auto broadcast_rank = + std::max(_ctx.at(ifm_index).shape().rank(), _ctx.at(alpha_index).shape().rank()); + const_cast<::neurun::model::Shape &>(_ctx.at(ifm_index).shape()).extendRank(broadcast_rank); + const_cast<::neurun::model::Shape &>(_ctx.at(alpha_index).shape()).extendRank(broadcast_rank); + } +} + +void ShapeFixer::visit(const model::operation::TransposeConvNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::SQRTNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::LogicalOrNode &node) +{ + const auto input0_index{node.getInputs().at(model::operation::LogicalOrNode::Input::INPUT0)}; + const auto input1_index{node.getInputs().at(model::operation::LogicalOrNode::Input::INPUT1)}; + + if (!(_ctx.at(input0_index).shape() == _ctx.at(input1_index).shape())) + { + const auto broadcast_rank = + std::max(_ctx.at(input0_index).shape().rank(), _ctx.at(input1_index).shape().rank()); + const_cast<::neurun::model::Shape &>(_ctx.at(input0_index).shape()).extendRank(broadcast_rank); + const_cast<::neurun::model::Shape &>(_ctx.at(input1_index).shape()).extendRank(broadcast_rank); + } +} + +void ShapeFixer::visit(const model::operation::LogicalNotNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::SquaredDifferenceNode &node) +{ + const auto lhs_index{node.getInputs().at(model::operation::SquaredDifferenceNode::Input::LHS)}; + const auto rhs_index{node.getInputs().at(model::operation::SquaredDifferenceNode::Input::RHS)}; + + 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()); + const_cast<neurun::model::Shape &>(_ctx.at(lhs_index).shape()).extendRank(broadcast_rank); + const_cast<neurun::model::Shape &>(_ctx.at(rhs_index).shape()).extendRank(broadcast_rank); + } +} + +void ShapeFixer::visit(const model::operation::TopKV2Node &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::GatherNode &node) +{ + const auto ofm_index{node.getOutputs().at(0)}; + const auto ifm_index{node.getInputs().at(model::operation::GatherNode::Input::INPUT)}; + const auto indices_index{node.getInputs().at(model::operation::GatherNode::Input::INDICES)}; + _tensor_builder->dimCorrection(ofm_index, false); + _tensor_builder->dimCorrection(ifm_index, false); + _tensor_builder->dimCorrection(indices_index, false); +} + +void ShapeFixer::visit(const model::operation::NegNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::AbsNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::ArgMaxNode &node) +{ + const auto ofm_index{node.getOutputs().at(0)}; + const auto ifm_index{node.getInputs().at(model::operation::ArgMaxNode::Input::INPUT)}; + _tensor_builder->dimCorrection(ofm_index, false); + _tensor_builder->dimCorrection(ifm_index, false); +} + +void ShapeFixer::visit(const model::operation::DequantizeNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::MeanNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::LocalResponseNormalizationNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::DepthToSpaceNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::ReduceMinNode &) { /* DO NOTHING */} + +void ShapeFixer::visit(const model::operation::SplitNode &node) +{ + const auto input_index{node.getInputs().at(model::operation::SplitNode::Input::INPUT)}; + _tensor_builder->dimCorrection(input_index, false); + for (const auto &output : node.getOutputs()) + _tensor_builder->dimCorrection(output, false); +} + +void ShapeFixer::visit(const model::operation::UnpackNode &node) +{ + const auto input_index{node.getInputs().at(model::operation::UnpackNode::Input::INPUT)}; + _tensor_builder->dimCorrection(input_index, false); + for (const auto &output_index : node.getOutputs()) + _tensor_builder->dimCorrection(output_index, false); +} + +void ShapeFixer::visit(const model::operation::PadNode &node) +{ + const auto input_index{node.getInputs().at(model::operation::PadNode::Input::INPUT)}; + const auto output_index{node.getOutputs().at(0)}; + _tensor_builder->dimCorrection(input_index, false); + _tensor_builder->dimCorrection(output_index, false); +} + +} // namespace acl_cl +} // namespace backend +} // namespace neurun |