From 3dd5b6884a65c06bcb9d15589ee2dc2978e3b336 Mon Sep 17 00:00:00 2001 From: Pablo Tello Date: Mon, 4 Mar 2019 14:14:02 +0000 Subject: COMPMID-1933: Implement NEHeightConcatenateLayer. Added support to concactenate tensors along the Y axis in NEConcatenateLayer. Change-Id: Ib714bfcf9954cc35918efa7d52fc9164bb08bdf6 Signed-off-by: Pablo Tello Reviewed-on: https://review.mlplatform.org/c/841 Reviewed-by: Gian Marco Iodice Reviewed-by: Georgios Pinitas Tested-by: Arm Jenkins Comments-Addressed: Arm Jenkins --- tests/datasets/ShapeDatasets.h | 6 +- tests/validation/CL/WidthConcatenateLayer.cpp | 48 +++--- tests/validation/Helpers.cpp | 13 +- tests/validation/Helpers.h | 7 +- tests/validation/NEON/HeightConcatenateLayer.cpp | 131 +++++++++++++++ tests/validation/NEON/WidthConcatenateLayer.cpp | 35 ++-- .../validation/fixtures/ConcatenateLayerFixture.h | 183 +++++++++++++++++++++ tests/validation/fixtures/LSTMLayerFixture.h | 4 +- .../fixtures/WidthConcatenateLayerFixture.h | 171 ------------------- tests/validation/reference/ConcatenateLayer.cpp | 131 +++++++++++++++ tests/validation/reference/ConcatenateLayer.h | 45 +++++ .../validation/reference/WidthConcatenateLayer.cpp | 102 ------------ tests/validation/reference/WidthConcatenateLayer.h | 45 ----- 13 files changed, 555 insertions(+), 366 deletions(-) create mode 100644 tests/validation/NEON/HeightConcatenateLayer.cpp create mode 100644 tests/validation/fixtures/ConcatenateLayerFixture.h delete mode 100644 tests/validation/fixtures/WidthConcatenateLayerFixture.h create mode 100644 tests/validation/reference/ConcatenateLayer.cpp create mode 100644 tests/validation/reference/ConcatenateLayer.h delete mode 100644 tests/validation/reference/WidthConcatenateLayer.cpp delete mode 100644 tests/validation/reference/WidthConcatenateLayer.h (limited to 'tests') diff --git a/tests/datasets/ShapeDatasets.h b/tests/datasets/ShapeDatasets.h index fddc7731fe..b6923c15c9 100644 --- a/tests/datasets/ShapeDatasets.h +++ b/tests/datasets/ShapeDatasets.h @@ -732,11 +732,11 @@ public: } }; -/** Data set containing tensor shapes for WidthConcatenateLayer. */ -class WidthConcatenateLayerShapes final : public ShapeDataset +/** Data set containing tensor shapes for ConcatenateLayer. */ +class ConcatenateLayerShapes final : public ShapeDataset { public: - WidthConcatenateLayerShapes() + ConcatenateLayerShapes() : ShapeDataset("Shape", { TensorShape{ 232U, 65U, 3U }, diff --git a/tests/validation/CL/WidthConcatenateLayer.cpp b/tests/validation/CL/WidthConcatenateLayer.cpp index 647e0413a1..493320b9ad 100644 --- a/tests/validation/CL/WidthConcatenateLayer.cpp +++ b/tests/validation/CL/WidthConcatenateLayer.cpp @@ -24,14 +24,14 @@ #include "arm_compute/core/Types.h" #include "arm_compute/runtime/CL/CLTensor.h" #include "arm_compute/runtime/CL/CLTensorAllocator.h" -#include "arm_compute/runtime/CL/functions/CLWidthConcatenateLayer.h" +#include "arm_compute/runtime/CL/functions/CLConcatenateLayer.h" #include "tests/CL/CLAccessor.h" #include "tests/datasets/ShapeDatasets.h" #include "tests/framework/Asserts.h" #include "tests/framework/Macros.h" #include "tests/framework/datasets/Datasets.h" #include "tests/validation/Validation.h" -#include "tests/validation/fixtures/WidthConcatenateLayerFixture.h" +#include "tests/validation/fixtures/ConcatenateLayerFixture.h" namespace arm_compute { @@ -72,8 +72,7 @@ DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip( inputs_vector_info_raw.emplace_back(&input); } - bool is_valid = bool(CLWidthConcatenateLayer::validate(inputs_vector_info_raw, - &output_info.clone()->set_is_resizable(false))); + bool is_valid = bool(CLConcatenateLayer::validate(inputs_vector_info_raw,&output_info.clone()->set_is_resizable(false),DataLayoutDimension::WIDTH )); ARM_COMPUTE_EXPECT(is_valid == expected, framework::LogLevel::ERRORS); } // clang-format on @@ -93,26 +92,30 @@ TEST_CASE(Configuration, framework::DatasetMode::ALL) ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); // Create and configure function - CLWidthConcatenateLayer concat_layer; + CLConcatenateLayer concat_layer; - concat_layer.configure({ &src1, &src2, &src3 }, &dst); + concat_layer.configure({ &src1, &src2, &src3 }, &dst, DataLayoutDimension::WIDTH); } template -using CLWidthConcatenateLayerFixture = WidthConcatenateLayerValidationFixture; +using CLWidthConcatenateLayerFixture = ConcatenateLayerValidationFixture; TEST_SUITE(Float) TEST_SUITE(FP16) -FIXTURE_DATA_TEST_CASE(RunSmall, CLWidthConcatenateLayerFixture, framework::DatasetMode::PRECOMMIT, combine(concat(datasets::Small2DShapes(), datasets::Tiny4DShapes()), +FIXTURE_DATA_TEST_CASE(RunSmall, CLWidthConcatenateLayerFixture, framework::DatasetMode::PRECOMMIT, combine(combine(concat(datasets::Small2DShapes(), datasets::Tiny4DShapes()), framework::dataset::make("DataType", - DataType::F16))) + DataType::F16)), + framework::dataset::make("Axis", 0))) + { // Validate output validate(CLAccessor(_target), _reference); } -FIXTURE_DATA_TEST_CASE(RunLarge, CLWidthConcatenateLayerFixture, framework::DatasetMode::NIGHTLY, combine(concat(datasets::Large2DShapes(), datasets::Small4DShapes()), - framework::dataset::make("DataType", - DataType::F16))) +FIXTURE_DATA_TEST_CASE(RunLarge, CLWidthConcatenateLayerFixture, framework::DatasetMode::NIGHTLY, combine(combine(concat(datasets::Large2DShapes(), datasets::Small4DShapes()), + framework::dataset::make("DataType", + DataType::F16)), + framework::dataset::make("Axis", 0))) + { // Validate output validate(CLAccessor(_target), _reference); @@ -120,15 +123,18 @@ FIXTURE_DATA_TEST_CASE(RunLarge, CLWidthConcatenateLayerFixture, framework TEST_SUITE_END() TEST_SUITE(FP32) -FIXTURE_DATA_TEST_CASE(RunSmall, CLWidthConcatenateLayerFixture, framework::DatasetMode::PRECOMMIT, combine(concat(datasets::Small2DShapes(), datasets::Tiny4DShapes()), +FIXTURE_DATA_TEST_CASE(RunSmall, CLWidthConcatenateLayerFixture, framework::DatasetMode::PRECOMMIT, combine(combine(concat(datasets::Small2DShapes(), datasets::Tiny4DShapes()), framework::dataset::make("DataType", - DataType::F32))) + DataType::F32)), + framework::dataset::make("Axis", 0))) + { // Validate output validate(CLAccessor(_target), _reference); } -FIXTURE_DATA_TEST_CASE(RunLarge, CLWidthConcatenateLayerFixture, framework::DatasetMode::NIGHTLY, combine(datasets::WidthConcatenateLayerShapes(), framework::dataset::make("DataType", - DataType::F32))) +FIXTURE_DATA_TEST_CASE(RunLarge, CLWidthConcatenateLayerFixture, framework::DatasetMode::NIGHTLY, combine(combine(datasets::ConcatenateLayerShapes(), framework::dataset::make("DataType", + DataType::F32)), + framework::dataset::make("Axis", 0))) { // Validate output validate(CLAccessor(_target), _reference); @@ -138,15 +144,17 @@ TEST_SUITE_END() TEST_SUITE(Quantized) TEST_SUITE(QASYMM8) -FIXTURE_DATA_TEST_CASE(RunSmall, CLWidthConcatenateLayerFixture, framework::DatasetMode::PRECOMMIT, combine(concat(datasets::Small2DShapes(), datasets::Tiny4DShapes()), +FIXTURE_DATA_TEST_CASE(RunSmall, CLWidthConcatenateLayerFixture, framework::DatasetMode::PRECOMMIT, combine(combine(concat(datasets::Small2DShapes(), datasets::Tiny4DShapes()), framework::dataset::make("DataType", - DataType::QASYMM8))) + DataType::QASYMM8)), + framework::dataset::make("Axis", 0))) { // Validate output validate(CLAccessor(_target), _reference); } -FIXTURE_DATA_TEST_CASE(RunLarge, CLWidthConcatenateLayerFixture, framework::DatasetMode::NIGHTLY, combine(datasets::WidthConcatenateLayerShapes(), framework::dataset::make("DataType", - DataType::QASYMM8))) +FIXTURE_DATA_TEST_CASE(RunLarge, CLWidthConcatenateLayerFixture, framework::DatasetMode::NIGHTLY, combine(combine(datasets::ConcatenateLayerShapes(), framework::dataset::make("DataType", + DataType::QASYMM8)), + framework::dataset::make("Axis", 0))) { // Validate output validate(CLAccessor(_target), _reference); diff --git a/tests/validation/Helpers.cpp b/tests/validation/Helpers.cpp index 11c454ea67..e9612f2223 100644 --- a/tests/validation/Helpers.cpp +++ b/tests/validation/Helpers.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 ARM Limited. + * Copyright (c) 2017-2019 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -98,17 +98,18 @@ TensorShape calculate_depth_concatenate_shape(const std::vector &in return out_shape; } -TensorShape calculate_width_concatenate_shape(const std::vector &input_shapes) +TensorShape calculate_concatenate_shape(const std::vector &input_shapes, size_t axis) { ARM_COMPUTE_ERROR_ON(input_shapes.empty()); - TensorShape out_shape = input_shapes[0]; + ARM_COMPUTE_ERROR_ON(axis >= out_shape.num_dimensions()); - int width = std::accumulate(input_shapes.begin(), input_shapes.end(), 0, [](int sum, const TensorShape & shape) + const int new_size = std::accumulate(input_shapes.begin(), input_shapes.end(), 0, [&](int sum, const TensorShape & shape) { - return sum + shape.x(); + ARM_COMPUTE_ERROR_ON(axis >= shape.num_dimensions()); + return sum + shape[axis]; }); - out_shape.set(0, width); + out_shape.set(axis, new_size); return out_shape; } diff --git a/tests/validation/Helpers.h b/tests/validation/Helpers.h index 4d1d21440d..2e8c667a41 100644 --- a/tests/validation/Helpers.h +++ b/tests/validation/Helpers.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 ARM Limited. + * Copyright (c) 2017-2019 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -128,13 +128,14 @@ void fill_mask_from_pattern(uint8_t *mask, int cols, int rows, MatrixPattern pat */ TensorShape calculate_depth_concatenate_shape(const std::vector &input_shapes); -/** Calculate output tensor shape give a vector of input tensor to concatenate +/** Calculate output tensor shape for the concatenate operation along a given axis * * @param[in] input_shapes Shapes of the tensors to concatenate across width. + * @param[in] axis Axis to use for the concatenate operation * * @return The shape of output concatenated tensor. */ -TensorShape calculate_width_concatenate_shape(const std::vector &input_shapes); +TensorShape calculate_concatenate_shape(const std::vector &input_shapes, size_t axis); /** Parameters of Harris Corners algorithm. */ struct HarrisCornersParameters diff --git a/tests/validation/NEON/HeightConcatenateLayer.cpp b/tests/validation/NEON/HeightConcatenateLayer.cpp new file mode 100644 index 0000000000..f5400f9246 --- /dev/null +++ b/tests/validation/NEON/HeightConcatenateLayer.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2019 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "arm_compute/core/Types.h" +#include "arm_compute/runtime/NEON/functions/NEConcatenateLayer.h" +#include "arm_compute/runtime/Tensor.h" +#include "arm_compute/runtime/TensorAllocator.h" +#include "tests/NEON/Accessor.h" +#include "tests/datasets/ShapeDatasets.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Macros.h" +#include "tests/framework/datasets/Datasets.h" +#include "tests/validation/Validation.h" +#include "tests/validation/fixtures/ConcatenateLayerFixture.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +TEST_SUITE(NEON) +TEST_SUITE(HeightConcatenateLayer) + +// *INDENT-OFF* +// clang-format off +DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip( + framework::dataset::make("InputInfo1", { TensorInfo(TensorShape(23U, 15U, 5U), 1, DataType::F32), // Mismatching data type input/output + TensorInfo(TensorShape(22U, 27U, 5U), 1, DataType::F32), // Mismatching y dimension + TensorInfo(TensorShape(11U, 25U, 5U), 1, DataType::F32), // Mismatching total height + TensorInfo(TensorShape(16U, 25U, 5U), 1, DataType::F32) + }), + framework::dataset::make("InputInfo2", { TensorInfo(TensorShape(23U, 15U, 4U), 1, DataType::F32), + TensorInfo(TensorShape(22U, 127U, 5U), 1, DataType::F32), + TensorInfo(TensorShape(11U, 26U, 5U), 1, DataType::F32), + TensorInfo(TensorShape(16U, 25U, 5U), 1, DataType::F32) + })), + framework::dataset::make("OutputInfo", { TensorInfo(TensorShape(23U, 30U, 5U), 1, DataType::F16), + TensorInfo(TensorShape(22U, 12U, 5U), 1, DataType::F32), + TensorInfo(TensorShape(11U, 7U, 5U), 1, DataType::F32), + TensorInfo(TensorShape(16U, 50U, 5U), 1, DataType::F32) + })), + framework::dataset::make("Expected", { false, false, false, true })), + input_info1, input_info2, output_info,expected) +{ + std::vector inputs_vector_info; + inputs_vector_info.emplace_back(std::move(input_info1)); + inputs_vector_info.emplace_back(std::move(input_info2)); + + std::vector inputs_vector_info_raw; + for(auto &input : inputs_vector_info) + { + inputs_vector_info_raw.emplace_back(&input); + } + + bool is_valid = bool(NEConcatenateLayer::validate(inputs_vector_info_raw, &output_info.clone()->set_is_resizable(false), DataLayoutDimension::HEIGHT)); + ARM_COMPUTE_EXPECT(is_valid == expected, framework::LogLevel::ERRORS); +} +// clang-format on +// *INDENT-ON* + +template +using NEHeightConcatenateLayerFixture = ConcatenateLayerValidationFixture; + +TEST_SUITE(Float) +TEST_SUITE(FP32) +FIXTURE_DATA_TEST_CASE(RunSmall, NEHeightConcatenateLayerFixture, framework::DatasetMode::PRECOMMIT, combine(combine(concat(datasets::Small2DShapes(), datasets::Tiny4DShapes()), + framework::dataset::make("DataType", + DataType::F32)), + framework::dataset::make("Axis", 1))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEHeightConcatenateLayerFixture, framework::DatasetMode::NIGHTLY, combine(combine(datasets::ConcatenateLayerShapes(), framework::dataset::make("DataType", + DataType::F32)), + framework::dataset::make("Axis", 1))) + +{ + // Validate output + validate(Accessor(_target), _reference); +} +TEST_SUITE_END() // FP32 +TEST_SUITE_END() // Float + +TEST_SUITE(Quantized) +TEST_SUITE(QASYMM8) +FIXTURE_DATA_TEST_CASE(RunSmall, NEHeightConcatenateLayerFixture, framework::DatasetMode::PRECOMMIT, combine(combine(concat(datasets::Small2DShapes(), datasets::Tiny4DShapes()), + framework::dataset::make("DataType", + DataType::QASYMM8)), + framework::dataset::make("Axis", 1))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEHeightConcatenateLayerFixture, framework::DatasetMode::NIGHTLY, combine(combine(datasets::ConcatenateLayerShapes(), + framework::dataset::make("DataType", + DataType::QASYMM8)), + framework::dataset::make("Axis", 1))) +{ + // Validate output + validate(Accessor(_target), _reference); +} +TEST_SUITE_END() // QASYMM8 +TEST_SUITE_END() // Quantized + +TEST_SUITE_END() +TEST_SUITE_END() +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/NEON/WidthConcatenateLayer.cpp b/tests/validation/NEON/WidthConcatenateLayer.cpp index 6e94e92d05..dba14ebb35 100644 --- a/tests/validation/NEON/WidthConcatenateLayer.cpp +++ b/tests/validation/NEON/WidthConcatenateLayer.cpp @@ -22,7 +22,7 @@ * SOFTWARE. */ #include "arm_compute/core/Types.h" -#include "arm_compute/runtime/NEON/functions/NEWidthConcatenateLayer.h" +#include "arm_compute/runtime/NEON/functions/NEConcatenateLayer.h" #include "arm_compute/runtime/Tensor.h" #include "arm_compute/runtime/TensorAllocator.h" #include "tests/NEON/Accessor.h" @@ -31,7 +31,7 @@ #include "tests/framework/Macros.h" #include "tests/framework/datasets/Datasets.h" #include "tests/validation/Validation.h" -#include "tests/validation/fixtures/WidthConcatenateLayerFixture.h" +#include "tests/validation/fixtures/ConcatenateLayerFixture.h" namespace arm_compute { @@ -72,27 +72,30 @@ DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip( inputs_vector_info_raw.emplace_back(&input); } - bool is_valid = bool(NEWidthConcatenateLayer::validate(inputs_vector_info_raw, - &output_info.clone()->set_is_resizable(false))); + bool is_valid = bool(NEConcatenateLayer::validate(inputs_vector_info_raw, + &output_info.clone()->set_is_resizable(false),DataLayoutDimension::WIDTH)); ARM_COMPUTE_EXPECT(is_valid == expected, framework::LogLevel::ERRORS); } // clang-format on // *INDENT-ON* - template -using NEWidthConcatenateLayerFixture = WidthConcatenateLayerValidationFixture; +using NEWidthConcatenateLayerFixture = ConcatenateLayerValidationFixture; TEST_SUITE(Float) TEST_SUITE(FP32) -FIXTURE_DATA_TEST_CASE(RunSmall, NEWidthConcatenateLayerFixture, framework::DatasetMode::PRECOMMIT, combine(concat(datasets::Small2DShapes(), datasets::Tiny4DShapes()), +FIXTURE_DATA_TEST_CASE(RunSmall, NEWidthConcatenateLayerFixture, framework::DatasetMode::PRECOMMIT, combine(combine(concat(datasets::Small2DShapes(), datasets::Tiny4DShapes()), framework::dataset::make("DataType", - DataType::F32))) + DataType::F32)), + framework::dataset::make("Axis", 0))) + { // Validate output validate(Accessor(_target), _reference); } -FIXTURE_DATA_TEST_CASE(RunLarge, NEWidthConcatenateLayerFixture, framework::DatasetMode::NIGHTLY, combine(datasets::WidthConcatenateLayerShapes(), framework::dataset::make("DataType", - DataType::F32))) +FIXTURE_DATA_TEST_CASE(RunLarge, NEWidthConcatenateLayerFixture, framework::DatasetMode::NIGHTLY, combine(combine(datasets::ConcatenateLayerShapes(), framework::dataset::make("DataType", + DataType::F32)), + framework::dataset::make("Axis", 0))) + { // Validate output validate(Accessor(_target), _reference); @@ -102,15 +105,19 @@ TEST_SUITE_END() TEST_SUITE(Quantized) TEST_SUITE(QASYMM8) -FIXTURE_DATA_TEST_CASE(RunSmall, NEWidthConcatenateLayerFixture, framework::DatasetMode::PRECOMMIT, combine(concat(datasets::Small2DShapes(), datasets::Tiny4DShapes()), +FIXTURE_DATA_TEST_CASE(RunSmall, NEWidthConcatenateLayerFixture, framework::DatasetMode::PRECOMMIT, combine(combine(concat(datasets::Small2DShapes(), datasets::Tiny4DShapes()), framework::dataset::make("DataType", - DataType::QASYMM8))) + DataType::QASYMM8)), + framework::dataset::make("Axis", 0))) + { // Validate output validate(Accessor(_target), _reference); } -FIXTURE_DATA_TEST_CASE(RunLarge, NEWidthConcatenateLayerFixture, framework::DatasetMode::NIGHTLY, combine(datasets::WidthConcatenateLayerShapes(), framework::dataset::make("DataType", - DataType::QASYMM8))) +FIXTURE_DATA_TEST_CASE(RunLarge, NEWidthConcatenateLayerFixture, framework::DatasetMode::NIGHTLY, combine(combine(datasets::ConcatenateLayerShapes(), framework::dataset::make("DataType", + DataType::QASYMM8)), + framework::dataset::make("Axis", 0))) + { // Validate output validate(Accessor(_target), _reference); diff --git a/tests/validation/fixtures/ConcatenateLayerFixture.h b/tests/validation/fixtures/ConcatenateLayerFixture.h new file mode 100644 index 0000000000..db09957c09 --- /dev/null +++ b/tests/validation/fixtures/ConcatenateLayerFixture.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2018-2019 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef ARM_COMPUTE_TEST_WIDTHCONCATENATE_LAYER_FIXTURE +#define ARM_COMPUTE_TEST_WIDTHCONCATENATE_LAYER_FIXTURE + +#include "arm_compute/core/TensorShape.h" +#include "arm_compute/core/Types.h" +#include "arm_compute/core/utils/misc/ShapeCalculator.h" +#include "tests/AssetsLibrary.h" +#include "tests/Globals.h" +#include "tests/IAccessor.h" +#include "tests/framework/Asserts.h" +#include "tests/framework/Fixture.h" +#include "tests/validation/Helpers.h" +#include "tests/validation/reference/ConcatenateLayer.h" + +#include + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +template +class ConcatenateLayerValidationFixture : public framework::Fixture +{ +public: + template + void setup(TensorShape shape, DataType data_type, unsigned int axis) + { + // Create input shapes + std::mt19937 gen(library->seed()); + std::uniform_int_distribution<> num_dis(2, 8); + std::uniform_int_distribution<> offset_dis(0, 20); + + const int num_tensors = num_dis(gen); + + std::vector shapes(num_tensors, shape); + + // vector holding the quantization info: + // the last element is the output quantization info + // all other elements are the quantization info for the input tensors + std::vector qinfo(num_tensors + 1, QuantizationInfo()); + for(auto &qi : qinfo) + { + qi = QuantizationInfo(1.f / 255.f, offset_dis(gen)); + } + std::bernoulli_distribution mutate_dis(0.5f); + std::uniform_real_distribution<> change_dis(-0.25f, 0.f); + + // Generate more shapes based on the input + for(auto &s : shapes) + { + // Randomly change the first dimension + if(mutate_dis(gen)) + { + // Decrease the dimension by a small percentage. Don't increase + // as that could make tensor too large. + s.set(axis, s[axis] + 2 * static_cast(s[axis] * change_dis(gen))); + } + } + + _target = compute_target(shapes, qinfo, data_type, axis); + _reference = compute_reference(shapes, qinfo, data_type, axis); + } + +protected: + template + void fill(U &&tensor, int i) + { + library->fill_tensor_uniform(tensor, i); + } + + TensorType compute_target(const std::vector &shapes, const std::vector &qinfo, DataType data_type, unsigned int axis) + { + std::vector srcs; + std::vector src_ptrs; + + // Create tensors + srcs.reserve(shapes.size()); + + for(size_t j = 0; j < shapes.size(); ++j) + { + srcs.emplace_back(create_tensor(shapes[j], data_type, 1, qinfo[j])); + src_ptrs.emplace_back(&srcs.back()); + } + + const TensorShape dst_shape = misc::shape_calculator::calculate_concatenate_shape(src_ptrs, axis); + TensorType dst = create_tensor(dst_shape, data_type, 1, qinfo[shapes.size()]); + + // Create and configure function + FunctionType concat; + switch(axis) + { + case 0: + concat.configure(src_ptrs, &dst, DataLayoutDimension::WIDTH); + break; + case 1: + concat.configure(src_ptrs, &dst, DataLayoutDimension::HEIGHT); + break; + case 2: + concat.configure(src_ptrs, &dst, DataLayoutDimension::CHANNEL); + break; + default: + ARM_COMPUTE_ERROR("Not supported"); + break; + } + + for(auto &src : srcs) + { + ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); + } + + ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Allocate tensors + for(auto &src : srcs) + { + src.allocator()->allocate(); + ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS); + } + + dst.allocator()->allocate(); + ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); + + // Fill tensors + int i = 0; + for(auto &src : srcs) + { + fill(AccessorType(src), i++); + } + + // Compute function + concat.run(); + + return dst; + } + + SimpleTensor compute_reference(const std::vector &shapes, const std::vector &qinfo, DataType data_type, unsigned int axis) + { + std::vector> srcs; + + // Create and fill tensors + for(size_t j = 0; j < shapes.size(); ++j) + { + srcs.emplace_back(shapes[j], data_type, 1, qinfo[j]); + fill(srcs.back(), j); + } + + const TensorShape dst_shape = calculate_concatenate_shape(shapes, axis); + SimpleTensor dst{ dst_shape, data_type, 1, qinfo[shapes.size()] }; + return reference::concatenate_layer(srcs, dst, axis); + } + + TensorType _target{}; + SimpleTensor _reference{}; +}; +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* ARM_COMPUTE_TEST_WIDTHCONCATENATE_LAYER_FIXTURE */ diff --git a/tests/validation/fixtures/LSTMLayerFixture.h b/tests/validation/fixtures/LSTMLayerFixture.h index b30f1e534b..2cf83b8b3d 100644 --- a/tests/validation/fixtures/LSTMLayerFixture.h +++ b/tests/validation/fixtures/LSTMLayerFixture.h @@ -29,11 +29,11 @@ #include "tests/framework/Fixture.h" #include "tests/validation/reference/ActivationLayer.h" #include "tests/validation/reference/ArithmeticOperations.h" +#include "tests/validation/reference/ConcatenateLayer.h" #include "tests/validation/reference/FullyConnectedLayer.h" #include "tests/validation/reference/GEMM.h" #include "tests/validation/reference/PixelWiseMultiplication.h" #include "tests/validation/reference/Transpose.h" -#include "tests/validation/reference/WidthConcatenateLayer.h" namespace arm_compute { @@ -415,7 +415,7 @@ protected: scratch_inputs.emplace_back(std::move(cell_state_out)); scratch_inputs.emplace_back(std::move(forget_gate)); scratch_inputs.emplace_back(std::move(output)); - scratch = reference::widthconcatenate_layer(scratch_inputs, scratch); + scratch = reference::concatenate_layer(scratch_inputs, scratch, Window::DimX); _reference_scratch = std::move(scratch); return output_state_out; } diff --git a/tests/validation/fixtures/WidthConcatenateLayerFixture.h b/tests/validation/fixtures/WidthConcatenateLayerFixture.h deleted file mode 100644 index 47a03ed865..0000000000 --- a/tests/validation/fixtures/WidthConcatenateLayerFixture.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2018-2019 ARM Limited. - * - * SPDX-License-Identifier: MIT - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef ARM_COMPUTE_TEST_WIDTHCONCATENATE_LAYER_FIXTURE -#define ARM_COMPUTE_TEST_WIDTHCONCATENATE_LAYER_FIXTURE - -#include "arm_compute/core/TensorShape.h" -#include "arm_compute/core/Types.h" -#include "arm_compute/core/utils/misc/ShapeCalculator.h" -#include "tests/AssetsLibrary.h" -#include "tests/Globals.h" -#include "tests/IAccessor.h" -#include "tests/framework/Asserts.h" -#include "tests/framework/Fixture.h" -#include "tests/validation/Helpers.h" -#include "tests/validation/reference/WidthConcatenateLayer.h" - -#include - -namespace arm_compute -{ -namespace test -{ -namespace validation -{ -template -class WidthConcatenateLayerValidationFixture : public framework::Fixture -{ -public: - template - void setup(TensorShape shape, DataType data_type) - { - // Create input shapes - std::mt19937 gen(library->seed()); - std::uniform_int_distribution<> num_dis(2, 8); - std::uniform_int_distribution<> offset_dis(0, 20); - - const int num_tensors = num_dis(gen); - - std::vector shapes(num_tensors, shape); - - // vector holding the quantization info: - // the last element is the output quantization info - // all other elements are the quantization info for the input tensors - std::vector qinfo(num_tensors + 1, QuantizationInfo()); - for(auto &qi : qinfo) - { - qi = QuantizationInfo(1.f / 255.f, offset_dis(gen)); - } - std::bernoulli_distribution mutate_dis(0.5f); - std::uniform_real_distribution<> change_dis(-0.25f, 0.f); - - // Generate more shapes based on the input - for(auto &s : shapes) - { - // Randomly change the first dimension - if(mutate_dis(gen)) - { - // Decrease the dimension by a small percentage. Don't increase - // as that could make tensor too large. - s.set(0, s[0] + 2 * static_cast(s[0] * change_dis(gen))); - } - } - - _target = compute_target(shapes, qinfo, data_type); - _reference = compute_reference(shapes, qinfo, data_type); - } - -protected: - template - void fill(U &&tensor, int i) - { - library->fill_tensor_uniform(tensor, i); - } - - TensorType compute_target(std::vector shapes, const std::vector &qinfo, DataType data_type) - { - std::vector srcs; - std::vector src_ptrs; - - // Create tensors - srcs.reserve(shapes.size()); - - for(size_t j = 0; j < shapes.size(); ++j) - { - srcs.emplace_back(create_tensor(shapes[j], data_type, 1, qinfo[j])); - src_ptrs.emplace_back(&srcs.back()); - } - - TensorShape dst_shape = misc::shape_calculator::calculate_width_concatenate_shape(src_ptrs); - - TensorType dst = create_tensor(dst_shape, data_type, 1, qinfo[shapes.size()]); - - // Create and configure function - FunctionType width_concat; - width_concat.configure(src_ptrs, &dst); - - for(auto &src : srcs) - { - ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); - } - - ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); - - // Allocate tensors - for(auto &src : srcs) - { - src.allocator()->allocate(); - ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS); - } - - dst.allocator()->allocate(); - ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS); - - // Fill tensors - int i = 0; - for(auto &src : srcs) - { - fill(AccessorType(src), i++); - } - - // Compute function - width_concat.run(); - - return dst; - } - - SimpleTensor compute_reference(std::vector shapes, const std::vector &qinfo, DataType data_type) - { - std::vector> srcs; - - // Create and fill tensors - for(size_t j = 0; j < shapes.size(); ++j) - { - srcs.emplace_back(shapes[j], data_type, 1, qinfo[j]); - fill(srcs.back(), j); - } - - const TensorShape dst_shape = calculate_width_concatenate_shape(shapes); - SimpleTensor dst{ dst_shape, data_type, 1, qinfo[shapes.size()] }; - - return reference::widthconcatenate_layer(srcs, dst); - } - - TensorType _target{}; - SimpleTensor _reference{}; -}; -} // namespace validation -} // namespace test -} // namespace arm_compute -#endif /* ARM_COMPUTE_TEST_WIDTHCONCATENATE_LAYER_FIXTURE */ diff --git a/tests/validation/reference/ConcatenateLayer.cpp b/tests/validation/reference/ConcatenateLayer.cpp new file mode 100644 index 0000000000..1440878829 --- /dev/null +++ b/tests/validation/reference/ConcatenateLayer.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2019 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "ConcatenateLayer.h" + +#include "tests/validation/Helpers.h" +#include "tests/validation/reference/Permute.h" + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +namespace +{ +template +SimpleTensor widthconcatenate_layer(const std::vector> &srcs, SimpleTensor &dst) +{ + // Create reference + std::vector shapes; + for(const auto &src : srcs) + { + shapes.emplace_back(src.shape()); + } + // Compute reference + int width_offset = 0; + const int width_out = dst.shape().x(); + // Set output tensor to 0 + std::fill_n(dst.data(), dst.num_elements(), 0); + for(const auto &src : srcs) + { + ARM_COMPUTE_ERROR_ON(width_offset >= width_out); + + const int width = src.shape().x(); + const int height = src.shape().y(); + const int depth = src.shape().z(); + const int upper_dims = src.shape().total_size() / (width * height * depth); + + const T *src_ptr = src.data(); + T *dst_ptr = dst.data(); + + for(int u = 0; u < upper_dims; ++u) + { + for(int d = 0; d < depth; ++d) + { + for(int r = 0; r < height; ++r) + { + const int offset = u * height * depth + d * height + r; + if(src.data_type() == DataType::QASYMM8 && src.quantization_info() != dst.quantization_info()) + { + std::transform(src_ptr, src_ptr + width, dst_ptr + width_offset + offset * width_out, [src, dst](T t) + { + const float dequantized_input = src.quantization_info().dequantize(t); + return dst.quantization_info().quantize(dequantized_input, RoundingPolicy::TO_NEAREST_UP); + }); + src_ptr += width; + } + else + { + std::copy(src_ptr, src_ptr + width, dst_ptr + width_offset + offset * width_out); + src_ptr += width; + } + } + } + } + width_offset += width; + } + return dst; +} + +template SimpleTensor widthconcatenate_layer(const std::vector> &srcs, SimpleTensor &dst); +template SimpleTensor widthconcatenate_layer(const std::vector> &srcs, SimpleTensor &dst); +template SimpleTensor widthconcatenate_layer(const std::vector> &srcs, SimpleTensor &dst); +} // namespace + +template +SimpleTensor concatenate_layer(std::vector> &srcs, SimpleTensor &dst, unsigned int axis) +{ + switch(axis) + { + case Window::DimX: + { + return widthconcatenate_layer(srcs, dst); + } + case Window::DimY: + { + for(auto &t : srcs) + { + t = reference::permute(t, PermutationVector(1U, 0U)); + } + dst = reference::permute(dst, PermutationVector(1U, 0U)); + return reference::permute(widthconcatenate_layer(srcs, dst), PermutationVector(1U, 0U)); + } + default: + { + ARM_COMPUTE_ERROR("Not supported"); + return dst; + } + } +} + +template SimpleTensor concatenate_layer(std::vector> &srcs, SimpleTensor &dst, unsigned int axis); +template SimpleTensor concatenate_layer(std::vector> &srcs, SimpleTensor &dst, unsigned int axis); +template SimpleTensor concatenate_layer(std::vector> &srcs, SimpleTensor &dst, unsigned int axis); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute diff --git a/tests/validation/reference/ConcatenateLayer.h b/tests/validation/reference/ConcatenateLayer.h new file mode 100644 index 0000000000..14fd097eee --- /dev/null +++ b/tests/validation/reference/ConcatenateLayer.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_TEST_CONCATENATE_LAYER_H__ +#define __ARM_COMPUTE_TEST_CONCATENATE_LAYER_H__ + +#include "tests/SimpleTensor.h" + +#include + +namespace arm_compute +{ +namespace test +{ +namespace validation +{ +namespace reference +{ +template +SimpleTensor concatenate_layer(std::vector> &srcs, SimpleTensor &dst, unsigned int axis); +} // namespace reference +} // namespace validation +} // namespace test +} // namespace arm_compute +#endif /* __ARM_COMPUTE_TEST_CONCATENATE_LAYER_H__ */ diff --git a/tests/validation/reference/WidthConcatenateLayer.cpp b/tests/validation/reference/WidthConcatenateLayer.cpp deleted file mode 100644 index 38543393ce..0000000000 --- a/tests/validation/reference/WidthConcatenateLayer.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2018-2019 ARM Limited. - * - * SPDX-License-Identifier: MIT - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include "WidthConcatenateLayer.h" - -#include "tests/validation/Helpers.h" - -namespace arm_compute -{ -namespace test -{ -namespace validation -{ -namespace reference -{ -template -SimpleTensor widthconcatenate_layer(const std::vector> &srcs, SimpleTensor &dst) -{ - // Create reference - std::vector shapes; - - for(const auto &src : srcs) - { - shapes.emplace_back(src.shape()); - } - - // Compute reference - int width_offset = 0; - const int width_out = dst.shape().x(); - - // Set output tensor to 0 - std::fill_n(dst.data(), dst.num_elements(), 0); - - for(const auto &src : srcs) - { - ARM_COMPUTE_ERROR_ON(width_offset >= width_out); - - const int width = src.shape().x(); - const int height = src.shape().y(); - const int depth = src.shape().z(); - const int upper_dims = src.shape().total_size() / (width * height * depth); - - const T *src_ptr = src.data(); - T *dst_ptr = dst.data(); - - for(int u = 0; u < upper_dims; ++u) - { - for(int d = 0; d < depth; ++d) - { - for(int r = 0; r < height; ++r) - { - const int offset = u * height * depth + d * height + r; - if(src.data_type() == DataType::QASYMM8 && src.quantization_info() != dst.quantization_info()) - { - std::transform(src_ptr, src_ptr + width, dst_ptr + width_offset + offset * width_out, [src, dst](T t) - { - const float dequantized_input = src.quantization_info().dequantize(t); - return dst.quantization_info().quantize(dequantized_input, RoundingPolicy::TO_NEAREST_UP); - }); - src_ptr += width; - } - else - { - std::copy(src_ptr, src_ptr + width, dst_ptr + width_offset + offset * width_out); - src_ptr += width; - } - } - } - } - width_offset += width; - } - - return dst; -} - -template SimpleTensor widthconcatenate_layer(const std::vector> &srcs, SimpleTensor &dst); -template SimpleTensor widthconcatenate_layer(const std::vector> &srcs, SimpleTensor &dst); -template SimpleTensor widthconcatenate_layer(const std::vector> &srcs, SimpleTensor &dst); -} // namespace reference -} // namespace validation -} // namespace test -} // namespace arm_compute diff --git a/tests/validation/reference/WidthConcatenateLayer.h b/tests/validation/reference/WidthConcatenateLayer.h deleted file mode 100644 index 0f1f428f10..0000000000 --- a/tests/validation/reference/WidthConcatenateLayer.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2018-2019 ARM Limited. - * - * SPDX-License-Identifier: MIT - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef __ARM_COMPUTE_TEST_WIDTHCONCATENATE_LAYER_H__ -#define __ARM_COMPUTE_TEST_WIDTHCONCATENATE_LAYER_H__ - -#include "tests/SimpleTensor.h" - -#include - -namespace arm_compute -{ -namespace test -{ -namespace validation -{ -namespace reference -{ -template -SimpleTensor widthconcatenate_layer(const std::vector> &srcs, SimpleTensor &dst); -} // namespace reference -} // namespace validation -} // namespace test -} // namespace arm_compute -#endif /* __ARM_COMPUTE_TEST_WIDTHCONCATENATE_LAYER_H__ */ -- cgit v1.2.1