blob: 46a7e6f79f66e763858c86b6dfe340ed0b5d0ce3 [file] [log] [blame]
telsoa014fcda012018-03-09 14:13:49 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
telsoa014fcda012018-03-09 14:13:49 +00004//
5
6#include "NeonLayerSupport.hpp"
David Beck3e9e1152018-10-17 14:17:50 +01007#include "NeonBackendId.hpp"
telsoa014fcda012018-03-09 14:13:49 +00008
telsoa014fcda012018-03-09 14:13:49 +00009#include <armnn/Descriptors.hpp>
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000010#include <InternalTypes.hpp>
11#include <LayerSupportCommon.hpp>
telsoa014fcda012018-03-09 14:13:49 +000012#include <armnn/Tensor.hpp>
Aron Virginas-Tarfc824312018-10-15 15:00:13 +010013#include <armnn/Types.hpp>
telsoa014fcda012018-03-09 14:13:49 +000014
David Beck111b5d92018-11-12 14:59:37 +000015#include <backendsCommon/BackendRegistry.hpp>
David Beck3e9e1152018-10-17 14:17:50 +010016
telsoa014fcda012018-03-09 14:13:49 +000017#include <boost/core/ignore_unused.hpp>
18
Matteo Martincighd95e9062019-01-31 15:35:59 +000019#if defined(ARMCOMPUTENEON_ENABLED)
Matthew Bentham955258d2018-12-10 10:48:52 +000020#include "workloads/NeonAdditionWorkload.hpp"
Nattapat Chaimanowongd4b70592018-10-12 11:21:49 +010021#include "workloads/NeonActivationWorkload.hpp"
Matthew Benthamc48ac8c2018-12-12 16:15:59 +000022#include "workloads/NeonBatchNormalizationWorkload.hpp"
Nattapat Chaimanowong974b65f2018-10-15 15:07:34 +010023#include "workloads/NeonConvolution2dWorkload.hpp"
Nattapat Chaimanowong77140882018-10-17 11:12:19 +010024#include "workloads/NeonDepthwiseConvolutionWorkload.hpp"
kevmay01eed85922019-01-28 08:37:25 +000025#include "workloads/NeonGreaterWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010026#include "workloads/NeonL2NormalizationFloatWorkload.hpp"
Nattapat Chaimanowong4e6597a2018-12-20 14:14:06 +000027#include "workloads/NeonMaximumWorkload.hpp"
Matthew Benthamfd899962018-12-31 15:49:42 +000028#include "workloads/NeonMeanWorkload.hpp"
Nikhil Raj8599a412018-11-19 14:51:07 +000029#include "workloads/NeonMergerWorkload.hpp"
Conor Kennedy54b21692019-01-09 07:57:38 +000030#include "workloads/NeonMinimumWorkload.hpp"
Conor Kennedyb99480b2019-03-08 08:24:41 +000031#include "workloads/NeonMultiplicationWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010032#include "workloads/NeonNormalizationFloatWorkload.hpp"
33#include "workloads/NeonFullyConnectedWorkload.hpp"
Éanna Ó Catháin12055742019-01-25 10:01:40 +000034#include "workloads/NeonPadWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010035#include "workloads/NeonPermuteWorkload.hpp"
Nattapat Chaimanowong5d2e7002018-10-12 16:03:56 +010036#include "workloads/NeonPooling2dWorkload.hpp"
Sadik Armaganc625f002018-12-17 11:32:16 +000037#include "workloads/NeonResizeBilinearWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010038#include "workloads/NeonSoftmaxBaseWorkload.hpp"
Conor Kennedyb99480b2019-03-08 08:24:41 +000039#include "workloads/NeonSubtractionWorkload.hpp"
telsoa014fcda012018-03-09 14:13:49 +000040#endif
41
42using namespace boost;
43
44namespace armnn
45{
telsoa014fcda012018-03-09 14:13:49 +000046
Aron Virginas-Tarfc824312018-10-15 15:00:13 +010047namespace
arovir017ff76c52018-10-09 09:40:58 +010048{
telsoa014fcda012018-03-09 14:13:49 +000049
arovir01085f0a42018-10-08 14:48:19 +010050bool IsNeonBackendSupported(Optional<std::string&> reasonIfUnsupported)
telsoa014fcda012018-03-09 14:13:49 +000051{
Matteo Martincighd95e9062019-01-31 15:35:59 +000052#if defined(ARMCOMPUTENEON_ENABLED)
telsoa014fcda012018-03-09 14:13:49 +000053 return true;
54#else
arovir01085f0a42018-10-08 14:48:19 +010055 if (reasonIfUnsupported)
telsoa014fcda012018-03-09 14:13:49 +000056 {
arovir01085f0a42018-10-08 14:48:19 +010057 reasonIfUnsupported.value() = "The armnn library has been built without NEON support";
telsoa014fcda012018-03-09 14:13:49 +000058 }
59 return false;
60#endif
61}
62
telsoa01c577f2c2018-08-31 09:22:23 +010063template<typename FloatFunc, typename Uint8Func, typename ... Params>
arovir01085f0a42018-10-08 14:48:19 +010064bool IsSupportedForDataTypeNeon(Optional<std::string&> reasonIfUnsupported,
telsoa014fcda012018-03-09 14:13:49 +000065 DataType dataType,
telsoa01c577f2c2018-08-31 09:22:23 +010066 FloatFunc floatFuncPtr,
telsoa014fcda012018-03-09 14:13:49 +000067 Uint8Func uint8FuncPtr,
68 Params&&... params)
69{
70 return IsNeonBackendSupported(reasonIfUnsupported) &&
71 IsSupportedForDataTypeGeneric(reasonIfUnsupported,
72 dataType,
73 floatFuncPtr,
telsoa01c577f2c2018-08-31 09:22:23 +010074 floatFuncPtr,
telsoa014fcda012018-03-09 14:13:49 +000075 uint8FuncPtr,
narpra01db2b1602019-01-23 15:23:11 +000076 &FalseFunc<>,
kevmay012b4d88e2019-01-24 14:05:09 +000077 &FalseFunc<>,
telsoa014fcda012018-03-09 14:13:49 +000078 std::forward<Params>(params)...);
79}
80
Matteo Martincighd95e9062019-01-31 15:35:59 +000081#if defined(ARMCOMPUTENEON_ENABLED)
telsoa014fcda012018-03-09 14:13:49 +000082template<class FuncType, class... Args>
arovir01085f0a42018-10-08 14:48:19 +010083inline bool IsWorkloadSupported(FuncType& func, Optional<std::string&> reasonIfUnsupported, Args&&... args)
telsoa014fcda012018-03-09 14:13:49 +000084{
85 arm_compute::Status aclStatus = func(std::forward<Args>(args)...);
86 const bool supported = (aclStatus.error_code() == arm_compute::ErrorCode::OK);
87 if (!supported && reasonIfUnsupported)
88 {
arovir01085f0a42018-10-08 14:48:19 +010089 reasonIfUnsupported.value() = aclStatus.error_description();
telsoa014fcda012018-03-09 14:13:49 +000090 }
91 return supported;
92}
93
94#define FORWARD_WORKLOAD_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
95 return IsWorkloadSupported(func, reasonIfUnsupported, __VA_ARGS__);
96#else
97#define FORWARD_WORKLOAD_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
98 return IsNeonBackendSupported(reasonIfUnsupported);
99#endif
100
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100101} // anonymous namespace
102
103bool NeonLayerSupport::IsActivationSupported(const TensorInfo& input,
104 const TensorInfo& output,
105 const ActivationDescriptor& descriptor,
106 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000107{
108 ignore_unused(descriptor);
telsoa01c577f2c2018-08-31 09:22:23 +0100109 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonActivationWorkloadValidate,
110 reasonIfUnsupported,
111 input,
112 output,
113 descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000114}
115
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100116bool NeonLayerSupport::IsAdditionSupported(const TensorInfo& input0,
117 const TensorInfo& input1,
118 const TensorInfo& output,
119 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000120{
telsoa01c577f2c2018-08-31 09:22:23 +0100121 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAdditionWorkloadValidate,
122 reasonIfUnsupported,
123 input0,
124 input1,
125 output);
telsoa014fcda012018-03-09 14:13:49 +0000126}
127
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100128bool NeonLayerSupport::IsBatchNormalizationSupported(const TensorInfo& input,
129 const TensorInfo& output,
130 const TensorInfo& mean,
131 const TensorInfo& var,
132 const TensorInfo& beta,
133 const TensorInfo& gamma,
134 const BatchNormalizationDescriptor& descriptor,
135 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000136{
telsoa01c577f2c2018-08-31 09:22:23 +0100137 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchNormalizationValidate,
138 reasonIfUnsupported,
139 input,
140 output,
141 mean,
142 var,
143 beta,
144 gamma,
145 descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000146}
147
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100148bool NeonLayerSupport::IsConstantSupported(const TensorInfo& output,
149 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000150{
151 return IsSupportedForDataTypeNeon(reasonIfUnsupported,
152 output.GetDataType(),
153 &TrueFunc<>,
154 &TrueFunc<>);
155}
156
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100157bool NeonLayerSupport::IsConvertFp16ToFp32Supported(const TensorInfo& input,
158 const TensorInfo& output,
159 Optional<std::string&> reasonIfUnsupported) const
160{
161 ignore_unused(input);
162 ignore_unused(output);
163 ignore_unused(reasonIfUnsupported);
164 return true;
165}
166
167bool NeonLayerSupport::IsConvertFp32ToFp16Supported(const TensorInfo& input,
168 const TensorInfo& output,
169 Optional<std::string&> reasonIfUnsupported) const
170{
171 ignore_unused(input);
172 ignore_unused(output);
173 ignore_unused(reasonIfUnsupported);
174 return true;
175}
176
177bool NeonLayerSupport::IsConvolution2dSupported(const TensorInfo& input,
178 const TensorInfo& output,
179 const Convolution2dDescriptor& descriptor,
180 const TensorInfo& weights,
181 const Optional<TensorInfo>& biases,
182 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000183{
surmeh013537c2c2018-05-18 16:31:43 +0100184 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvolution2dWorkloadValidate,
185 reasonIfUnsupported,
186 input,
187 output,
188 descriptor,
189 weights,
190 biases);
telsoa014fcda012018-03-09 14:13:49 +0000191}
192
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100193bool NeonLayerSupport::IsDepthwiseConvolutionSupported(const TensorInfo& input,
194 const TensorInfo& output,
195 const DepthwiseConvolution2dDescriptor& descriptor,
196 const TensorInfo& weights,
197 const Optional<TensorInfo>& biases,
198 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000199{
telsoa01c577f2c2018-08-31 09:22:23 +0100200 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthwiseConvolutionWorkloadValidate,
201 reasonIfUnsupported,
202 input,
203 output,
204 descriptor,
205 weights,
206 biases);
telsoa014fcda012018-03-09 14:13:49 +0000207}
208
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100209bool NeonLayerSupport::IsFloorSupported(const TensorInfo& input,
210 const TensorInfo& output,
211 Optional<std::string&> reasonIfUnsupported) const
212{
213 ignore_unused(output);
214 return IsNeonBackendSupported(reasonIfUnsupported) &&
215 IsSupportedForDataTypeGeneric(reasonIfUnsupported,
216 input.GetDataType(),
217 &FalseFuncF16<>,
218 &TrueFunc<>,
narpra01db2b1602019-01-23 15:23:11 +0000219 &FalseFuncU8<>,
kevmay012b4d88e2019-01-24 14:05:09 +0000220 &FalseFuncI32<>,
221 &FalseFuncU8<>);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100222}
223
224bool NeonLayerSupport::IsFullyConnectedSupported(const TensorInfo& input,
225 const TensorInfo& output,
226 const TensorInfo& weights,
227 const TensorInfo& biases,
228 const FullyConnectedDescriptor& descriptor,
229 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000230{
telsoa01c577f2c2018-08-31 09:22:23 +0100231 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonFullyConnectedWorkloadValidate,
232 reasonIfUnsupported,
233 input,
234 output,
235 weights,
236 biases,
237 descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000238}
239
kevmay01eed85922019-01-28 08:37:25 +0000240bool NeonLayerSupport::IsGreaterSupported(const armnn::TensorInfo& input0,
241 const armnn::TensorInfo& input1,
242 const armnn::TensorInfo& output,
243 armnn::Optional<std::string&> reasonIfUnsupported) const
244{
245 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonGreaterWorkloadValidate,
246 reasonIfUnsupported,
247 input0,
248 input1,
249 output);
250}
251
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100252bool NeonLayerSupport::IsInputSupported(const TensorInfo& input,
253 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000254{
255 return IsSupportedForDataTypeNeon(reasonIfUnsupported,
256 input.GetDataType(),
257 &TrueFunc<>,
258 &TrueFunc<>);
259}
260
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100261bool NeonLayerSupport::IsL2NormalizationSupported(const TensorInfo& input,
262 const TensorInfo& output,
263 const L2NormalizationDescriptor& descriptor,
264 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000265{
Matteo Martincighbcd3c852018-09-28 14:14:12 +0100266 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonL2NormalizationWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000267}
268
Nattapat Chaimanowong4e6597a2018-12-20 14:14:06 +0000269bool NeonLayerSupport::IsMaximumSupported(const TensorInfo& input0,
270 const TensorInfo& input1,
271 const TensorInfo& output,
272 Optional<std::string&> reasonIfUnsupported) const
273{
274 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMaximumWorkloadValidate,
275 reasonIfUnsupported,
276 input0,
277 input1,
278 output);
279}
280
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100281bool NeonLayerSupport::IsMeanSupported(const TensorInfo& input,
282 const TensorInfo& output,
283 const MeanDescriptor& descriptor,
284 Optional<std::string&> reasonIfUnsupported) const
narpra0132b90462018-09-13 11:07:48 +0100285{
Matthew Benthamfd899962018-12-31 15:49:42 +0000286 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMeanWorkloadValidate,
287 reasonIfUnsupported,
288 input,
289 output,
290 descriptor);
narpra0132b90462018-09-13 11:07:48 +0100291}
292
Matteo Martincigh992d6dc2019-01-10 17:34:20 +0000293bool NeonLayerSupport::IsMemCopySupported(const TensorInfo &input,
294 const TensorInfo &output,
295 Optional<std::string &> reasonIfUnsupported) const
296{
297 ignore_unused(input);
298 ignore_unused(output);
299 return true;
300}
301
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100302bool NeonLayerSupport::IsMergerSupported(const std::vector<const TensorInfo*> inputs,
Nikhil Raj8599a412018-11-19 14:51:07 +0000303 const TensorInfo& output,
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100304 const OriginsDescriptor& descriptor,
305 Optional<std::string&> reasonIfUnsupported) const
306{
Nikhil Raj8599a412018-11-19 14:51:07 +0000307 if(descriptor.GetNumDimensions() - descriptor.GetConcatAxis() == 1)
308 {
309 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMergerWorkloadValidate,
310 reasonIfUnsupported,
311 inputs,
312 output,
313 descriptor);
314 }
315 else
316 {
317 return IsSupportedForDataTypeNeon(reasonIfUnsupported,
318 inputs[0]->GetDataType(),
319 &TrueFunc<>,
320 &TrueFunc<>);
321 }
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100322}
323
Conor Kennedy54b21692019-01-09 07:57:38 +0000324bool NeonLayerSupport::IsMinimumSupported(const TensorInfo& input0,
325 const TensorInfo& input1,
326 const TensorInfo& output,
327 Optional<std::string&> reasonIfUnsupported) const
328{
329 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMinimumWorkloadValidate,
330 reasonIfUnsupported,
331 input0,
332 input1,
333 output);
334}
335
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100336bool NeonLayerSupport::IsMultiplicationSupported(const TensorInfo& input0,
337 const TensorInfo& input1,
338 const TensorInfo& output,
339 Optional<std::string&> reasonIfUnsupported) const
340{
341 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMultiplicationWorkloadValidate,
342 reasonIfUnsupported,
343 input0,
344 input1,
345 output);
346}
347
348bool NeonLayerSupport::IsNormalizationSupported(const TensorInfo& input,
349 const TensorInfo& output,
350 const NormalizationDescriptor& descriptor,
351 Optional<std::string&> reasonIfUnsupported) const
352{
353 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonNormalizationWorkloadValidate,
354 reasonIfUnsupported,
355 input,
356 output,
357 descriptor);
358}
359
360bool NeonLayerSupport::IsOutputSupported(const TensorInfo& output,
361 Optional<std::string&> reasonIfUnsupported) const
362{
kevmay012b4d88e2019-01-24 14:05:09 +0000363 return IsNeonBackendSupported(reasonIfUnsupported) &&
364 IsSupportedForDataTypeGeneric(reasonIfUnsupported,
365 output.GetDataType(),
366 &TrueFunc<>,
367 &TrueFunc<>,
368 &TrueFunc<>,
369 &FalseFuncI32<>,
370 &TrueFunc<>);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100371}
372
Éanna Ó Catháin12055742019-01-25 10:01:40 +0000373bool NeonLayerSupport::IsPadSupported(const TensorInfo& input,
374 const TensorInfo& output,
375 const PadDescriptor& descriptor,
376 Optional<std::string&> reasonIfUnsupported) const
377{
378 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPadWorkloadValidate,
379 reasonIfUnsupported,
380 input,
381 output,
382 descriptor);
383}
384
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100385bool NeonLayerSupport::IsPermuteSupported(const TensorInfo& input,
386 const TensorInfo& output,
387 const PermuteDescriptor& descriptor,
388 Optional<std::string&> reasonIfUnsupported) const
389{
390 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPermuteWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000391}
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100392
393bool NeonLayerSupport::IsPooling2dSupported(const TensorInfo& input,
394 const TensorInfo& output,
395 const Pooling2dDescriptor& descriptor,
396 Optional<std::string&> reasonIfUnsupported) const
397{
398 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPooling2dWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
399}
400
401bool NeonLayerSupport::IsReshapeSupported(const TensorInfo& input,
Matteo Martincigh992d6dc2019-01-10 17:34:20 +0000402 const ReshapeDescriptor& descriptor,
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100403 Optional<std::string&> reasonIfUnsupported) const
404{
Matteo Martincigh992d6dc2019-01-10 17:34:20 +0000405 ignore_unused(descriptor);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100406 return IsSupportedForDataTypeNeon(reasonIfUnsupported,
407 input.GetDataType(),
408 &TrueFunc<>,
409 &TrueFunc<>);
410}
411
Sadik Armaganc625f002018-12-17 11:32:16 +0000412bool NeonLayerSupport::IsResizeBilinearSupported(const TensorInfo& input,
413 const TensorInfo& output,
414 Optional<std::string&> reasonIfUnsupported) const
415{
416 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonResizeBilinearWorkloadValidate,
417 reasonIfUnsupported,
418 input,
419 output);
420}
421
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100422bool NeonLayerSupport::IsSoftmaxSupported(const TensorInfo& input,
423 const TensorInfo& output,
424 const SoftmaxDescriptor& descriptor,
425 Optional<std::string&> reasonIfUnsupported) const
426{
427 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSoftmaxWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
428}
429
430bool NeonLayerSupport::IsSplitterSupported(const TensorInfo& input,
431 const ViewsDescriptor& descriptor,
432 Optional<std::string&> reasonIfUnsupported) const
433{
434 ignore_unused(descriptor);
435 return IsSupportedForDataTypeNeon(reasonIfUnsupported,
436 input.GetDataType(),
437 &TrueFunc<>,
438 &TrueFunc<>);
439}
440
441bool NeonLayerSupport::IsSubtractionSupported(const TensorInfo& input0,
442 const TensorInfo& input1,
443 const TensorInfo& output,
444 Optional<std::string&> reasonIfUnsupported) const
445{
446 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSubtractionWorkloadValidate,
447 reasonIfUnsupported,
448 input0,
449 input1,
450 output);
451}
452
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100453} // namespace armnn