From 80838f166ee1d6eb152dc85f21642157b80301c0 Mon Sep 17 00:00:00 2001 From: Georgios Pinitas Date: Thu, 12 Dec 2019 18:23:13 +0000 Subject: COMPMID-2819: Avoid overflows in pooling shape calculation Pooling shape calculator was performing operations in the unsigned domain leading to overflows in irregular shapes. Thus, we perform all operations in the signed domain and we get the maximum between the given shape and 1, returning always a valid tensor. Signed-off-by: Georgios Pinitas Change-Id: Ia95d7e54929c8bc29e99dc80a61065e403b29a94 Reviewed-on: https://review.mlplatform.org/c/ml/ComputeLibrary/+/2467 Tested-by: Arm Jenkins Reviewed-by: Giorgio Arena Comments-Addressed: Arm Jenkins --- arm_compute/core/Utils.h | 4 ++-- src/core/Utils.cpp | 34 +++++++++++++++++++--------------- tests/datasets/PoolingLayerDataset.h | 1 + 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/arm_compute/core/Utils.h b/arm_compute/core/Utils.h index a2c18bb205..22a1e7064d 100644 --- a/arm_compute/core/Utils.h +++ b/arm_compute/core/Utils.h @@ -943,8 +943,8 @@ std::pair deconvolution_output_dimensions(unsigned i * * @return A pair with the new width in the first position and the new height in the second. */ -std::pair scaled_dimensions(unsigned int width, unsigned int height, - unsigned int kernel_width, unsigned int kernel_height, +std::pair scaled_dimensions(int width, int height, + int kernel_width, int kernel_height, const PadStrideInfo &pad_stride_info, const Size2D &dilation = Size2D(1U, 1U)); diff --git a/src/core/Utils.cpp b/src/core/Utils.cpp index f930804ce3..59dc3652fa 100644 --- a/src/core/Utils.cpp +++ b/src/core/Utils.cpp @@ -399,34 +399,38 @@ std::pair arm_compute::deconvolution_output_dimensio return std::make_pair(w, h); } -std::pair arm_compute::scaled_dimensions(unsigned int width, unsigned int height, - unsigned int kernel_width, unsigned int kernel_height, +std::pair arm_compute::scaled_dimensions(int width, int height, + int kernel_width, int kernel_height, const PadStrideInfo &pad_stride_info, const Size2D &dilation) { - const unsigned int pad_left = pad_stride_info.pad_left(); - const unsigned int pad_top = pad_stride_info.pad_top(); - const unsigned int pad_right = pad_stride_info.pad_right(); - const unsigned int pad_bottom = pad_stride_info.pad_bottom(); - const unsigned int stride_x = pad_stride_info.stride().first; - const unsigned int stride_y = pad_stride_info.stride().second; - unsigned int w = 0; - unsigned int h = 0; + const int dilation_x = dilation.x(); + const int dilation_y = dilation.y(); + const int pad_left = pad_stride_info.pad_left(); + const int pad_top = pad_stride_info.pad_top(); + const int pad_right = pad_stride_info.pad_right(); + const int pad_bottom = pad_stride_info.pad_bottom(); + const int stride_x = pad_stride_info.stride().first; + const int stride_y = pad_stride_info.stride().second; + int w = 0; + int h = 0; switch(pad_stride_info.round()) { case DimensionRoundingType::FLOOR: - w = static_cast(std::floor((static_cast(width + pad_left + pad_right - (dilation.x() * (kernel_width - 1) + 1)) / stride_x) + 1)); - h = static_cast(std::floor((static_cast(height + pad_top + pad_bottom - (dilation.y() * (kernel_height - 1) + 1)) / stride_y) + 1)); + w = static_cast(std::floor((static_cast(width + pad_left + pad_right - (dilation_x * (kernel_width - 1) + 1)) / stride_x) + 1)); + h = static_cast(std::floor((static_cast(height + pad_top + pad_bottom - (dilation_y * (kernel_height - 1) + 1)) / stride_y) + 1)); break; case DimensionRoundingType::CEIL: - w = static_cast(std::ceil((static_cast(width + pad_left + pad_right - (dilation.x() * (kernel_width - 1) + 1)) / stride_x) + 1)); - h = static_cast(std::ceil((static_cast(height + pad_top + pad_bottom - (dilation.y() * (kernel_height - 1) + 1)) / stride_y) + 1)); + w = static_cast(std::ceil((static_cast(width + pad_left + pad_right - (dilation_x * (kernel_width - 1) + 1)) / stride_x) + 1)); + h = static_cast(std::ceil((static_cast(height + pad_top + pad_bottom - (dilation_y * (kernel_height - 1) + 1)) / stride_y) + 1)); break; default: ARM_COMPUTE_ERROR("Unsupported rounding type"); } - return std::make_pair(w, h); + w = std::max(1, w); + h = std::max(1, h); + return std::make_pair(static_cast(w), static_cast(h)); } bool arm_compute::needs_serialized_reduction(ReductionOperation op, DataType dt, unsigned int axis) diff --git a/tests/datasets/PoolingLayerDataset.h b/tests/datasets/PoolingLayerDataset.h index 56fcdc3d0f..943279ee46 100644 --- a/tests/datasets/PoolingLayerDataset.h +++ b/tests/datasets/PoolingLayerDataset.h @@ -106,6 +106,7 @@ public: PoolingLayerDatasetSpecial() { // Special cases + add_config(TensorShape(2U, 3U, 4U, 1U), PoolingLayerInfo(PoolingType::AVG, Size2D(3, 3), DataLayout::NCHW, PadStrideInfo(3, 3, 0, 0), true)); add_config(TensorShape(60U, 52U, 3U, 2U), PoolingLayerInfo(PoolingType::AVG, Size2D(100, 100), DataLayout::NCHW, PadStrideInfo(5, 5, 50, 50), true)); // Asymmetric padding add_config(TensorShape(112U, 112U, 32U), PoolingLayerInfo(PoolingType::MAX, 3, DataLayout::NCHW, PadStrideInfo(2, 2, 0, 1, 0, 1, DimensionRoundingType::FLOOR))); -- cgit v1.2.1