xref: /aosp_15_r20/external/ComputeLibrary/arm_compute/core/IAccessWindow.h (revision c217d954acce2dbc11938adb493fc0abd69584f3)
1 /*
2  * Copyright (c) 2017-2019 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_IACCESS_WINDOW_H
25 #define ARM_COMPUTE_IACCESS_WINDOW_H
26 
27 #include "arm_compute/core/Coordinates.h"
28 #include "arm_compute/core/TensorShape.h"
29 #include "arm_compute/core/Types.h"
30 
31 #include <array>
32 
33 namespace arm_compute
34 {
35 class Window;
36 class ITensorInfo;
37 
38 /** Decrease @p required in steps of @p step until it's less than @p available.
39  *
40  * @param[in] required  Number of required bytes.
41  * @param[in] available Number of available bytes.
42  * @param[in] step      Step size used to decrease required bytes.
43  *
44  * @return Largest value smaller than @p available that is a multiple of @p step
45  *
46  **/
adjust_down(int required,int available,int step)47 inline int adjust_down(int required, int available, int step)
48 {
49     ARM_COMPUTE_ERROR_ON(step <= 0);
50 
51     return required - step * ((required - available + step - 1) / step);
52 }
53 
54 /** Increase @p required in steps of @p step until it's greater than @p available.
55  *
56  * @param[in] required  Number of required bytes.
57  * @param[in] available Number of available bytes.
58  * @param[in] step      Step size used to increase required bytes.
59  *
60  * @return Largest value smaller than @p available that is a multiple of @p step
61  *
62  **/
adjust_up(int required,int available,int step)63 inline int adjust_up(int required, int available, int step)
64 {
65     ARM_COMPUTE_ERROR_ON(step <= 0);
66 
67     return required + step * ((available - required + step - 1) / step);
68 }
69 
70 /** Interface describing methods to update access window and padding based on kernel parameters. */
71 class IAccessWindow
72 {
73 public:
74     /** Default virtual destructor */
75     virtual ~IAccessWindow() = default;
76     /** Shrink the window if padding is not large enough.
77      *
78      * @param[in] window Window used by the kernel.
79      *
80      * @return True if the window has been changed.
81      *
82      */
83     virtual bool update_window_if_needed(Window &window) const = 0;
84     /** Increase the padding to be large enough for the window.
85      *
86      * @param[in] window Window used by the kernel.
87      *
88      * @return True if the padding has been changed.
89      */
90     virtual bool update_padding_if_needed(const Window &window) = 0;
91     /** Compute the valid region based on access pattern and valid region of the inputs.
92      *
93      * @note This method assumes that there is no border.
94      *
95      * @param[in] window             Execution window of the kernel.
96      * @param[in] input_valid_region Combined valid region of all inputs.
97      * @param[in] border_undefined   Undefined borders are excluded from the valid region.
98      * @param[in] border_size        Size of the border around the XY-plane of the tensor.
99      *
100      * @return a valid region.
101      *
102      */
103     virtual ValidRegion compute_valid_region(const Window &window, ValidRegion input_valid_region, bool border_undefined, BorderSize border_size) const = 0;
104 };
105 
106 /** Implementation of a rectangular access pattern. */
107 class AccessWindowRectangle : public IAccessWindow
108 {
109 public:
110     /** Constructor for a rectangular access pattern.
111      *
112      * @note Width and height have to be non-negative.
113      *
114      * @param[in,out] info   Tensor info of the accessed kernel.
115      * @param[in]     x      Offset of the access in X direction.
116      * @param[in]     y      Offset of the access in Y direction.
117      * @param[in]     width  Number of elements that are accessed in X direction.
118      * @param[in]     height Number of elements that are accessed in Y direction.
119      */
AccessWindowRectangle(ITensorInfo * info,int x,int y,int width,int height)120     AccessWindowRectangle(ITensorInfo *info, int x, int y, int width, int height)
121         : AccessWindowRectangle(info, x, y, width, height, 1.f, 1.f)
122     {
123     }
124 
125     /** Constructor for a rectangular access pattern.
126      *
127      * @note Width, height and scale have to be non-negative.
128      *
129      * @param[in,out] info    Tensor info of the accessed kernel.
130      * @param[in]     x       Offset of the access in X direction.
131      * @param[in]     y       Offset of the access in Y direction.
132      * @param[in]     width   Number of elements that are accessed in X direction.
133      * @param[in]     height  Number of elements that are accessed in Y direction.
134      * @param[in]     scale_x Ratio along the X direction between the window used by the execute_window_loop and the rectangular access pattern defined
135      * @param[in]     scale_y Ratio along the Y direction between the window used by the execute_window_loop and the rectangular access pattern defined
136      */
AccessWindowRectangle(ITensorInfo * info,int x,int y,int width,int height,float scale_x,float scale_y)137     AccessWindowRectangle(ITensorInfo *info, int x, int y, int width, int height, float scale_x, float scale_y)
138         : _info(info), _x(x), _y(y), _width(width), _height(height), _scale_x(scale_x), _scale_y(scale_y)
139     {
140         ARM_COMPUTE_ERROR_ON(width < 0);
141         ARM_COMPUTE_ERROR_ON(height < 0);
142         ARM_COMPUTE_ERROR_ON(scale_x < 0);
143         ARM_COMPUTE_ERROR_ON(scale_y < 0);
144     }
145 
146     /** Prevent instances of this class from being copied (As this class contains pointers) */
147     AccessWindowRectangle(const AccessWindowRectangle &) = delete;
148     /** Allow instances of this class to be move constructed */
149     AccessWindowRectangle(AccessWindowRectangle &&) = default;
150     /** Prevent instances of this class from being copied (As this class contains pointers) */
151     AccessWindowRectangle &operator=(const AccessWindowRectangle &) = delete;
152     /** Allow instances of this class to be moved */
153     AccessWindowRectangle &operator=(AccessWindowRectangle &&) = default;
154     /** Default destructor */
155     ~AccessWindowRectangle() = default;
156 
157     /** Set the valid region based on access pattern, valid region of the inputs and border mode.
158      *
159      * @param[in] window             Execution window of the kernel.
160      * @param[in] input_valid_region Combined valid region of all inputs.
161      * @param[in] border_undefined   (Optional) Undefined borders are excluded from the valid region.
162      * @param[in] border_size        (Optional) Size of the border around the XY-plane of the tensor.
163      */
164     void set_valid_region(const Window &window, const ValidRegion &input_valid_region, bool border_undefined = false, const BorderSize &border_size = BorderSize(0));
165 
166     /** Compute the valid region based on access pattern, valid region of the inputs and border mode.
167      *
168      * @note This method assumes that there is no border.
169      *
170      * @param[in] window             Execution window of the kernel.
171      * @param[in] input_valid_region Combined valid region of all inputs.
172      *
173      * @return a valid region.
174      *
175      */
176     ValidRegion compute_valid_region(const Window &window, const ValidRegion &input_valid_region) const;
177 
178     // Inherited methods overridden:
179 
180     /** Compute the valid region based on access pattern and valid region of the inputs.
181      *
182      * @note This method assumes that all elements written by the kernel are valid.
183      *
184      * @param[in] window             Execution window of the kernel.
185      * @param[in] input_valid_region Combined valid region of all inputs.
186      * @param[in] border_undefined   Undefined borders are excluded from the valid region.
187      * @param[in] border_size        Size of the border around the XY-plane of the tensor.
188      *
189      * @return a valid region.
190      *
191      */
192     ValidRegion compute_valid_region(const Window &window, ValidRegion input_valid_region, bool border_undefined, BorderSize border_size) const override;
193 
194     bool update_window_if_needed(Window &window) const override;
195     bool update_padding_if_needed(const Window &window) override;
196 
197 protected:
198     PaddingSize get_needed_padding(const Window &window) const;
199 
200 protected:
201     ITensorInfo *_info;
202     int          _x;
203     int          _y;
204     int          _width;
205     int          _height;
206     float        _scale_x;
207     float        _scale_y;
208 };
209 
210 /** Implementation of a column access pattern. */
211 class AccessWindowVertical : public AccessWindowRectangle
212 {
213 public:
214     /** Constructor for a column access pattern.
215      *
216      * @note Height has to be non-negative.
217      *
218      * @param[in,out] info    Tensor info of the accessed kernel.
219      * @param[in]     y       Offset of the access in Y direction.
220      * @param[in]     height  Number of elements that are accessed in Y direction.
221      * @param[in]     scale_y Ratio along the Y direction between the window used by the execute_window_loop and the rectangular access pattern defined
222      */
223     AccessWindowVertical(ITensorInfo *info, int y, int height, float scale_y = 1.f)
224         : AccessWindowRectangle(info, 0, y, 1, height, 1.f, scale_y)
225     {
226         ARM_COMPUTE_ERROR_ON(height < 0);
227         ARM_COMPUTE_ERROR_ON(scale_y < 0);
228     }
229 };
230 
231 /** Implementation of a row access pattern. */
232 class AccessWindowHorizontal : public AccessWindowRectangle
233 {
234 public:
235     /** Constructor for a row access pattern.
236      *
237      * @note Width has to be non-negative.
238      *
239      * @param[in,out] info    Tensor info of the accessed kernel.
240      * @param[in]     x       Offset of the access in X direction.
241      * @param[in]     width   Number of elements that are accessed in X direction.
242      * @param[in]     scale_x Ratio along the X direction between the window used by the execute_window_loop and the rectangular access pattern defined
243      */
244     AccessWindowHorizontal(ITensorInfo *info, int x, int width, float scale_x = 1.f)
245         : AccessWindowRectangle(info, x, 0, width, 1, scale_x, 1.f)
246     {
247         ARM_COMPUTE_ERROR_ON(width < 0);
248         ARM_COMPUTE_ERROR_ON(scale_x < 0);
249     }
250 };
251 } // namespace arm_compute
252 #endif /*ARM_COMPUTE_IACCESS_WINDOW_H*/
253