From 6a14adb2faefd2f4638647595dfdef12e29f8a01 Mon Sep 17 00:00:00 2001 From: Pablo Tello Date: Tue, 5 Mar 2019 17:33:08 +0000 Subject: COMPMID-1932: Implement CLHeightConcatenateLayer. Change-Id: I244ff2352c3c9620148dab6475aee62b218b96ef Signed-off-by: Pablo Tello Reviewed-on: https://review.mlplatform.org/c/871 Tested-by: Arm Jenkins Comments-Addressed: Arm Jenkins Reviewed-by: Gian Marco Iodice --- src/runtime/CL/functions/CLConcatenateLayer.cpp | 105 ++++++++++++++++++++++-- 1 file changed, 98 insertions(+), 7 deletions(-) (limited to 'src/runtime/CL') diff --git a/src/runtime/CL/functions/CLConcatenateLayer.cpp b/src/runtime/CL/functions/CLConcatenateLayer.cpp index 018c674c83..13164fdff9 100644 --- a/src/runtime/CL/functions/CLConcatenateLayer.cpp +++ b/src/runtime/CL/functions/CLConcatenateLayer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 ARM Limited. + * Copyright (c) 2018-2019 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -23,6 +23,9 @@ */ #include "arm_compute/runtime/CL/functions/CLConcatenateLayer.h" +#include "arm_compute/core/CL/kernels/CLHeightConcatenateLayerKernel.h" +#include "arm_compute/core/utils/misc/ShapeCalculator.h" +#include "arm_compute/runtime/CL/CLScheduler.h" #include "arm_compute/runtime/CL/functions/CLDepthConcatenateLayer.h" #include "arm_compute/runtime/CL/functions/CLWidthConcatenateLayer.h" @@ -35,15 +38,74 @@ namespace arm_compute { CLConcatenateLayer::CLConcatenateLayer() - : _concat_function(nullptr) + : _concat_function(nullptr), + _hconcat_kernels(), + _num_inputs(0), + _axis(Window::DimX) { } +Status CLConcatenateLayer::validate_h_concatenate(const std::vector &inputs_vector, const ITensorInfo *output) // NOLINT +{ + const unsigned int num_inputs = inputs_vector.size(); + + ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(output); + ARM_COMPUTE_RETURN_ERROR_ON(num_inputs < 2); + + // Output auto inizialitation if not yet initialized + TensorInfo tmp_output_info = *output->clone(); + const TensorShape output_shape = arm_compute::misc::shape_calculator::calculate_concatenate_shape(inputs_vector, Window::DimY); + auto_init_if_empty(tmp_output_info, output_shape, 1, inputs_vector[0]->data_type()); + + unsigned int height_offset = 0; + // Validate generic case of WidthConcatenate kernel + for(const auto &input : inputs_vector) + { + ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input); + ARM_COMPUTE_RETURN_ON_ERROR(CLHeightConcatenateLayerKernel::validate(input, height_offset, &tmp_output_info)); + height_offset += input->dimension(Window::DimY); + } + + return Status{}; +} + +void CLConcatenateLayer::configure_h_concatenate(std::vector inputs_vector, ICLTensor *output) // NOLINT +{ + _num_inputs = inputs_vector.size(); + + std::vector inputs_vector_info(inputs_vector.size()); + std::transform(inputs_vector.begin(), inputs_vector.end(), inputs_vector_info.begin(), [](ICLTensor * t) + { + ARM_COMPUTE_ERROR_ON_NULLPTR(t); + return t->info(); + }); + + const TensorShape output_shape = arm_compute::misc::shape_calculator::calculate_concatenate_shape(inputs_vector, Window::DimY); + + // Output auto inizialitation if not yet initialized + auto_init_if_empty(*output->info(), output_shape, 1, inputs_vector[0]->info()->data_type()); + + ARM_COMPUTE_ERROR_THROW_ON(CLConcatenateLayer::validate_h_concatenate(inputs_vector_info, output->info())); + + // Configure generic case WidthConcatenate kernels + _hconcat_kernels = arm_compute::support::cpp14::make_unique(_num_inputs); + + unsigned int height_offset = 0; + unsigned int i = 0; + std::transform(inputs_vector.begin(), inputs_vector.end(), inputs_vector.begin(), [&](ICLTensor * t) + { + auto &kernel = _hconcat_kernels[i++]; + kernel.configure(t, height_offset, output); + height_offset += t->info()->dimension(Window::DimY); + return t; + }); +} + void CLConcatenateLayer::configure(const std::vector &inputs_vector, ICLTensor *output, DataLayoutDimension axis) { ARM_COMPUTE_ERROR_ON(output == nullptr); - - switch(get_data_layout_dimension_index(output->info()->data_layout(), axis)) + _axis = get_data_layout_dimension_index(output->info()->data_layout(), axis); + switch(_axis) { case 0: { @@ -52,6 +114,11 @@ void CLConcatenateLayer::configure(const std::vector &inputs_vector _concat_function = std::move(func); break; } + case 1: + { + configure_h_concatenate(inputs_vector, output); + break; + } case 2: { auto func = support::cpp14::make_unique(); @@ -60,7 +127,7 @@ void CLConcatenateLayer::configure(const std::vector &inputs_vector break; } default: - ARM_COMPUTE_ERROR("Concatenation is supported across width and depth only!"); + ARM_COMPUTE_ERROR("Concatenation is supported across width, height and depth only!"); } } @@ -73,6 +140,9 @@ Status CLConcatenateLayer::validate(const std::vector &inputs_vec case 0: ARM_COMPUTE_RETURN_ON_ERROR(CLWidthConcatenateLayer::validate(inputs_vector, output)); break; + case 1: + ARM_COMPUTE_RETURN_ON_ERROR(CLConcatenateLayer::validate_h_concatenate(inputs_vector, output)); + break; case 2: ARM_COMPUTE_RETURN_ON_ERROR(CLDepthConcatenateLayer::validate(inputs_vector, output)); break; @@ -84,7 +154,28 @@ Status CLConcatenateLayer::validate(const std::vector &inputs_vec void CLConcatenateLayer::run() { - ARM_COMPUTE_ERROR_ON(_concat_function == nullptr); - _concat_function->run(); + switch(_axis) + { + case 0: + case 2: + { + ARM_COMPUTE_ERROR_ON(_concat_function == nullptr); + _concat_function->run(); + break; + } + case 1: + { + for(unsigned int i = 0; i < _num_inputs; ++i) + { + CLScheduler::get().enqueue(_hconcat_kernels[i], true); + } + break; + } + default: + { + ARM_COMPUTE_ERROR("Axis not supported"); + break; + } + } } } // namespace arm_compute -- cgit v1.2.1