xref: /aosp_15_r20/external/ComputeLibrary/src/core/helpers/WindowHelpers.h (revision c217d954acce2dbc11938adb493fc0abd69584f3)
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  */
24 #ifndef SRC_CORE_HELPERS_WINDOWHELPERS_H
25 #define SRC_CORE_HELPERS_WINDOWHELPERS_H
26 
27 #include "arm_compute/core/IAccessWindow.h"
28 #include "arm_compute/core/Steps.h"
29 #include "arm_compute/core/Window.h"
30 
31 namespace arm_compute
32 {
33 /** Update window and padding size for each of the access patterns.
34  *
35  * First the window size is reduced based on all access patterns that are not
36  * allowed to modify the padding of the underlying tensor. Then the padding of
37  * the remaining tensors is increased to match the window.
38  *
39  * @param[in] win      Window that is used by the kernel.
40  * @param[in] patterns Access patterns used to calculate the final window and padding.
41  *
42  * @return True if the window has been changed. Changes to the padding do not
43  *         influence the returned value.
44  */
45 template <typename... Ts>
update_window_and_padding(Window & win,Ts &&...patterns)46 bool update_window_and_padding(Window &win, Ts &&... patterns)
47 {
48     bool window_changed = false;
49 
50     utility::for_each([&](const IAccessWindow & w)
51     {
52         window_changed |= w.update_window_if_needed(win);
53     },
54     patterns...);
55 
56     utility::for_each([&](IAccessWindow & w)
57     {
58         w.update_padding_if_needed(win);
59     },
60     patterns...);
61 
62     return window_changed;
63 }
64 
65 /** Intersect multiple valid regions.
66  *
67  * @param[in] regions Valid regions.
68  *
69  * @return Intersection of all regions.
70  */
71 template <typename... Ts>
intersect_valid_regions(const Ts &...regions)72 ValidRegion intersect_valid_regions(const Ts &... regions)
73 {
74     auto intersect = [](const ValidRegion & r1, const ValidRegion & r2) -> ValidRegion
75     {
76         ValidRegion region;
77 
78         for(size_t d = 0; d < std::min(r1.anchor.num_dimensions(), r2.anchor.num_dimensions()); ++d)
79         {
80             region.anchor.set(d, std::max(r1.anchor[d], r2.anchor[d]));
81         }
82 
83         for(size_t d = 0; d < std::min(r1.shape.num_dimensions(), r2.shape.num_dimensions()); ++d)
84         {
85             region.shape.set(d, std::min(r1.shape[d], r2.shape[d]));
86         }
87 
88         return region;
89     };
90 
91     return utility::foldl(intersect, regions...);
92 }
93 
94 #ifndef DOXYGEN_SKIP_THIS
95 /** Calculate the maximum window for a given tensor shape and border setting
96  *
97  * @param[in] valid_region Valid region object defining the shape of the tensor space for which the window is created.
98  * @param[in] steps        (Optional) Number of elements processed for each step.
99  * @param[in] skip_border  (Optional) If true exclude the border region from the window.
100  * @param[in] border_size  (Optional) Border size.
101  *
102  * @return The maximum window the kernel can be executed on.
103  */
104 Window calculate_max_window(const ValidRegion &valid_region, const Steps &steps = Steps(), bool skip_border = false, BorderSize border_size = BorderSize());
105 
106 /** Calculate the maximum window for a given tensor shape and border setting
107  *
108  * @param[in] shape       Shape of the tensor space
109  * @param[in] steps       (Optional) Number of elements processed for each step.
110  * @param[in] skip_border (Optional) If true exclude the border region from the window.
111  * @param[in] border_size (Optional) Border size.
112  *
113  * @return The maximum window the kernel can be executed on.
114  */
115 Window calculate_max_window(const TensorShape &shape, const Steps &steps = Steps(), bool skip_border = false, BorderSize border_size = BorderSize());
116 
117 /** Calculate the maximum window for a given tensor shape and border setting
118  *
119  * @param[in] info        Tensor info object defining the shape of the object for which the window is created.
120  * @param[in] steps       (Optional) Number of elements processed for each step.
121  * @param[in] skip_border (Optional) If true exclude the border region from the window.
122  * @param[in] border_size (Optional) Border size.
123  *
124  * @return The maximum window the kernel can be executed on.
125  */
126 inline Window calculate_max_window(const ITensorInfo &info, const Steps &steps = Steps(), bool skip_border = false, BorderSize border_size = BorderSize())
127 {
128     return calculate_max_window(info.tensor_shape(), steps, skip_border, border_size);
129 }
130 
131 /** Calculate the maximum window used by a horizontal kernel for a given tensor shape and border setting
132  *
133  * @param[in] valid_region Valid region object defining the shape of the tensor space for which the window is created.
134  * @param[in] steps        (Optional) Number of elements processed for each step.
135  * @param[in] skip_border  (Optional) If true exclude the border region from the window.
136  * @param[in] border_size  (Optional) Border size. The border region will be excluded from the window.
137  *
138  * @return The maximum window the kernel can be executed on.
139  */
140 Window calculate_max_window_horizontal(const ValidRegion &valid_region, const Steps &steps = Steps(), bool skip_border = false, BorderSize border_size = BorderSize());
141 
142 /** Calculate the maximum window used by a horizontal kernel for a given tensor shape and border setting
143  *
144  * @param[in] info        Tensor info object defining the shape of the object for which the window is created.
145  * @param[in] steps       (Optional) Number of elements processed for each step.
146  * @param[in] skip_border (Optional) If true exclude the border region from the window.
147  * @param[in] border_size (Optional) Border size.
148  *
149  * @return The maximum window the kernel can be executed on.
150  */
151 inline Window calculate_max_window_horizontal(const ITensorInfo &info, const Steps &steps = Steps(), bool skip_border = false, BorderSize border_size = BorderSize())
152 {
153     return calculate_max_window_horizontal(info.valid_region(), steps, skip_border, border_size);
154 }
155 
156 /** Calculate the maximum window for a given tensor shape and border setting. The window will also includes the border.
157  *
158  * @param[in] valid_region Valid region object defining the shape of the tensor space for which the window is created.
159  * @param[in] steps        (Optional) Number of elements processed for each step.
160  * @param[in] border_size  (Optional) Border size. The border region will be included in the window.
161  *
162  * @return The maximum window the kernel can be executed on.
163  */
164 Window calculate_max_enlarged_window(const ValidRegion &valid_region, const Steps &steps = Steps(), BorderSize border_size = BorderSize());
165 
166 /** Calculate the maximum window for a given tensor shape and border setting. The window will also includes the border.
167  *
168  * @param[in] info        Tensor info object defining the shape of the object for which the window is created.
169  * @param[in] steps       (Optional) Number of elements processed for each step.
170  * @param[in] border_size (Optional) Border size. The border region will be included in the window.
171  *
172  * @return The maximum window the kernel can be executed on.
173  */
174 inline Window calculate_max_enlarged_window(const ITensorInfo &info, const Steps &steps = Steps(), BorderSize border_size = BorderSize())
175 {
176     return calculate_max_enlarged_window(info.valid_region(), steps, border_size);
177 }
178 
179 /** Calculate the squashed or maximum window for the given tensor shape.
180  *
181  * If the tensor data resides continuously in the memory, the tensor can be interpreted
182  * as 1D array and all the dimensions can be squashed together into the x-dimension.
183  * Otherwise, generate the max window for the given tensor shape.
184  *
185  * @param[in] src Tensor info object defining the shape of the input tensor.
186  *
187  * @return The maximum window the kernel can be executed on and the preferred split dimension.
188  */
189 std::pair<Window, size_t> calculate_squashed_or_max_window(const ITensorInfo &src);
190 
191 /** Calculate the squashed or maximum window for the given tensor shapes.
192  *
193  * If the tensor data resides continuously in the memory, the tensor can be interpreted
194  * as 1D array and all the dimensions can be squashed together into the x-dimension.
195  * Otherwise, generate the max window for the given tensor shapes.
196  *
197  * @param[in] src0 Tensor info object defining the shape of the first input tensor.
198  * @param[in] src1 Tensor info object defining the shape of the second input tensor.
199  *
200  * @return The squashed or maximum window the kernel can be executed on and the preferred split dimension.
201  */
202 std::pair<Window, size_t> calculate_squashed_or_max_window(const ITensorInfo &src0, const ITensorInfo &src1);
203 
204 /** Function to compute the shape of output and window for the given inputs
205  *
206  * @param[in] infos Input tensor informations
207  *
208  * @return A pair of the shape and window
209  */
210 template <typename... Shapes>
compute_output_shape_and_window(const Shapes &...shapes)211 std::pair<TensorShape, Window> compute_output_shape_and_window(const Shapes &... shapes)
212 {
213     const TensorShape out_shape = TensorShape::broadcast_shape(shapes...);
214     return std::make_pair(out_shape, calculate_max_window(out_shape));
215 }
216 #endif /* DOXYGEN_SKIP_THIS */
217 } // namespace arm_compute
218 
219 #endif /* SRC_CORE_HELPERS_WINDOWHELPERS_H */
220