Compute Library
 21.05
Helpers.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016-2020 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #ifndef ARM_COMPUTE_HELPERS_H
25 #define ARM_COMPUTE_HELPERS_H
26 
27 #include "arm_compute/core/Error.h"
30 #include "arm_compute/core/Types.h"
33 
34 #include <array>
35 #include <cstddef>
36 #include <cstdint>
37 #include <tuple>
38 
39 namespace arm_compute
40 {
41 class IKernel;
42 class ITensor;
43 class ITensorInfo;
44 
45 /** Iterator updated by @ref execute_window_loop for each window element */
46 class Iterator
47 {
48 public:
49  /** Default constructor to create an empty iterator */
50  constexpr Iterator();
51  /** Create a container iterator for the metadata and allocation contained in the ITensor
52  *
53  * @param[in] tensor The tensor to associate to the iterator.
54  * @param[in] window The window which will be used to iterate over the tensor.
55  */
56  Iterator(const ITensor *tensor, const Window &window);
57 
58  /** Increment the iterator along the specified dimension of the step value associated to the dimension.
59  *
60  * @warning It is the caller's responsibility to call increment(dimension+1) when reaching the end of a dimension, the iterator will not check for overflow.
61  *
62  * @note When incrementing a dimension 'n' the coordinates of all the dimensions in the range (0,n-1) are reset. For example if you iterate over a 2D image, everytime you change row (dimension 1), the iterator for the width (dimension 0) is reset to its start.
63  *
64  * @param[in] dimension Dimension to increment
65  */
66  void increment(size_t dimension);
67 
68  /** Return the offset in bytes from the first element to the current position of the iterator
69  *
70  * @return The current position of the iterator in bytes relative to the first element.
71  */
72  constexpr size_t offset() const;
73 
74  /** Return a pointer to the current pixel.
75  *
76  * @warning Only works if the iterator was created with an ITensor.
77  *
78  * @return equivalent to buffer() + offset()
79  */
80  constexpr uint8_t *ptr() const;
81 
82  /** Move the iterator back to the beginning of the specified dimension.
83  *
84  * @param[in] dimension Dimension to reset
85  */
86  void reset(size_t dimension);
87 
88 private:
89  uint8_t *_ptr;
90 
91  class Dimension
92  {
93  public:
94  constexpr Dimension()
95  : _dim_start(0), _stride(0)
96  {
97  }
98 
99  size_t _dim_start;
100  size_t _stride;
101  };
102 
103  std::array<Dimension, Coordinates::num_max_dimensions> _dims;
104 };
105 
106 /** Iterate through the passed window, automatically adjusting the iterators and calling the lambda_functino for each element.
107  * It passes the x and y positions to the lambda_function for each iteration
108  *
109  * @param[in] w Window to iterate through.
110  * @param[in] lambda_function The function of type void(function)( const Coordinates & id ) to call at each iteration.
111  * Where id represents the absolute coordinates of the item to process.
112  * @param[in,out] iterators Tensor iterators which will be updated by this function before calling lambda_function.
113  */
114 template <typename L, typename... Ts>
115 inline void execute_window_loop(const Window &w, L &&lambda_function, Ts &&... iterators);
116 
117 /** Permutes given Dimensions according to a permutation vector
118  *
119  * @warning Validity of permutation is not checked
120  *
121  * @param[in, out] dimensions Dimensions to permute
122  * @param[in] perm Permutation vector
123  */
124 template <typename T>
125 inline void permute(Dimensions<T> &dimensions, const PermutationVector &perm)
126 {
127  auto dimensions_copy = utility::make_array<Dimensions<T>::num_max_dimensions>(dimensions.begin(), dimensions.end());
128  for(unsigned int i = 0; i < perm.num_dimensions(); ++i)
129  {
130  T dimension_val = (perm[i] < dimensions.num_dimensions()) ? dimensions_copy[perm[i]] : 0;
131  dimensions.set(i, dimension_val);
132  }
133 }
134 
135 /** Permutes given TensorShape according to a permutation vector
136  *
137  * @warning Validity of permutation is not checked
138  *
139  * @param[in, out] shape Shape to permute
140  * @param[in] perm Permutation vector
141  */
142 inline void permute(TensorShape &shape, const PermutationVector &perm)
143 {
144  TensorShape shape_copy = shape;
145  for(unsigned int i = 0; i < perm.num_dimensions(); ++i)
146  {
147  size_t dimension_val = (perm[i] < shape.num_dimensions()) ? shape_copy[perm[i]] : 1;
148  shape.set(i, dimension_val, false, false); // Avoid changes in _num_dimension
149  }
150 }
151 
152 /** Helper function to calculate the Valid Region for Scale.
153  *
154  * @param[in] src_info Input tensor info used to check.
155  * @param[in] dst_shape Shape of the output.
156  * @param[in] interpolate_policy Interpolation policy.
157  * @param[in] sampling_policy Sampling policy.
158  * @param[in] border_undefined True if the border is undefined.
159  *
160  * @return The corresponding valid region
161  */
162 ValidRegion calculate_valid_region_scale(const ITensorInfo &src_info, const TensorShape &dst_shape,
163  InterpolationPolicy interpolate_policy, SamplingPolicy sampling_policy, bool border_undefined);
164 
165 /** Convert a linear index into n-dimensional coordinates.
166  *
167  * @param[in] shape Shape of the n-dimensional tensor.
168  * @param[in] index Linear index specifying the i-th element.
169  *
170  * @return n-dimensional coordinates.
171  */
172 inline Coordinates index2coords(const TensorShape &shape, int index);
173 
174 /** Convert n-dimensional coordinates into a linear index.
175  *
176  * @param[in] shape Shape of the n-dimensional tensor.
177  * @param[in] coord N-dimensional coordinates.
178  *
179  * @return linead index
180  */
181 inline int coords2index(const TensorShape &shape, const Coordinates &coord);
182 
183 /** Get the index of the given dimension.
184  *
185  * @param[in] data_layout The data layout.
186  * @param[in] data_layout_dimension The dimension which this index is requested for.
187  *
188  * @return The int conversion of the requested data layout index.
189  */
190 inline size_t get_data_layout_dimension_index(const DataLayout data_layout, const DataLayoutDimension data_layout_dimension);
191 
192 /** Get the DataLayoutDimension of a given index and layout.
193  *
194  * @param[in] data_layout The data layout.
195  * @param[in] index The data layout index.
196  *
197  * @return The dimension which this index is requested for.
198  */
200 
201 /** Calculate the number of output tiles required by Winograd Convolution layer. This utility function can be used by the Winograd input transform
202  * to know the number of tiles on the x and y direction
203  *
204  * @param[in] in_dims Spatial dimensions of the input tensor of convolution layer
205  * @param[in] kernel_size Kernel size
206  * @param[in] output_tile_size Size of a single output tile
207  * @param[in] conv_info Convolution info (i.e. pad, stride,...)
208  *
209  * @return the number of output tiles along the x and y directions of size "output_tile_size"
210  */
211 inline Size2D compute_winograd_convolution_tiles(const Size2D &in_dims, const Size2D &kernel_size, const Size2D &output_tile_size, const PadStrideInfo &conv_info)
212 {
213  int num_tiles_x = std::ceil((in_dims.width - (kernel_size.width - 1) + conv_info.pad_left() + conv_info.pad_right()) / static_cast<float>(output_tile_size.width));
214  int num_tiles_y = std::ceil((in_dims.height - (kernel_size.height - 1) + conv_info.pad_top() + conv_info.pad_bottom()) / static_cast<float>(output_tile_size.height));
215 
216  // Clamp in case we provide paddings but we have 1D convolution
217  num_tiles_x = std::min(num_tiles_x, static_cast<int>(in_dims.width));
218  num_tiles_y = std::min(num_tiles_y, static_cast<int>(in_dims.height));
219 
220  return Size2D(num_tiles_x, num_tiles_y);
221 }
222 
223 /** Wrap-around a number within the range 0 <= x < m
224  *
225  * @param[in] x Input value
226  * @param[in] m Range
227  *
228  * @return the wrapped-around number
229  */
230 template <typename T>
231 inline T wrap_around(T x, T m)
232 {
233  return x >= 0 ? x % m : (x % m + m) % m;
234 }
235 
236 /** Convert negative coordinates to positive in the range [0, num_dims_input]
237  *
238  * @param[out] coords Array of coordinates to be converted.
239  * @param[in] max_value Maximum value to be used when wrapping the negative values in coords
240  */
241 inline Coordinates &convert_negative_axis(Coordinates &coords, int max_value)
242 {
243  for(unsigned int i = 0; i < coords.num_dimensions(); ++i)
244  {
245  coords[i] = wrap_around(coords[i], max_value);
246  }
247  return coords;
248 }
249 } // namespace arm_compute
250 
252 #endif /*ARM_COMPUTE_HELPERS_H */
void set(size_t dimension, T value, bool increase_dim_unit=true)
Accessor to set the value of one of the dimensions.
Definition: Dimensions.h:76
InterpolationPolicy
Interpolation method.
Definition: Types.h:392
SimpleTensor< float > w
Definition: DFT.cpp:156
Shape of a tensor.
Definition: TensorShape.h:39
Coordinates index2coords(const TensorShape &shape, int index)
Convert a linear index into n-dimensional coordinates.
Definition: Helpers.inl:156
void increment(size_t dimension)
Increment the iterator along the specified dimension of the step value associated to the dimension.
Definition: Helpers.inl:122
DataLayoutDimension
[DataLayout enum definition]
Definition: Types.h:123
const DataLayout data_layout
Definition: Im2Col.cpp:151
Size2D compute_winograd_convolution_tiles(const Size2D &in_dims, const Size2D &kernel_size, const Size2D &output_tile_size, const PadStrideInfo &conv_info)
Calculate the number of output tiles required by Winograd Convolution layer.
Definition: Helpers.h:211
Interface for CPU tensor.
Definition: ITensor.h:36
Copyright (c) 2017-2021 Arm Limited.
size_t height
Height of the image region or rectangle.
Definition: Size2D.h:90
void permute(Dimensions< T > &dimensions, const PermutationVector &perm)
Permutes given Dimensions according to a permutation vector.
Definition: Helpers.h:125
T wrap_around(T x, T m)
Wrap-around a number within the range 0 <= x < m.
Definition: Helpers.h:231
Coordinates of an item.
Definition: Coordinates.h:37
Dimensions with dimensionality.
Definition: Dimensions.h:42
int coords2index(const TensorShape &shape, const Coordinates &coord)
Convert n-dimensional coordinates into a linear index.
Definition: Helpers.inl:175
constexpr uint8_t * ptr() const
Return a pointer to the current pixel.
Definition: Helpers.inl:139
Padding and stride information class.
Definition: Types.h:650
std::array< T, num_max_dimensions >::iterator begin()
Returns a read/write iterator that points to the first element in the dimension array.
Definition: Dimensions.h:215
DataLayoutDimension get_index_data_layout_dimension(const DataLayout data_layout, const size_t index)
Get the DataLayoutDimension of a given index and layout.
Definition: Helpers.inl:222
constexpr Iterator()
Default constructor to create an empty iterator.
Definition: Helpers.inl:90
TensorInfo src_info(src_shape, 1, data_type)
Strides of an item in bytes.
Definition: Strides.h:37
ValidRegion calculate_valid_region_scale(const ITensorInfo &src_info, const TensorShape &dst_shape, InterpolationPolicy interpolate_policy, SamplingPolicy sampling_policy, bool border_undefined)
Helper function to calculate the Valid Region for Scale.
Definition: Helpers.cpp:28
void reset(size_t dimension)
Move the iterator back to the beginning of the specified dimension.
Definition: Helpers.inl:144
std::array< T, num_max_dimensions >::iterator end()
Returns a read/write iterator that points one past the last element in the dimension array.
Definition: Dimensions.h:239
size_t width
Width of the image region or rectangle.
Definition: Size2D.h:89
Class for specifying the size of an image or rectangle.
Definition: Size2D.h:34
unsigned int num_dimensions() const
Returns the effective dimensionality of the tensor.
Definition: Dimensions.h:143
void execute_window_loop(const Window &w, L &&lambda_function, Ts &&... iterators)
Iterate through the passed window, automatically adjusting the iterators and calling the lambda_funct...
Definition: Helpers.inl:77
Coordinates & convert_negative_axis(Coordinates &coords, int max_value)
Convert negative coordinates to positive in the range [0, num_dims_input].
Definition: Helpers.h:241
constexpr size_t offset() const
Return the offset in bytes from the first element to the current position of the iterator.
Definition: Helpers.inl:134
size_t get_data_layout_dimension_index(const DataLayout data_layout, const DataLayoutDimension data_layout_dimension)
Get the index of the given dimension.
Definition: Helpers.inl:193
Iterator updated by execute_window_loop for each window element.
Definition: Helpers.h:46
DataLayout
[DataLayout enum definition]
Definition: Types.h:114
Describe a multidimensional execution window.
Definition: Window.h:39
SamplingPolicy
Available Sampling Policies.
Definition: Types.h:102