aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUsama Arif <usama.arif@arm.com>2019-03-19 10:57:05 +0000
committerPablo Marquez <pablo.tello@arm.com>2019-03-21 13:09:34 +0000
commit89890c630c438debe9661eeb444d81d6e2b3e1a5 (patch)
tree2066af5b7e73ba683863fbc8646959da0a344893
parent6a14adb2faefd2f4638647595dfdef12e29f8a01 (diff)
downloadComputeLibrary-89890c630c438debe9661eeb444d81d6e2b3e1a5.tar.gz
COMPMID-2066: Create reference implementation for reflect and symmetric paddings
Change-Id: I18f864b1fa902e5bb0aee8168c02bff73cfd3e59 Signed-off-by: Usama Arif <usama.arif@arm.com> Reviewed-on: https://review.mlplatform.org/c/874 Comments-Addressed: Arm Jenkins <bsgcomp@arm.com> Tested-by: Arm Jenkins <bsgcomp@arm.com> Reviewed-by: Pablo Marquez <pablo.tello@arm.com>
-rw-r--r--arm_compute/core/Types.h8
-rw-r--r--tests/validation/reference/PadLayer.cpp104
-rw-r--r--tests/validation/reference/PadLayer.h10
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 <typename T>
-SimpleTensor<T> pad_layer(const SimpleTensor<T> &src, const PaddingList &paddings)
+SimpleTensor<T> pad_layer(const SimpleTensor<T> &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<PaddingInfo> 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<T> 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<T> pad_layer(const SimpleTensor<T> &src, const PaddingList &padding
const size_t m = coord[4];
const size_t n = coord[5];
- std::array<size_t, TensorShape::num_max_dimensions> dims = { { 0, 1, 2, 3, 4, 5 } };
- std::array<size_t, TensorShape::num_max_dimensions> coords = { { i, j, k, l, m, n } };
+ const std::array<size_t, TensorShape::num_max_dimensions> dims = { { 0, 1, 2, 3, 4, 5 } };
+ const std::array<size_t, TensorShape::num_max_dimensions> 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<T> pad_layer(const SimpleTensor<T> &src, const PaddingList &padding
return dst;
}
-template SimpleTensor<float> pad_layer(const SimpleTensor<float> &src, const PaddingList &paddings);
-template SimpleTensor<half> pad_layer(const SimpleTensor<half> &src, const PaddingList &paddings);
-template SimpleTensor<uint32_t> pad_layer(const SimpleTensor<uint32_t> &src, const PaddingList &paddings);
-template SimpleTensor<uint8_t> pad_layer(const SimpleTensor<uint8_t> &src, const PaddingList &paddings);
-template SimpleTensor<int8_t> pad_layer(const SimpleTensor<int8_t> &src, const PaddingList &paddings);
-template SimpleTensor<uint16_t> pad_layer(const SimpleTensor<uint16_t> &src, const PaddingList &paddings);
-template SimpleTensor<int16_t> pad_layer(const SimpleTensor<int16_t> &src, const PaddingList &paddings);
+template SimpleTensor<float> pad_layer(const SimpleTensor<float> &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode);
+template SimpleTensor<half> pad_layer(const SimpleTensor<half> &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode);
+template SimpleTensor<uint32_t> pad_layer(const SimpleTensor<uint32_t> &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode);
+template SimpleTensor<uint8_t> pad_layer(const SimpleTensor<uint8_t> &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode);
+template SimpleTensor<int8_t> pad_layer(const SimpleTensor<int8_t> &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode);
+template SimpleTensor<uint16_t> pad_layer(const SimpleTensor<uint16_t> &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode);
+template SimpleTensor<int16_t> pad_layer(const SimpleTensor<int16_t> &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 <typename T>
-SimpleTensor<T> pad_layer(const SimpleTensor<T> &src, const PaddingList &paddings);
+SimpleTensor<T> pad_layer(const SimpleTensor<T> &src, const PaddingList &paddings, const PixelValue const_value = PixelValue(), const PaddingMode mode = PaddingMode::CONSTANT);
} // namespace reference
} // namespace validation
} // namespace test