diff options
Diffstat (limited to 'runtimes/neurun/src/backend/acl_cl/StageGenerator.cc')
-rw-r--r-- | runtimes/neurun/src/backend/acl_cl/StageGenerator.cc | 593 |
1 files changed, 0 insertions, 593 deletions
diff --git a/runtimes/neurun/src/backend/acl_cl/StageGenerator.cc b/runtimes/neurun/src/backend/acl_cl/StageGenerator.cc deleted file mode 100644 index 89bbd7bd2..000000000 --- a/runtimes/neurun/src/backend/acl_cl/StageGenerator.cc +++ /dev/null @@ -1,593 +0,0 @@ -/* - * 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 "backend/acl_cl/StageGenerator.h" - -#include "kernel/acl_cl/CLFunction.h" - -#include <arm_compute/runtime/CL/functions/CLConvolutionLayer.h> -#include <arm_compute/runtime/CL/functions/CLPoolingLayer.h> -#include <arm_compute/runtime/CL/functions/CLActivationLayer.h> -#include <arm_compute/runtime/CL/functions/CLReshapeLayer.h> -#include <arm_compute/runtime/CL/functions/CLFullyConnectedLayer.h> -#include <arm_compute/runtime/CL/functions/CLSoftmaxLayer.h> - -#include "kernel/acl_cl/ConcatLayer.h" - -#include "util/Padding.h" - -#include "model/operand/Index.h" - -#include "util/logging.h" - -#include "NeuralNetworks.h" - -#include "util/Utils.h" - -template <typename T> std::unique_ptr<T> make_layer(void) { return std::unique_ptr<T>{new T}; } - -std::unique_ptr<::neurun::kernel::acl_cl::CLFunction> -make_cl_function(std::unique_ptr<::arm_compute::IFunction> &&layer) -{ - return std::unique_ptr<::neurun::kernel::acl_cl::CLFunction>( - new ::neurun::kernel::acl_cl::CLFunction(std::move(layer))); -} - -::arm_compute::PadStrideInfo asPadStringInfo(const neurun::util::Padding &padding, - const neurun::util::Stride &stride) -{ - return ::arm_compute::PadStrideInfo{stride.horizontal, - stride.vertical, - padding.left, - padding.right, - padding.top, - padding.bottom, - ::arm_compute::DimensionRoundingType::FLOOR}; -} - -namespace neurun -{ -namespace backend -{ -namespace acl_cl -{ - -// -// ActivationBuilder -// -class ActivationBuilder -{ -public: - ActivationBuilder(IExecutionBuilder &builder) : _builder(builder) - { - // DO NOTHING - } - -private: - void appendReLU(::arm_compute::ICLTensor *tensor); - -public: - void append(FuseCode code, ::arm_compute::ICLTensor *tensor); - -private: - IExecutionBuilder &_builder; -}; - -void ActivationBuilder::appendReLU(::arm_compute::ICLTensor *ifm_alloc) -{ - const ::arm_compute::ActivationLayerInfo act_info{ - ::arm_compute::ActivationLayerInfo::ActivationFunction::RELU}; - - auto fn = make_layer<::arm_compute::CLActivationLayer>(); - - fn->configure(ifm_alloc, nullptr, act_info); - - auto acl_fn = make_cl_function(std::move(fn)); - - _builder.append(std::move(acl_fn)); -} - -void ActivationBuilder::append(FuseCode code, ::arm_compute::ICLTensor *ifm_alloc) -{ - switch (code) - { - case ANEURALNETWORKS_FUSED_NONE: - { - // DO NOTHING - break; - } - case ANEURALNETWORKS_FUSED_RELU: - { - appendReLU(ifm_alloc); - break; - } - default: - { - throw std::runtime_error("Not supported, yet"); - } - } -} - -// -// StageGenerator -// -StageGenerator::StageGenerator(const neurun::model::operand::Set &ctx, - const std::shared_ptr<TensorBuilder> &tensor_builder) - : _ctx(ctx), _tensor_builder(tensor_builder) -{ - // DO NOTHING -} - -void StageGenerator::visit(const model::operation::Conv2DNode &node) -{ - using model::operation::Conv2DNode; - - const auto ofm_index{node.getOutputs().at(0)}; - const auto ifm_index{node.getInputs().at(Conv2DNode::Input::INPUT)}; - const auto ker_index{node.getInputs().at(Conv2DNode::Input::KERNEL)}; - const auto bias_index{node.getInputs().at(Conv2DNode::Input::BIAS)}; - - const auto vstride_index{node.param().vstride_index}; - const auto hstride_index{node.param().hstride_index}; - - const auto padding_index{node.param().padding_index}; - const auto activation_index{node.param().activation_index}; - - const auto ofm_shape = _ctx.at(ofm_index).shape().asFeature(); - const auto ifm_shape = _ctx.at(ifm_index).shape().asFeature(); - const auto ker_shape = _ctx.at(ker_index).shape().asKernel(); - - const PaddingCode padding_type = - static_cast<PaddingCode>(_ctx.at(padding_index).asScalar<int32_t>()); - - assert((ANEURALNETWORKS_PADDING_SAME == padding_type) || - (ANEURALNETWORKS_PADDING_VALID == padding_type)); - - neurun::util::Stride stride; - - stride.vertical = _ctx.at(vstride_index).asScalar<int32_t>(); - stride.horizontal = _ctx.at(hstride_index).asScalar<int32_t>(); - - // Construct operation parameters - struct Param - { - model::operand::Index ofm_index; - model::operand::Index ifm_index; - model::operand::Index ker_index; - model::operand::Index bias_index; - - neurun::util::Padding padding; - neurun::util::Stride stride; - - FuseCode activation; - }; - - Param param; - - param.ofm_index = ofm_index; - param.ifm_index = ifm_index; - param.ker_index = ker_index; - param.bias_index = bias_index; - - param.stride = stride; - param.padding = - (padding_type == ANEURALNETWORKS_PADDING_SAME) - ? neurun::util::same_padding(ifm_shape, ofm_shape, stride, ker_shape.W, ker_shape.H) - : neurun::util::valid_padding(); - - param.activation = static_cast<FuseCode>(_ctx.at(activation_index).asScalar<int32_t>()); - - auto tensors = _tensor_builder; - - returnStage([tensors, param](IExecutionBuilder &builder) { - auto ofm_alloc = tensors->at(param.ofm_index).get(); - auto ifm_alloc = tensors->at(param.ifm_index).get(); - auto ker_alloc = tensors->at(param.ker_index).get(); - auto bias_alloc = tensors->at(param.bias_index).get(); - - const auto conv_info = asPadStringInfo(param.padding, param.stride); - - std::unique_ptr<::arm_compute::CLConvolutionLayer> fn{new ::arm_compute::CLConvolutionLayer}; - - fn->configure(ifm_alloc->handle(), ker_alloc->handle(), bias_alloc->handle(), - ofm_alloc->handle(), conv_info); - - auto acl_fn = make_cl_function(std::move(fn)); - - builder.append(std::move(acl_fn)); - - ActivationBuilder{builder}.append(param.activation, ofm_alloc->handle()); - }); -} - -void StageGenerator::visit(const model::operation::MaxPool2DNode &node) -{ - const auto ofm_index{node.getOutputs().at(0)}; - const auto ifm_index{node.getInputs().at(model::operation::MaxPool2DNode::Input::INPUT)}; - - const auto kh_index{node.param().kh_index}; - const auto kw_index{node.param().kw_index}; - - const auto vstride_index{node.param().vstride_index}; - const auto hstride_index{node.param().hstride_index}; - - const auto padding_index{node.param().padding_index}; - - const auto ofm_shape = _ctx.at(ofm_index).shape().asFeature(); - const auto ifm_shape = _ctx.at(ifm_index).shape().asFeature(); - - const int32_t kh = _ctx.at(kh_index).asScalar<int32_t>(); - const int32_t kw = _ctx.at(kw_index).asScalar<int32_t>(); - - const int32_t vstride = _ctx.at(vstride_index).asScalar<int32_t>(); - const int32_t hstride = _ctx.at(hstride_index).asScalar<int32_t>(); - - const PaddingCode padding_type = - static_cast<PaddingCode>(_ctx.at(padding_index).asScalar<int32_t>()); - - // Construct operation parameters - struct Param - { - model::operand::Index ofm_index; - model::operand::Index ifm_index; - - uint32_t kw; - uint32_t kh; - - neurun::util::Padding padding; - neurun::util::Stride stride; - - // TODO Add 'activation' field - }; - - Param param; - - param.ofm_index = ofm_index; - param.ifm_index = ifm_index; - - param.kh = kh; - param.kw = kw; - - param.stride.vertical = vstride; - param.stride.horizontal = hstride; - - param.padding = (padding_type == ANEURALNETWORKS_PADDING_SAME) - ? neurun::util::same_padding(ifm_shape, ofm_shape, param.stride, kw, kh) - : neurun::util::valid_padding(); - - VERBOSE(MaxPool2D) << "IFM_H: " << ifm_shape.H << std::endl; - VERBOSE(MaxPool2D) << "IFM_W: " << ifm_shape.W << std::endl; - VERBOSE(MaxPool2D) << "OFM_H: " << ofm_shape.H << std::endl; - VERBOSE(MaxPool2D) << "OFM_W: " << ofm_shape.W << std::endl; - VERBOSE(MaxPool2D) << "KER_H: " << kh << std::endl; - VERBOSE(MaxPool2D) << "KER_W: " << kw << std::endl; - VERBOSE(MaxPool2D) << "STRIDE_H: " << vstride << std::endl; - VERBOSE(MaxPool2D) << "STRIDE_W: " << hstride << std::endl; - VERBOSE(MaxPool2D) << "PAD(T): " << param.padding.top << std::endl; - VERBOSE(MaxPool2D) << "PAD(B): " << param.padding.bottom << std::endl; - VERBOSE(MaxPool2D) << "PAD(L): " << param.padding.left << std::endl; - VERBOSE(MaxPool2D) << "PAD(R): " << param.padding.right << std::endl; - - auto tensors = _tensor_builder; - - returnStage([tensors, param](IExecutionBuilder &builder) { - auto ofm_alloc = tensors->at(param.ofm_index).get(); - auto ifm_alloc = tensors->at(param.ifm_index).get(); - - ::arm_compute::PoolingLayerInfo info{::arm_compute::PoolingType::MAX, - ::arm_compute::Size2D{param.kw, param.kh}, - asPadStringInfo(param.padding, param.stride)}; - - std::unique_ptr<::arm_compute::CLPoolingLayer> fn{new ::arm_compute::CLPoolingLayer}; - - fn->configure(ifm_alloc->handle(), ofm_alloc->handle(), info); - - auto acl_fn = make_cl_function(std::move(fn)); - - builder.append((std::move(acl_fn))); - }); -} - -void StageGenerator::visit(const model::operation::AvgPool2DNode &node) -{ - const auto ofm_index{node.getOutputs().at(0)}; - const auto ifm_index{node.getInputs().at(model::operation::AvgPool2DNode::Input::INPUT)}; - - const auto kh_index{node.param().kh_index}; - const auto kw_index{node.param().kw_index}; - - const auto vstride_index{node.param().vstride_index}; - const auto hstride_index{node.param().hstride_index}; - - const auto padding_index{node.param().padding_index}; - - const auto ofm_shape = _ctx.at(ofm_index).shape().asFeature(); - const auto ifm_shape = _ctx.at(ifm_index).shape().asFeature(); - - const int32_t kh = _ctx.at(kh_index).asScalar<int32_t>(); - const int32_t kw = _ctx.at(kw_index).asScalar<int32_t>(); - - const int32_t vstride = _ctx.at(vstride_index).asScalar<int32_t>(); - const int32_t hstride = _ctx.at(hstride_index).asScalar<int32_t>(); - - const PaddingCode padding_type = - static_cast<PaddingCode>(_ctx.at(padding_index).asScalar<int32_t>()); - - assert((ANEURALNETWORKS_PADDING_SAME == padding_type) || - (ANEURALNETWORKS_PADDING_VALID == padding_type)); - - // Construct operation parameters - struct Param - { - model::operand::Index ofm_index; - model::operand::Index ifm_index; - - uint32_t kw; - uint32_t kh; - - neurun::util::Padding padding; - neurun::util::Stride stride; - - // TODO Add 'activation' field - }; - - Param param; - - param.ofm_index = ofm_index; - param.ifm_index = ifm_index; - - param.kh = kh; - param.kw = kw; - - param.stride.vertical = vstride; - param.stride.horizontal = hstride; - - param.padding = (padding_type == ANEURALNETWORKS_PADDING_SAME) - ? neurun::util::same_padding(ifm_shape, ofm_shape, param.stride, kw, kh) - : neurun::util::valid_padding(); - - VERBOSE(AvgPool2D) << "IFM_H: " << ifm_shape.H << std::endl; - VERBOSE(AvgPool2D) << "IFM_W: " << ifm_shape.W << std::endl; - VERBOSE(AvgPool2D) << "OFM_H: " << ofm_shape.H << std::endl; - VERBOSE(AvgPool2D) << "OFM_W: " << ofm_shape.W << std::endl; - VERBOSE(AvgPool2D) << "KER_H: " << kh << std::endl; - VERBOSE(AvgPool2D) << "KER_W: " << kw << std::endl; - VERBOSE(AvgPool2D) << "STRIDE_H: " << vstride << std::endl; - VERBOSE(AvgPool2D) << "STRIDE_W: " << hstride << std::endl; - VERBOSE(AvgPool2D) << "PAD: " << neurun::util::to_string(padding_type) << std::endl; - VERBOSE(AvgPool2D) << "PAD(T): " << param.padding.top << std::endl; - VERBOSE(AvgPool2D) << "PAD(B): " << param.padding.bottom << std::endl; - VERBOSE(AvgPool2D) << "PAD(L): " << param.padding.left << std::endl; - VERBOSE(AvgPool2D) << "PAD(R): " << param.padding.right << std::endl; - - auto tensors = _tensor_builder; - - returnStage([tensors, param](IExecutionBuilder &builder) { - auto ofm_alloc = tensors->at(param.ofm_index).get(); - auto ifm_alloc = tensors->at(param.ifm_index).get(); - - ::arm_compute::PoolingLayerInfo info{ - ::arm_compute::PoolingType::AVG, ::arm_compute::Size2D{param.kw, param.kh}, - asPadStringInfo(param.padding, param.stride), true /* exclude_padding */}; - - std::unique_ptr<::arm_compute::CLPoolingLayer> fn{new ::arm_compute::CLPoolingLayer}; - - fn->configure(ifm_alloc->handle(), ofm_alloc->handle(), info); - - auto acl_fn = make_cl_function(std::move(fn)); - - builder.append((std::move(acl_fn))); - }); -} - -void StageGenerator::visit(const model::operation::ConcatNode &node) -{ - const auto ofm_index{node.getOutputs().at(0)}; - const auto axis_index{node.param().axis_index}; - - struct Param - { - model::operand::Index output_index; - std::vector<model::operand::Index> input_indexes; - - int32_t axis; - }; - - Param param; - - param.output_index = ofm_index; - for (const auto &e : node.getInputs()) - { - param.input_indexes.emplace_back(e); - } - param.axis = _ctx.at(axis_index).asScalar<int32_t>(); - - auto tensors = _tensor_builder; - - returnStage([tensors, param](IExecutionBuilder &builder) { - // If tensor allocator allocate as subtensor - bool canEliminate = true; - for (auto ifm_ind : param.input_indexes) - { - if (!tensors->isSubTensorOf(param.output_index, ifm_ind)) - { - canEliminate = false; - break; - } - } - if (canEliminate) - { - // If concat eliminated, return with nothing to do - return; - } - - auto output_alloc = tensors->at(param.output_index).get(); - - std::vector<::neurun::backend::acl_cl::operand::ICLTensor *> input_allocs; - for (auto ifm_ind : param.input_indexes) - { - input_allocs.emplace_back( - dynamic_cast<::neurun::backend::acl_cl::operand::CLTensor *>(tensors->at(ifm_ind).get())); - } - - std::unique_ptr<::neurun::kernel::acl_cl::ConcatLayer> fn{ - new ::neurun::kernel::acl_cl::ConcatLayer}; - - fn->configure(input_allocs, param.axis, - dynamic_cast<::neurun::backend::acl_cl::operand::CLTensor *>(output_alloc)); - - auto acl_fn = make_cl_function(std::move(fn)); - - builder.append(std::move(acl_fn)); - }); -} - -void StageGenerator::visit(const model::operation::FullyConnectedNode &node) -{ - using model::operation::FullyConnectedNode; - - const auto output_index{node.getOutputs().at(0)}; - const auto input_index{node.getInputs().at(FullyConnectedNode::Input::INPUT)}; - const auto weight_index{node.getInputs().at(FullyConnectedNode::Input::WEIGHT)}; - const auto bias_index{node.getInputs().at(FullyConnectedNode::Input::BIAS)}; - const auto activation_index{node.param().activation_index}; - - // Construct operation parameters - struct Param - { - model::operand::Index output_index; - - model::operand::Index input_index; - model::operand::Index weight_index; - model::operand::Index bias_index; - - FuseCode activation; - }; - - Param param; - - param.output_index = output_index; - param.input_index = input_index; - param.weight_index = weight_index; - param.bias_index = bias_index; - - param.activation = static_cast<FuseCode>(_ctx.at(activation_index).asScalar<int32_t>()); - - auto tensors = _tensor_builder; - - returnStage([tensors, param](IExecutionBuilder &builder) { - auto output_alloc = tensors->at(param.output_index).get(); - auto input_alloc = tensors->at(param.input_index).get(); - auto weight_alloc = tensors->at(param.weight_index).get(); - auto bias_alloc = tensors->at(param.bias_index).get(); - - auto fn = make_layer<::arm_compute::CLFullyConnectedLayer>(); - - fn->configure(input_alloc->handle(), weight_alloc->handle(), bias_alloc->handle(), - output_alloc->handle()); - - auto acl_fn = make_cl_function(std::move(fn)); - - builder.append(std::move(acl_fn)); - - ActivationBuilder{builder}.append(param.activation, output_alloc->handle()); - }); -} - -void StageGenerator::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)}; - - struct Param - { - model::operand::Index output_index; - model::operand::Index input_index; - }; - - Param param; - - param.output_index = output_index; - param.input_index = input_index; - - auto tensors = _tensor_builder; - - 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::CLReshapeLayer>(); - - 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::SoftmaxNode &node) -{ - const auto output_index{node.getOutputs().at(0)}; - const auto input_index{node.getInputs().at(model::operation::SoftmaxNode::Input::INPUT)}; - const auto scale_index{node.param().scale_index}; - - assert(_ctx.at(scale_index).shape().rank() == 0); - - struct Param - { - model::operand::Index output_index; - model::operand::Index input_index; - float scale; - }; - - Param param; - - param.output_index = output_index; - param.input_index = input_index; - param.scale = _ctx.at(scale_index).asScalar<float>(); - - auto tensors = _tensor_builder; - - 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::CLSoftmaxLayer>(); - - fn->configure(input_alloc->handle(), output_alloc->handle(), param.scale); - - auto acl_fn = make_cl_function(std::move(fn)); - - builder.append(std::move(acl_fn)); - }); -} - -void StageGenerator::visit(const model::operation::PermuteNode & /* node */) -{ - throw "Unsupported"; -} - -void StageGenerator::visit(const model::operation::AddNode &) -{ - VERBOSE(Add) << "generate CPU Add" << std::endl; - - throw std::runtime_error("NYI"); -} - -} // namespace acl_cl -} // namespace backend -} // namespace neurun |