From 375156937a0783432c5d18e199b5d8d2b3ec33f7 Mon Sep 17 00:00:00 2001 From: ramelg01 Date: Sat, 26 Feb 2022 22:06:20 +0000 Subject: Implementation of ClPooling3d - For NDHWC layout - For F16 and F32 data types - Mixed Precision stil not supported Resolves: COMPMID-4670 Signed-off-by: ramy.elgammal@arm.com Change-Id: I0e14a13e4625569e8e5ee67e6033bd1efe0da469 Reviewed-on: https://review.mlplatform.org/c/ml/ComputeLibrary/+/7262 Comments-Addressed: Arm Jenkins Reviewed-by: SiCong Li Reviewed-by: Gunes Bayir Tested-by: Arm Jenkins --- arm_compute/core/Types.h | 139 +++++++++++++++++++------- arm_compute/core/Utils.h | 34 +++++++ arm_compute/core/Window.h | 3 +- arm_compute/core/utils/misc/ShapeCalculator.h | 63 ++++-------- 4 files changed, 159 insertions(+), 80 deletions(-) (limited to 'arm_compute/core') diff --git a/arm_compute/core/Types.h b/arm_compute/core/Types.h index 6c49cc35c0..47b9485d80 100644 --- a/arm_compute/core/Types.h +++ b/arm_compute/core/Types.h @@ -1264,6 +1264,109 @@ struct PoolingLayerInfo bool fp_mixed_precision; }; +/** Pooling Layer Information struct*/ +struct Pooling3dLayerInfo +{ + /** Default Constructor */ + Pooling3dLayerInfo() + : pool_type(PoolingType::MAX), + pool_size(Size3D()), + stride(Size3D()), + padding(Padding3D()), + exclude_padding(false), + is_global_pooling(false), + fp_mixed_precision(false), + round_type(DimensionRoundingType::FLOOR) + { + } + /** Constructor + * + * @param[in] pool_type Pooling type @ref PoolingType. + * @param[in] pool_size Pooling size, in elements, across x, y and z. + * @param[in] stride (Optional) stride information @ref Size3D + * @param[in] padding (Optional) padding information @ref Padding3D + * @param[in] exclude_padding (Optional) Strategy when accounting padding in calculations. + * True will exclude padding while false will not (Used in AVG/L2 pooling to determine the pooling area). + * Defaults to false; + * @param[in] fp_mixed_precision (Optional) Use wider accumulators (32 bit instead of 16 for FP16) to improve accuracy. + * @param[in] round_type (Optional) Dimensions rounding. Defaults to @ref FLOOR + */ + explicit Pooling3dLayerInfo(PoolingType pool_type, + unsigned int pool_size, + Size3D stride = Size3D(1U, 1U, 1U), + Padding3D padding = Padding3D(), + bool exclude_padding = false, + bool fp_mixed_precision = false, + DimensionRoundingType round_type = DimensionRoundingType::FLOOR) + : pool_type(pool_type), + pool_size(Size3D(pool_size, pool_size, pool_size)), + stride(stride), + padding(padding), + exclude_padding(exclude_padding), + is_global_pooling(false), + fp_mixed_precision(fp_mixed_precision), + round_type(round_type) + { + } + + /** Constructor + * + * @param[in] pool_type Pooling type @ref PoolingType. + * @param[in] pool_size Pooling size, in elements, across x, y and z. + * @param[in] stride (Optional) stride information @ref Size3D + * @param[in] padding (Optional) padding information @ref Padding3D + * @param[in] exclude_padding (Optional) Strategy when accounting padding in calculations. + * True will exclude padding while false will not (Used in AVG/L2 pooling to determine the pooling area). + * Defaults to false; + * @param[in] fp_mixed_precision (Optional) Use wider accumulators (32 bit instead of 16 for FP16) to improve accuracy. + * @param[in] round_type (Optional) Dimensions rounding. Defaults to @ref FLOOR + */ + explicit Pooling3dLayerInfo(PoolingType pool_type, + Size3D pool_size, + Size3D stride = Size3D(1U, 1U, 1U), + Padding3D padding = Padding3D(), + bool exclude_padding = false, + bool fp_mixed_precision = false, + DimensionRoundingType round_type = DimensionRoundingType::FLOOR) + : pool_type(pool_type), + pool_size(pool_size), + stride(stride), + padding(padding), + exclude_padding(exclude_padding), + is_global_pooling(false), + fp_mixed_precision(fp_mixed_precision), + round_type(round_type) + { + } + + /** Constructor + * + * @note This constructor is used for global pooling + * + * @param[in] pool_type Pooling type @ref PoolingType. + */ + explicit Pooling3dLayerInfo(PoolingType pool_type) + : pool_type(pool_type), + pool_size(Size3D()), + stride(Size3D(1U, 1U, 1U)), + padding(Padding3D(0, 0, 0)), + exclude_padding(false), + is_global_pooling(true), + fp_mixed_precision(false), + round_type(DimensionRoundingType::FLOOR) + { + } + + PoolingType pool_type; + Size3D pool_size; + Size3D stride; + Padding3D padding; + bool exclude_padding; + bool is_global_pooling; + bool fp_mixed_precision; + DimensionRoundingType round_type; +}; + /** ROI Pooling Layer Information class */ class ROIPoolingLayerInfo final { @@ -1307,42 +1410,6 @@ private: unsigned int _sampling_ratio; }; -struct Pool3DInfo -{ - Pool3DInfo() = default; - - /** Constructor - * - * @param[in] pool_type Pooling type @ref PoolingType. - * @param[in] pool_size Pooling size, in elements, across x, y and z @ref Size3D - * @param[in] padding Paddings in x, y and z dimensions - * @param[in] strides Strides in x, y and z dimensions @ref Size3D - * @param[in] round_type Dimension rounding type (ceil or floor) - * @param[in] exclude_padding Strategy when accounting padding in calculations. - * True will exclude padding while false will not (Used in AVG/L2 pooling to determine the pooling area). - * @param[in] is_global_pooling Sets the pool size to the input size if True - */ - Pool3DInfo(const PoolingType pool_type, - const Size3D pool_size, - const Padding3D padding, - const Size3D strides, - const DimensionRoundingType round_type, - bool exclude_padding, - bool is_global_pooling) - : pool_type(pool_type), pool_size(pool_size), padding(padding), strides(strides), round_type(round_type), exclude_padding(exclude_padding), is_global_pooling(is_global_pooling) - - { - } - - PoolingType pool_type{ PoolingType::MAX }; - Size3D pool_size{ 1U, 1U, 1U }; - Padding3D padding{}; - Size3D strides{ 1U, 1U, 1U }; - DimensionRoundingType round_type{ DimensionRoundingType::FLOOR }; - bool exclude_padding{ false }; - bool is_global_pooling{ false }; -}; - /** Generate Proposals Information class */ class GenerateProposalsInfo { diff --git a/arm_compute/core/Utils.h b/arm_compute/core/Utils.h index 2d774770ae..a47cfbdec6 100644 --- a/arm_compute/core/Utils.h +++ b/arm_compute/core/Utils.h @@ -793,6 +793,23 @@ std::pair scaled_dimensions_signed(int width, int height, int kernel_width, int kernel_height, const PadStrideInfo &pad_stride_info); +/** Returns calculated width, height and depth of output scaled tensor depending on dimensions rounding mode. + * + * @param[in] width Width of input tensor + * @param[in] height Height of input tensor + * @param[in] depth Depth of input tensor + * @param[in] kernel_width Kernel width. + * @param[in] kernel_height Kernel height. + * @param[in] kernel_depth Kernel depth. + * @param[in] pool3d_info Pad and stride and round information for 3d pooling + * + * @return A tuple with the new width in the first position, the new height in the second, and the new depth in the third. + * Returned values can be < 1 + */ +std::tuple scaled_3d_dimensions_signed(int width, int height, int depth, + int kernel_width, int kernel_height, int kernel_depth, + const Pooling3dLayerInfo &pool3d_info); + /** Check if the given reduction operation should be handled in a serial way. * * @param[in] op Reduction operation to perform @@ -893,6 +910,23 @@ const std::string &string_from_pooling_type(PoolingType type); * @return True if the pool region is entirely outside the input tensor, False otherwise. */ bool is_pool_region_entirely_outside_input(const PoolingLayerInfo &info); +/** Check if the 3d pool region is entirely outside the input tensor + * + * @param[in] info @ref Pooling3dLayerInfo to be checked. + * + * @return True if the pool region is entirely outside the input tensor, False otherwise. + */ +bool is_pool_3d_region_entirely_outside_input(const Pooling3dLayerInfo &info); +/** Check if the 3D padding is symmetric i.e. padding in each opposite sides are euqal (left=right, top=bottom and front=back) + * + * @param[in] info @ref Padding3D input 3D padding object to check if it is symmetric + * + * @return True if padding is symmetric + */ +inline bool is_symmetric(const Padding3D& info) +{ + return ((info.left == info.right) && (info.top == info.bottom) && (info.front == info.back)); +} /** Translates a given GEMMLowp output stage to a string. * * @param[in] output_stage @ref GEMMLowpOutputStageInfo to be translated to string. diff --git a/arm_compute/core/Window.h b/arm_compute/core/Window.h index 150320a90e..f603e6c148 100644 --- a/arm_compute/core/Window.h +++ b/arm_compute/core/Window.h @@ -47,6 +47,8 @@ public: static constexpr size_t DimZ = 2; /** Alias for dimension 3 also known as W dimension */ static constexpr size_t DimW = 3; + /** Alias for dimension 4 also known as V dimension */ + static constexpr size_t DimV = 4; /** Default constructor: create a window containing a single element. */ constexpr Window() @@ -348,7 +350,6 @@ public: { return slide_window_slice<4>(slice); } - /** Collapse the dimensions between @p first and @p last if possible. * * A dimension is collapsable if it starts from 0 and matches the corresponding dimension in the full_window diff --git a/arm_compute/core/utils/misc/ShapeCalculator.h b/arm_compute/core/utils/misc/ShapeCalculator.h index ee4fe0c02f..df907c106e 100644 --- a/arm_compute/core/utils/misc/ShapeCalculator.h +++ b/arm_compute/core/utils/misc/ShapeCalculator.h @@ -1467,52 +1467,29 @@ inline TensorShape compute_conv3d_shape(const TensorShape &src, const TensorShap * * @return the calculated shape */ -inline TensorShape compute_pool3d_shape(const TensorShape &src, Pool3DInfo pool3d_info) +inline TensorShape compute_pool3d_shape(const TensorShape &src, Pooling3dLayerInfo pool3d_info) { TensorShape output_shape{ src }; - const int idx_width = 1; - const int idx_height = 2; - const int idx_depth = 3; - const int pool_size_width = pool3d_info.is_global_pooling ? src[idx_width] : pool3d_info.pool_size.width; - const int pool_size_height = pool3d_info.is_global_pooling ? src[idx_height] : pool3d_info.pool_size.height; - const int pool_size_depth = pool3d_info.is_global_pooling ? src[idx_depth] : pool3d_info.pool_size.depth; - const int pool_stride_width = pool3d_info.strides.width; - const int pool_stride_height = pool3d_info.strides.height; - const int pool_stride_depth = pool3d_info.strides.depth; - - int output_width_size = 0; - int output_height_size = 0; - int output_depth_size = 0; - - const size_t pad_left = pool3d_info.padding.left; - const size_t pad_right = pool3d_info.padding.right; - const size_t pad_top = pool3d_info.padding.top; - const size_t pad_bottom = pool3d_info.padding.bottom; - const size_t pad_front = pool3d_info.padding.front; - const size_t pad_back = pool3d_info.padding.back; - - switch(pool3d_info.round_type) - { - case DimensionRoundingType::FLOOR: - output_width_size = static_cast(std::floor((static_cast(src[idx_width] + pad_left + pad_right - pool_size_width)) / pool_stride_width) + 1); - output_height_size = static_cast(std::floor((static_cast(src[idx_height] + pad_top + pad_bottom - pool_size_height)) / pool_stride_height) + 1); - output_depth_size = static_cast(std::floor((static_cast(src[idx_depth] + pad_front + pad_back - pool_size_depth)) / pool_stride_depth) + 1); - break; - case DimensionRoundingType::CEIL: - output_width_size = static_cast(std::ceil((static_cast(src[idx_width] + pad_left + pad_right - pool_size_width)) / pool_stride_width) + 1); - output_height_size = static_cast(std::ceil((static_cast(src[idx_height] + pad_top + pad_bottom - pool_size_height)) / pool_stride_height) + 1); - output_depth_size = static_cast(std::ceil((static_cast(src[idx_depth] + pad_front + pad_back - pool_size_depth)) / pool_stride_depth) + 1); - break; - default: - ARM_COMPUTE_ERROR("Unsupported rounding type"); - } - - ARM_COMPUTE_ERROR_ON_MSG((output_width_size < 1 || output_height_size < 1 || output_depth_size < 1), "Calculated output dimension size is invalid"); - - output_shape.set(idx_width, static_cast(output_width_size)); - output_shape.set(idx_height, static_cast(output_height_size)); - output_shape.set(idx_depth, static_cast(output_depth_size)); + const auto data_layout = DataLayout::NDHWC; + const int idx_width = get_data_layout_dimension_index(data_layout, DataLayoutDimension::WIDTH); + const int idx_height = get_data_layout_dimension_index(data_layout, DataLayoutDimension::HEIGHT); + const int idx_depth = get_data_layout_dimension_index(data_layout, DataLayoutDimension::DEPTH); + const int pool_size_width = pool3d_info.is_global_pooling ? src[idx_width] : pool3d_info.pool_size.width; + const int pool_size_height = pool3d_info.is_global_pooling ? src[idx_height] : pool3d_info.pool_size.height; + const int pool_size_depth = pool3d_info.is_global_pooling ? src[idx_depth] : pool3d_info.pool_size.depth; + int output_width = 0; + int output_height = 0; + int output_depth = 0; + + std::tie(output_width, output_height, output_depth) = scaled_3d_dimensions_signed(src[idx_width], src[idx_height], src[idx_depth], pool_size_width, pool_size_height, + pool_size_depth, pool3d_info); + + ARM_COMPUTE_ERROR_ON_MSG((output_width < 1 || output_height < 1 || output_depth < 1), "Calculated output dimension size is invalid"); + + output_shape.set(idx_width, static_cast(output_width)); + output_shape.set(idx_height, static_cast(output_height)); + output_shape.set(idx_depth, static_cast(output_depth)); return output_shape; } -- cgit v1.2.1