From 89890c630c438debe9661eeb444d81d6e2b3e1a5 Mon Sep 17 00:00:00 2001 From: Usama Arif Date: Tue, 19 Mar 2019 10:57:05 +0000 Subject: COMPMID-2066: Create reference implementation for reflect and symmetric paddings Change-Id: I18f864b1fa902e5bb0aee8168c02bff73cfd3e59 Signed-off-by: Usama Arif Reviewed-on: https://review.mlplatform.org/c/874 Comments-Addressed: Arm Jenkins Tested-by: Arm Jenkins Reviewed-by: Pablo Marquez --- arm_compute/core/Types.h | 8 +++ tests/validation/reference/PadLayer.cpp | 104 ++++++++++++++++++++++++++------ tests/validation/reference/PadLayer.h | 10 +-- 3 files changed, 99 insertions(+), 23 deletions(-) diff --git a/arm_compute/core/Types.h b/arm_compute/core/Types.h index 1ce44ee2e8..5a469a6c9a 100644 --- a/arm_compute/core/Types.h +++ b/arm_compute/core/Types.h @@ -133,6 +133,14 @@ enum class ConvolutionMethod WINOGRAD /**< Convolution using Winograd */ }; +/** Padding mode to use for PadLayer */ +enum class PaddingMode +{ + CONSTANT, + REFLECT, + SYMMETRIC +}; + /** Supported comparison operations */ enum class ComparisonOperation { diff --git a/tests/validation/reference/PadLayer.cpp b/tests/validation/reference/PadLayer.cpp index b9a93ddaff..d072bc529b 100644 --- a/tests/validation/reference/PadLayer.cpp +++ b/tests/validation/reference/PadLayer.cpp @@ -36,27 +36,27 @@ namespace validation namespace reference { template -SimpleTensor pad_layer(const SimpleTensor &src, const PaddingList &paddings) +SimpleTensor pad_layer(const SimpleTensor &src, const PaddingList &paddings, const PixelValue const_value, const PaddingMode mode) { - DataType dst_data_type = src.data_type(); + const DataType dst_data_type = src.data_type(); - TensorShape orig_shape = src.shape(); + const TensorShape orig_shape = src.shape(); std::vector paddings_extended = paddings; - for(size_t i = paddings.size(); i < TensorShape::num_max_dimensions; i++) + for(size_t i = paddings.size(); i < TensorShape::num_max_dimensions; ++i) { paddings_extended.emplace_back(PaddingInfo{ 0, 0 }); } - TensorShape padded_shape = misc::shape_calculator::compute_padded_shape(orig_shape, paddings); + const TensorShape padded_shape = misc::shape_calculator::compute_padded_shape(orig_shape, paddings); SimpleTensor dst(padded_shape, dst_data_type); // Reference algorithm: loop over the different dimension of the input. - for(int idx = 0; idx < dst.num_elements(); idx++) + for(int idx = 0; idx < dst.num_elements(); ++idx) { - Coordinates coord = index2coord(padded_shape, idx); + const Coordinates coord = index2coord(padded_shape, idx); const size_t i = coord.x(); const size_t j = coord.y(); @@ -65,23 +65,89 @@ SimpleTensor pad_layer(const SimpleTensor &src, const PaddingList &padding const size_t m = coord[4]; const size_t n = coord[5]; - std::array dims = { { 0, 1, 2, 3, 4, 5 } }; - std::array coords = { { i, j, k, l, m, n } }; + const std::array dims = { { 0, 1, 2, 3, 4, 5 } }; + const std::array coords = { { i, j, k, l, m, n } }; auto is_padding_area = [&](size_t i) { return (coords[i] < paddings_extended[i].first || coords[i] > orig_shape[i] + paddings_extended[i].first - 1); }; - // If the tuple [i,j,k,l,m] is in the padding area, then seimply set the value + auto orig_coord_reflect = [&](size_t i) + { + if(is_padding_area(i)) + { + if(coords[i] < paddings_extended[i].first) + { + return paddings_extended[i].first - coords[i]; + } + else + { + return 2 * orig_shape[i] + paddings_extended[i].first - 2 - coords[i]; + } + } + return coords[i] - paddings_extended[i].first; + }; + + auto orig_coord_symm = [&](size_t i) + { + if(is_padding_area(i)) + { + if(coords[i] < paddings_extended[i].first) + { + return paddings_extended[i].first - coords[i] - 1; + } + else + { + return 2 * orig_shape[i] + paddings_extended[i].first - 1 - coords[i]; + } + } + return coords[i] - paddings_extended[i].first; + }; + + // If the tuple [i,j,k,l,m] is in the padding area, then simply set the value if(std::any_of(dims.begin(), dims.end(), is_padding_area)) { - dst[idx] = T(0); + switch(mode) + { + case PaddingMode::CONSTANT: + const_value.get(dst[idx]); + break; + case PaddingMode::REFLECT: + { + const Coordinates orig_coords{ orig_coord_reflect(0), + orig_coord_reflect(1), + orig_coord_reflect(2), + orig_coord_reflect(3), + orig_coord_reflect(4), + orig_coord_reflect(5) }; + + const size_t idx_src = coord2index(orig_shape, orig_coords); + dst[idx] = src[idx_src]; + break; + } + case PaddingMode::SYMMETRIC: + { + const Coordinates orig_coords{ orig_coord_symm(0), + orig_coord_symm(1), + orig_coord_symm(2), + orig_coord_symm(3), + orig_coord_symm(4), + orig_coord_symm(5) }; + + const size_t idx_src = coord2index(orig_shape, orig_coords); + dst[idx] = src[idx_src]; + break; + } + default: + ARM_COMPUTE_ERROR("Padding mode not supported."); + break; + } } else { // If the tuple[i,j,k,l,m] is not in the padding area, then copy the input into the output - Coordinates orig_coords{ i - paddings_extended[0].first, + const Coordinates orig_coords{ i - paddings_extended[0].first, j - paddings_extended[1].first, k - paddings_extended[2].first, l - paddings_extended[3].first, @@ -96,13 +162,13 @@ SimpleTensor pad_layer(const SimpleTensor &src, const PaddingList &padding return dst; } -template SimpleTensor pad_layer(const SimpleTensor &src, const PaddingList &paddings); -template SimpleTensor pad_layer(const SimpleTensor &src, const PaddingList &paddings); -template SimpleTensor pad_layer(const SimpleTensor &src, const PaddingList &paddings); -template SimpleTensor pad_layer(const SimpleTensor &src, const PaddingList &paddings); -template SimpleTensor pad_layer(const SimpleTensor &src, const PaddingList &paddings); -template SimpleTensor pad_layer(const SimpleTensor &src, const PaddingList &paddings); -template SimpleTensor pad_layer(const SimpleTensor &src, const PaddingList &paddings); +template SimpleTensor pad_layer(const SimpleTensor &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode); +template SimpleTensor pad_layer(const SimpleTensor &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode); +template SimpleTensor pad_layer(const SimpleTensor &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode); +template SimpleTensor pad_layer(const SimpleTensor &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode); +template SimpleTensor pad_layer(const SimpleTensor &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode); +template SimpleTensor pad_layer(const SimpleTensor &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode); +template SimpleTensor pad_layer(const SimpleTensor &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode); } // namespace reference } // namespace validation } // namespace test diff --git a/tests/validation/reference/PadLayer.h b/tests/validation/reference/PadLayer.h index 9406b05c4d..5ebb5edf5e 100644 --- a/tests/validation/reference/PadLayer.h +++ b/tests/validation/reference/PadLayer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 ARM Limited. + * Copyright (c) 2018-2019 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -39,13 +39,15 @@ namespace reference /** Reference function to pad an ND tensor. This function is not supposed to be optimized, but to * clearly and naively execute the padding of a tensor * - * @param[in] src Tensor to pad - * @param[in] paddings Padding size in each dimension + * @param[in] src Tensor to pad + * @param[in] paddings Padding size in each dimension + * @param[in] const_value Constant value to fill padding with + * @param[in] mode [optional] Padding mode to use * * @return The padded Tensor */ template -SimpleTensor pad_layer(const SimpleTensor &src, const PaddingList &paddings); +SimpleTensor pad_layer(const SimpleTensor &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode = PaddingMode::CONSTANT); } // namespace reference } // namespace validation } // namespace test -- cgit v1.2.1