aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorMatthew Jackson <matthew.jackson@arm.com>2019-08-22 16:13:27 +0100
committerMatthew Jackson <matthew.jackson@arm.com>2019-08-28 09:22:18 +0000
commitb9070a42a44ec1a0102e2f0b04523d2e96392903 (patch)
tree476ae6897e26380a00e4ccfdcd315d6b6f884622 /tests
parent275f99cb09606191c5589952d57175be655de74a (diff)
downloadComputeLibrary-b9070a42a44ec1a0102e2f0b04523d2e96392903.tar.gz
COMPMID-2605: Add asymmetric padding support for Deconvolution layer
Change-Id: I63b773bdce25f1342ccd3a08ded623a1508f70fe Signed-off-by: Matthew Jackson <matthew.jackson@arm.com> Reviewed-on: https://review.mlplatform.org/c/1797 Comments-Addressed: Arm Jenkins <bsgcomp@arm.com> Tested-by: Arm Jenkins <bsgcomp@arm.com> Reviewed-by: Michele Di Giorgio <michele.digiorgio@arm.com> Reviewed-by: Giuseppe Rossini <giuseppe.rossini@arm.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/validation/CL/DeconvolutionLayer.cpp22
-rw-r--r--tests/validation/NEON/DeconvolutionLayer.cpp35
-rw-r--r--tests/validation/fixtures/DeconvolutionLayerFixture.h24
-rw-r--r--tests/validation/reference/DeconvolutionLayer.cpp50
4 files changed, 101 insertions, 30 deletions
diff --git a/tests/validation/CL/DeconvolutionLayer.cpp b/tests/validation/CL/DeconvolutionLayer.cpp
index 44b3428c52..9dafd1ef89 100644
--- a/tests/validation/CL/DeconvolutionLayer.cpp
+++ b/tests/validation/CL/DeconvolutionLayer.cpp
@@ -55,6 +55,9 @@ const auto data4x4 = datasets::SmallDeconvolutionShapes() * framework::dataset::
const auto data3x3 = datasets::SmallDeconvolutionShapes() * framework::dataset::make("StrideX", 1, 4) * framework::dataset::make("StrideY", 1, 4) * framework::dataset::make("PadX", 0, 2)
* framework::dataset::make("PadY", 0, 2) * framework::dataset::make("NumKernels", { 3 });
+const auto data3x3_asymm = datasets::SmallDeconvolutionShapes() * framework::dataset::make("StrideX", 1, 2) * framework::dataset::make("StrideY", 1, 2) * framework::dataset::make("PadLeft", 0, 1)
+ * framework::dataset::make("PadRight", 0, 1) * framework::dataset::make("PadTop", 0, 1) * framework::dataset::make("PadBottom", 0, 1) * framework::dataset::make("NumKernels", { 3 });
+
const auto data3x3_precommit = datasets::SmallDeconvolutionShapes() * framework::dataset::make("StrideX", 1, 2) * framework::dataset::make("StrideY", 1, 2) * framework::dataset::make("PadX", 0, 2)
* framework::dataset::make("PadY", 0, 2) * framework::dataset::make("NumKernels", { 3 });
@@ -120,16 +123,19 @@ DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(zip(zip(
// *INDENT-ON*
template <typename T>
-using CLDeconvolutionLayerFixture4x4 = DeconvolutionValidationFixture<CLTensor, CLAccessor, CLDeconvolutionLayer, T, 4, 4>;
+using CLDeconvolutionLayerFixture4x4 = DeconvolutionValidationFixture<CLTensor, CLAccessor, CLDeconvolutionLayer, T, 4, 4>;
+
+template <typename T>
+using CLDeconvolutionLayerFixture3x3 = DeconvolutionValidationFixture<CLTensor, CLAccessor, CLDeconvolutionLayer, T, 3, 3>;
template <typename T>
-using CLDeconvolutionLayerFixture3x3 = DeconvolutionValidationFixture<CLTensor, CLAccessor, CLDeconvolutionLayer, T, 3, 3>;
+using CLDeconvolutionLayerAsymmFixture3x3 = DeconvolutionValidationAsymmFixture<CLTensor, CLAccessor, CLDeconvolutionLayer, T, 3, 3>;
template <typename T>
-using CLDeconvolutionLayerFixture2x2 = DeconvolutionValidationFixture<CLTensor, CLAccessor, CLDeconvolutionLayer, T, 2, 2>;
+using CLDeconvolutionLayerFixture2x2 = DeconvolutionValidationFixture<CLTensor, CLAccessor, CLDeconvolutionLayer, T, 2, 2>;
template <typename T>
-using CLDeconvolutionLayerFixture1x1 = DeconvolutionValidationFixture<CLTensor, CLAccessor, CLDeconvolutionLayer, T, 1, 1>;
+using CLDeconvolutionLayerFixture1x1 = DeconvolutionValidationFixture<CLTensor, CLAccessor, CLDeconvolutionLayer, T, 1, 1>;
TEST_SUITE(Float)
TEST_SUITE(FP32)
@@ -153,6 +159,14 @@ FIXTURE_DATA_TEST_CASE(RunSmall, CLDeconvolutionLayerFixture3x3<float>, framewor
// Validate output
validate(CLAccessor(_target), _reference, tolerance_fp32);
}
+FIXTURE_DATA_TEST_CASE(RunAsymm, CLDeconvolutionLayerAsymmFixture3x3<float>, framework::DatasetMode::NIGHTLY, combine(combine(combine(data3x3_asymm, framework::dataset::make("DataType",
+ DataType::F32)),
+ data_layouts_dataset),
+ add_bias_dataset))
+{
+ // Validate output
+ validate(CLAccessor(_target), _reference, tolerance_fp32);
+}
FIXTURE_DATA_TEST_CASE(RunLarge, CLDeconvolutionLayerFixture3x3<float>, framework::DatasetMode::NIGHTLY, combine(combine(combine(data3x3, framework::dataset::make("DataType", DataType::F32)),
data_layouts_dataset),
add_bias_dataset))
diff --git a/tests/validation/NEON/DeconvolutionLayer.cpp b/tests/validation/NEON/DeconvolutionLayer.cpp
index 727f501393..500ef10661 100644
--- a/tests/validation/NEON/DeconvolutionLayer.cpp
+++ b/tests/validation/NEON/DeconvolutionLayer.cpp
@@ -56,6 +56,9 @@ const auto data4x4 = datasets::SmallDeconvolutionShapes() * framework::dataset::
const auto data3x3 = datasets::SmallDeconvolutionShapes() * framework::dataset::make("StrideX", 1, 4) * framework::dataset::make("StrideY", 1, 4) * framework::dataset::make("PadX", 0, 2)
* framework::dataset::make("PadY", 0, 2) * framework::dataset::make("NumKernels", { 3 });
+const auto data3x3_asymm = datasets::SmallDeconvolutionShapes() * framework::dataset::make("StrideX", 1, 2) * framework::dataset::make("StrideY", 1, 2) * framework::dataset::make("PadLeft", 0, 1)
+ * framework::dataset::make("PadRight", 0, 1) * framework::dataset::make("PadTop", 0, 1) * framework::dataset::make("PadBottom", 0, 1) * framework::dataset::make("NumKernels", { 3 });
+
const auto data3x3_precommit = datasets::SmallDeconvolutionShapes() * framework::dataset::make("StrideX", 1, 2) * framework::dataset::make("StrideY", 1, 2) * framework::dataset::make("PadX", 0, 2)
* framework::dataset::make("PadY", 0, 2) * framework::dataset::make("NumKernels", { 3 });
@@ -74,13 +77,14 @@ DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, (combine(datasets::Sm
input_shape, data_type)
{
// Create shapes
- const unsigned int kernel_size_x = 3;
- const unsigned int kernel_size_y = 3;
- const unsigned int num_kernels = 1;
- const TensorShape weights_shape(kernel_size_x, kernel_size_y, input_shape.z(), num_kernels);
- const TensorShape bias_shape(num_kernels);
- auto out_dim = deconvolution_output_dimensions(input_shape.x(), input_shape.y(), kernel_size_x, kernel_size_y, 1, 1, 1, 1);
- TensorShape output_shape = compute_deconvolution_output_shape(out_dim, TensorInfo(input_shape, 1, data_type), TensorInfo(weights_shape, 1, data_type));
+ const unsigned int kernel_size_x = 3;
+ const unsigned int kernel_size_y = 3;
+ const unsigned int num_kernels = 1;
+ const TensorShape weights_shape(kernel_size_x, kernel_size_y, input_shape.z(), num_kernels);
+ const TensorShape bias_shape(num_kernels);
+ const PadStrideInfo info(1, 1, 1, 1);
+ auto out_dim = deconvolution_output_dimensions(input_shape.x(), input_shape.y(), kernel_size_x, kernel_size_y, info);
+ TensorShape output_shape = compute_deconvolution_output_shape(out_dim, TensorInfo(input_shape, 1, data_type), TensorInfo(weights_shape, 1, data_type));
// Create tensors
Tensor src = create_tensor<Tensor>(input_shape, data_type, 1);
@@ -157,13 +161,16 @@ DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(zip(zip(
// *INDENT-ON*
template <typename T>
-using NEDeconvolutionLayerFixture4x4 = DeconvolutionValidationFixture<Tensor, Accessor, NEDeconvolutionLayer, T, 4, 4>;
+using NEDeconvolutionLayerFixture4x4 = DeconvolutionValidationFixture<Tensor, Accessor, NEDeconvolutionLayer, T, 4, 4>;
+
+template <typename T>
+using NEDeconvolutionLayerFixture3x3 = DeconvolutionValidationFixture<Tensor, Accessor, NEDeconvolutionLayer, T, 3, 3>;
template <typename T>
-using NEDeconvolutionLayerFixture3x3 = DeconvolutionValidationFixture<Tensor, Accessor, NEDeconvolutionLayer, T, 3, 3>;
+using NEDeconvolutionLayerAsymmFixture3x3 = DeconvolutionValidationAsymmFixture<Tensor, Accessor, NEDeconvolutionLayer, T, 3, 3>;
template <typename T>
-using NEDeconvolutionLayerFixture1x1 = DeconvolutionValidationFixture<Tensor, Accessor, NEDeconvolutionLayer, T, 1, 1>;
+using NEDeconvolutionLayerFixture1x1 = DeconvolutionValidationFixture<Tensor, Accessor, NEDeconvolutionLayer, T, 1, 1>;
TEST_SUITE(Float)
TEST_SUITE(FP32)
@@ -185,6 +192,14 @@ FIXTURE_DATA_TEST_CASE(RunSmall, NEDeconvolutionLayerFixture3x3<float>, framewor
// Validate output
validate(Accessor(_target), _reference, tolerance_fp32);
}
+FIXTURE_DATA_TEST_CASE(RunAsymm, NEDeconvolutionLayerAsymmFixture3x3<float>, framework::DatasetMode::NIGHTLY, combine(combine(combine(data3x3_asymm, framework::dataset::make("DataType",
+ DataType::F32)),
+ data_layouts_dataset),
+ add_bias_dataset))
+{
+ // Validate output
+ validate(Accessor(_target), _reference, tolerance_fp32);
+}
FIXTURE_DATA_TEST_CASE(RunLarge, NEDeconvolutionLayerFixture3x3<float>, framework::DatasetMode::NIGHTLY, combine(combine(combine(data3x3, framework::dataset::make("DataType", DataType::F32)),
data_layouts_dataset),
add_bias_dataset))
diff --git a/tests/validation/fixtures/DeconvolutionLayerFixture.h b/tests/validation/fixtures/DeconvolutionLayerFixture.h
index 9f90f07c97..a25a65f997 100644
--- a/tests/validation/fixtures/DeconvolutionLayerFixture.h
+++ b/tests/validation/fixtures/DeconvolutionLayerFixture.h
@@ -218,7 +218,27 @@ public:
const TensorShape weights_shape(kernel_size_x, kernel_size_y, input_shape.z(), num_kernels);
const TensorShape bias_shape(num_kernels);
const PadStrideInfo info(sx, sy, padx, pady, DimensionRoundingType::CEIL);
- auto out_dim = deconvolution_output_dimensions(input_shape.x(), input_shape.y(), kernel_size_x, kernel_size_y, padx, pady, sx, sy);
+ auto out_dim = deconvolution_output_dimensions(input_shape.x(), input_shape.y(), kernel_size_x, kernel_size_y, info);
+ TensorInfo input_info(input_shape, 1, data_type);
+ TensorInfo weights_info(weights_shape, 1, data_type);
+ TensorShape output_shape = compute_deconvolution_output_shape(out_dim, input_info, weights_info);
+ DeconvolutionLayerFixtureBase<TensorType, AccessorType, FunctionType, T>::setup(input_shape, weights_shape, bias_shape, output_shape, info, data_type, data_layout, QuantizationInfo(), add_bias);
+ }
+};
+
+template <typename TensorType, typename AccessorType, typename FunctionType, typename T, unsigned int kernel_size_x, unsigned int kernel_size_y>
+class DeconvolutionValidationAsymmFixture : public DeconvolutionLayerFixtureBase<TensorType, AccessorType, FunctionType, T>
+{
+public:
+ template <typename...>
+ void setup(TensorShape input_shape, unsigned int sx, unsigned int sy, unsigned int pad_left, unsigned int pad_right, unsigned int pad_top,
+ unsigned int pad_bottom, unsigned int num_kernels, DataType data_type, DataLayout data_layout, bool add_bias)
+ {
+ ARM_COMPUTE_ERROR_ON_MSG(kernel_size_x != kernel_size_y, "Only square kernels supported");
+ const TensorShape weights_shape(kernel_size_x, kernel_size_y, input_shape.z(), num_kernels);
+ const TensorShape bias_shape(num_kernels);
+ const PadStrideInfo info(sx, sy, pad_left, pad_right, pad_top, pad_bottom, DimensionRoundingType::CEIL);
+ auto out_dim = deconvolution_output_dimensions(input_shape.x(), input_shape.y(), kernel_size_x, kernel_size_y, info);
TensorInfo input_info(input_shape, 1, data_type);
TensorInfo weights_info(weights_shape, 1, data_type);
TensorShape output_shape = compute_deconvolution_output_shape(out_dim, input_info, weights_info);
@@ -238,7 +258,7 @@ public:
const TensorShape weights_shape(kernel_size_x, kernel_size_y, input_shape.z(), num_kernels);
const TensorShape bias_shape(num_kernels);
const PadStrideInfo info(sx, sy, padx, pady, DimensionRoundingType::CEIL);
- auto out_dim = deconvolution_output_dimensions(input_shape.x(), input_shape.y(), kernel_size_x, kernel_size_y, padx, pady, sx, sy);
+ auto out_dim = deconvolution_output_dimensions(input_shape.x(), input_shape.y(), kernel_size_x, kernel_size_y, info);
TensorInfo input_info(input_shape, 1, data_type, quantization_info);
TensorInfo weights_info(weights_shape, 1, data_type, quantization_info);
TensorShape output_shape = compute_deconvolution_output_shape(out_dim, input_info, weights_info);
diff --git a/tests/validation/reference/DeconvolutionLayer.cpp b/tests/validation/reference/DeconvolutionLayer.cpp
index af59830722..343ea5e725 100644
--- a/tests/validation/reference/DeconvolutionLayer.cpp
+++ b/tests/validation/reference/DeconvolutionLayer.cpp
@@ -38,21 +38,44 @@ SimpleTensor<T> deconvolution_layer(const SimpleTensor<T> &src, const SimpleTens
const PadStrideInfo &info)
{
// Create reference
- const int stride_x = info.stride().first;
- const int stride_y = info.stride().second;
- const int weights_width = weights.shape().x();
- const int weights_height = weights.shape().y();
- const int weights_upper_dims = weights.shape().total_size() / (weights_width * weights_height);
+ const unsigned int pad_left = info.pad_left();
+ const unsigned int pad_right = info.pad_right();
+ const unsigned int pad_top = info.pad_top();
+ const unsigned int pad_bottom = info.pad_bottom();
+ const int stride_x = info.stride().first;
+ const int stride_y = info.stride().second;
+ const int weights_width = weights.shape().x();
+ const int weights_height = weights.shape().y();
+ const int weights_upper_dims = weights.shape().total_size() / (weights_width * weights_height);
+
+ ARM_COMPUTE_ERROR_ON(pad_left > (weights.shape().x() - 1));
+ ARM_COMPUTE_ERROR_ON(pad_right > (weights.shape().x() - 1));
+ ARM_COMPUTE_ERROR_ON(pad_top > (weights.shape().y() - 1));
+ ARM_COMPUTE_ERROR_ON(pad_bottom > (weights.shape().y() - 1));
// Find the upsampled dimensions
unsigned int out_x = (src.shape().x() - 1) * stride_x + 1;
unsigned int out_y = (src.shape().y() - 1) * stride_y + 1;
// Find the padding needed for the convolution with stride 1 in order to match output shape
- unsigned int padx = output_shape.x() - (out_x - weights_width + 1);
- unsigned int pady = output_shape.y() - (out_y - weights_height + 1);
- out_x += padx;
- out_y += pady;
+ unsigned int deconv_pad_x = output_shape.x() - (out_x - weights_width + 1);
+ unsigned int deconv_pad_y = output_shape.y() - (out_y - weights_height + 1);
+ out_x += deconv_pad_x;
+ out_y += deconv_pad_y;
+
+ unsigned int deconv_pad_left = pad_right > pad_left ? pad_right - pad_left : 0;
+ unsigned int deconv_pad_right = pad_left > pad_right ? pad_left - pad_right : 0;
+ deconv_pad_x -= deconv_pad_left + deconv_pad_right;
+ ARM_COMPUTE_ERROR_ON((deconv_pad_x % 2) != 0);
+ deconv_pad_left += deconv_pad_x / 2;
+ deconv_pad_right += deconv_pad_x / 2;
+
+ unsigned int deconv_pad_top = pad_bottom > pad_top ? pad_bottom - pad_top : 0;
+ unsigned int deconv_pad_bottom = pad_top > pad_bottom ? pad_top - pad_bottom : 0;
+ deconv_pad_y -= deconv_pad_top + deconv_pad_bottom;
+ ARM_COMPUTE_ERROR_ON((deconv_pad_y % 2) != 0);
+ deconv_pad_top += deconv_pad_y / 2;
+ deconv_pad_bottom += deconv_pad_y / 2;
TensorShape scaled_shape = src.shape();
scaled_shape.set(0, out_x);
@@ -64,7 +87,6 @@ SimpleTensor<T> deconvolution_layer(const SimpleTensor<T> &src, const SimpleTens
const int width_scaled = scaled.shape().x();
const int height_scaled = scaled.shape().y();
const int num_2d_slices = src.shape().total_size() / (width_in * height_in);
- ARM_COMPUTE_ERROR_ON(info.pad().first > (weights.shape().x() - 1));
if(src.data_type() == DataType::QASYMM8)
{
@@ -94,10 +116,10 @@ SimpleTensor<T> deconvolution_layer(const SimpleTensor<T> &src, const SimpleTens
{
const int offset_slice_in = slice * width_in * height_in;
const int offset_slice_out = slice * width_scaled * height_scaled;
- const int start_x = padx / 2;
- const int start_y = pady / 2;
- const int end_y = height_scaled - pady / 2;
- const int end_x = width_scaled - padx / 2;
+ const int start_x = deconv_pad_left;
+ const int start_y = deconv_pad_top;
+ const int end_x = width_scaled - deconv_pad_right;
+ const int end_y = height_scaled - deconv_pad_bottom;
for(int yi = start_y, in_y = 0; yi < end_y; yi += stride_y, in_y++)
{