From 149203bc23d5c84fe1326d9dea4730750fab6710 Mon Sep 17 00:00:00 2001 From: Dana Zlotnik Date: Wed, 26 Jan 2022 12:38:03 +0200 Subject: Port MaxUnpoolingLayer kernel and add KernelSelect vaidation test Resolves COMPMID-4958 Change-Id: Ibed5155f2e3ece46635f6ea9617bf11cefc402b1 Signed-off-by: Dana Zlotnik Reviewed-on: https://review.mlplatform.org/c/ml/ComputeLibrary/+/7028 Tested-by: Arm Jenkins Reviewed-by: Giorgio Arena Comments-Addressed: Arm Jenkins --- Android.bp | 3 +- .../runtime/NEON/functions/NEMaxUnpoolingLayer.h | 9 +- docs/user_guide/release_version_and_change_log.dox | 2 +- filelist.json | 9 +- src/core/NEON/NEKernels.h | 1 - .../NEON/kernels/NEMaxUnpoolingLayerKernel.cpp | 171 --------------------- src/core/NEON/kernels/NEMaxUnpoolingLayerKernel.h | 96 ------------ src/cpu/kernels/CpuMaxUnpoolingLayerKernel.cpp | 148 ++++++++++++++++++ src/cpu/kernels/CpuMaxUnpoolingLayerKernel.h | 92 +++++++++++ src/cpu/kernels/maxunpool/generic/neon/fp16.cpp | 4 +- src/cpu/kernels/maxunpool/generic/neon/fp32.cpp | 4 +- src/cpu/kernels/maxunpool/generic/neon/impl.cpp | 10 +- src/cpu/kernels/maxunpool/generic/neon/impl.h | 2 +- src/cpu/kernels/maxunpool/generic/neon/qasymm8.cpp | 4 +- .../maxunpool/generic/neon/qasymm8_signed.cpp | 4 +- src/cpu/kernels/maxunpool/list.h | 2 +- src/cpu/operators/CpuMaxUnpooling.cpp | 45 ++++++ src/cpu/operators/CpuMaxUnpooling.h | 58 +++++++ src/runtime/NEON/functions/NEMaxUnpoolingLayer.cpp | 37 ++++- tests/validation/NEON/MaxUnpoolingLayer.cpp | 34 +++- 20 files changed, 431 insertions(+), 304 deletions(-) delete mode 100644 src/core/NEON/kernels/NEMaxUnpoolingLayerKernel.cpp delete mode 100644 src/core/NEON/kernels/NEMaxUnpoolingLayerKernel.h create mode 100644 src/cpu/kernels/CpuMaxUnpoolingLayerKernel.cpp create mode 100644 src/cpu/kernels/CpuMaxUnpoolingLayerKernel.h create mode 100644 src/cpu/operators/CpuMaxUnpooling.cpp create mode 100644 src/cpu/operators/CpuMaxUnpooling.h diff --git a/Android.bp b/Android.bp index 6add3f3c2d..ebea73329e 100644 --- a/Android.bp +++ b/Android.bp @@ -278,7 +278,6 @@ cc_library_static { "src/core/NEON/kernels/NEInstanceNormalizationLayerKernel.cpp", "src/core/NEON/kernels/NEL2NormalizeLayerKernel.cpp", "src/core/NEON/kernels/NELogicalKernel.cpp", - "src/core/NEON/kernels/NEMaxUnpoolingLayerKernel.cpp", "src/core/NEON/kernels/NEMeanStdDevNormalizationKernel.cpp", "src/core/NEON/kernels/NENormalizationLayerKernel.cpp", "src/core/NEON/kernels/NEPadLayerKernel.cpp", @@ -414,6 +413,7 @@ cc_library_static { "src/cpu/kernels/CpuGemmMatrixMultiplyKernel.cpp", "src/cpu/kernels/CpuGemmTranspose1xWKernel.cpp", "src/cpu/kernels/CpuIm2ColKernel.cpp", + "src/cpu/kernels/CpuMaxUnpoolingLayerKernel.cpp", "src/cpu/kernels/CpuMulKernel.cpp", "src/cpu/kernels/CpuPermuteKernel.cpp", "src/cpu/kernels/CpuPool2dKernel.cpp", @@ -558,6 +558,7 @@ cc_library_static { "src/cpu/operators/CpuGemmDirectConv2d.cpp", "src/cpu/operators/CpuGemmLowpMatrixMultiplyCore.cpp", "src/cpu/operators/CpuGemmLowpOutputStage.cpp", + "src/cpu/operators/CpuMaxUnpooling.cpp", "src/cpu/operators/CpuMul.cpp", "src/cpu/operators/CpuPermute.cpp", "src/cpu/operators/CpuPool2d.cpp", diff --git a/arm_compute/runtime/NEON/functions/NEMaxUnpoolingLayer.h b/arm_compute/runtime/NEON/functions/NEMaxUnpoolingLayer.h index 41ea040457..2f77540e1e 100644 --- a/arm_compute/runtime/NEON/functions/NEMaxUnpoolingLayer.h +++ b/arm_compute/runtime/NEON/functions/NEMaxUnpoolingLayer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021 Arm Limited. + * Copyright (c) 2020-2022 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -33,12 +33,10 @@ namespace arm_compute class ITensor; class ITensorInfo; class NEFill; -class NEMaxUnpoolingLayerKernel; /** Function to perform MaxUnpooling. This function calls the following kernels: * * -# @ref NEFill - * -# @ref NEMaxUnpoolingLayerKernel */ class NEMaxUnpoolingLayer : public IFunction { @@ -94,8 +92,9 @@ public: void run() override; private: - std::unique_ptr _fill_func; - std::unique_ptr _unpooling_layer_kernel; + std::unique_ptr _fill_func; + struct Impl; + std::unique_ptr _impl; }; } #endif /* ARM_COMPUTE_NEMAXUNPOOLINGLAYER_H */ diff --git a/docs/user_guide/release_version_and_change_log.dox b/docs/user_guide/release_version_and_change_log.dox index 97a531c470..56fd277ac4 100644 --- a/docs/user_guide/release_version_and_change_log.dox +++ b/docs/user_guide/release_version_and_change_log.dox @@ -612,7 +612,7 @@ v20.08 Public major release - New OpenCL kernels / functions: - @ref CLMaxUnpoolingLayerKernel - New Arm® Neon™ kernels / functions: - - @ref NEMaxUnpoolingLayerKernel + - NEMaxUnpoolingLayerKernel - New graph example: - graph_yolov3_output_detector - GEMMTuner improvements: diff --git a/filelist.json b/filelist.json index bba3d568a6..b672a832b1 100644 --- a/filelist.json +++ b/filelist.json @@ -1612,15 +1612,16 @@ "deps": [ "Fill" ], "files": { "common": [ - "src/core/NEON/kernels/NEMaxUnpoolingLayerKernel.cpp", - "src/runtime/NEON/functions/NEMaxUnpoolingLayer.cpp" + "src/cpu/kernels/CpuMaxUnpoolingLayerKernel.cpp", + "src/runtime/NEON/functions/NEMaxUnpoolingLayer.cpp", + "src/cpu/operators/CpuMaxUnpooling.cpp" ], "neon":{ - "common":["src/cpu/kernels/maxunpool/generic/neon/impl.cpp"], "fp32":["src/cpu/kernels/maxunpool/generic/neon/fp32.cpp"], "fp16":["src/cpu/kernels/maxunpool/generic/neon/fp16.cpp"], "qasymm8":["src/cpu/kernels/maxunpool/generic/neon/qasymm8.cpp"], - "qasymm8_signed":["src/cpu/kernels/maxunpool/generic/neon/qasymm8_signed.cpp"] + "qasymm8_signed":[ "src/cpu/kernels/maxunpool/generic/neon/qasymm8_signed.cpp"], + "common":["src/cpu/kernels/maxunpool/generic/neon/impl.cpp"] } } }, diff --git a/src/core/NEON/NEKernels.h b/src/core/NEON/NEKernels.h index cd01659c0d..12a1bb9a11 100644 --- a/src/core/NEON/NEKernels.h +++ b/src/core/NEON/NEKernels.h @@ -45,7 +45,6 @@ #include "src/core/NEON/kernels/NEInstanceNormalizationLayerKernel.h" #include "src/core/NEON/kernels/NEL2NormalizeLayerKernel.h" #include "src/core/NEON/kernels/NELogicalKernel.h" -#include "src/core/NEON/kernels/NEMaxUnpoolingLayerKernel.h" #include "src/core/NEON/kernels/NEMeanStdDevNormalizationKernel.h" #include "src/core/NEON/kernels/NENormalizationLayerKernel.h" #include "src/core/NEON/kernels/NEPadLayerKernel.h" diff --git a/src/core/NEON/kernels/NEMaxUnpoolingLayerKernel.cpp b/src/core/NEON/kernels/NEMaxUnpoolingLayerKernel.cpp deleted file mode 100644 index 93da8a24c5..0000000000 --- a/src/core/NEON/kernels/NEMaxUnpoolingLayerKernel.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2020-2022 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 "src/core/NEON/kernels/NEMaxUnpoolingLayerKernel.h" - -#include "arm_compute/core/TensorInfo.h" -#include "arm_compute/core/Validate.h" -#include "arm_compute/core/Window.h" -#include "arm_compute/core/utils/misc/ShapeCalculator.h" -#include "src/core/CPP/Validate.h" -#include "src/core/common/Registrars.h" -#include "src/core/helpers/AutoConfiguration.h" -#include "src/core/helpers/WindowHelpers.h" -#include "src/cpu/kernels/maxunpool/list.h" -#include "support/ToolchainSupport.h" - -namespace arm_compute -{ -using namespace misc::shape_calculator; - -namespace -{ -struct MaxUnpoolingSelectorData -{ - DataType dt; -}; - -using MaxUnpoolingSelctorPtr = std::add_pointer::type; -using MaxUnpoolingUKernelPtr = std::add_pointer::type; - -struct MaxUnpoolingKernel -{ - const char *name; - const MaxUnpoolingSelctorPtr is_selected; - MaxUnpoolingUKernelPtr ukernel; -}; - -static const MaxUnpoolingKernel available_kernels[] = -{ - { - "fp32_neon_maxunpooling", - [](const MaxUnpoolingSelectorData & data) { return data.dt == DataType::F32; }, - REGISTER_FP32_NEON(arm_compute::cpu::neon_fp32_maxunpooling) - }, -#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC - { - "fp16_neon_maxunpooling", - [](const MaxUnpoolingSelectorData & data) { return data.dt == DataType::F16; }, - REGISTER_FP16_NEON(arm_compute::cpu::neon_fp16_maxunpooling) - }, -#endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC -#if defined(ARM_COMPUTE_ENABLE_NEON) - { - "qs8_neon_maxunpooling", - [](const MaxUnpoolingSelectorData & data) { return data.dt == DataType::QASYMM8; }, - REGISTER_QASYMM8_NEON(arm_compute::cpu::neon_qs8_maxunpooling) - }, - { - "qu8_neon_maxunpooling", - [](const MaxUnpoolingSelectorData & data) { return data.dt == DataType::QASYMM8_SIGNED; }, - REGISTER_QASYMM8_SIGNED_NEON(arm_compute::cpu::neon_qu8_maxunpooling) - }, -#endif //defined(ARM_COMPUTE_ENABLE_NEON) -}; - -/** Micro-kernel selector - * - * @param[in] data Selection data passed to help pick the appropriate micro-kernel - * - * @return A matching micro-kernel else nullptr - */ -const MaxUnpoolingKernel *get_implementation(const MaxUnpoolingSelectorData &data) -{ - for(const auto &uk : available_kernels) - { - if(uk.is_selected(data)) - { - return &uk; - } - } - return nullptr; -} - -Status validate_arguments(const ITensorInfo *input, const ITensorInfo *output, const PoolingLayerInfo &pool_info, const ITensorInfo *indices) -{ - ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input, output, indices); - ARM_COMPUTE_RETURN_ERROR_ON_CPU_F16_UNSUPPORTED(input); - ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QASYMM8, DataType::QASYMM8_SIGNED, DataType::F16, DataType::F32); - ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(indices, 1, DataType::U32); - ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES(input, indices); - - int pool_stride_x = 0; - int pool_stride_y = 0; - PoolingType pool_type = pool_info.pool_type; - const PadStrideInfo pad_stride_info = pool_info.pad_stride_info; - std::tie(pool_stride_x, pool_stride_y) = pad_stride_info.stride(); - const int pool_size_x = pool_info.pool_size.width; - const int pool_size_y = pool_info.pool_size.height; - const Size2D pool_size(pool_size_x, pool_size_y); - - ARM_COMPUTE_RETURN_ERROR_ON_MSG(pool_type != PoolingType::MAX, "Pooling indices only supported for MAX pooling method"); - ARM_COMPUTE_RETURN_ERROR_ON_MSG((pool_size != Size2D(2, 2)), "Pooling indices only supported for pool size 2x2"); - if(output->total_size() != 0) - { - ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, output); - ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_LAYOUT(input, output); - } - - return Status{}; -} -} // namespace - -NEMaxUnpoolingLayerKernel::NEMaxUnpoolingLayerKernel() - : _input(nullptr), _output(nullptr), _indices(nullptr) -{ -} - -void NEMaxUnpoolingLayerKernel::configure(const ITensor *input, const ITensor *indices, ITensor *output, const PoolingLayerInfo &pool_info) -{ - ARM_COMPUTE_ERROR_ON_NULLPTR(input, output); - ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(input->info(), output->info(), pool_info, indices->info())); - - _input = input; - _output = output; - _indices = indices; - - const TensorShape output_shape = compute_unpool_shape(*input->info(), pool_info); - auto_init_if_empty(*output->info(), input->info()->clone()->set_tensor_shape(output_shape)); - - auto window = calculate_max_window(*input->info(), Steps()); - INEKernel::configure(window); -} - -Status NEMaxUnpoolingLayerKernel::validate(const ITensorInfo *input, const ITensorInfo *indices, const ITensorInfo *output, const PoolingLayerInfo &pool_info) -{ - ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input, indices, output); - ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(input, output, pool_info, indices)); - return Status{}; -} - -void NEMaxUnpoolingLayerKernel::run(const Window &window, const ThreadInfo &info) -{ - ARM_COMPUTE_UNUSED(info); - ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this); - ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(INEKernel::window(), window); - const auto *uk = get_implementation(MaxUnpoolingSelectorData{ _input->info()->data_type() }); - ARM_COMPUTE_ERROR_ON(uk == nullptr || uk->ukernel == nullptr); - - uk->ukernel(_input, _output, _indices, window); -} -} // namespace arm_compute diff --git a/src/core/NEON/kernels/NEMaxUnpoolingLayerKernel.h b/src/core/NEON/kernels/NEMaxUnpoolingLayerKernel.h deleted file mode 100644 index f7f9a31f6d..0000000000 --- a/src/core/NEON/kernels/NEMaxUnpoolingLayerKernel.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2020-2022 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_NEMAXUNPOOLINGLAYERKERNEL_H -#define ARM_COMPUTE_NEMAXUNPOOLINGLAYERKERNEL_H - -#include "src/core/NEON/INEKernel.h" - -namespace arm_compute -{ -class ITensor; - -/** Interface for the pooling layer kernel */ -class NEMaxUnpoolingLayerKernel : public INEKernel -{ -public: - const char *name() const override - { - return "NEMaxUnpoolingLayerKernel"; - } - /** Default constructor */ - NEMaxUnpoolingLayerKernel(); - /** Prevent instances of this class from being copied (As this class contains pointers) */ - NEMaxUnpoolingLayerKernel(const NEMaxUnpoolingLayerKernel &) = delete; - /** Prevent instances of this class from being copied (As this class contains pointers) */ - NEMaxUnpoolingLayerKernel &operator=(const NEMaxUnpoolingLayerKernel &) = delete; - /** Allow instances of this class to be moved */ - NEMaxUnpoolingLayerKernel(NEMaxUnpoolingLayerKernel &&) = default; - /** Allow instances of this class to be moved */ - NEMaxUnpoolingLayerKernel &operator=(NEMaxUnpoolingLayerKernel &&) = default; - /** Default destructor */ - ~NEMaxUnpoolingLayerKernel() = default; - /** Set the input and output tensors. - * - * @note Output shape must be equal to the shape of the original input to pool. - * - * @param[in] input Source tensor. Data types supported: QASYMM8/QASYMM8_SIGNED/F16/F32. - * @param[in] indices Tensor containing the offset to store the input elements in the output tensor. - * @ref NEPoolingLayer with indices should precede this function in order to - * properly reconstruct the output tensor. - * The tensor shape of this tensor has to be equal to the input tensor shape. Data type supported: U32. - * @param[out] output Destination tensor. Data types supported: Same as @p input. - * @param[in] pool_info Contains pooling operation information described in @ref PoolingLayerInfo. - */ - void configure(const ITensor *input, const ITensor *indices, ITensor *output, const PoolingLayerInfo &pool_info); - /** Static function to check if given info will lead to a valid configuration of @ref NEMaxUnpoolingLayerKernel - * - * @param[in] input Source tensor info. Data types supported: QASYMM8/QASYMM8_SIGNED/F16/F32. - * @param[in] output Destination tensor info. Data types supported: Same as @p input. - * @param[in] indices Tensor info of the indices of the maximal values. Data type supported: U32. - * @param[in] pool_info Contains pooling operation information described in @ref PoolingLayerInfo. - * - * @return a status - */ - static Status validate(const ITensorInfo *input, const ITensorInfo *indices, const ITensorInfo *output, const PoolingLayerInfo &pool_info); - - // Inherited methods overridden: - void run(const Window &window, const ThreadInfo &info) override; - -private: - /** Function to perform 2x2 pooling and compute the pooling indices. The indices can be used for max unpool. - * - * @param[in] window_input Input region on which to execute the kernel. - */ - template - void unpooling2(const Window &window_input); - - using UnpoolingFunction = void (NEMaxUnpoolingLayerKernel::*)(const Window &window); - -private: - const ITensor *_input; - ITensor *_output; - const ITensor *_indices; -}; -} // namespace arm_compute -#endif /*ARM_COMPUTE_NEMAXUNPOOLINGLAYERKERNEL_H */ diff --git a/src/cpu/kernels/CpuMaxUnpoolingLayerKernel.cpp b/src/cpu/kernels/CpuMaxUnpoolingLayerKernel.cpp new file mode 100644 index 0000000000..604f22f6cc --- /dev/null +++ b/src/cpu/kernels/CpuMaxUnpoolingLayerKernel.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2020-2022 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 "src/cpu/kernels/CpuMaxUnpoolingLayerKernel.h" + +#include "arm_compute/core/TensorInfo.h" +#include "arm_compute/core/Validate.h" +#include "arm_compute/core/Window.h" +#include "arm_compute/core/utils/misc/ShapeCalculator.h" +#include "src/core/CPP/Validate.h" +#include "src/core/common/Registrars.h" +#include "src/core/helpers/AutoConfiguration.h" +#include "src/core/helpers/WindowHelpers.h" +#include "src/cpu/kernels/maxunpool/list.h" +#include "support/ToolchainSupport.h" + +namespace arm_compute +{ +namespace cpu +{ +namespace kernels +{ +using namespace misc::shape_calculator; + +namespace +{ +static const std::vector available_kernels = +{ + { + "neon_fp32_maxunpooling", + [](const DataTypeISASelectorData & data) { return data.dt == DataType::F32; }, + REGISTER_FP32_NEON(neon_fp32_maxunpooling) + }, + { + "neon_fp16_maxunpooling", + [](const DataTypeISASelectorData & data) { return data.dt == DataType::F16 && data.isa.fp16; }, + REGISTER_FP16_NEON(neon_fp16_maxunpooling) + }, + { + "neon_qu8_maxunpooling", + [](const DataTypeISASelectorData & data) { return data.dt == DataType::QASYMM8; }, + REGISTER_QASYMM8_NEON(neon_qs8_maxunpooling) + }, + { + "neon_qs8_maxunpooling", + [](const DataTypeISASelectorData & data) { return data.dt == DataType::QASYMM8_SIGNED; }, + REGISTER_QASYMM8_SIGNED_NEON(neon_qu8_maxunpooling) + }, +}; + +Status validate_arguments(const ITensorInfo *src, const ITensorInfo *indices, const ITensorInfo *dst, const PoolingLayerInfo &pool_info) +{ + ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src, indices, dst); + ARM_COMPUTE_RETURN_ERROR_ON_CPU_F16_UNSUPPORTED(src); + ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(src, 1, DataType::QASYMM8, DataType::QASYMM8_SIGNED, DataType::F16, DataType::F32); + ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(indices, 1, DataType::U32); + ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES(src, indices); + + int pool_stride_x = 0; + int pool_stride_y = 0; + PoolingType pool_type = pool_info.pool_type; + const PadStrideInfo pad_stride_info = pool_info.pad_stride_info; + std::tie(pool_stride_x, pool_stride_y) = pad_stride_info.stride(); + const int pool_size_x = pool_info.pool_size.width; + const int pool_size_y = pool_info.pool_size.height; + const Size2D pool_size(pool_size_x, pool_size_y); + + ARM_COMPUTE_RETURN_ERROR_ON_MSG(pool_type != PoolingType::MAX, "Pooling indices only supported for MAX pooling method"); + ARM_COMPUTE_RETURN_ERROR_ON_MSG((pool_size != Size2D(2, 2)), "Pooling indices only supported for pool size 2x2"); + if(dst->total_size() != 0) + { + ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(src, dst); + ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_LAYOUT(src, dst); + } + + return Status{}; +} +} // namespace + +void CpuMaxUnpoolingLayerKernel::configure(const ITensorInfo *src, const ITensorInfo *indices, ITensorInfo *dst, const PoolingLayerInfo &pool_info) +{ + ARM_COMPUTE_ERROR_ON_NULLPTR(src, dst, indices); + ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(src, indices, dst, pool_info)); + ARM_COMPUTE_UNUSED(indices); + + const auto uk = CpuMaxUnpoolingLayerKernel::get_implementation(DataTypeISASelectorData{ src->data_type(), CPUInfo::get().get_isa() }); + ARM_COMPUTE_ERROR_ON_NULLPTR(uk); + _run_method = uk->ukernel; + + const TensorShape output_shape = compute_unpool_shape(*src, pool_info); + auto_init_if_empty(*dst, src->clone()->set_tensor_shape(output_shape)); + + auto window = calculate_max_window(*src, Steps()); + ICpuKernel::configure(window); +} + +Status CpuMaxUnpoolingLayerKernel::validate(const ITensorInfo *src, const ITensorInfo *indices, const ITensorInfo *dst, const PoolingLayerInfo &pool_info) +{ + ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src, indices, dst); + ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(src, indices, dst, pool_info)); + return Status{}; +} + +void CpuMaxUnpoolingLayerKernel::run_op(ITensorPack &tensors, const Window &window, const ThreadInfo &info) +{ + ARM_COMPUTE_UNUSED(info); + ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this); + ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(ICpuKernel::window(), window); + + const auto src = tensors.get_const_tensor(TensorType::ACL_SRC_0); + const auto indices = tensors.get_const_tensor(TensorType::ACL_SRC_1); + const auto dst = tensors.get_tensor(TensorType::ACL_DST); + + _run_method(src, indices, dst, window); +} + +const char *CpuMaxUnpoolingLayerKernel::name() const +{ + return "CpuMaxUnpoolingLayerKernel"; +} + +const std::vector &CpuMaxUnpoolingLayerKernel::get_available_kernels() +{ + return available_kernels; +} +} // namespace kernels +} // namespace cpu +} // namespace arm_compute \ No newline at end of file diff --git a/src/cpu/kernels/CpuMaxUnpoolingLayerKernel.h b/src/cpu/kernels/CpuMaxUnpoolingLayerKernel.h new file mode 100644 index 0000000000..d0c13471c8 --- /dev/null +++ b/src/cpu/kernels/CpuMaxUnpoolingLayerKernel.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2020-2022 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_CPUMAXUNPOOLINGLAYERKERNEL_H +#define ARM_COMPUTE_CPUMAXUNPOOLINGLAYERKERNEL_H + +#include "src/core/common/Macros.h" +#include "src/cpu/ICpuKernel.h" + +namespace arm_compute +{ +namespace cpu +{ +namespace kernels +{ +/** Interface for the pooling layer kernel */ +class CpuMaxUnpoolingLayerKernel : public ICpuKernel +{ +private: + using MaxUnpoolingUKernelPtr = std::add_pointer::type; + +public: + /** Default constructor */ + CpuMaxUnpoolingLayerKernel() = default; + ARM_COMPUTE_DISALLOW_COPY_ALLOW_MOVE(CpuMaxUnpoolingLayerKernel); + + /** Configure kernel for a given list of arguments + * + * @note Dst shape must be equal to the shape of the original src to pool. + * + * @param[in] src Source tensor to permute. Data types supported: QASYMM8/QASYMM8_SIGNED/F16/F32. + * @param[in] indices Tensor containing the offset to store the src elements in the dst tensor. + * @ref CpuMaxUnpooling with indices should precede this function in order to + * properly reconstruct the output tensor. + * The tensor shape of this tensor has to be equal to the src tensor shape. Data type supported: U32. + * @param[out] dst Destination tensor. Data types supported: Same as @p src + * @param[in] pool_info Contains pooling operation information described in @ref PoolingLayerInfo. + */ + void configure(const ITensorInfo *src, const ITensorInfo *indices, ITensorInfo *dst, const PoolingLayerInfo &pool_info); + /** Static function to check if given info will lead to a valid configuration of @ref CpuMaxUnpoolingLayerKernel + * + * @param[in] src Source tensor to permute. Data types supported: QASYMM8/QASYMM8_SIGNED/F16/F32. + * @param[in] indices Tensor info of the indices of the maximal values. Data type supported: U32. + * @param[out] dst Destination tensor. Data types supported: Same as @p src + * @param[in] pool_info Contains pooling operation information described in @ref PoolingLayerInfo. + * + * @return a status + */ + static Status validate(const ITensorInfo *src, const ITensorInfo *indices, const ITensorInfo *dst, const PoolingLayerInfo &pool_info); + + // Inherited methods overridden: + void run_op(ITensorPack &tensors, const Window &window, const ThreadInfo &info) override; + + struct MaxUnpoolingKernel + { + const char *name; + const DataTypeISASelectorPtr is_selected; + MaxUnpoolingUKernelPtr ukernel; + }; + + static const std::vector &get_available_kernels(); + + const char *name() const override; + +private: + MaxUnpoolingUKernelPtr _run_method{ nullptr }; +}; + +} // namespace kernels +} // namespace cpu +} // namespace arm_compute +#endif /*ARM_COMPUTE_CPUMAXUNPOOLINGLAYERKERNEL_H */ diff --git a/src/cpu/kernels/maxunpool/generic/neon/fp16.cpp b/src/cpu/kernels/maxunpool/generic/neon/fp16.cpp index d43503aa2f..e81ff92311 100644 --- a/src/cpu/kernels/maxunpool/generic/neon/fp16.cpp +++ b/src/cpu/kernels/maxunpool/generic/neon/fp16.cpp @@ -27,9 +27,9 @@ namespace arm_compute { namespace cpu { -void neon_fp16_maxunpooling(const ITensor *input, ITensor *output, const ITensor *indices, const Window &window) +void neon_fp16_maxunpooling(const ITensor *input, const ITensor *indices, ITensor *output, const Window &window) { - return max_unpooling(input, output, indices, window); + return max_unpooling(input, indices, output, window); } } // namespace cpu } // namespace arm_compute diff --git a/src/cpu/kernels/maxunpool/generic/neon/fp32.cpp b/src/cpu/kernels/maxunpool/generic/neon/fp32.cpp index 2f96e86695..ba0d7851a9 100644 --- a/src/cpu/kernels/maxunpool/generic/neon/fp32.cpp +++ b/src/cpu/kernels/maxunpool/generic/neon/fp32.cpp @@ -26,9 +26,9 @@ namespace arm_compute { namespace cpu { -void neon_fp32_maxunpooling(const ITensor *input, ITensor *output, const ITensor *indices, const Window &window) +void neon_fp32_maxunpooling(const ITensor *input, const ITensor *indices, ITensor *output, const Window &window) { - return max_unpooling(input, output, indices, window); + return max_unpooling(input, indices, output, window); } } // namespace cpu } // namespace arm_compute diff --git a/src/cpu/kernels/maxunpool/generic/neon/impl.cpp b/src/cpu/kernels/maxunpool/generic/neon/impl.cpp index 8bbc8d128f..77e3b8594a 100644 --- a/src/cpu/kernels/maxunpool/generic/neon/impl.cpp +++ b/src/cpu/kernels/maxunpool/generic/neon/impl.cpp @@ -29,7 +29,7 @@ class Window; namespace cpu { template -void max_unpooling(const ITensor *input, ITensor *output, const ITensor *indices, const Window &window) +void max_unpooling(const ITensor *input, const ITensor *indices, ITensor *output, const Window &window) { Iterator input_itr(input, window); Iterator indices_itr(indices, window); @@ -43,12 +43,12 @@ void max_unpooling(const ITensor *input, ITensor *output, const ITensor *indices }, input_itr, indices_itr); } -template void max_unpooling(const ITensor *input, ITensor *output, const ITensor *indices, const Window &window); -template void max_unpooling(const ITensor *input, ITensor *output, const ITensor *indices, const Window &window); -template void max_unpooling(const ITensor *input, ITensor *output, const ITensor *indices, const Window &window); +template void max_unpooling(const ITensor *input, const ITensor *indices, ITensor *output, const Window &window); +template void max_unpooling(const ITensor *input, const ITensor *indices, ITensor *output, const Window &window); +template void max_unpooling(const ITensor *input, const ITensor *indices, ITensor *output, const Window &window); #if defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(ENABLE_FP16_KERNELS) -template void max_unpooling(const ITensor *input, ITensor *output, const ITensor *indices, const Window &window); +template void max_unpooling(const ITensor *input, const ITensor *indices, ITensor *output, const Window &window); #endif //defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(ENABLE_FP16_KERNELS) } // namespace cpu } // namespace arm_compute diff --git a/src/cpu/kernels/maxunpool/generic/neon/impl.h b/src/cpu/kernels/maxunpool/generic/neon/impl.h index 6a14c66b33..3fea9cfcf3 100644 --- a/src/cpu/kernels/maxunpool/generic/neon/impl.h +++ b/src/cpu/kernels/maxunpool/generic/neon/impl.h @@ -33,7 +33,7 @@ class Window; namespace cpu { template -void max_unpooling(const ITensor *input, ITensor *output, const ITensor *indices, const Window &window); +void max_unpooling(const ITensor *input, const ITensor *indices, ITensor *output, const Window &window); } // namespace cpu } // namespace arm_compute #endif //define SRC_CORE_SVE_KERNELS_MAXUNPOOLING_IMPL_H diff --git a/src/cpu/kernels/maxunpool/generic/neon/qasymm8.cpp b/src/cpu/kernels/maxunpool/generic/neon/qasymm8.cpp index b6d0f48fda..53e601bba6 100644 --- a/src/cpu/kernels/maxunpool/generic/neon/qasymm8.cpp +++ b/src/cpu/kernels/maxunpool/generic/neon/qasymm8.cpp @@ -26,9 +26,9 @@ namespace arm_compute { namespace cpu { -void neon_qs8_maxunpooling(const ITensor *input, ITensor *output, const ITensor *indices, const Window &window) +void neon_qs8_maxunpooling(const ITensor *input, const ITensor *indices, ITensor *output, const Window &window) { - return max_unpooling(input, output, indices, window); + return max_unpooling(input, indices, output, window); } } // namespace cpu } // namespace arm_compute diff --git a/src/cpu/kernels/maxunpool/generic/neon/qasymm8_signed.cpp b/src/cpu/kernels/maxunpool/generic/neon/qasymm8_signed.cpp index 79f3013805..a3c346fba7 100644 --- a/src/cpu/kernels/maxunpool/generic/neon/qasymm8_signed.cpp +++ b/src/cpu/kernels/maxunpool/generic/neon/qasymm8_signed.cpp @@ -26,9 +26,9 @@ namespace arm_compute { namespace cpu { -void neon_qu8_maxunpooling(const ITensor *input, ITensor *output, const ITensor *indices, const Window &window) +void neon_qu8_maxunpooling(const ITensor *input, const ITensor *indices, ITensor *output, const Window &window) { - return max_unpooling(input, output, indices, window); + return max_unpooling(input, indices, output, window); } } // namespace cpu } // namespace arm_compute diff --git a/src/cpu/kernels/maxunpool/list.h b/src/cpu/kernels/maxunpool/list.h index 0f9bb499d3..2c4fe940d9 100644 --- a/src/cpu/kernels/maxunpool/list.h +++ b/src/cpu/kernels/maxunpool/list.h @@ -28,7 +28,7 @@ namespace arm_compute namespace cpu { #define DECLARE_MAXUNPOOL_KERNEL(func_name) \ - void func_name(const ITensor *input, ITensor *output, const ITensor *indices, const Window &window) + void func_name(const ITensor *input, const ITensor *indices, ITensor *output, const Window &window) DECLARE_MAXUNPOOL_KERNEL(neon_fp32_maxunpooling); DECLARE_MAXUNPOOL_KERNEL(neon_fp16_maxunpooling); DECLARE_MAXUNPOOL_KERNEL(neon_qs8_maxunpooling); diff --git a/src/cpu/operators/CpuMaxUnpooling.cpp b/src/cpu/operators/CpuMaxUnpooling.cpp new file mode 100644 index 0000000000..24e9fd6d46 --- /dev/null +++ b/src/cpu/operators/CpuMaxUnpooling.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018-2022 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 "src/cpu/operators/CpuMaxUnpooling.h" +#include "src/common/utils/Log.h" +#include "src/cpu/kernels/CpuMaxUnpoolingLayerKernel.h" + +namespace arm_compute +{ +namespace cpu +{ +void CpuMaxUnpooling::configure(const ITensorInfo *src, const ITensorInfo *indices, ITensorInfo *dst, const PoolingLayerInfo &pool_info) +{ + ARM_COMPUTE_LOG_PARAMS(src, indices, dst, pool_info); + auto k = std::make_unique(); + k->configure(src, indices, dst, pool_info); + _kernel = std::move(k); +} + +Status CpuMaxUnpooling::validate(const ITensorInfo *src, const ITensorInfo *indices, const ITensorInfo *dst, const PoolingLayerInfo &pool_info) +{ + return kernels::CpuMaxUnpoolingLayerKernel::validate(src, indices, dst, pool_info); +} +} // namesapce cpu +} // namespace arm_compute diff --git a/src/cpu/operators/CpuMaxUnpooling.h b/src/cpu/operators/CpuMaxUnpooling.h new file mode 100644 index 0000000000..aa1f1072a5 --- /dev/null +++ b/src/cpu/operators/CpuMaxUnpooling.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021-2022 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_CPU_MAXUNPOOLING_H +#define ARM_COMPUTE_CPU_MAXUNPOOLING_H + +#include "src/cpu/ICpuOperator.h" + +namespace arm_compute +{ +namespace cpu +{ +/** Basic function to run @ref kernels::CpuMaxUnpoolingLayerKernel */ +class CpuMaxUnpooling : public ICpuOperator +{ +public: + /** Configure operator for a given list of arguments + * + * @param[in] src Source tensor to permute. Data types supported: QASYMM8/QASYMM8_SIGNED/F16/F32. + * @param[in] indices Tensor containing the offset to store the src elements in the dst tensor. + * @ref CpuMaxUnpooling with indices should precede this function in order to + * properly reconstruct the output tensor. + * The tensor shape of this tensor has to be equal to the src tensor shape. Data type supported: U32. + * @param[out] dst Destination tensor. Data types supported: Same as @p src + * @param[in] pool_info Contains pooling operation information described in @ref PoolingLayerInfo. + */ + void configure(const ITensorInfo *src, const ITensorInfo *indices, ITensorInfo *dst, const PoolingLayerInfo &pool_info); + /** Static function to check if given info will lead to a valid configuration + * + * Similar to @ref CpuMaxUnpooling::configure() + * + * @return a status + */ + static Status validate(const ITensorInfo *src, const ITensorInfo *indices, const ITensorInfo *dst, const PoolingLayerInfo &pool_info); +}; +} // namespace cpu +} // namespace arm_compute +#endif /* ARM_COMPUTE_CPU_MAXUNPOOLING_H */ diff --git a/src/runtime/NEON/functions/NEMaxUnpoolingLayer.cpp b/src/runtime/NEON/functions/NEMaxUnpoolingLayer.cpp index 39f717545b..97ddaea41d 100644 --- a/src/runtime/NEON/functions/NEMaxUnpoolingLayer.cpp +++ b/src/runtime/NEON/functions/NEMaxUnpoolingLayer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021 Arm Limited. + * Copyright (c) 2020-2022 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -28,14 +28,23 @@ #include "arm_compute/runtime/NEON/NEScheduler.h" #include "arm_compute/runtime/NEON/functions/NEFill.h" #include "src/common/utils/Log.h" -#include "src/core/NEON/kernels/NEMaxUnpoolingLayerKernel.h" +#include "src/cpu/kernels/CpuMaxUnpoolingLayerKernel.h" +#include "src/cpu/operators/CpuMaxUnpooling.h" namespace arm_compute { +struct NEMaxUnpoolingLayer::Impl +{ + const ITensor *src{ nullptr }; + const ITensor *indices{ nullptr }; + ITensor *dst{ nullptr }; + std::unique_ptr op{ nullptr }; +}; + NEMaxUnpoolingLayer::~NEMaxUnpoolingLayer() = default; NEMaxUnpoolingLayer::NEMaxUnpoolingLayer() - : _fill_func(), _unpooling_layer_kernel() + : _fill_func(), _impl() { } @@ -44,20 +53,32 @@ void NEMaxUnpoolingLayer::configure(ITensor *input, ITensor *indices, ITensor *o ARM_COMPUTE_LOG_PARAMS(input, indices, output, pool_info); const PixelValue zero_value(0.f); - _fill_func = std::make_unique(); - _unpooling_layer_kernel = std::make_unique(); + _fill_func = std::make_unique(); + _impl = std::make_unique(); + _impl->src = input; + _impl->indices = indices; + _impl->dst = output; + + _impl->op = std::make_unique(); _fill_func->configure(output, zero_value); - _unpooling_layer_kernel->configure(input, indices, output, pool_info); + _impl->op->configure(input->info(), indices->info(), output->info(), pool_info); } Status NEMaxUnpoolingLayer::validate(const ITensorInfo *input, const ITensorInfo *indices, const ITensorInfo *output, const PoolingLayerInfo &pool_info) { - return NEMaxUnpoolingLayerKernel::validate(input, indices, output, pool_info); + ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input, output, indices); + ARM_COMPUTE_RETURN_ON_ERROR(cpu::CpuMaxUnpooling::validate(input, indices, output, pool_info)); + return Status{}; } void NEMaxUnpoolingLayer::run() { + ITensorPack pack; + pack.add_tensor(TensorType::ACL_SRC_0, _impl->src); + pack.add_tensor(TensorType::ACL_SRC_1, _impl->indices); + pack.add_tensor(TensorType::ACL_DST, _impl->dst); + _fill_func->run(); - NEScheduler::get().schedule(_unpooling_layer_kernel.get(), Window::DimY); + _impl->op->run(pack); } } /* namespace arm_compute */ diff --git a/tests/validation/NEON/MaxUnpoolingLayer.cpp b/tests/validation/NEON/MaxUnpoolingLayer.cpp index 65838f5b30..8904993afe 100644 --- a/tests/validation/NEON/MaxUnpoolingLayer.cpp +++ b/tests/validation/NEON/MaxUnpoolingLayer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021 Arm Limited. + * Copyright (c) 2020-2022 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -26,6 +26,7 @@ #include "arm_compute/runtime/NEON/functions/NEPoolingLayer.h" #include "arm_compute/runtime/Tensor.h" #include "arm_compute/runtime/TensorAllocator.h" +#include "src/cpu/kernels/CpuMaxUnpoolingLayerKernel.h" #include "tests/NEON/Accessor.h" #include "tests/datasets/ShapeDatasets.h" #include "tests/framework/Asserts.h" @@ -33,7 +34,6 @@ #include "tests/framework/datasets/Datasets.h" #include "tests/validation/Validation.h" #include "tests/validation/fixtures/MaxUnpoolingLayerFixture.h" - namespace arm_compute { namespace test @@ -74,7 +74,37 @@ FIXTURE_DATA_TEST_CASE(MaxUnpooling, NEMaxUnpoolingLayerFixture, framework } TEST_SUITE_END() // FP16 #endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */ + TEST_SUITE_END() // Float + +TEST_SUITE(KernelSelection) + +DATA_TEST_CASE(KernelSelection, framework::DatasetMode::ALL, + combine(framework::dataset::make("CpuExt", std::string("NEON")), + framework::dataset::make("DataType", { DataType::F32, + DataType::F16, + DataType::QASYMM8, + DataType::QASYMM8_SIGNED + })), + cpu_ext, data_type) +{ + using namespace cpu::kernels; + + cpuinfo::CpuIsaInfo cpu_isa{}; + cpu_isa.neon = (cpu_ext == "NEON"); + cpu_isa.sve = (cpu_ext == "SVE"); + cpu_isa.fp16 = (data_type == DataType::F16); + + const auto *selected_impl = CpuMaxUnpoolingLayerKernel::get_implementation(DataTypeISASelectorData{ data_type, cpu_isa }, cpu::KernelSelectionType::Preferred); + + ARM_COMPUTE_ERROR_ON_NULLPTR(selected_impl); + + std::string expected = lower_string(cpu_ext) + "_" + cpu_impl_dt(data_type) + "_maxunpooling"; + std::string actual = selected_impl->name; + + ARM_COMPUTE_EXPECT_EQUAL(expected, actual, framework::LogLevel::ERRORS); +} +TEST_SUITE_END() // KernelSelection TEST_SUITE_END() // PoolingLayer TEST_SUITE_END() // Neon } // namespace validation -- cgit v1.2.1