xref: /aosp_15_r20/external/ComputeLibrary/src/core/NEON/kernels/arm_conv/pooling/pooling_u8.cpp (revision c217d954acce2dbc11938adb493fc0abd69584f3)
1 /*
2  * Copyright (c) 2021-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 
25 #include "arm_gemm_local.hpp"
26 
27 #include "pooling_implementation.hpp"
28 #include "pooling_depthfirst.hpp"
29 #include "pooling_depthfirst_generic.hpp"
30 
31 #include "kernels/cpp_nhwc_1x1_stride_any_depthfirst.hpp"
32 #if defined(__aarch64__)
33 #if defined(ARM_COMPUTE_ENABLE_SME)
34 #include "kernels/sme_u8_nhwc_avg_generic_depthfirst.hpp"
35 #include "kernels/sme_u8_nhwc_max_2x2_s1_output2x2_depthfirst.hpp"
36 #include "kernels/sme_u8_nhwc_max_generic_depthfirst.hpp"
37 #endif  // defined(ARM_COMPUTE_ENABLE_SME)
38 #if defined(ARM_COMPUTE_ENABLE_SVE)
39 #include "kernels/sve_u8_nhwc_avg_generic_depthfirst.hpp"
40 #include "kernels/sve_u8_nhwc_max_2x2_s1_output2x2_depthfirst.hpp"
41 #include "kernels/sve_u8_nhwc_max_generic_depthfirst.hpp"
42 #endif  // defined(ARM_COMPUTE_ENABLE_SVE)
43 #include "kernels/a64_u8_nhwc_max_2x2_s1_output2x2_depthfirst.hpp"
44 #include "kernels/a64_u8_nhwc_avg_generic_depthfirst.hpp"
45 #include "kernels/a64_u8_nhwc_max_generic_depthfirst.hpp"
46 #endif  // defined(__aarch64__)
47 
48 #include <cstdint>
49 
50 namespace arm_conv {
51 namespace pooling {
52 
53 static const PoolingImplementation<uint8_t, uint8_t> pooling_u8_methods[] = {
54   {
55     PoolingMethod::DEPTHFIRST,
56     "cpp_u8_nhwc_1x1_stride_any_depthfirst",
__anonf8850bd90102() 57     [] (const PoolingArgs &args, const Nothing &) -> bool {
58       return args.pool_window.rows == 1 && args.pool_window.cols == 1;
59     },
60     nullptr,
__anonf8850bd90202() 61     [] (const PoolingArgs &args, const Nothing &) -> PoolingCommon<uint8_t, uint8_t> * {
62       auto strat = new cpp_nhwc_1x1_stride_any_depthfirst<uint8_t>(args.cpu_info);
63       return new PoolingDepthfirstGeneric<uint8_t>(strat, args);
64     },
65   },
66 #if defined(__aarch64__)
67 #if defined(ARM_COMPUTE_ENABLE_SME)
68   {
69     PoolingMethod::DEPTHFIRST,
70     "sme_u8_nhwc_max_2x2_s1_output2x2_depthfirst",
__anonf8850bd90302() 71     [] (const PoolingArgs &args, const Nothing &os) -> bool {
72       return args.cpu_info->has_sme() &&
73              is_supported<sme_u8_nhwc_max_2x2_s1_output2x2_depthfirst>(args, os);
74     },
75     nullptr,
__anonf8850bd90402() 76     [] (const PoolingArgs &args, const Nothing &) -> PoolingCommon<uint8_t, uint8_t> * {
77       auto strat = new sme_u8_nhwc_max_2x2_s1_output2x2_depthfirst(args.cpu_info);
78       return new PoolingDepthfirst<uint8_t>(strat, args);
79     },
80   },
81   {
82     PoolingMethod::DEPTHFIRST,
83     "sme_u8_nhwc_avg_generic_depthfirst",
__anonf8850bd90502() 84     [] (const PoolingArgs &args, const Nothing &) -> bool {
85       // This kernel can only be used when there is either no padding, or we don't care
86       // about the value of the padding. Otherwise, we would need to pass in the zero-point
87       // for the quantization regime.
88       return (args.exclude_padding ||
89               (args.padding.top == 0 && args.padding.bottom == 0 &&
90                args.padding.left == 0 && args.padding.right == 0)
91               ) && args.pool_type == PoolingType::AVERAGE &&
92              args.cpu_info->has_sme2();
93     },
94     nullptr,
__anonf8850bd90602() 95     [] (const PoolingArgs &args, const Nothing &) -> PoolingCommon<uint8_t, uint8_t> * {
96       auto strat = new sme_u8_nhwc_avg_generic_depthfirst(args.cpu_info);
97       return new PoolingDepthfirstGeneric<uint8_t>(strat, args);
98     },
99   },
100   {
101     PoolingMethod::DEPTHFIRST,
102     "sme_u8_nhwc_max_generic_depthfirst",
__anonf8850bd90702() 103     [] (const PoolingArgs &args, const Nothing &) -> bool {
104       return args.cpu_info->has_sme() && args.pool_type == PoolingType::MAX;
105     },
106     nullptr,
__anonf8850bd90802() 107     [] (const PoolingArgs &args, const Nothing &) -> PoolingCommon<uint8_t, uint8_t> * {
108       auto strat = new sme_u8_nhwc_max_generic_depthfirst(args.cpu_info);
109       return new PoolingDepthfirstGeneric<uint8_t>(strat, args);
110     },
111   },
112 #endif  // defined(ARM_COMPUTE_ENABLE_SME)
113 #if defined(ARM_COMPUTE_ENABLE_SVE)
114   {
115     PoolingMethod::DEPTHFIRST,
116     "sve_u8_nhwc_max_2x2_s1_output2x2_depthfirst",
__anonf8850bd90902() 117     [] (const PoolingArgs &args, const Nothing &os) -> bool {
118       return args.cpu_info->has_sve() &&
119              is_supported<sve_u8_nhwc_max_2x2_s1_output2x2_depthfirst>(args, os);
120     },
121     nullptr,
__anonf8850bd90a02() 122     [] (const PoolingArgs &args, const Nothing &) -> PoolingCommon<uint8_t, uint8_t> * {
123       auto strat = new sve_u8_nhwc_max_2x2_s1_output2x2_depthfirst(args.cpu_info);
124       return new PoolingDepthfirst<uint8_t>(strat, args);
125     },
126   },
127   {
128     PoolingMethod::DEPTHFIRST,
129     "sve_u8_nhwc_avg_generic_depthfirst",
__anonf8850bd90b02() 130     [] (const PoolingArgs &args, const Nothing &) -> bool {
131       // This kernel can only be used when there is either no padding, or we don't care
132       // about the value of the padding. Otherwise, we would need to pass in the zero-point
133       // for the quantization regime.
134       return (args.exclude_padding ||
135               (args.padding.top == 0 && args.padding.bottom == 0 &&
136                args.padding.left == 0 && args.padding.right == 0)
137               ) && args.pool_type == PoolingType::AVERAGE &&
138              args.cpu_info->has_sve2();
139     },
140     nullptr,
__anonf8850bd90c02() 141     [] (const PoolingArgs &args, const Nothing &) -> PoolingCommon<uint8_t, uint8_t> * {
142       auto strat = new sve_u8_nhwc_avg_generic_depthfirst(args.cpu_info);
143       return new PoolingDepthfirstGeneric<uint8_t>(strat, args);
144     },
145   },
146   {
147     PoolingMethod::DEPTHFIRST,
148     "sve_u8_nhwc_max_generic_depthfirst",
__anonf8850bd90d02() 149     [] (const PoolingArgs &args, const Nothing &) -> bool {
150       return args.cpu_info->has_sve() && args.pool_type == PoolingType::MAX;
151     },
152     nullptr,
__anonf8850bd90e02() 153     [] (const PoolingArgs &args, const Nothing &) -> PoolingCommon<uint8_t, uint8_t> * {
154       auto strat = new sve_u8_nhwc_max_generic_depthfirst(args.cpu_info);
155       return new PoolingDepthfirstGeneric<uint8_t>(strat, args);
156     },
157   },
158 #endif  // defined(ARM_COMPUTE_ENABLE_SVE)
159   {
160     PoolingMethod::DEPTHFIRST,
161     "a64_u8_nhwc_max_2x2_s1_output2x2_depthfirst",
162     is_supported<a64_u8_nhwc_max_2x2_s1_output2x2_depthfirst>,
163     nullptr,
__anonf8850bd90f02() 164     [] (const PoolingArgs &args, const Nothing &) -> PoolingCommon<uint8_t, uint8_t> * {
165       auto strat = new a64_u8_nhwc_max_2x2_s1_output2x2_depthfirst(args.cpu_info);
166       return new PoolingDepthfirst<uint8_t>(strat, args);
167     },
168   },
169   {
170     PoolingMethod::DEPTHFIRST,
171     "a64_u8_nhwc_avg_generic_depthfirst",
__anonf8850bd91002() 172     [] (const PoolingArgs &args, const Nothing &) -> bool {
173       // This kernel can only be used when there is either no padding, or we don't care
174       // about the value of the padding. Otherwise, we would need to pass in the zero-point
175       // for the quantization regime.
176       return (args.exclude_padding ||
177               (args.padding.top == 0 && args.padding.bottom == 0 &&
178                args.padding.left == 0 && args.padding.right == 0)
179               ) && args.pool_type == PoolingType::AVERAGE;
180     },
181     nullptr,
__anonf8850bd91102() 182     [] (const PoolingArgs &args, const Nothing &) -> PoolingCommon<uint8_t, uint8_t> * {
183       auto strat = new a64_u8_nhwc_avg_generic_depthfirst(args.cpu_info);
184       return new PoolingDepthfirstGeneric<uint8_t>(strat, args);
185     },
186   },
187   {
188     PoolingMethod::DEPTHFIRST,
189     "a64_u8_nhwc_max_generic_depthfirst",
__anonf8850bd91202() 190     [] (const PoolingArgs &args, const Nothing &) -> bool { return args.pool_type == PoolingType::MAX; },
191     nullptr,
__anonf8850bd91302() 192     [] (const PoolingArgs &args, const Nothing &) -> PoolingCommon<uint8_t, uint8_t> * {
193       auto strat = new a64_u8_nhwc_max_generic_depthfirst(args.cpu_info);
194       return new PoolingDepthfirstGeneric<uint8_t>(strat, args);
195     },
196   },
197 #endif  // defined(__aarch64__)
198   { PoolingMethod::DEFAULT, "", nullptr, nullptr, nullptr },  // End of list
199 };
200 
201 template <>
pooling_implementation_list()202 const PoolingImplementation<uint8_t, uint8_t> *pooling_implementation_list()
203 {
204   return pooling_u8_methods;
205 }
206 
207 template UniquePoolingCommon<uint8_t, uint8_t> pooling(const PoolingArgs &, const Nothing &);
208 
209 }  //  namespace pooling
210 }  //  namespace arm_conv
211