blob: 3846801ac1482024052d42346d8693cd5e3bc168 [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
19#ifdef 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"
David Beck0dbe0ee2018-09-24 15:59:27 +010025#include "workloads/NeonL2NormalizationFloatWorkload.hpp"
Nattapat Chaimanowong4e6597a2018-12-20 14:14:06 +000026#include "workloads/NeonMaximumWorkload.hpp"
Matthew Benthamfd899962018-12-31 15:49:42 +000027#include "workloads/NeonMeanWorkload.hpp"
Nikhil Raj8599a412018-11-19 14:51:07 +000028#include "workloads/NeonMergerWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010029#include "workloads/NeonMultiplicationFloatWorkload.hpp"
30#include "workloads/NeonNormalizationFloatWorkload.hpp"
31#include "workloads/NeonFullyConnectedWorkload.hpp"
32#include "workloads/NeonPermuteWorkload.hpp"
Nattapat Chaimanowong5d2e7002018-10-12 16:03:56 +010033#include "workloads/NeonPooling2dWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010034#include "workloads/NeonSoftmaxBaseWorkload.hpp"
35#include "workloads/NeonSubtractionFloatWorkload.hpp"
telsoa014fcda012018-03-09 14:13:49 +000036#endif
37
38using namespace boost;
39
40namespace armnn
41{
telsoa014fcda012018-03-09 14:13:49 +000042
Aron Virginas-Tarfc824312018-10-15 15:00:13 +010043namespace
arovir017ff76c52018-10-09 09:40:58 +010044{
telsoa014fcda012018-03-09 14:13:49 +000045
arovir01085f0a42018-10-08 14:48:19 +010046bool IsNeonBackendSupported(Optional<std::string&> reasonIfUnsupported)
telsoa014fcda012018-03-09 14:13:49 +000047{
48#if ARMCOMPUTENEON_ENABLED
49 return true;
50#else
arovir01085f0a42018-10-08 14:48:19 +010051 if (reasonIfUnsupported)
telsoa014fcda012018-03-09 14:13:49 +000052 {
arovir01085f0a42018-10-08 14:48:19 +010053 reasonIfUnsupported.value() = "The armnn library has been built without NEON support";
telsoa014fcda012018-03-09 14:13:49 +000054 }
55 return false;
56#endif
57}
58
telsoa01c577f2c2018-08-31 09:22:23 +010059template<typename FloatFunc, typename Uint8Func, typename ... Params>
arovir01085f0a42018-10-08 14:48:19 +010060bool IsSupportedForDataTypeNeon(Optional<std::string&> reasonIfUnsupported,
telsoa014fcda012018-03-09 14:13:49 +000061 DataType dataType,
telsoa01c577f2c2018-08-31 09:22:23 +010062 FloatFunc floatFuncPtr,
telsoa014fcda012018-03-09 14:13:49 +000063 Uint8Func uint8FuncPtr,
64 Params&&... params)
65{
66 return IsNeonBackendSupported(reasonIfUnsupported) &&
67 IsSupportedForDataTypeGeneric(reasonIfUnsupported,
68 dataType,
69 floatFuncPtr,
telsoa01c577f2c2018-08-31 09:22:23 +010070 floatFuncPtr,
telsoa014fcda012018-03-09 14:13:49 +000071 uint8FuncPtr,
72 std::forward<Params>(params)...);
73}
74
75#if ARMCOMPUTENEON_ENABLED
76template<class FuncType, class... Args>
arovir01085f0a42018-10-08 14:48:19 +010077inline bool IsWorkloadSupported(FuncType& func, Optional<std::string&> reasonIfUnsupported, Args&&... args)
telsoa014fcda012018-03-09 14:13:49 +000078{
79 arm_compute::Status aclStatus = func(std::forward<Args>(args)...);
80 const bool supported = (aclStatus.error_code() == arm_compute::ErrorCode::OK);
81 if (!supported && reasonIfUnsupported)
82 {
arovir01085f0a42018-10-08 14:48:19 +010083 reasonIfUnsupported.value() = aclStatus.error_description();
telsoa014fcda012018-03-09 14:13:49 +000084 }
85 return supported;
86}
87
88#define FORWARD_WORKLOAD_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
89 return IsWorkloadSupported(func, reasonIfUnsupported, __VA_ARGS__);
90#else
91#define FORWARD_WORKLOAD_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
92 return IsNeonBackendSupported(reasonIfUnsupported);
93#endif
94
Aron Virginas-Tarfc824312018-10-15 15:00:13 +010095} // anonymous namespace
96
97bool NeonLayerSupport::IsActivationSupported(const TensorInfo& input,
98 const TensorInfo& output,
99 const ActivationDescriptor& descriptor,
100 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000101{
102 ignore_unused(descriptor);
telsoa01c577f2c2018-08-31 09:22:23 +0100103 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonActivationWorkloadValidate,
104 reasonIfUnsupported,
105 input,
106 output,
107 descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000108}
109
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100110bool NeonLayerSupport::IsAdditionSupported(const TensorInfo& input0,
111 const TensorInfo& input1,
112 const TensorInfo& output,
113 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000114{
telsoa01c577f2c2018-08-31 09:22:23 +0100115 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAdditionWorkloadValidate,
116 reasonIfUnsupported,
117 input0,
118 input1,
119 output);
telsoa014fcda012018-03-09 14:13:49 +0000120}
121
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100122bool NeonLayerSupport::IsBatchNormalizationSupported(const TensorInfo& input,
123 const TensorInfo& output,
124 const TensorInfo& mean,
125 const TensorInfo& var,
126 const TensorInfo& beta,
127 const TensorInfo& gamma,
128 const BatchNormalizationDescriptor& descriptor,
129 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000130{
telsoa01c577f2c2018-08-31 09:22:23 +0100131 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchNormalizationValidate,
132 reasonIfUnsupported,
133 input,
134 output,
135 mean,
136 var,
137 beta,
138 gamma,
139 descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000140}
141
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100142bool NeonLayerSupport::IsConstantSupported(const TensorInfo& output,
143 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000144{
145 return IsSupportedForDataTypeNeon(reasonIfUnsupported,
146 output.GetDataType(),
147 &TrueFunc<>,
148 &TrueFunc<>);
149}
150
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100151bool NeonLayerSupport::IsConvertFp16ToFp32Supported(const TensorInfo& input,
152 const TensorInfo& output,
153 Optional<std::string&> reasonIfUnsupported) const
154{
155 ignore_unused(input);
156 ignore_unused(output);
157 ignore_unused(reasonIfUnsupported);
158 return true;
159}
160
161bool NeonLayerSupport::IsConvertFp32ToFp16Supported(const TensorInfo& input,
162 const TensorInfo& output,
163 Optional<std::string&> reasonIfUnsupported) const
164{
165 ignore_unused(input);
166 ignore_unused(output);
167 ignore_unused(reasonIfUnsupported);
168 return true;
169}
170
171bool NeonLayerSupport::IsConvolution2dSupported(const TensorInfo& input,
172 const TensorInfo& output,
173 const Convolution2dDescriptor& descriptor,
174 const TensorInfo& weights,
175 const Optional<TensorInfo>& biases,
176 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000177{
surmeh013537c2c2018-05-18 16:31:43 +0100178 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvolution2dWorkloadValidate,
179 reasonIfUnsupported,
180 input,
181 output,
182 descriptor,
183 weights,
184 biases);
telsoa014fcda012018-03-09 14:13:49 +0000185}
186
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100187bool NeonLayerSupport::IsDepthwiseConvolutionSupported(const TensorInfo& input,
188 const TensorInfo& output,
189 const DepthwiseConvolution2dDescriptor& descriptor,
190 const TensorInfo& weights,
191 const Optional<TensorInfo>& biases,
192 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000193{
telsoa01c577f2c2018-08-31 09:22:23 +0100194 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthwiseConvolutionWorkloadValidate,
195 reasonIfUnsupported,
196 input,
197 output,
198 descriptor,
199 weights,
200 biases);
telsoa014fcda012018-03-09 14:13:49 +0000201}
202
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100203bool NeonLayerSupport::IsFloorSupported(const TensorInfo& input,
204 const TensorInfo& output,
205 Optional<std::string&> reasonIfUnsupported) const
206{
207 ignore_unused(output);
208 return IsNeonBackendSupported(reasonIfUnsupported) &&
209 IsSupportedForDataTypeGeneric(reasonIfUnsupported,
210 input.GetDataType(),
211 &FalseFuncF16<>,
212 &TrueFunc<>,
213 &FalseFuncU8<>);
214}
215
216bool NeonLayerSupport::IsFullyConnectedSupported(const TensorInfo& input,
217 const TensorInfo& output,
218 const TensorInfo& weights,
219 const TensorInfo& biases,
220 const FullyConnectedDescriptor& descriptor,
221 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000222{
telsoa01c577f2c2018-08-31 09:22:23 +0100223 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonFullyConnectedWorkloadValidate,
224 reasonIfUnsupported,
225 input,
226 output,
227 weights,
228 biases,
229 descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000230}
231
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100232bool NeonLayerSupport::IsInputSupported(const TensorInfo& input,
233 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000234{
235 return IsSupportedForDataTypeNeon(reasonIfUnsupported,
236 input.GetDataType(),
237 &TrueFunc<>,
238 &TrueFunc<>);
239}
240
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100241bool NeonLayerSupport::IsL2NormalizationSupported(const TensorInfo& input,
242 const TensorInfo& output,
243 const L2NormalizationDescriptor& descriptor,
244 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000245{
Matteo Martincighbcd3c852018-09-28 14:14:12 +0100246 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonL2NormalizationWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000247}
248
Nattapat Chaimanowong4e6597a2018-12-20 14:14:06 +0000249bool NeonLayerSupport::IsMaximumSupported(const TensorInfo& input0,
250 const TensorInfo& input1,
251 const TensorInfo& output,
252 Optional<std::string&> reasonIfUnsupported) const
253{
254 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMaximumWorkloadValidate,
255 reasonIfUnsupported,
256 input0,
257 input1,
258 output);
259}
260
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100261bool NeonLayerSupport::IsMeanSupported(const TensorInfo& input,
262 const TensorInfo& output,
263 const MeanDescriptor& descriptor,
264 Optional<std::string&> reasonIfUnsupported) const
narpra0132b90462018-09-13 11:07:48 +0100265{
Matthew Benthamfd899962018-12-31 15:49:42 +0000266 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMeanWorkloadValidate,
267 reasonIfUnsupported,
268 input,
269 output,
270 descriptor);
narpra0132b90462018-09-13 11:07:48 +0100271}
272
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100273bool NeonLayerSupport::IsMergerSupported(const std::vector<const TensorInfo*> inputs,
Nikhil Raj8599a412018-11-19 14:51:07 +0000274 const TensorInfo& output,
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100275 const OriginsDescriptor& descriptor,
276 Optional<std::string&> reasonIfUnsupported) const
277{
Nikhil Raj8599a412018-11-19 14:51:07 +0000278 if(descriptor.GetNumDimensions() - descriptor.GetConcatAxis() == 1)
279 {
280 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMergerWorkloadValidate,
281 reasonIfUnsupported,
282 inputs,
283 output,
284 descriptor);
285 }
286 else
287 {
288 return IsSupportedForDataTypeNeon(reasonIfUnsupported,
289 inputs[0]->GetDataType(),
290 &TrueFunc<>,
291 &TrueFunc<>);
292 }
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100293}
294
295bool NeonLayerSupport::IsMultiplicationSupported(const TensorInfo& input0,
296 const TensorInfo& input1,
297 const TensorInfo& output,
298 Optional<std::string&> reasonIfUnsupported) const
299{
300 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMultiplicationWorkloadValidate,
301 reasonIfUnsupported,
302 input0,
303 input1,
304 output);
305}
306
307bool NeonLayerSupport::IsNormalizationSupported(const TensorInfo& input,
308 const TensorInfo& output,
309 const NormalizationDescriptor& descriptor,
310 Optional<std::string&> reasonIfUnsupported) const
311{
312 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonNormalizationWorkloadValidate,
313 reasonIfUnsupported,
314 input,
315 output,
316 descriptor);
317}
318
319bool NeonLayerSupport::IsOutputSupported(const TensorInfo& output,
320 Optional<std::string&> reasonIfUnsupported) const
321{
322 return IsSupportedForDataTypeNeon(reasonIfUnsupported,
323 output.GetDataType(),
324 &TrueFunc<>,
325 &TrueFunc<>);
326}
327
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100328bool NeonLayerSupport::IsPermuteSupported(const TensorInfo& input,
329 const TensorInfo& output,
330 const PermuteDescriptor& descriptor,
331 Optional<std::string&> reasonIfUnsupported) const
332{
333 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPermuteWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000334}
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100335
336bool NeonLayerSupport::IsPooling2dSupported(const TensorInfo& input,
337 const TensorInfo& output,
338 const Pooling2dDescriptor& descriptor,
339 Optional<std::string&> reasonIfUnsupported) const
340{
341 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPooling2dWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
342}
343
344bool NeonLayerSupport::IsReshapeSupported(const TensorInfo& input,
345 Optional<std::string&> reasonIfUnsupported) const
346{
347 return IsSupportedForDataTypeNeon(reasonIfUnsupported,
348 input.GetDataType(),
349 &TrueFunc<>,
350 &TrueFunc<>);
351}
352
353bool NeonLayerSupport::IsResizeBilinearSupported(const TensorInfo& input,
354 Optional<std::string&> reasonIfUnsupported) const
355{
356 ignore_unused(input);
357 ignore_unused(reasonIfUnsupported);
358 return false;
359}
360
361bool NeonLayerSupport::IsSoftmaxSupported(const TensorInfo& input,
362 const TensorInfo& output,
363 const SoftmaxDescriptor& descriptor,
364 Optional<std::string&> reasonIfUnsupported) const
365{
366 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSoftmaxWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
367}
368
369bool NeonLayerSupport::IsSplitterSupported(const TensorInfo& input,
370 const ViewsDescriptor& descriptor,
371 Optional<std::string&> reasonIfUnsupported) const
372{
373 ignore_unused(descriptor);
374 return IsSupportedForDataTypeNeon(reasonIfUnsupported,
375 input.GetDataType(),
376 &TrueFunc<>,
377 &TrueFunc<>);
378}
379
380bool NeonLayerSupport::IsSubtractionSupported(const TensorInfo& input0,
381 const TensorInfo& input1,
382 const TensorInfo& output,
383 Optional<std::string&> reasonIfUnsupported) const
384{
385 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSubtractionWorkloadValidate,
386 reasonIfUnsupported,
387 input0,
388 input1,
389 output);
390}
391
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100392} // namespace armnn