From d33fe343103edbea4fb1cf6121c49caef36ff379 Mon Sep 17 00:00:00 2001 From: Michalis Spyrou Date: Fri, 4 Jan 2019 17:10:25 +0000 Subject: COMPMID-1862 Functions in arm_compute/core/utils/misc/ShapeCalculator.h need to be documented Change-Id: I34e185aa756c05803a0e5e442c719fffa96f396c Reviewed-on: https://review.mlplatform.org/473 Tested-by: Arm Jenkins Reviewed-by: Michele Di Giorgio --- arm_compute/core/utils/misc/ShapeCalculator.h | 361 +++++++++++++++++++++++--- 1 file changed, 331 insertions(+), 30 deletions(-) (limited to 'arm_compute/core/utils/misc') diff --git a/arm_compute/core/utils/misc/ShapeCalculator.h b/arm_compute/core/utils/misc/ShapeCalculator.h index ba0d8e254d..70727424b3 100644 --- a/arm_compute/core/utils/misc/ShapeCalculator.h +++ b/arm_compute/core/utils/misc/ShapeCalculator.h @@ -38,6 +38,15 @@ namespace misc { namespace shape_calculator { +/** Calculate the output tensor shape of a vector input given the convolution dimensions + * + * @param[in] input Input tensor shape + * @param[in] conv_w Convolution width + * @param[in] conv_h Convolution height + * @param[in] data_layout Data layout + * + * @return the calculated shape + */ inline TensorShape compute_vector_to_tensor_output_shape(const TensorShape &input, size_t conv_w, size_t conv_h, const DataLayout &data_layout) { const size_t idx_w = get_data_layout_dimension_index(data_layout, DataLayoutDimension::WIDTH); @@ -52,6 +61,13 @@ inline TensorShape compute_vector_to_tensor_output_shape(const TensorShape &inpu return output_shape; } +/** Calculate the permuted shape of an input given a permutation vector + * + * @param[in] input Input tensor info + * @param[in] perm Permutation vector + * + * @return the calculated shape + */ inline TensorShape compute_permutation_output_shape(const ITensorInfo &input, const PermutationVector &perm) { TensorShape output_shape = input.tensor_shape(); @@ -59,6 +75,13 @@ inline TensorShape compute_permutation_output_shape(const ITensorInfo &input, co return output_shape; } +/** Calculate the output shape of the reorg layer given a stride + * + * @param[in] input Input tensor info + * @param[in] stride Stride + * + * @return the calculated shape + */ inline TensorShape compute_reorg_output_shape(const ITensorInfo &input, int32_t stride) { const size_t idx_width = get_data_layout_dimension_index(input.data_layout(), DataLayoutDimension::WIDTH); @@ -78,6 +101,14 @@ inline TensorShape compute_reorg_output_shape(const ITensorInfo &input, int32_t return output_shape; } +/** Calculate the reshaped shape of the weights + * + * @param[in] weights Weights tensor info + * @param[in] has_bias (Optional) Set to true if there is bias + * @param[in] num_groups (Optional) Number of groups + * + * @return the calculated shape of the reshaped weights + */ inline TensorShape compute_weights_reshaped_shape(const ITensorInfo &weights, bool has_bias = false, unsigned int num_groups = 1) { // Number of groups greater than one are only supported for NCHW data layout, and the number of weights must be a multiple of it. @@ -101,6 +132,14 @@ inline TensorShape compute_weights_reshaped_shape(const ITensorInfo &weights, bo return weights_reshaped; } +/** Calculate the Left Hand Side matrix reshaped shape + * + * @param[in] a Input tensor info + * @param[in] lhs_info Left Hand Side matrix information + * @param[in] reinterpret_input_as_3d (Optional) Set to true if the input need to be interpreted as 3d + * + * @return the calculated shape + */ inline TensorShape compute_lhs_reshaped_shape(const ITensorInfo &a, const GEMMLHSMatrixInfo &lhs_info, bool reinterpret_input_as_3d = false) { ARM_COMPUTE_ERROR_ON(lhs_info.m0 == 0); @@ -138,6 +177,13 @@ inline TensorShape compute_lhs_reshaped_shape(const ITensorInfo &a, const GEMMLH return lhs_shape; } +/** Calculate the Right Hand Side matrix reshaped shape + * + * @param[in] a Input tensor info + * @param[in] rhs_info Right Hand Side matrix information + * + * @return the calculated shape + */ inline TensorShape compute_rhs_reshaped_shape(const ITensorInfo &a, const GEMMRHSMatrixInfo &rhs_info) { ARM_COMPUTE_ERROR_ON(rhs_info.n0 == 0); @@ -166,6 +212,14 @@ inline TensorShape compute_rhs_reshaped_shape(const ITensorInfo &a, const GEMMRH return rhs_shape; } +/** Calculate the interleaved shape of an input tensor + * + * @param[in] a Input tensor info + * @param[in] mult_interleave4x4_height (Optional) Interleave4x4 height + * @param[in] reinterpret_input_as_3d (Optional) Set to true if the input need to be interpreted as 3d + * + * @return the calculated shape + */ inline TensorShape compute_interleaved_shape(const ITensorInfo &a, int mult_interleave4x4_height = 1, bool reinterpret_input_as_3d = false) { // The interleaved output matrix will have the following shape: [ a_height * W, ceil(a_width / W) ] where W = 4 * mult_interleave4x4_height @@ -196,6 +250,12 @@ inline TensorShape compute_interleaved_shape(const ITensorInfo &a, int mult_inte return shape_interleaved_a; } +/** Calculate the transposed 1xW shape + * + * @param[in] b Input tensor info + * + * @return the calculated shape + */ inline TensorShape compute_transpose1xW_shape(const ITensorInfo &b) { // The transpose1xW output matrix will have the following shape: [ b_height * 16, ceil(b_width / 16.0f) ] @@ -206,6 +266,13 @@ inline TensorShape compute_transpose1xW_shape(const ITensorInfo &b) return shape_transposed1xW_b; } +/** Calculate the transposed 1xW width element shape + * + * @param[in] b Input tensor info + * @param[in] mult_transpose1xW_width (Optional) Transpose1xW width + * + * @return the calculated shape + */ inline TensorShape compute_transpose1xW_with_element_size_shape(const ITensorInfo &b, int mult_transpose1xW_width = 1) { // Note: mult_transpose1xW_width expresses the number of chunks with size 1x(W) we want to store on the same row @@ -220,6 +287,12 @@ inline TensorShape compute_transpose1xW_with_element_size_shape(const ITensorInf return shape_transposed1xW_b; } +/** Calculate the reductionA shape used in GEMMLowp + * + * @param[in] b Input tensor info + * + * @return the calculated shape + */ inline TensorShape compute_reductionA_shape(const ITensorInfo &b) { TensorShape shape_vector_sum_col{ b.tensor_shape() }; @@ -231,6 +304,12 @@ inline TensorShape compute_reductionA_shape(const ITensorInfo &b) return shape_vector_sum_col; } +/** Calculate the reductionB shape used in GEMMLowp + * + * @param[in] a Input tensor info + * + * @return the calculated shape + */ inline TensorShape compute_reductionB_shape(const ITensorInfo &a) { TensorShape shape_vector_sum_row{ a.tensor_shape() }; @@ -243,6 +322,15 @@ inline TensorShape compute_reductionB_shape(const ITensorInfo &a) return shape_vector_sum_row; } +/** Calculate the Col2Im shape + * + * @param[in] input Input tensor info + * @param[in] convolved_dims Convolved dimensions + * @param[in] batch_size_on_z True if batch size is on z axis + * @param[in] num_groups (Optional) Number of groups when performing a grouped convolution + * + * @return the calculated shape + */ inline TensorShape compute_col2im_shape(const ITensorInfo &input, const Size2D &convolved_dims, bool batch_size_on_z, unsigned int num_groups = 1) { ARM_COMPUTE_ERROR_ON(num_groups == 0); @@ -268,6 +356,12 @@ inline TensorShape compute_col2im_shape(const ITensorInfo &input, const Size2D & return col2im_shape; } +/** Calculate the transposed shape of a tensor + * + * @param[in] input Input tensor info + * + * @return the calculated shape + */ inline TensorShape compute_transposed_shape(const ITensorInfo &input) { TensorShape shape_transposed{ input.tensor_shape() }; @@ -278,6 +372,15 @@ inline TensorShape compute_transposed_shape(const ITensorInfo &input) return shape_transposed; } +/** Calculate the depthwise convolution output shape of a tensor + * + * @param[in] input Input tensor info + * @param[in] weights Weights tensor info + * @param[in] conv_info Padding and stride information to use for the convolution. + * @param[in] depth_multiplier Multiplier to apply to the input's depth in order to retrieve the output's depth. + * + * @return the calculated shape + */ inline TensorShape compute_depthwise_convolution_shape(const ITensorInfo &input, const ITensorInfo &weights, PadStrideInfo conv_info, unsigned int depth_multiplier) { const TensorShape input_shape{ input.tensor_shape() }; @@ -302,6 +405,20 @@ inline TensorShape compute_depthwise_convolution_shape(const ITensorInfo &input, return output_shape; } +/** Calculate the upsampled output shape used for deconvolution + * + * @param[in] input Input tensor info + * @param[in] weights Weights tensor shape + * @param[in] sx Stride on x axis + * @param[in] sy Stride on y axis + * @param[in] inner_border_right The number of zeros added to right edge of the input. + * @param[in] inner_border_top The number of zeros added to top edge of the input. + * @param[in] out_dims Output shape dimensions + * @param[in] padx Padding on x axis + * @param[in] pady Padding on y axis + * + * @return the calculated shape + */ inline TensorShape compute_deconvolution_upsampled_shape(const ITensorInfo &input, const ITensorInfo &weights, unsigned int sx, unsigned int sy, unsigned int inner_border_right, unsigned int inner_border_top, std::pair &out_dims, unsigned int &padx, unsigned int &pady) @@ -327,6 +444,14 @@ inline TensorShape compute_deconvolution_upsampled_shape(const ITensorInfo &inpu return scale_out_shape; } +/** Calculate the output shape of the deconvolution layer + * + * @param[in] out_dims Output x and y shape dimensions + * @param[in] input Input tensor info + * @param[in] weights Weights tensor shape + * + * @return the calculated shape + */ inline TensorShape compute_deconvolution_output_shape(const std::pair &out_dims, const ITensorInfo &input, const ITensorInfo &weights) { const TensorShape input_shape{ input.tensor_shape() }; @@ -345,6 +470,18 @@ inline TensorShape compute_deconvolution_output_shape(const std::pair(y_interleave))); - - return output_shape; -} - -inline TensorShape compute_fully_connected_reshaped_weights_shape(const ITensorInfo *input, bool transpose_weights, bool is_batched_fc_layer, const int interleave) -{ - TensorShape output_shape{ input->tensor_shape() }; - - // Transpose weights if the user hasn't done it - if(transpose_weights) - { - output_shape = compute_transposed_shape(*input); - } - - // If we run multiple batches we need 1xW transpose, too. - if(is_batched_fc_layer) - { - output_shape = compute_transposed_shape(input->clone()->set_tensor_shape(output_shape)); - output_shape = compute_interleave_custom_shape(output_shape, interleave, interleave); - } - - return output_shape; -} - +/** Calculate the winograd filter transform shape + * + * @param[in] input Input tensor info + * @param[in] winograd_info Winograd information + * + * @return the calculated shape + */ inline TensorShape compute_winograd_filter_transform_shape(const ITensorInfo &input, const WinogradInfo &winograd_info) { TensorShape tensor_shape{ input.tensor_shape() }; @@ -466,6 +593,13 @@ inline TensorShape compute_winograd_filter_transform_shape(const ITensorInfo &in return tensor_shape; } +/** Calculate the winograd input transform shape + * + * @param[in] input Input tensor info + * @param[in] winograd_info Winograd information + * + * @return the calculated shape + */ inline TensorShape compute_winograd_input_transform_shape(const ITensorInfo &input, const WinogradInfo &winograd_info) { const PadStrideInfo conv_info = winograd_info.convolution_info; @@ -495,6 +629,13 @@ inline TensorShape compute_winograd_input_transform_shape(const ITensorInfo &inp return output_shape; } +/** Calculate the winograd output transform shape + * + * @param[in] input Input tensor info + * @param[in] winograd_info Winograd information + * + * @return the calculated shape + */ inline TensorShape compute_winograd_output_transform_shape(const ITensorInfo &input, const WinogradInfo &winograd_info) { const PadStrideInfo conv_info = winograd_info.convolution_info; @@ -522,6 +663,14 @@ inline TensorShape compute_winograd_output_transform_shape(const ITensorInfo &in return tensor_shape; } +/** Calculate the deep convolution shape output shape of a tensor + * + * @param[in] input Input tensor info + * @param[in] weights Weights tensor info + * @param[in] conv_info Contains padding and stride information + * + * @return the calculated shape + */ inline TensorShape compute_deep_convolution_shape(const ITensorInfo &input, const ITensorInfo &weights, PadStrideInfo conv_info) { const TensorShape input_shape{ input.tensor_shape() }; @@ -548,6 +697,12 @@ inline TensorShape compute_deep_convolution_shape(const ITensorInfo &input, cons return output_shape; } +/** Calculate the min/max shape output shape of a tensor + * + * @param[in] input Input tensor info + * + * @return the calculated shape + */ inline TensorShape compute_min_max_shape(const ITensorInfo *input) { TensorShape output_shape{ input->tensor_shape() }; @@ -558,6 +713,13 @@ inline TensorShape compute_min_max_shape(const ITensorInfo *input) return output_shape; } +/** Calculate the output pool shape of a tensor + * + * @param[in] input Input tensor info + * @param[in] pool_info Pooling layer info + * + * @return the calculated shape + */ inline TensorShape compute_pool_shape(const ITensorInfo &input, PoolingLayerInfo pool_info) { unsigned int pooled_w = 0; @@ -583,6 +745,13 @@ inline TensorShape compute_pool_shape(const ITensorInfo &input, PoolingLayerInfo return output_shape; } +/** Calculate the RNN shape of a tensor + * + * @param[in] input Input tensor info + * @param[in] batch_size Batch size + * + * @return the calculated shape + */ inline TensorShape compute_rnn_shape(const ITensorInfo *input, const unsigned int batch_size) { TensorShape output_shape{ input->tensor_shape() }; @@ -591,6 +760,15 @@ inline TensorShape compute_rnn_shape(const ITensorInfo *input, const unsigned in return output_shape; } +/** Calculate the matrix multiplication output shape of two tensors + * + * @param[in] input0 First input tensor info + * @param[in] input1 Second input tensor info + * @param[in] is_interleaved_transposed True if the input is interleaved transposed + * @param[in] reshape_info GEMM reshape info + * + * @return the calculated shape + */ inline TensorShape compute_mm_shape(const ITensorInfo &input0, const ITensorInfo &input1, bool is_interleaved_transposed, const GEMMReshapeInfo &reshape_info) { ARM_COMPUTE_ERROR_ON_MSG(input0.num_dimensions() > 4, "The number of dimensions for the matrix A must be <= 4"); @@ -619,6 +797,14 @@ inline TensorShape compute_mm_shape(const ITensorInfo &input0, const ITensorInfo return output_shape; } +/** Calculate the matrix multiplication output shape of two tensors + * + * @param[in] input0 First input tensor info + * @param[in] input1 Second input tensor info + * @param[in] gemm_info GEMM reshape info + * + * @return the calculated shape + */ inline TensorShape compute_mm_shape(const ITensorInfo &input0, const ITensorInfo &input1, const GEMMReshapeInfo &gemm_info) { ARM_COMPUTE_ERROR_ON_MSG(input0.num_dimensions() > 4, "The number of dimensions for the matrix A must be <= 4"); @@ -644,6 +830,14 @@ inline TensorShape compute_mm_shape(const ITensorInfo &input0, const ITensorInfo return output_shape; } +/** Calculate the matrix multiplication output shape of two tensors + * + * @param[in] input Input tensor info + * @param[in] gemm_3d_depth (Optional) GEMM 3d depth + * @param[in] batch_size_on_z (Optional) True if batch size is on z axis + * + * @return the calculated shape + */ inline TensorShape compute_output_stage_shape(const ITensorInfo &input, unsigned int gemm_3d_depth = 1, bool batch_size_on_z = false) { ARM_COMPUTE_ERROR_ON(input.data_layout() != DataLayout::NHWC && gemm_3d_depth > 1); @@ -663,6 +857,18 @@ inline TensorShape compute_output_stage_shape(const ITensorInfo &input, unsigned return output_shape; } +/** Calculate the strided slice output shape of a tensor + * + * @param[in] input Input tensor info + * @param[in] starts The starts of the dimensions of the input tensor to be sliced + * @param[in] ends The ends of the dimensions of the input tensor to be sliced + * @param[in] strides The strides of the dimensions of the input tensor to be sliced + * @param[in] begin_mask If the ith bit of begin_mask is set, starts[i] is ignored and the fullest possible range in that dimension is used instead. + * @param[in] end_mask If the ith bit of end_mask is set, ends[i] is ignored and the fullest possible range in that dimension is used instead. + * @param[in] shrink_axis_mask If the ith bit of shrink_axis_mask is set, it implies that the ith specification shrinks the dimensionality by 1 + * + * @return the calculated shape + */ inline TensorShape compute_strided_slice_shape(const ITensorInfo &input, const Coordinates &starts, const Coordinates &ends, const Coordinates &strides, int32_t begin_mask, int32_t end_mask, int32_t shrink_axis_mask) @@ -671,6 +877,14 @@ inline TensorShape compute_strided_slice_shape(const ITensorInfo &input, return compute_strided_slice_output_shape(input.tensor_shape(), starts, ends, strides, begin_mask, end_mask, shrink_axis_mask); } +/** Calculate the slice output shape of a tensor + * + * @param[in] input_shape Input tensor info + * @param[in] starts The starts of the dimensions of the input tensor to be sliced + * @param[in] ends The ends of the dimensions of the input tensor to be sliced + * + * @return the calculated shape + */ inline TensorShape compute_slice_shape(const TensorShape &input_shape, const Coordinates &starts, const Coordinates &ends) { using namespace arm_compute::helpers::tensor_transform; @@ -680,6 +894,14 @@ inline TensorShape compute_slice_shape(const TensorShape &input_shape, const Coo 0, construct_slice_end_mask(ends), 0); } +/** Calculate the batch to space output shape of a tensor + * + * @param[in] input Input tensor info + * @param[in] block_x Block shape x value + * @param[in] block_y Block shape y value + * + * @return the calculated shape + */ inline TensorShape compute_batch_to_space_shape(const ITensorInfo *input, const int block_x, const int block_y) { ARM_COMPUTE_ERROR_ON(block_x <= 0 || block_y <= 0); @@ -697,6 +919,14 @@ inline TensorShape compute_batch_to_space_shape(const ITensorInfo *input, const return output_shape; } +/** Calculate the split output shape of a tensor + * + * @param[in] input Input tensor info + * @param[in] axis Axis on which to split the input + * @param[in] num_splits Number of splits + * + * @return the calculated shape + */ inline TensorShape compute_split_shape(const ITensorInfo *input, unsigned int axis, unsigned int num_splits) { TensorShape empty_shape; @@ -722,6 +952,16 @@ inline TensorShape compute_split_shape(const ITensorInfo *input, unsigned int ax return out_shape; } +/** Calculate the space to batch output shape of a tensor + * + * @param[in] input Input tensor info + * @param[in] block_x Block shape x value + * @param[in] block_y Block shape y value + * @param[in] padding_left Left padding values + * @param[in] padding_right Right padding values + * + * @return the calculated shape + */ inline TensorShape compute_space_to_batch_shape(const ITensorInfo *input, const int block_x, const int block_y, const Size2D &padding_left, const Size2D &padding_right) { TensorShape output_shape{ input->tensor_shape() }; @@ -738,6 +978,13 @@ inline TensorShape compute_space_to_batch_shape(const ITensorInfo *input, const return output_shape; } +/** Calculate the prior box output shape of a tensor + * + * @param[in] input Input tensor info + * @param[in] info PriorBoxLayer info + * + * @return the calculated shape + */ inline TensorShape compute_prior_box_shape(const ITensorInfo &input, const PriorBoxLayerInfo &info) { DataLayout data_layout = input.data_layout(); @@ -752,6 +999,13 @@ inline TensorShape compute_prior_box_shape(const ITensorInfo &input, const Prior return output_shape; } +/** Calculate the padded shape of a tensor + * + * @param[in] input_shape Input tensor shape + * @param[in] padding Paddings list + * + * @return the calculated shape + */ inline TensorShape compute_padded_shape(const TensorShape &input_shape, const PaddingList &padding) { TensorShape padded_shape = input_shape; @@ -762,6 +1016,13 @@ inline TensorShape compute_padded_shape(const TensorShape &input_shape, const Pa return padded_shape; } +/** Calculate the tiled shape of a tensor + * + * @param[in] input_shape Input tensor shape + * @param[in] multiples Paddings list + * + * @return the calculated shape + */ inline TensorShape compute_tiled_shape(const TensorShape &input_shape, const Multiples &multiples) { TensorShape tiled_shape = input_shape; @@ -772,6 +1033,13 @@ inline TensorShape compute_tiled_shape(const TensorShape &input_shape, const Mul return tiled_shape; } +/** Calculate the upsampled shape of a tensor + * + * @param[in] input Input tensor info + * @param[in] info Contains stride information (x and y) + * + * @return the calculated shape + */ inline TensorShape compute_upsample_shape(const ITensorInfo &input, const Size2D &info) { const DataLayout data_layout = input.data_layout(); @@ -787,6 +1055,12 @@ inline TensorShape compute_upsample_shape(const ITensorInfo &input, const Size2D return scale_out_shape; } +/** Get the tensor shape + * + * @param[in] data Input data + * + * @return the extracted tensor shape + */ template inline TensorShape extract_shape(T *data) { @@ -803,6 +1077,13 @@ inline TensorShape extract_shape(const TensorShape *data) return *data; } +/** Calculate the unstack shape of a tensor + * + * @param[in] input_shape Input tensor shape + * @param[in] axis Axis on which to perform the unstack operation + * + * @return the calculated shape + */ inline TensorShape calculate_unstack_shape(TensorShape input_shape, unsigned int axis) { ARM_COMPUTE_ERROR_ON(axis > input_shape.num_dimensions()); @@ -810,6 +1091,12 @@ inline TensorShape calculate_unstack_shape(TensorShape input_shape, unsigned int return input_shape; } +/** Calculate the depth concatenate output shape of a vector of tensors + * + * @param[in] inputs_vector Vector containing the shapes of the inputs + * + * @return the calculated shape + */ template inline TensorShape calculate_depth_concatenate_shape(const std::vector &inputs_vector) { @@ -835,6 +1122,12 @@ inline TensorShape calculate_depth_concatenate_shape(const std::vector &inp return out_shape; } +/** Calculate the width concatenate output shape of a vector of tensors + * + * @param[in] inputs_vector Vector containing the shapes of the inputs + * + * @return the calculated shape + */ template inline TensorShape calculate_width_concatenate_shape(const std::vector &inputs_vector) { @@ -853,6 +1146,14 @@ inline TensorShape calculate_width_concatenate_shape(const std::vector &inp return out_shape; } +/** Calculate the stack output shape of a tensor + * + * @param[in] a Input tensor info + * @param[in] axis Axis on which to perform the stack operation + * @param[in] num_tensors Number of tensors to stack + * + * @return the calculated shape + */ inline TensorShape compute_stack_shape(const ITensorInfo &a, unsigned int axis, unsigned int num_tensors) { ARM_COMPUTE_ERROR_ON(axis > a.num_dimensions()); -- cgit v1.2.1