Compute Library
 23.11
WindowHelpers.cpp
Go to the documentation of this file.
1 /*
2 * Copyright (c) 2020-2022 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  */
25 
26 namespace arm_compute
27 {
28 Window
29 calculate_max_window(const ValidRegion &valid_region, const Steps &steps, bool skip_border, BorderSize border_size)
30 {
31  if (!skip_border)
32  {
33  border_size = BorderSize(0);
34  }
35 
36  const Coordinates &anchor = valid_region.anchor;
38 
39  Window window;
40 
41  window.set(0, Window::Dimension(
42  // Skip the border left of the image
43  anchor[0] + border_size.left,
44  // Skip the border right of the image
45  // Make sure the window width is a multiple of the step size
46  anchor[0] + border_size.left +
47  ceil_to_multiple(std::max(0, static_cast<int>(shape[0]) - static_cast<int>(border_size.left) -
48  static_cast<int>(border_size.right)),
49  steps[0]),
50  steps[0]));
51 
52  size_t n = 1;
53 
54  if (anchor.num_dimensions() > 1)
55  {
56  window.set(1,
58  // Skip the border above the image
59  anchor[1] + border_size.top,
60  // Skip the border below the image
61  anchor[1] + border_size.top +
62  ceil_to_multiple(std::max(0, static_cast<int>(shape[1]) - static_cast<int>(border_size.top) -
63  static_cast<int>(border_size.bottom)),
64  steps[1]),
65  steps[1]));
66 
67  ++n;
68  }
69 
70  if (anchor.num_dimensions() > 2)
71  {
72  window.set(2, Window::Dimension(anchor[2], std::max<size_t>(1, shape[2]), steps[2]));
73 
74  ++n;
75  }
76 
77  for (; n < anchor.num_dimensions(); ++n)
78  {
79  window.set(n, Window::Dimension(anchor[n], std::max<size_t>(1, shape[n])));
80  }
81 
82  for (; n < Coordinates::num_max_dimensions; ++n)
83  {
84  window.set(n, Window::Dimension(0, 1));
85  }
86 
87  return window;
88 }
89 
90 Window calculate_max_window(const TensorShape &shape, const Steps &steps, bool skip_border, BorderSize border_size)
91 {
92  if (!skip_border)
93  {
94  border_size = BorderSize(0);
95  }
96 
97  Window window;
98 
99  window.set(0, Window::Dimension(
100  // Skip the border left of the image
101  border_size.left,
102  // Skip the border right of the image
103  // Make sure the window width is a multiple of the step size
104  border_size.left +
105  ceil_to_multiple(std::max(0, static_cast<int>(shape[0]) - static_cast<int>(border_size.left) -
106  static_cast<int>(border_size.right)),
107  steps[0]),
108  steps[0]));
109 
110  size_t n = 1;
111 
112  if (shape.num_dimensions() > 1)
113  {
114  window.set(1, Window::Dimension(
115  // Skip the border above the image
116  border_size.top,
117  // Skip the border below the image
118  border_size.top + ceil_to_multiple(std::max(0, static_cast<int>(shape[1]) -
119  static_cast<int>(border_size.top) -
120  static_cast<int>(border_size.bottom)),
121  steps[1]),
122  steps[1]));
123 
124  ++n;
125  }
126 
127  if (shape.num_dimensions() > 2)
128  {
129  window.set(2, Window::Dimension(0, std::max<size_t>(1, shape[2]), steps[2]));
130 
131  ++n;
132  }
133 
134  for (; n < shape.num_dimensions(); ++n)
135  {
136  window.set(n, Window::Dimension(0, std::max<size_t>(1, shape[n])));
137  }
138 
139  for (; n < Coordinates::num_max_dimensions; ++n)
140  {
141  window.set(n, Window::Dimension(0, 1));
142  }
143 
144  return window;
145 }
146 
148 {
149  const Coordinates &anchor = valid_region.anchor;
151 
152  Window window;
153 
154  window.set(0, Window::Dimension(
155  // move the anchor to the start from the border
156  anchor[0] - border_size.left,
157  // move the anchor to include the right end border
158  // Make sure the window width is a multiple of the step size
159  anchor[0] - border_size.left +
160  ceil_to_multiple(shape[0] + border_size.left + border_size.right, steps[0]),
161  steps[0]));
162 
163  size_t n = 1;
164 
165  if (anchor.num_dimensions() > 1)
166  {
167  window.set(1, Window::Dimension(
168  // Include the border above the image
169  anchor[1] - border_size.top,
170  // Include the border below the image
171  anchor[1] - border_size.top +
172  ceil_to_multiple(shape[1] + border_size.top + border_size.bottom, steps[1]),
173  steps[1]));
174 
175  ++n;
176  }
177 
178  if (anchor.num_dimensions() > 2)
179  {
180  window.set(2, Window::Dimension(0, std::max<size_t>(1, shape[n]), steps[2]));
181 
182  ++n;
183  }
184 
185  for (; n < anchor.num_dimensions(); ++n)
186  {
187  window.set(n, Window::Dimension(anchor[n], std::max<size_t>(1, shape[n])));
188  }
189 
190  for (; n < Coordinates::num_max_dimensions; ++n)
191  {
192  window.set(n, Window::Dimension(0, 1));
193  }
194 
195  return window;
196 }
197 
199  const Steps &steps,
200  bool skip_border,
201  BorderSize border_size)
202 {
203  if (skip_border)
204  {
205  border_size.top = 0;
206  border_size.bottom = 0;
207  }
208  else
209  {
210  border_size.left = 0;
211  border_size.right = 0;
212  }
213 
214  const Coordinates &anchor = valid_region.anchor;
216 
217  Window window;
218 
219  window.set(0, Window::Dimension(
220  // Skip the border left of the image
221  anchor[0] + border_size.left,
222  // Skip the border right of the image
223  // Make sure the window width is a multiple of the step size
224  anchor[0] + border_size.left +
225  ceil_to_multiple(std::max(0, static_cast<int>(shape[0]) - static_cast<int>(border_size.left) -
226  static_cast<int>(border_size.right)),
227  steps[0]),
228  steps[0]));
229 
230  size_t n = 1;
231 
232  if (anchor.num_dimensions() > 1)
233  {
234  window.set(1, Window::Dimension(
235  // Skip the border above the image
236  anchor[1] - border_size.top,
237  // Skip the border below the image
238  anchor[1] + shape[1] + border_size.bottom, 1));
239 
240  ++n;
241  }
242 
243  for (; n < anchor.num_dimensions(); ++n)
244  {
245  window.set(n, Window::Dimension(anchor[n], std::max<size_t>(1, shape[n])));
246  }
247 
248  for (; n < Coordinates::num_max_dimensions; ++n)
249  {
250  window.set(n, Window::Dimension(0, 1));
251  }
252 
253  return window;
254 }
255 
256 std::pair<Window, size_t> calculate_squashed_or_max_window(const ITensorInfo &src0, const ITensorInfo &src1)
257 {
258  const auto &shape0 = src0.tensor_shape();
259  const auto &shape1 = src1.tensor_shape();
260  const auto &strides0 = src0.strides_in_bytes();
261  const auto &strides1 = src1.strides_in_bytes();
262  const auto num_dimensions = std::max(src0.num_dimensions(), src1.num_dimensions());
263 
264  Window win;
265  size_t split_dimension = Window::DimY;
266  size_t dim = 0;
267 
268  size_t squashed_bytes = src0.element_size();
269 
270  // Try to squash the low dimensions together.
271  for (; dim < num_dimensions; ++dim)
272  {
273  if (shape0[dim] != shape1[dim] || strides0[dim] != squashed_bytes || strides1[dim] != squashed_bytes)
274  {
275  break;
276  }
277 
278  squashed_bytes *= shape0[dim];
279  }
280 
281  if (dim == num_dimensions)
282  {
283  auto squashed_elements = squashed_bytes / src0.element_size();
284 
285  split_dimension = Window::DimX;
286 
287  // The input tensors can be interpreted as 1D array.
288  win.set(0, Window::Dimension(0, squashed_elements, 1));
289 
290  for (dim = 1; dim < Coordinates::num_max_dimensions; ++dim)
291  {
292  win.set(dim, Window::Dimension(0, 1, 1));
293  }
294  }
295  else
296  {
297  // Generates the max window.
298  for (dim = 0; dim < Coordinates::num_max_dimensions; ++dim)
299  {
300  win.set(dim, Window::Dimension(0, std::max(shape0[dim], shape1[dim]), 1));
301  }
302  }
303 
304  return std::make_pair(win, split_dimension);
305 }
306 
307 std::pair<Window, size_t> calculate_squashed_or_max_window(const ITensorInfo &src)
308 {
309  const auto &shape = src.tensor_shape();
310  const auto &strides = src.strides_in_bytes();
311  const auto num_dimensions = src.num_dimensions();
312 
313  Window win;
314  size_t split_dimension = Window::DimY;
315  size_t dim = 0;
316  size_t squashed_bytes = src.element_size();
317 
318  // Try to squash the low dimensions together.
319  for (; dim < num_dimensions; ++dim)
320  {
321  if (strides[dim] != squashed_bytes)
322  {
323  break;
324  }
325  squashed_bytes *= shape[dim];
326  }
327  if (dim == num_dimensions)
328  {
329  const auto squashed_elements = squashed_bytes / src.element_size();
330  split_dimension = Window::DimX;
331  // The input tensor can be interpreted as 1D array.
332  win.set(0, Window::Dimension(0, squashed_elements, 1));
333  for (dim = 1; dim < Coordinates::num_max_dimensions; ++dim)
334  {
335  win.set(dim, Window::Dimension(0, 1, 1));
336  }
337  }
338  else
339  {
340  // Generate the max window.
341  for (dim = 0; dim < Coordinates::num_max_dimensions; ++dim)
342  {
343  win.set(dim, Window::Dimension(0, shape[dim], 1));
344  }
345  }
346  return std::make_pair(win, split_dimension);
347 }
348 
349 } // namespace arm_compute
arm_compute::Steps
Class to describe a number of elements in each dimension.
Definition: Steps.h:40
arm_compute::BorderSize::right
unsigned int right
right of the border
Definition: Types.h:340
arm_compute::test::validation::src
SimpleTensor< float > src
Definition: DFT.cpp:155
arm_compute::ITensorInfo::tensor_shape
virtual const TensorShape & tensor_shape() const =0
Size for each dimension of the tensor.
arm_compute::calculate_max_window
Window calculate_max_window(const ValidRegion &valid_region, const Steps &steps, bool skip_border, BorderSize border_size)
Definition: WindowHelpers.cpp:29
arm_compute::BorderSize
Container for 2D border size.
Definition: Types.h:239
arm_compute::TensorShape
Shape of a tensor.
Definition: TensorShape.h:39
arm_compute::ITensorInfo::element_size
virtual size_t element_size() const =0
Element size in bytes calculated as data_size() * num_channels()
arm_compute::Window::DimX
static constexpr size_t DimX
Alias for dimension 0 also known as X dimension.
Definition: Window.h:43
arm_compute::BorderSize::top
unsigned int top
top of the border
Definition: Types.h:339
arm_compute::test::validation::valid_region
const ValidRegion valid_region
Definition: Scale.cpp:214
arm_compute::test::validation::shape
shape
Definition: DFT.cpp:115
arm_compute::BorderSize::bottom
unsigned int bottom
bottom of the border
Definition: Types.h:341
arm_compute::calculate_max_window_horizontal
Window calculate_max_window_horizontal(const ValidRegion &valid_region, const Steps &steps, bool skip_border, BorderSize border_size)
Definition: WindowHelpers.cpp:198
arm_compute::ValidRegion
Container for valid region of a window.
Definition: Types.h:143
WindowHelpers.h
arm_compute::Coordinates
Coordinates of an item.
Definition: Coordinates.h:37
arm_compute::Window::Dimension
Describe one of the image's dimensions with a start, end and step.
Definition: Window.h:79
arm_compute::Window::set
void set(size_t dimension, const Dimension &dim)
Set the values of a given dimension.
Definition: Window.inl:53
arm_compute::Window::DimY
static constexpr size_t DimY
Alias for dimension 1 also known as Y dimension.
Definition: Window.h:45
arm_compute::ceil_to_multiple
auto ceil_to_multiple(S value, T divisor) -> decltype(((value+divisor - 1)/divisor) *divisor)
Computes the smallest number larger or equal to value that is a multiple of divisor.
Definition: Math.h:50
arm_compute::Window
Describe a multidimensional execution window.
Definition: Window.h:39
arm_compute::ValidRegion::shape
TensorShape shape
Shape of the valid region.
Definition: Types.h:223
arm_compute::calculate_squashed_or_max_window
std::pair< Window, size_t > calculate_squashed_or_max_window(const ITensorInfo &src0, const ITensorInfo &src1)
Definition: WindowHelpers.cpp:256
arm_compute
Copyright (c) 2017-2023 Arm Limited.
Definition: introduction.dox:24
arm_compute::BorderSize::left
unsigned int left
left of the border
Definition: Types.h:342
arm_compute::ITensorInfo::strides_in_bytes
virtual const Strides & strides_in_bytes() const =0
The strides in bytes for accessing each dimension of the tensor.
arm_compute::ITensorInfo
Store the tensor's metadata.
Definition: ITensorInfo.h:44
arm_compute::calculate_max_enlarged_window
Window calculate_max_enlarged_window(const ValidRegion &valid_region, const Steps &steps, BorderSize border_size)
Definition: WindowHelpers.cpp:147
arm_compute::Dimensions::num_dimensions
unsigned int num_dimensions() const
Returns the effective dimensionality of the tensor.
Definition: Dimensions.h:142
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::ITensorInfo::num_dimensions
virtual size_t num_dimensions() const =0
The number of dimensions of the tensor (rank)
arm_compute::ValidRegion::anchor
Coordinates anchor
Anchor for the start of the valid region.
Definition: Types.h:222