Compute Library
 23.11
WindowIterator.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-2021 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_WINDOW_ITERATOR_H
25 #define ARM_COMPUTE_WINDOW_ITERATOR_H
27 #include "arm_compute/core/Error.h"
30 
31 namespace arm_compute
32 {
33 /** Convert an offset in window steps into absolute coordinates.
34  *
35  * @param[in] w Window @p offset is related to.
36  * @param[in] offset Offset inside the window expressed in number of window steps.
37  *
38  * @return Absolute coordinates.
39  */
41 {
42  Coordinates position;
43  for (unsigned int i = 0; i < Coordinates::num_max_dimensions; ++i)
44  {
45  position.set(i, w[i].start() + offset[i] * w[i].step());
46  }
47  return position;
48 }
49 
50 /** Tensor accessors to make it easier to interface with arm_gemm */
51 template <typename T>
53 {
54 public:
55  /** Constructor:
56  *
57  * @param[in] tensor Source tensor, must be allocated.
58  */
60  : _first(tensor.ptr_to_element(Coordinates())), _strides(tensor.info()->strides_in_bytes())
61  {
62  }
63  /** Get the stride of the dimension dim expressed in number of Ts.
64  *
65  * @param[in] dim Dimension of the wanted stride.
66  *
67  * @return Stride in number of Ts.
68  */
69  inline size_t stride(size_t dim) const
70  {
71  ARM_COMPUTE_ERROR_ON(_strides[dim] % sizeof(T) != 0);
72  return _strides[dim] / sizeof(T);
73  }
74 
75  /** Manually set the stride of a dimension
76  *
77  * @param[in] dim Dimension of the stride to set.
78  * @param[in] size Value to set the stride to (in bytes).
79  */
80  void set_stride(size_t dim, size_t size)
81  {
82  _strides[dim] = size;
83  }
84 
85  /** Manually set the strides
86  *
87  * @param[in] strides Strides to set
88  */
89  void set_strides(const Strides &strides)
90  {
91  _strides = strides;
92  }
93 
94  /** Returns a pointer to the element at coordinates (x,y,z,w)
95  *
96  * @param[in] x X coordinates
97  * @param[in] y (optional) Y coordinates
98  * @param[in] z (optional) Z coordinates
99  * @param[in] w (optional) W coordinates
100  */
101  inline T *get_ptr(unsigned int x, unsigned int y = 0, unsigned int z = 0, unsigned int w = 0)
102  {
103  return reinterpret_cast<T *>(_first + x * _strides[0] + y * _strides[1] + z * _strides[2] + w * _strides[3]);
104  }
105 
106  /** Returns a pointer to the element at coordinates (x,y,z,w)
107  *
108  * @param[in] x X coordinates
109  * @param[in] y (optional) Y coordinates
110  * @param[in] z (optional) Z coordinates
111  * @param[in] w (optional) W coordinates
112  */
113  inline T *operator()(unsigned int x, unsigned int y = 0, unsigned int z = 0, unsigned int w = 0)
114  {
115  return get_ptr(x, y, z, w);
116  }
117 
118  /** Returns a pointer to the first element of the tensor
119  *
120  * @return Pointer to the first element.
121  */
122  inline T *first_element()
123  {
124  return reinterpret_cast<T *>(_first);
125  }
126 
127  /** Returns a pointer to the first element of the tensor
128  *
129  * @return Pointer to the first element.
130  */
131  inline T *operator()()
132  {
133  return first_element();
134  }
135 
136 private:
137  uint8_t *_first; /**< Pointer to the first element of the tensor.*/
138  Strides _strides; /**< Strides in bytes of the tensor */
139 };
140 
141 /** Iterate over a portion of a Window */
142 template <typename L>
144 {
145 public:
146  /** Construct a WindowIterator object
147  *
148  * @param[in] w Window to use for the iteration
149  * @param[in] start Where to start iterating from (In Window coordinates)
150  * @param[in] end Where to stop iterating (In Window coordinates).
151  * @param[in] lambda_function Lambda function to call for every iteration between start and end. (It will be called last for end - 1)
152  */
153  WindowIterator(const Window &w, const Coordinates &start, const Coordinates &end, L &&lambda_function)
154  : _lambda_function(std::move(lambda_function)),
155  _position(convert_window_coord_to_position(w, start)),
157  _w(w)
158  {
159  }
160  /** Iterate over the lowest 3 dimensions of the window.
161  *
162  * @param[in] on_new_row_size Callback to be called before lambda_function every time the width of the row processed changes.
163  */
164  template <typename M>
165  void iterate_3D(M &&on_new_row_size)
166  {
167  while (_end.z() != _position.z())
168  {
169  iterate_2D_internal(on_new_row_size, _w.x().end() - _w.x().step(), _w.y().end() - _w.y().step());
170  _position[2] += _w.z().step();
171  _position[1] = _w.y().start();
172  _position[0] = _w.x().start();
173  }
174  // Left over:
175  iterate_2D(on_new_row_size);
176  }
177 
178  /** Iterate over the lowest 2 dimensions of the window.
179  *
180  * @param[in] on_new_row_size Callback to be called before lambda_function every time the width of the row processed changes.
181  */
182  template <typename M>
183  void iterate_2D(M &&on_new_row_size)
184  {
185  iterate_2D_internal(on_new_row_size, _end.x(), _end.y());
186  }
187 
188  /** Change the step used for the iteration.
189  *
190  * @note Does not affect the start and end points.
191  *
192  * @param[in] dim Dimension to change
193  * @param[in] step New step to use for the given dimension.
194  */
195  inline void set_step(size_t dim, int step)
196  {
197  _w.set_dimension_step(dim, step);
198  }
199 
200  /** Returns the coordinates in absolute coordinates of the end position
201  *
202  * @return End position coordinates.
203  */
204  const Coordinates &end_position() const
205  {
206  return _end;
207  }
208 
209 private:
210  template <typename M>
211  void iterate_2D_internal(M &&on_new_row_size, int end_x, int end_y)
212  {
213  //Is there more than one row to process ?
214  if (end_y == _position.y())
215  {
216  // Both start and end belong to the same row:
217  iterate_over_dim0(end_x + _w.x().step(), on_new_row_size);
218  }
219  else
220  {
221  // Do we start from the beginning of the row ?
222  if (_w.x().start() != _position.x())
223  {
224  //Start in the middle of a row: process left-over X
225  iterate_over_dim0(_w.x().end(), on_new_row_size);
226  _position[1] += _w.y().step();
227  }
228 
229  //Middle rows
230  bool no_leftover = end_x + _w.x().step() == _w.x().end();
231  if (no_leftover)
232  {
233  //Switch to full row size:
234  on_new_row_size(_w[0].start(), _w.x().end());
235  // Shouldn't be possible to reach that point and not have at least one entire row to process
236  ARM_COMPUTE_ERROR_ON(_w.y().end() == _position.y());
237  // No leftover: all the rows lefts to process are full width:
238  iterate_over_dim1(end_y + _w.y().step());
239  }
240  else
241  {
242  // Are there full rows to process ?
243  if (_position[1] != end_y)
244  {
245  //Switch to full row size:
246  on_new_row_size(_w[0].start(), _w.x().end());
247  iterate_over_dim1(end_y);
248  }
249 
250  //Leftover end x
251  _position[0] = _w.x().start();
252  iterate_over_dim0(end_x + _w.x().step(), on_new_row_size);
253  }
254  }
255  }
256 
257  /** Process full rows below 'end'
258  *
259  * @param[in] end Y position to stop at.
260  */
261  void iterate_over_dim1(int end)
262  {
263  for (; _position[1] != end; _position[1] += _w[1].step())
264  {
265  _position[0] = _w[0].start();
266  iterate_over_dim0(_w[0].end());
267  }
268  }
269 
270  /** Process elements of a given row up to 'end'
271  *
272  * @param[in] end X position to stop at.
273  * @param[in] on_new_row_size Callback to call before starting iterating
274  */
275  template <typename M>
276  void iterate_over_dim0(int end, M &&on_new_row_size)
277  {
278  on_new_row_size(_position.x(), end);
279  iterate_over_dim0(end);
280  }
281 
282  /** Process elements of a given row up to 'end'
283  *
284  * @param[in] end X position to stop at.
285  */
286  void iterate_over_dim0(int end)
287  {
288  // Both start and end belong to the same row:
289  ARM_COMPUTE_ERROR_ON(_position[0] > end);
290  for (; _position.x() < end; _position[0] += _w[0].step())
291  {
292  _lambda_function(_position);
293  }
294  }
295 
296  L _lambda_function; /**< Function to call for each iteration */
297  Coordinates _position; /**< Absolute coordinates of the current position */
298  Coordinates _end; /**< Absolute coordinates of the point after the last iteration */
299  Window _w; /**< Window to iterate over */
300 };
301 
302 /** Create a WindowIterator object
303  *
304  * @param[in] w Window to use for the iteration
305  * @param[in] start Where to start iterating from (In Window coordinates)
306  * @param[in] end Where to stop iterating (In Window coordinates).
307  * @param[in] lambda_function Lambda function to call for every iteration between start and end. (It will be called last for end - 1)
308  *
309  * @return A WindowIterator object.
310  */
311 template <typename L>
312 WindowIterator<L>
313 create_window_iterator(const Window &w, const Coordinates &start, const Coordinates &end, L &&lambda_function)
314 {
315  return WindowIterator<L>(w, start, end, std::move(lambda_function));
316 }
317 } // namespace arm_compute
318 #endif /*ARM_COMPUTE_WINDOW_ITERATOR_H*/
arm_compute::create_window_iterator
WindowIterator< L > create_window_iterator(const Window &w, const Coordinates &start, const Coordinates &end, L &&lambda_function)
Create a WindowIterator object.
Definition: WindowIterator.h:313
arm_compute::Window::Dimension::start
constexpr int start() const
Return the start of the dimension.
Definition: Window.h:96
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:75
arm_compute::TensorAccessor::operator()
T * operator()()
Returns a pointer to the first element of the tensor.
Definition: WindowIterator.h:131
arm_compute::Window::Dimension::step
constexpr int step() const
Return the step of the dimension.
Definition: Window.h:106
Window.h
arm_compute::WindowIterator::end_position
const Coordinates & end_position() const
Returns the coordinates in absolute coordinates of the end position.
Definition: WindowIterator.h:204
arm_compute::WindowIterator::WindowIterator
WindowIterator(const Window &w, const Coordinates &start, const Coordinates &end, L &&lambda_function)
Construct a WindowIterator object.
Definition: WindowIterator.h:153
arm_compute::ITensor
Interface for CPU tensor.
Definition: ITensor.h:36
Error.h
arm_compute::WindowIterator::iterate_3D
void iterate_3D(M &&on_new_row_size)
Iterate over the lowest 3 dimensions of the window.
Definition: WindowIterator.h:165
arm_compute::Dimensions::z
T z() const
Alias to access the size of the third dimension.
Definition: Dimensions.h:96
arm_compute::Strides
Strides of an item in bytes.
Definition: Strides.h:38
arm_compute::WindowIterator::set_step
void set_step(size_t dim, int step)
Change the step used for the iteration.
Definition: WindowIterator.h:195
arm_compute::Window::set_dimension_step
void set_dimension_step(size_t dimension, int step)
Set the step of a given dimension.
Definition: Window.inl:181
ARM_COMPUTE_ERROR_ON
#define ARM_COMPUTE_ERROR_ON(cond)
If the condition is true then an error message is printed and an exception thrown.
Definition: Error.h:466
Coordinates.h
arm_compute::WindowIterator
Iterate over a portion of a Window.
Definition: WindowIterator.h:143
arm_compute::test::validation::w
SimpleTensor< float > w
Definition: DFT.cpp:156
arm_compute::Window::y
constexpr const Dimension & y() const
Alias to access the second dimension of the window.
Definition: Window.h:167
arm_compute::TensorAccessor::first_element
T * first_element()
Returns a pointer to the first element of the tensor.
Definition: WindowIterator.h:122
offset
__global uchar * offset(const Image *img, int x, int y)
Get the pointer position of a Image.
Definition: helpers.h:1128
arm_compute::Dimensions::x
T x() const
Alias to access the size of the first dimension.
Definition: Dimensions.h:86
arm_compute::WindowIterator::iterate_2D
void iterate_2D(M &&on_new_row_size)
Iterate over the lowest 2 dimensions of the window.
Definition: WindowIterator.h:183
arm_compute::convert_window_coord_to_position
Coordinates convert_window_coord_to_position(const Window &w, const Coordinates &offset)
Convert an offset in window steps into absolute coordinates.
Definition: WindowIterator.h:40
arm_compute::Coordinates
Coordinates of an item.
Definition: Coordinates.h:37
tensor
CLTensor * tensor
Pointer to the auxiliary tensor.
Definition: ClWorkloadRuntime.cpp:67
arm_compute::TensorAccessor::stride
size_t stride(size_t dim) const
Get the stride of the dimension dim expressed in number of Ts.
Definition: WindowIterator.h:69
arm_compute::TensorAccessor::set_strides
void set_strides(const Strides &strides)
Manually set the strides.
Definition: WindowIterator.h:89
arm_compute::TensorAccessor::get_ptr
T * get_ptr(unsigned int x, unsigned int y=0, unsigned int z=0, unsigned int w=0)
Returns a pointer to the element at coordinates (x,y,z,w)
Definition: WindowIterator.h:101
M
unsigned int M
Definition: CpuGemmAssemblyDispatch.cpp:102
arm_compute::Window
Describe a multidimensional execution window.
Definition: Window.h:39
arm_compute::TensorAccessor::set_stride
void set_stride(size_t dim, size_t size)
Manually set the stride of a dimension.
Definition: WindowIterator.h:80
arm_compute
Copyright (c) 2017-2023 Arm Limited.
Definition: introduction.dox:24
arm_compute::mlgo::parser::end
void end(TokenStream &in, bool &valid)
Definition: MLGOParser.cpp:283
ITensor.h
arm_compute::test::validation::info
ScaleKernelInfo info(interpolation_policy, default_border_mode, PixelValue(), sampling_policy, false)
arm_compute::cpu::step
constexpr int step
Definition: fp32.cpp:35
arm_compute::Window::Dimension::end
constexpr int end() const
Return the end of the dimension.
Definition: Window.h:101
arm_compute::Dimensions::y
T y() const
Alias to access the size of the second dimension.
Definition: Dimensions.h:91
arm_compute::TensorAccessor::TensorAccessor
TensorAccessor(const ITensor &tensor)
Constructor:
Definition: WindowIterator.h:59
arm_compute::TensorAccessor::operator()
T * operator()(unsigned int x, unsigned int y=0, unsigned int z=0, unsigned int w=0)
Returns a pointer to the element at coordinates (x,y,z,w)
Definition: WindowIterator.h:113
arm_compute::Window::x
constexpr const Dimension & x() const
Alias to access the first dimension of the window.
Definition: Window.h:158
arm_compute::Dimensions< int >::num_max_dimensions
static constexpr size_t num_max_dimensions
Number of dimensions the tensor has.
Definition: Dimensions.h:46
arm_compute::TensorAccessor
Tensor accessors to make it easier to interface with arm_gemm.
Definition: WindowIterator.h:52
arm_compute::Window::z
constexpr const Dimension & z() const
Alias to access the third dimension of the window.
Definition: Window.h:176