Compute Library
 23.08
Helpers.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016-2021, 2023 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  /** Create a container iterator for the tensor with the specified number of dimensions, stride, buffer pointer and window.
59  *
60  * @param[in] num_dims The number of dimensions.
61  * @param[in] strides The strides in bytes.
62  * @param[in] buffer The data buffer.
63  * @param[in] offset The offset in bytes from the beginning of the buffer to the first element of the tensor.
64  * @param[in] window The window which will be used to iterate over the tensor.
65  */
66  Iterator(size_t num_dims, const Strides &strides, uint8_t *buffer, size_t offset, const Window &window);
67 
68  /** Increment the iterator along the specified dimension of the step value associated to the dimension.
69  *
70  * @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.
71  *
72  * @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.
73  *
74  * @param[in] dimension Dimension to increment
75  */
76  void increment(size_t dimension);
77 
78  /** Return the offset in bytes from the first element to the current position of the iterator
79  *
80  * @return The current position of the iterator in bytes relative to the first element.
81  */
82  constexpr size_t offset() const;
83 
84  /** Return a pointer to the current pixel.
85  *
86  * @warning Only works if the iterator was created with an ITensor.
87  *
88  * @return equivalent to buffer() + offset()
89  */
90  constexpr uint8_t *ptr() const;
91 
92  /** Move the iterator back to the beginning of the specified dimension.
93  *
94  * @param[in] dimension Dimension to reset
95  */
96  void reset(size_t dimension);
97 
98 private:
99 
100  /** Initialize a container iterator for the tensor with the specified number of dimensions, stride, buffer pointer and window.
101  *
102  * @param[in] num_dims The number of dimensions.
103  * @param[in] strides The strides in bytes.
104  * @param[in] buffer The data buffer.
105  * @param[in] offset The offset in bytes from the beginning of the buffer to the first element of the tensor.
106  * @param[in] window The window which will be used to iterate over the tensor.
107  */
108  void initialize(size_t num_dims, const Strides &strides, uint8_t *buffer, size_t offset, const Window &window);
109 
110  uint8_t *_ptr;
111 
112  class Dimension
113  {
114  public:
115  constexpr Dimension()
116  : _dim_start(0), _stride(0)
117  {
118  }
119 
120  size_t _dim_start;
121  size_t _stride;
122  };
123 
124  std::array<Dimension, Coordinates::num_max_dimensions> _dims;
125 };
126 
127 /** Iterate through the passed window, automatically adjusting the iterators and calling the lambda_functino for each element.
128  * It passes the x and y positions to the lambda_function for each iteration
129  *
130  * @param[in] w Window to iterate through.
131  * @param[in] lambda_function The function of type void(function)( const Coordinates & id ) to call at each iteration.
132  * Where id represents the absolute coordinates of the item to process.
133  * @param[in,out] iterators Tensor iterators which will be updated by this function before calling lambda_function.
134  */
135 template <typename L, typename... Ts>
136 inline void execute_window_loop(const Window &w, L &&lambda_function, Ts &&... iterators);
137 
138 /** Permutes given Dimensions according to a permutation vector
139  *
140  * @warning Validity of permutation is not checked
141  *
142  * @param[in, out] dimensions Dimensions to permute
143  * @param[in] perm Permutation vector
144  */
145 template <typename T>
146 inline void permute(Dimensions<T> &dimensions, const PermutationVector &perm)
147 {
148  auto dimensions_copy = utility::make_array<Dimensions<T>::num_max_dimensions>(dimensions.begin(), dimensions.end());
149  for(unsigned int i = 0; i < perm.num_dimensions(); ++i)
150  {
151  T dimension_val = (perm[i] < dimensions.num_dimensions()) ? dimensions_copy[perm[i]] : 0;
152  dimensions.set(i, dimension_val);
153  }
154 }
155 
156 /** Permutes given TensorShape according to a permutation vector
157  *
158  * @warning Validity of permutation is not checked
159  *
160  * @param[in, out] shape Shape to permute
161  * @param[in] perm Permutation vector
162  */
163 inline void permute(TensorShape &shape, const PermutationVector &perm)
164 {
165  TensorShape shape_copy = shape;
166  for(unsigned int i = 0; i < perm.num_dimensions(); ++i)
167  {
168  size_t dimension_val = (perm[i] < shape.num_dimensions()) ? shape_copy[perm[i]] : 1;
169  shape.set(i, dimension_val, false, false); // Avoid changes in _num_dimension
170  }
171 }
172 
173 /** Helper function to calculate the Valid Region for Scale.
174  *
175  * @param[in] src_info Input tensor info used to check.
176  * @param[in] dst_shape Shape of the output.
177  * @param[in] interpolate_policy Interpolation policy.
178  * @param[in] sampling_policy Sampling policy.
179  * @param[in] border_undefined True if the border is undefined.
180  *
181  * @return The corresponding valid region
182  */
183 ValidRegion calculate_valid_region_scale(const ITensorInfo &src_info, const TensorShape &dst_shape,
184  InterpolationPolicy interpolate_policy, SamplingPolicy sampling_policy, bool border_undefined);
185 
186 /** Convert a linear index into n-dimensional coordinates.
187  *
188  * @param[in] shape Shape of the n-dimensional tensor.
189  * @param[in] index Linear index specifying the i-th element.
190  *
191  * @return n-dimensional coordinates.
192  */
193 inline Coordinates index2coords(const TensorShape &shape, int index);
194 
195 /** Convert n-dimensional coordinates into a linear index.
196  *
197  * @param[in] shape Shape of the n-dimensional tensor.
198  * @param[in] coord N-dimensional coordinates.
199  *
200  * @return linead index
201  */
202 inline int coords2index(const TensorShape &shape, const Coordinates &coord);
203 
204 /** Returns a static map used to find an index or dimension based on a data layout
205  *
206  * *** Layouts ***
207  *
208  * *** 4D ***
209  * [N C H W]
210  * [3 2 1 0]
211  * [N H W C]
212  *
213  * * *** 5D ***
214  * [N C D H W]
215  * [4 3 2 1 0]
216  * [N D H W C]
217  */
218 const std::map<DataLayout, std::vector<DataLayoutDimension>> &get_layout_map();
219 
220 /** Get the index of the given dimension.
221  *
222  * @param[in] data_layout The data layout.
223  * @param[in] data_layout_dimension The dimension which this index is requested for.
224  *
225  * @return The int conversion of the requested data layout index.
226  */
227 inline size_t get_data_layout_dimension_index(const DataLayout &data_layout, const DataLayoutDimension &data_layout_dimension);
228 
229 /** Get the DataLayoutDimension of a given index and layout.
230  *
231  * @param[in] data_layout The data layout.
232  * @param[in] index The data layout index.
233  *
234  * @return The dimension which this index is requested for.
235  */
237 
238 /** Calculate the number of output tiles required by Winograd Convolution layer. This utility function can be used by the Winograd input transform
239  * to know the number of tiles on the x and y direction
240  *
241  * @param[in] in_dims Spatial dimensions of the input tensor of convolution layer
242  * @param[in] kernel_size Kernel size
243  * @param[in] output_tile_size Size of a single output tile
244  * @param[in] conv_info Convolution info (i.e. pad, stride,...)
245  *
246  * @return the number of output tiles along the x and y directions of size "output_tile_size"
247  */
248 inline Size2D compute_winograd_convolution_tiles(const Size2D &in_dims, const Size2D &kernel_size, const Size2D &output_tile_size, const PadStrideInfo &conv_info)
249 {
250  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));
251  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));
252 
253  // Clamp in case we provide paddings but we have 1D convolution
254  num_tiles_x = std::min(num_tiles_x, static_cast<int>(in_dims.width));
255  num_tiles_y = std::min(num_tiles_y, static_cast<int>(in_dims.height));
256 
257  return Size2D(num_tiles_x, num_tiles_y);
258 }
259 
260 /** Wrap-around a number within the range 0 <= x < m
261  *
262  * @param[in] x Input value
263  * @param[in] m Range
264  *
265  * @return the wrapped-around number
266  */
267 template <typename T>
268 inline T wrap_around(T x, T m)
269 {
270  return x >= 0 ? x % m : (x % m + m) % m;
271 }
272 
273 /** Convert negative coordinates to positive in the range [0, num_dims_input]
274  *
275  * @param[out] coords Array of coordinates to be converted.
276  * @param[in] max_value Maximum value to be used when wrapping the negative values in coords
277  */
278 inline Coordinates &convert_negative_axis(Coordinates &coords, int max_value)
279 {
280  for(unsigned int i = 0; i < coords.num_dimensions(); ++i)
281  {
282  coords[i] = wrap_around(coords[i], max_value);
283  }
284  return coords;
285 }
286 } // namespace arm_compute
287 
289 #endif /*ARM_COMPUTE_HELPERS_H */
arm_compute::test::validation::dst_shape
TensorShape dst_shape
Definition: DFT.cpp:164
arm_compute::Dimensions::set
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
arm_compute::DataLayout
DataLayout
[DataLayout enum definition]
Definition: CoreTypes.h:109
arm_compute::Iterator::increment
void increment(size_t dimension)
Increment the iterator along the specified dimension of the step value associated to the dimension.
Definition: Helpers.inl:132
arm_compute::compute_winograd_convolution_tiles
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:248
arm_compute::DataLayoutDimension
DataLayoutDimension
[DataLayout enum definition]
Definition: CoreTypes.h:120
arm_compute::SamplingPolicy
SamplingPolicy
Available Sampling Policies.
Definition: Types.h:85
arm_compute::TensorShape
Shape of a tensor.
Definition: TensorShape.h:39
Types.h
Helpers.inl
Window.h
arm_compute::test::validation::sampling_policy
sampling_policy
Definition: Scale.cpp:250
arm_compute::Size2D
Class for specifying the size of an image or rectangle.
Definition: Size2D.h:34
arm_compute::InterpolationPolicy
InterpolationPolicy
Interpolation method.
Definition: Types.h:371
arm_compute::index2coords
Coordinates index2coords(const TensorShape &shape, int index)
Convert a linear index into n-dimensional coordinates.
Definition: Helpers.inl:166
arm_compute::permute
void permute(Dimensions< T > &dimensions, const PermutationVector &perm)
Permutes given Dimensions according to a permutation vector.
Definition: Helpers.h:146
arm_compute::Size2D::height
size_t height
Height of the image region or rectangle.
Definition: Size2D.h:91
arm_compute::ITensor
Interface for CPU tensor.
Definition: ITensor.h:36
arm_compute::wrap_around
T wrap_around(T x, T m)
Wrap-around a number within the range 0 <= x < m.
Definition: Helpers.h:268
Error.h
arm_compute::test::validation::data_layout
const auto data_layout
Definition: ConvolutionLayer.cpp:406
arm_compute::Strides
Strides of an item in bytes.
Definition: Strides.h:38
arm_compute::test::validation::m
const unsigned int m
Definition: GEMMMatrixMultiplyNative.cpp:359
arm_compute::test::validation::shape
shape
Definition: DFT.cpp:115
arm_compute::Iterator::ptr
constexpr uint8_t * ptr() const
Return a pointer to the current pixel.
Definition: Helpers.inl:149
arm_compute::get_layout_map
const std::map< DataLayout, std::vector< DataLayoutDimension > > & get_layout_map()
Returns a static map used to find an index or dimension based on a data layout.
Definition: Helpers.cpp:104
arm_compute::Size2D::width
size_t width
Width of the image region or rectangle.
Definition: Size2D.h:90
arm_compute::Iterator
Iterator updated by execute_window_loop for each window element.
Definition: Helpers.h:46
arm_compute::Iterator::Iterator
constexpr Iterator()
Default constructor to create an empty iterator.
Definition: Helpers.inl:90
arm_compute::test::validation::w
SimpleTensor< float > w
Definition: DFT.cpp:156
arm_compute::Coordinates
Coordinates of an item.
Definition: Coordinates.h:37
tensor
CLTensor * tensor
Pointer to the auxiliary tensor.
Definition: ClWorkloadRuntime.cpp:66
arm_compute::Iterator::reset
void reset(size_t dimension)
Move the iterator back to the beginning of the specified dimension.
Definition: Helpers.inl:154
arm_compute::PadStrideInfo
Definition: CoreTypes.h:138
arm_compute::Dimensions::begin
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
arm_compute::get_data_layout_dimension_index
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:203
arm_compute::coords2index
int coords2index(const TensorShape &shape, const Coordinates &coord)
Convert n-dimensional coordinates into a linear index.
Definition: Helpers.inl:185
arm_compute::Window
Describe a multidimensional execution window.
Definition: Window.h:39
arm_compute::calculate_valid_region_scale
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
arm_compute::Iterator::offset
constexpr size_t offset() const
Return the offset in bytes from the first element to the current position of the iterator.
Definition: Helpers.inl:144
arm_compute
Copyright (c) 2017-2023 Arm Limited.
Definition: introduction.dox:24
arm_compute::test::validation::conv_info
const auto conv_info
Definition: ConvolutionLayer.cpp:407
arm_compute::test::validation::src_info
TensorInfo src_info(src_shape, 1, data_type)
arm_compute::Dimensions::end
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
ITensor.h
arm_compute::execute_window_loop
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
arm_compute::Dimensions
Dimensions with dimensionality.
Definition: Dimensions.h:42
arm_compute::convert_negative_axis
Coordinates & convert_negative_axis(Coordinates &coords, int max_value)
Convert negative coordinates to positive in the range [0, num_dims_input].
Definition: Helpers.h:278
IAccessWindow.h
Validate.h
arm_compute::Dimensions::num_dimensions
unsigned int num_dimensions() const
Returns the effective dimensionality of the tensor.
Definition: Dimensions.h:143
arm_compute::get_index_data_layout_dimension
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:212