blob: eca386701b32ae44cc9ef5cb3e7f1eda5540fd40 [file] [log] [blame]
Laurent Carlier749294b2020-06-01 09:03:17 +01001//
Mike Kelly3ec30772023-03-08 13:47:17 +00002// Copyright © 2017-2023 Arm Ltd and Contributors. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
telsoa014fcda012018-03-09 14:13:49 +00004//
Aron Virginas-Tar56055192018-11-12 18:10:43 +00005
David Beck79141b92018-10-23 16:09:36 +01006#include "NeonBackendId.hpp"
Sadik Armagan04a72972020-09-14 15:44:18 +01007#include "NeonBackendModelContext.hpp"
Aron Virginas-Tar56055192018-11-12 18:10:43 +00008#include "NeonTensorHandle.hpp"
9#include "NeonWorkloadFactory.hpp"
10
David Beck0dbe0ee2018-09-24 15:59:27 +010011#include <Layer.hpp>
telsoa014fcda012018-03-09 14:13:49 +000012
Aron Virginas-Tar56055192018-11-12 18:10:43 +000013#include <armnn/Utils.hpp>
Jan Eilers8eb25602020-03-09 12:13:48 +000014#include <armnn/utility/IgnoreUnused.hpp>
Matthew Sloyan171214c2020-09-09 09:07:37 +010015#include <armnn/utility/NumericCast.hpp>
Jan Eilersbb446e52020-04-02 13:56:54 +010016#include <armnn/utility/PolymorphicDowncast.hpp>
telsoa01c577f2c2018-08-31 09:22:23 +010017
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000018#include <backendsCommon/MakeWorkloadHelper.hpp>
Colm Donelan0c479742021-12-10 12:43:54 +000019#include <armnn/backends/MemCopyWorkload.hpp>
Derek Lambertif674aa02019-08-01 15:56:25 +010020#include <backendsCommon/MemImportWorkload.hpp>
Colm Donelan0c479742021-12-10 12:43:54 +000021#include <armnn/backends/TensorHandle.hpp>
telsoa014fcda012018-03-09 14:13:49 +000022
Aron Virginas-Tar56055192018-11-12 18:10:43 +000023#include <neon/workloads/NeonWorkloadUtils.hpp>
24#include <neon/workloads/NeonWorkloads.hpp>
25
telsoa014fcda012018-03-09 14:13:49 +000026namespace armnn
27{
28
David Beck79141b92018-10-23 16:09:36 +010029namespace
30{
31static const BackendId s_Id{NeonBackendId()};
32}
33
David Beck29c75de2018-10-23 13:35:58 +010034bool NeonWorkloadFactory::IsLayerSupported(const Layer& layer,
35 Optional<DataType> dataType,
telsoa01c577f2c2018-08-31 09:22:23 +010036 std::string& outReasonIfUnsupported)
telsoa014fcda012018-03-09 14:13:49 +000037{
David Beck79141b92018-10-23 16:09:36 +010038 return IWorkloadFactory::IsLayerSupported(s_Id, layer, dataType, outReasonIfUnsupported);
39}
40
Sadik Armagan04a72972020-09-14 15:44:18 +010041bool NeonWorkloadFactory::IsLayerSupported(const IConnectableLayer& layer,
42 Optional<DataType> dataType,
43 std::string& outReasonIfUnsupported,
44 const ModelOptions& modelOptions)
45{
46 return IWorkloadFactory::IsLayerSupported(s_Id, layer, dataType, outReasonIfUnsupported, modelOptions);
47}
48
David Beck79141b92018-10-23 16:09:36 +010049const BackendId& NeonWorkloadFactory::GetBackendId() const
50{
51 return s_Id;
telsoa014fcda012018-03-09 14:13:49 +000052}
53
Matthew Sloyan0a7dc6b2021-02-10 16:50:53 +000054void NeonWorkloadFactory::SetNumberOfThreads()
55{
56 if (m_ModelContextPtr)
57 {
58 const unsigned int MIN_THREADS = 1;
59 const unsigned int MAX_THREADS = 64;
60
61 // Set the number of threads to be used if the user has set NumberOfThreads param
62 // Only set if within limit or valid input
63 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
64 auto numberOfThreads = modelOptions->GetNumberOfThreads();
65
66 if (numberOfThreads != 0 && numberOfThreads >= MIN_THREADS && numberOfThreads <= MAX_THREADS)
67 {
68 arm_compute::Scheduler::get().set_num_threads(numberOfThreads);
69 }
70 }
71}
72
Aron Virginas-Tar56055192018-11-12 18:10:43 +000073NeonWorkloadFactory::NeonWorkloadFactory(const std::shared_ptr<NeonMemoryManager>& memoryManager)
Sadik Armagan04a72972020-09-14 15:44:18 +010074 : m_MemoryManager(memoryManager), m_ModelContextPtr(IBackendInternal::IBackendSpecificModelContextPtr{})
75{
Matthew Sloyan0a7dc6b2021-02-10 16:50:53 +000076 SetNumberOfThreads();
Sadik Armagan04a72972020-09-14 15:44:18 +010077}
78
79NeonWorkloadFactory::NeonWorkloadFactory(const std::shared_ptr<NeonMemoryManager>& memoryManager,
80 const IBackendInternal::IBackendSpecificModelContextPtr& modelContextPtr)
81 : m_MemoryManager(memoryManager), m_ModelContextPtr(modelContextPtr)
surmeh013537c2c2018-05-18 16:31:43 +010082{
Matthew Sloyan0a7dc6b2021-02-10 16:50:53 +000083 SetNumberOfThreads();
surmeh013537c2c2018-05-18 16:31:43 +010084}
85
telsoa014fcda012018-03-09 14:13:49 +000086std::unique_ptr<ITensorHandle> NeonWorkloadFactory::CreateSubTensorHandle(ITensorHandle& parent,
87 TensorShape const& subTensorShape,
88 unsigned int const* subTensorOrigin) const
89{
telsoa014fcda012018-03-09 14:13:49 +000090 const arm_compute::TensorShape shape = armcomputetensorutils::BuildArmComputeTensorShape(subTensorShape);
91
92 arm_compute::Coordinates coords;
93 coords.set_num_dimensions(subTensorShape.GetNumDimensions());
94 for (unsigned int i = 0; i < subTensorShape.GetNumDimensions(); i++)
95 {
telsoa01c577f2c2018-08-31 09:22:23 +010096 // Arm compute indexes tensor coords in reverse order.
telsoa014fcda012018-03-09 14:13:49 +000097 unsigned int revertedIndex = subTensorShape.GetNumDimensions() - i - 1;
Matthew Sloyan171214c2020-09-09 09:07:37 +010098 coords.set(i, armnn::numeric_cast<int>(subTensorOrigin[revertedIndex]));
telsoa014fcda012018-03-09 14:13:49 +000099 }
100
Derek Lamberti0790dce2019-04-15 18:37:35 +0100101 const arm_compute::TensorShape parentShape = armcomputetensorutils::BuildArmComputeTensorShape(parent.GetShape());
102 if (!::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, parentShape, coords, shape))
103 {
104 return nullptr;
105 }
106
telsoa01c577f2c2018-08-31 09:22:23 +0100107 return std::make_unique<NeonSubTensorHandle>(
Jan Eilersbb446e52020-04-02 13:56:54 +0100108 PolymorphicDowncast<IAclTensorHandle*>(&parent), shape, coords);
telsoa014fcda012018-03-09 14:13:49 +0000109}
110
David Monahan3fb7e102019-08-20 11:25:29 +0100111std::unique_ptr<ITensorHandle> NeonWorkloadFactory::CreateTensorHandle(const TensorInfo& tensorInfo,
112 const bool IsMemoryManaged) const
telsoa014fcda012018-03-09 14:13:49 +0000113{
telsoa01c577f2c2018-08-31 09:22:23 +0100114 auto tensorHandle = std::make_unique<NeonTensorHandle>(tensorInfo);
David Monahan3fb7e102019-08-20 11:25:29 +0100115 if (IsMemoryManaged)
116 {
117 tensorHandle->SetMemoryGroup(m_MemoryManager->GetInterLayerMemoryGroup());
118 }
telsoa01c577f2c2018-08-31 09:22:23 +0100119 return tensorHandle;
telsoa014fcda012018-03-09 14:13:49 +0000120}
121
Francis Murtagh351d13d2018-09-24 15:01:18 +0100122std::unique_ptr<ITensorHandle> NeonWorkloadFactory::CreateTensorHandle(const TensorInfo& tensorInfo,
David Monahan3fb7e102019-08-20 11:25:29 +0100123 DataLayout dataLayout,
124 const bool IsMemoryManaged) const
Francis Murtagh351d13d2018-09-24 15:01:18 +0100125{
126 auto tensorHandle = std::make_unique<NeonTensorHandle>(tensorInfo, dataLayout);
David Monahan3fb7e102019-08-20 11:25:29 +0100127 if (IsMemoryManaged)
128 {
129 tensorHandle->SetMemoryGroup(m_MemoryManager->GetInterLayerMemoryGroup());
130 }
Francis Murtagh351d13d2018-09-24 15:01:18 +0100131 return tensorHandle;
132}
133
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000134std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateWorkload(LayerType type,
135 const QueueDescriptor& descriptor,
136 const WorkloadInfo& info) const
137{
138 switch(type)
139 {
140 case LayerType::Activation :
141 {
142 auto activationQueueDescriptor = PolymorphicDowncast<const ActivationQueueDescriptor*>(&descriptor);
143 return std::make_unique<NeonActivationWorkload>(*activationQueueDescriptor, info);
144 }
145 case LayerType::Addition :
146 {
147 auto additionQueueDescriptor = PolymorphicDowncast<const AdditionQueueDescriptor*>(&descriptor);
148 return std::make_unique<NeonAdditionWorkload>(*additionQueueDescriptor, info);
149 }
150 case LayerType::ArgMinMax :
151 {
152 auto argMinMaxQueueDescriptor = PolymorphicDowncast<const ArgMinMaxQueueDescriptor*>(&descriptor);
153 return std::make_unique<NeonArgMinMaxWorkload>(*argMinMaxQueueDescriptor, info);
154 }
Teresa Charlin0f86ecf2022-10-13 15:47:08 +0100155 case LayerType::BatchMatMul :
156 {
157 auto batchMatMulQueueDescriptor = PolymorphicDowncast<const BatchMatMulQueueDescriptor*>(&descriptor);
Teresa Charlin1fe6c812022-11-01 15:59:50 +0000158 bool isFastMathEnabled = false;
159 if (m_ModelContextPtr)
160 {
161 if (m_ModelContextPtr.get() != nullptr)
162 {
163 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
164 if (modelOptions)
165 {
166 isFastMathEnabled = modelOptions->IsFastMathEnabled();
167 }
168 }
169 }
170 return std::make_unique<NeonBatchMatMulWorkload>(*batchMatMulQueueDescriptor, info, isFastMathEnabled);
Teresa Charlin0f86ecf2022-10-13 15:47:08 +0100171 }
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000172 case LayerType::BatchNormalization :
173 {
174 auto batchNormalizationQueueDescriptor
175 = PolymorphicDowncast<const BatchNormalizationQueueDescriptor*>(&descriptor);
176 return std::make_unique<NeonBatchNormalizationWorkload>(*batchNormalizationQueueDescriptor, info);
177 }
178 case LayerType::BatchToSpaceNd :
179 {
180 auto batchToSpaceNdQueueDescriptor
181 = PolymorphicDowncast<const BatchToSpaceNdQueueDescriptor*>(&descriptor);
182 return std::make_unique<NeonBatchToSpaceNdWorkload>(*batchToSpaceNdQueueDescriptor, info);
183 }
184 case LayerType::Cast :
185 {
186 auto castQueueDescriptor = PolymorphicDowncast<const CastQueueDescriptor*>(&descriptor);
187 return std::make_unique<NeonCastWorkload>(*castQueueDescriptor, info);
188 }
189 case LayerType::ChannelShuffle :
190 {
191 auto channelShuffleQueueDescriptor = PolymorphicDowncast<const ChannelShuffleQueueDescriptor*>(&descriptor);
192 return std::make_unique<NeonChannelShuffleWorkload>(*channelShuffleQueueDescriptor, info);
193 }
194 case LayerType::Comparison :
195 {
196 auto comparisonQueueDescriptor = PolymorphicDowncast<const ComparisonQueueDescriptor*>(&descriptor);
197 return std::make_unique<NeonComparisonWorkload>(*comparisonQueueDescriptor, info);
198 }
199 case LayerType::Concat :
200 {
201 auto concatQueueDescriptor = PolymorphicDowncast<const ConcatQueueDescriptor*>(&descriptor);
202 return std::make_unique<NeonConcatWorkload>(*concatQueueDescriptor, info);
203 }
204 case LayerType::Constant :
205 {
206 auto constantQueueDescriptor = PolymorphicDowncast<const ConstantQueueDescriptor*>(&descriptor);
207 return std::make_unique<NeonConstantWorkload>(*constantQueueDescriptor, info);
208 }
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000209 case LayerType::ConvertFp16ToFp32 :
210 {
211 auto convertFp16ToFp32QueueDescriptor
212 = PolymorphicDowncast<const ConvertFp16ToFp32QueueDescriptor*>(&descriptor);
213 return std::make_unique<NeonConvertFp16ToFp32Workload>(*convertFp16ToFp32QueueDescriptor, info);
214 }
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000215 case LayerType::ConvertFp32ToFp16 :
216 {
217 auto convertFp32ToFp16QueueDescriptor
218 = PolymorphicDowncast<const ConvertFp32ToFp16QueueDescriptor*>(&descriptor);
219 return std::make_unique<NeonConvertFp32ToFp16Workload>(*convertFp32ToFp16QueueDescriptor, info);
220 }
221 case LayerType::Convolution2d :
222 {
223 auto convolution2dQueueDescriptor = PolymorphicDowncast<const Convolution2dQueueDescriptor*>(&descriptor);
224
225 bool isFastMathEnabled = false;
226 if (m_ModelContextPtr)
227 {
228 if (m_ModelContextPtr.get() != nullptr)
229 {
230 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
231 if (modelOptions)
232 {
233 isFastMathEnabled = modelOptions->IsFastMathEnabled();
234 }
235 }
236 }
237 return std::make_unique<NeonConvolution2dWorkload>(*convolution2dQueueDescriptor,
238 info,
239 m_MemoryManager->GetIntraLayerManager(),
240 isFastMathEnabled);
241 }
242 case LayerType::Convolution3d :
243 {
244 auto convolution3dQueueDescriptor = PolymorphicDowncast<const Convolution3dQueueDescriptor*>(&descriptor);
245
246 bool isFastMathEnabled = false;
247 if (m_ModelContextPtr)
248 {
249 if (m_ModelContextPtr.get() != nullptr)
250 {
251 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
252 if (modelOptions)
253 {
254 isFastMathEnabled = modelOptions->IsFastMathEnabled();
255 }
256 }
257 }
258 return std::make_unique<NeonConvolution3dWorkload>(*convolution3dQueueDescriptor,
259 info,
260 m_MemoryManager->GetIntraLayerManager(),
261 isFastMathEnabled);
262 }
263 case LayerType::Debug :
264 {
265 auto debugQueueDescriptor = PolymorphicDowncast<const DebugQueueDescriptor*>(&descriptor);
266 return MakeWorkloadHelper<NullWorkload, NullWorkload>(*debugQueueDescriptor, info);
267 }
268 case LayerType::DepthToSpace :
269 {
270 auto depthToSpaceQueueDescriptor = PolymorphicDowncast<const DepthToSpaceQueueDescriptor*>(&descriptor);
271 return std::make_unique<NeonDepthToSpaceWorkload>(*depthToSpaceQueueDescriptor, info);
272 }
273 case LayerType::DepthwiseConvolution2d :
274 {
275 auto depthwiseConvolution2dQueueDescriptor
276 = PolymorphicDowncast<const DepthwiseConvolution2dQueueDescriptor*>(&descriptor);
277 return std::make_unique<NeonDepthwiseConvolutionWorkload>(*depthwiseConvolution2dQueueDescriptor, info);
278 }
279 case LayerType::Dequantize :
280 {
281 auto dequantizeQueueDescriptor = PolymorphicDowncast<const DequantizeQueueDescriptor*>(&descriptor);
282 return std::make_unique<NeonDequantizeWorkload>(*dequantizeQueueDescriptor, info);
283 }
284 case LayerType::DetectionPostProcess :
285 {
286 auto detectionPostProcessQueueDescriptor
287 = PolymorphicDowncast<const DetectionPostProcessQueueDescriptor*>(&descriptor);
288 return MakeWorkloadHelper<NullWorkload, NullWorkload>(*detectionPostProcessQueueDescriptor, info);
289 }
290 case LayerType::Division :
291 {
292 auto divisionQueueDescriptor = PolymorphicDowncast<const DivisionQueueDescriptor*>(&descriptor);
293 return std::make_unique<NeonDivisionWorkload>(*divisionQueueDescriptor, info);
294 }
Mike Kelly3ec30772023-03-08 13:47:17 +0000295 case LayerType::ElementwiseBinary :
296 {
297 auto elementwiseBinaryQueueDescriptor
298 = PolymorphicDowncast<const ElementwiseBinaryQueueDescriptor*>(&descriptor);
299
300 switch (elementwiseBinaryQueueDescriptor->m_Parameters.m_Operation)
301 {
302 case BinaryOperation::Add:
303 {
304 AdditionQueueDescriptor additionQueueDescriptor;
305 additionQueueDescriptor.m_Inputs = descriptor.m_Inputs;
306 additionQueueDescriptor.m_Outputs = descriptor.m_Outputs;
307 return std::make_unique<NeonAdditionWorkload>(additionQueueDescriptor, info);
308 }
309 case BinaryOperation::Div:
310 {
311 DivisionQueueDescriptor divisionQueueDescriptor;
312 divisionQueueDescriptor.m_Inputs = descriptor.m_Inputs;
313 divisionQueueDescriptor.m_Outputs = descriptor.m_Outputs;
314 return std::make_unique<NeonDivisionWorkload>(divisionQueueDescriptor, info);
315 }
316 case BinaryOperation::Maximum:
317 {
318 MaximumQueueDescriptor maximumQueueDescriptor;
319 maximumQueueDescriptor.m_Inputs = descriptor.m_Inputs;
320 maximumQueueDescriptor.m_Outputs = descriptor.m_Outputs;
321 return std::make_unique<NeonMaximumWorkload>(maximumQueueDescriptor, info);
322 }
323 case BinaryOperation::Minimum:
324 {
325 MinimumQueueDescriptor minimumQueueDescriptor;
326 minimumQueueDescriptor.m_Inputs = descriptor.m_Inputs;
327 minimumQueueDescriptor.m_Outputs = descriptor.m_Outputs;
328 return std::make_unique<NeonMinimumWorkload>(minimumQueueDescriptor, info);
329 }
330 case BinaryOperation::Mul:
331 {
332 MultiplicationQueueDescriptor multiplicationQueueDescriptor;
333 multiplicationQueueDescriptor.m_Inputs = descriptor.m_Inputs;
334 multiplicationQueueDescriptor.m_Outputs = descriptor.m_Outputs;
335 return std::make_unique<NeonMultiplicationWorkload>(multiplicationQueueDescriptor, info);
336 }
John Mcloughlin34c1c382023-05-17 15:08:36 +0100337 case BinaryOperation::Power:
338 case BinaryOperation::SqDiff:
339 {
340 return std::make_unique<NeonElementwiseBinaryWorkload>(*elementwiseBinaryQueueDescriptor, info);
341 }
Mike Kelly3ec30772023-03-08 13:47:17 +0000342 case BinaryOperation::Sub:
343 {
344 SubtractionQueueDescriptor subtractionQueueDescriptor;
345 subtractionQueueDescriptor.m_Inputs = descriptor.m_Inputs;
346 subtractionQueueDescriptor.m_Outputs = descriptor.m_Outputs;
347 return std::make_unique<NeonSubtractionWorkload>(subtractionQueueDescriptor, info);
348 }
349 default:
350 return nullptr;
351 }
352 }
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000353 case LayerType::ElementwiseUnary :
354 {
355 auto elementwiseUnaryQueueDescriptor
356 = PolymorphicDowncast<const ElementwiseUnaryQueueDescriptor*>(&descriptor);
357
358 switch(elementwiseUnaryQueueDescriptor->m_Parameters.m_Operation)
359 {
360 case UnaryOperation::Abs:
361 {
362 AbsQueueDescriptor absQueueDescriptor;
363 absQueueDescriptor.m_Inputs = elementwiseUnaryQueueDescriptor->m_Inputs;
364 absQueueDescriptor.m_Outputs = elementwiseUnaryQueueDescriptor->m_Outputs;
365
366 return std::make_unique<NeonAbsWorkload>(absQueueDescriptor, info);
367 }
368 case UnaryOperation::Exp:
369 return std::make_unique<NeonExpWorkload>(*elementwiseUnaryQueueDescriptor, info);
370 case UnaryOperation::LogicalNot:
371 return std::make_unique<NeonLogicalNotWorkload>(*elementwiseUnaryQueueDescriptor, info);
372 case UnaryOperation::Log:
373 return std::make_unique<NeonLogWorkload>(*elementwiseUnaryQueueDescriptor, info);
374 case UnaryOperation::Neg:
375 return std::make_unique<NeonNegWorkload>(*elementwiseUnaryQueueDescriptor, info);
376 case UnaryOperation::Rsqrt:
377 {
378 RsqrtQueueDescriptor rsqrtQueueDescriptor;
379 rsqrtQueueDescriptor.m_Inputs = elementwiseUnaryQueueDescriptor->m_Inputs;
380 rsqrtQueueDescriptor.m_Outputs = elementwiseUnaryQueueDescriptor->m_Outputs;
381
382 return std::make_unique<NeonRsqrtWorkload>(rsqrtQueueDescriptor, info);
383 }
384 case UnaryOperation::Sin:
385 return std::make_unique<NeonSinWorkload>(*elementwiseUnaryQueueDescriptor, info);
Teresa Charlin03027232022-05-09 17:27:08 +0100386 case UnaryOperation::Sqrt:
387 return std::make_unique<NeonSqrtWorkload>(*elementwiseUnaryQueueDescriptor, info);
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000388 default:
389 return nullptr;
390 }
391 }
392 case LayerType::Fill :
393 {
394 auto fillQueueDescriptor = PolymorphicDowncast<const FillQueueDescriptor*>(&descriptor);
395 return std::make_unique<NeonFillWorkload>(*fillQueueDescriptor, info);
396 }
397 case LayerType::Floor :
398 {
399 auto floorQueueDescriptor = PolymorphicDowncast<const FloorQueueDescriptor*>(&descriptor);
400 return MakeWorkloadHelper<NeonFloorFloatWorkload, NullWorkload>(*floorQueueDescriptor, info);
401 }
402 case LayerType::FullyConnected :
403 {
404 auto fullyConnectedQueueDescriptor = PolymorphicDowncast<const FullyConnectedQueueDescriptor*>(&descriptor);
405 return std::make_unique<NeonFullyConnectedWorkload>(*fullyConnectedQueueDescriptor,
406 info,
407 m_MemoryManager->GetIntraLayerManager());
408 }
409 case LayerType::Gather :
410 {
411 auto gatherQueueDescriptor = PolymorphicDowncast<const GatherQueueDescriptor*>(&descriptor);
412 return std::make_unique<NeonGatherWorkload>(*gatherQueueDescriptor, info);
413 }
Teresa Charlinbd22c7d2022-04-26 18:14:12 +0100414 case LayerType::GatherNd :
415 {
416 auto gatherNdQueueDescriptor = PolymorphicDowncast<const GatherNdQueueDescriptor*>(&descriptor);
417 return std::make_unique<NeonGatherNdWorkload>(*gatherNdQueueDescriptor, info);
418 }
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000419 case LayerType::Input :
420 {
421 auto inputQueueDescriptor = PolymorphicDowncast<const InputQueueDescriptor*>(&descriptor);
422 return std::make_unique<CopyMemGenericWorkload>(*inputQueueDescriptor, info);
423 }
424 case LayerType::InstanceNormalization :
425 {
426 auto instanceNormalizationQueueDescriptor
427 = PolymorphicDowncast<const InstanceNormalizationQueueDescriptor*>(&descriptor);
428 return std::make_unique<NeonInstanceNormalizationWorkload>(*instanceNormalizationQueueDescriptor, info);
429 }
430 case LayerType::L2Normalization :
431 {
432 auto l2NormalizationQueueDescriptor
433 = PolymorphicDowncast<const L2NormalizationQueueDescriptor*>(&descriptor);
434 return MakeWorkloadHelper<NeonL2NormalizationFloatWorkload, NullWorkload>
435 (*l2NormalizationQueueDescriptor, info, m_MemoryManager->GetIntraLayerManager());
436 }
437 case LayerType::LogSoftmax :
438 {
439 auto logSoftmaxQueueDescriptor = PolymorphicDowncast<const LogSoftmaxQueueDescriptor*>(&descriptor);
440 return std::make_unique<NeonLogSoftmaxWorkload>(*logSoftmaxQueueDescriptor,
441 info,
442 m_MemoryManager->GetIntraLayerManager());
443 }
444 case LayerType::LogicalBinary :
445 {
446 auto logicalBinaryQueueDescriptor = PolymorphicDowncast<const LogicalBinaryQueueDescriptor*>(&descriptor);
447
448 switch(logicalBinaryQueueDescriptor->m_Parameters.m_Operation)
449 {
450 case LogicalBinaryOperation::LogicalAnd:
451 return std::make_unique<NeonLogicalAndWorkload>(*logicalBinaryQueueDescriptor, info);
452 case LogicalBinaryOperation::LogicalOr:
453 return std::make_unique<NeonLogicalOrWorkload>(*logicalBinaryQueueDescriptor, info);
454 default:
455 return nullptr;
456 }
457 }
458 case LayerType::Lstm :
459 {
460 auto lstmQueueDescriptor = PolymorphicDowncast<const LstmQueueDescriptor*>(&descriptor);
461 return MakeWorkloadHelper<NeonLstmFloatWorkload, NullWorkload>(*lstmQueueDescriptor, info);
462 }
463 case LayerType::Maximum :
464 {
465 auto maximumQueueDescriptor = PolymorphicDowncast<const MaximumQueueDescriptor*>(&descriptor);
466 return std::make_unique<NeonMaximumWorkload>(*maximumQueueDescriptor, info);
467 }
468 case LayerType::Mean :
469 {
470 auto meanQueueDescriptor = PolymorphicDowncast<const MeanQueueDescriptor*>(&descriptor);
471 return std::make_unique<NeonMeanWorkload>(*meanQueueDescriptor, info);
472 }
473 case LayerType::MemCopy :
474 {
475 auto memCopyQueueDescriptor = PolymorphicDowncast<const MemCopyQueueDescriptor*>(&descriptor);
476 if (memCopyQueueDescriptor->m_Inputs.empty() || !memCopyQueueDescriptor->m_Inputs[0])
477 {
478 throw InvalidArgumentException("NeonWorkloadFactory: Invalid null input for MemCopy workload");
479 }
480 return MakeWorkloadHelper<CopyMemGenericWorkload, CopyMemGenericWorkload>(*memCopyQueueDescriptor, info);
481 }
482 case LayerType::MemImport :
483 {
484 auto memImportQueueDescriptor = PolymorphicDowncast<const MemImportQueueDescriptor*>(&descriptor);
485 if (memImportQueueDescriptor->m_Inputs.empty() || !memImportQueueDescriptor->m_Inputs[0])
486 {
487 throw InvalidArgumentException("NeonWorkloadFactory: Invalid null input for MemImport workload");
488 }
489 return std::make_unique<ImportMemGenericWorkload>(*memImportQueueDescriptor, info);
490 }
491 case LayerType::Minimum :
492 {
493 auto minimumQueueDescriptor = PolymorphicDowncast<const MinimumQueueDescriptor*>(&descriptor);
494 return std::make_unique<NeonMinimumWorkload>(*minimumQueueDescriptor, info);
495 }
496 case LayerType::Multiplication :
497 {
498 auto multiplicationQueueDescriptor = PolymorphicDowncast<const MultiplicationQueueDescriptor*>(&descriptor);
499 return std::make_unique<NeonMultiplicationWorkload>(*multiplicationQueueDescriptor, info);
500 }
501 case LayerType::Normalization :
502 {
503 auto normalizationQueueDescriptor = PolymorphicDowncast<const NormalizationQueueDescriptor*>(&descriptor);
504 return MakeWorkloadHelper<NeonNormalizationFloatWorkload, NullWorkload>
505 (*normalizationQueueDescriptor, info, m_MemoryManager->GetIntraLayerManager());
506 }
507 case LayerType::Output :
508 {
509 auto outputQueueDescriptor = PolymorphicDowncast<const OutputQueueDescriptor*>(&descriptor);
510 return std::make_unique<CopyMemGenericWorkload>(*outputQueueDescriptor, info);
511 }
512 case LayerType::Pad :
513 {
514 auto padQueueDescriptor = PolymorphicDowncast<const PadQueueDescriptor*>(&descriptor);
515 return std::make_unique<NeonPadWorkload>(*padQueueDescriptor, info);
516 }
517 case LayerType::Permute :
518 {
519 auto permuteQueueDescriptor = PolymorphicDowncast<const PermuteQueueDescriptor*>(&descriptor);
520 return std::make_unique<NeonPermuteWorkload>(*permuteQueueDescriptor, info);
521 }
522 case LayerType::Pooling2d :
523 {
524 auto pooling2dQueueDescriptor = PolymorphicDowncast<const Pooling2dQueueDescriptor*>(&descriptor);
525 return std::make_unique<NeonPooling2dWorkload>(*pooling2dQueueDescriptor, info);
526 }
Ryan OShea19e79422022-05-04 00:38:03 +0100527 case LayerType::Pooling3d :
528 {
529 auto pooling3dQueueDescriptor = PolymorphicDowncast<const Pooling3dQueueDescriptor*>(&descriptor);
530 return std::make_unique<NeonPooling3dWorkload>(*pooling3dQueueDescriptor, info);
531 }
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000532 case LayerType::PreCompiled :
533 {
534 auto preCompiledQueueDescriptor = PolymorphicDowncast<const PreCompiledQueueDescriptor*>(&descriptor);
535 return MakeWorkloadHelper<NullWorkload, NullWorkload>(*preCompiledQueueDescriptor, info);
536 }
537 case LayerType::Prelu :
538 {
539 auto preluQueueDescriptor = PolymorphicDowncast<const PreluQueueDescriptor*>(&descriptor);
540 return std::make_unique<NeonPreluWorkload>(*preluQueueDescriptor, info);
541 }
542 case LayerType::QLstm :
543 {
544 auto qLstmQueueDescriptor = PolymorphicDowncast<const QLstmQueueDescriptor*>(&descriptor);
545 return std::make_unique<NeonQLstmWorkload>(*qLstmQueueDescriptor, info);
546 }
547 case LayerType::Quantize :
548 {
549 auto quantizeQueueDescriptor = PolymorphicDowncast<const QuantizeQueueDescriptor*>(&descriptor);
550 return std::make_unique<NeonQuantizeWorkload>(*quantizeQueueDescriptor, info);
551 }
552 case LayerType::QuantizedLstm :
553 {
554 auto quantizedLstmQueueDescriptor = PolymorphicDowncast<const QuantizedLstmQueueDescriptor*>(&descriptor);
555 return std::make_unique<NeonQuantizedLstmWorkload>(*quantizedLstmQueueDescriptor, info);
556 }
557 case LayerType::Rank :
558 {
559 auto rankQueueDescriptor = PolymorphicDowncast<const RankQueueDescriptor*>(&descriptor);
560 return std::make_unique<NeonRankWorkload>(*rankQueueDescriptor, info);
561 }
562 case LayerType::Reduce :
563 {
564 auto reduceQueueDescriptor = PolymorphicDowncast<const ReduceQueueDescriptor*>(&descriptor);
565 return std::make_unique<NeonReduceWorkload>(*reduceQueueDescriptor, info);
566 }
567 case LayerType::Reshape :
568 {
569 auto reshapeQueueDescriptor = PolymorphicDowncast<const ReshapeQueueDescriptor*>(&descriptor);
570 return std::make_unique<NeonReshapeWorkload>(*reshapeQueueDescriptor, info);
571 }
572 case LayerType::Resize :
573 {
574 auto resizeQueueDescriptor = PolymorphicDowncast<const ResizeQueueDescriptor*>(&descriptor);
575 return std::make_unique<NeonResizeWorkload>(*resizeQueueDescriptor, info);
576 }
577 case LayerType::Slice :
578 {
579 auto sliceQueueDescriptor = PolymorphicDowncast<const SliceQueueDescriptor*>(&descriptor);
580 return std::make_unique<NeonSliceWorkload>(*sliceQueueDescriptor, info);
581 }
582 case LayerType::Softmax :
583 {
584 auto softmaxQueueDescriptor = PolymorphicDowncast<const SoftmaxQueueDescriptor*>(&descriptor);
585 return std::make_unique<NeonSoftmaxWorkload>(*softmaxQueueDescriptor,
586 info,
587 m_MemoryManager->GetIntraLayerManager());
588 }
589 case LayerType::SpaceToBatchNd :
590 {
591 auto spaceToBatchNdQueueDescriptor
592 = PolymorphicDowncast<const SpaceToBatchNdQueueDescriptor*>(&descriptor);
593 return std::make_unique<NeonSpaceToBatchNdWorkload>(*spaceToBatchNdQueueDescriptor, info);
594 }
595 case LayerType::SpaceToDepth :
596 {
597 auto spaceToDepthQueueDescriptor = PolymorphicDowncast<const SpaceToDepthQueueDescriptor*>(&descriptor);
598 return std::make_unique<NeonSpaceToDepthWorkload>(*spaceToDepthQueueDescriptor, info);
599 }
600 case LayerType::Splitter :
601 {
602 auto splitterQueueDescriptor = PolymorphicDowncast<const SplitterQueueDescriptor*>(&descriptor);
603 return std::make_unique<NeonSplitterWorkload>(*splitterQueueDescriptor, info);
604 }
605 case LayerType::Stack :
606 {
607 auto stackQueueDescriptor = PolymorphicDowncast<const StackQueueDescriptor*>(&descriptor);
608 return std::make_unique<NeonStackWorkload>(*stackQueueDescriptor, info);
609 }
610 case LayerType::StridedSlice :
611 {
612 auto stridedSliceQueueDescriptor = PolymorphicDowncast<const StridedSliceQueueDescriptor*>(&descriptor);
613 return std::make_unique<NeonStridedSliceWorkload>(*stridedSliceQueueDescriptor, info);
614 }
615 case LayerType::Subtraction :
616 {
617 auto subtractionQueueDescriptor = PolymorphicDowncast<const SubtractionQueueDescriptor*>(&descriptor);
618 return std::make_unique<NeonSubtractionWorkload>(*subtractionQueueDescriptor, info);
619 }
620 case LayerType::Transpose :
621 {
622 auto transposeQueueDescriptor = PolymorphicDowncast<const TransposeQueueDescriptor*>(&descriptor);
623 return std::make_unique<NeonTransposeWorkload>(*transposeQueueDescriptor, info);
624 }
625 case LayerType::TransposeConvolution2d :
626 {
627 auto transposeConvolution2dQueueDescriptor
628 = PolymorphicDowncast<const TransposeConvolution2dQueueDescriptor*>(&descriptor);
629 return std::make_unique<NeonTransposeConvolution2dWorkload>(*transposeConvolution2dQueueDescriptor,
630 info,
631 m_MemoryManager->GetIntraLayerManager());
632 }
Cathal Corbettfd5bec42022-03-03 15:13:23 +0000633 case LayerType::UnidirectionalSequenceLstm :
634 {
635 auto desc = PolymorphicDowncast<const UnidirectionalSequenceLstmQueueDescriptor*>(&descriptor);
Mike Kelly12994962022-04-21 11:57:09 +0100636
637 if ((info.m_InputTensorInfos[0].GetDataType() == armnn::DataType::Float32) &&
638 (info.m_InputTensorInfos[1].GetDataType() == armnn::DataType::Float32) &&
639 (info.m_InputTensorInfos[2].GetDataType() == armnn::DataType::Float32) &&
640 (info.m_OutputTensorInfos[0].GetDataType() == armnn::DataType::Float32) &&
641 (info.m_OutputTensorInfos[1].GetDataType() == armnn::DataType::Float32) &&
642 (info.m_OutputTensorInfos[2].GetDataType() == armnn::DataType::Float32))
643 {
644 return std::make_unique<NeonUnidirectionalSequenceLstmFloatWorkload>(*desc, info);
645 }
646 else
647 {
648 return std::make_unique<NeonUnidirectionalSequenceLstmWorkload>(*desc, info);
649 }
Cathal Corbettfd5bec42022-03-03 15:13:23 +0000650 }
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000651 default:
652 return nullptr;
653 }
654}
655
telsoa014fcda012018-03-09 14:13:49 +0000656std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateActivation(const ActivationQueueDescriptor& descriptor,
657 const WorkloadInfo& info) const
658{
Nattapat Chaimanowongd4b70592018-10-12 11:21:49 +0100659 return std::make_unique<NeonActivationWorkload>(descriptor, info);
telsoa014fcda012018-03-09 14:13:49 +0000660}
661
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100662std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateAddition(const AdditionQueueDescriptor& descriptor,
663 const WorkloadInfo& info) const
telsoa014fcda012018-03-09 14:13:49 +0000664{
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100665 return std::make_unique<NeonAdditionWorkload>(descriptor, info);
telsoa014fcda012018-03-09 14:13:49 +0000666}
667
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100668std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateArgMinMax(const ArgMinMaxQueueDescriptor& descriptor,
669 const WorkloadInfo& info) const
telsoa014fcda012018-03-09 14:13:49 +0000670{
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100671 return std::make_unique<NeonArgMinMaxWorkload>(descriptor, info);
telsoa014fcda012018-03-09 14:13:49 +0000672}
673
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100674std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateBatchNormalization(
675 const BatchNormalizationQueueDescriptor& descriptor, const WorkloadInfo& info) const
676{
677 return std::make_unique<NeonBatchNormalizationWorkload>(descriptor, info);
678}
679
680std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateBatchToSpaceNd(const BatchToSpaceNdQueueDescriptor& descriptor,
681 const WorkloadInfo& info) const
682{
Mike Kelly56858022020-01-27 12:14:47 +0000683 return std::make_unique<NeonBatchToSpaceNdWorkload>(descriptor, info);
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100684}
685
Sadik Armagan48f011e2021-04-21 10:50:34 +0100686std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateCast(const CastQueueDescriptor& descriptor,
687 const WorkloadInfo& info) const
688{
689 return std::make_unique<NeonCastWorkload>(descriptor, info);
690}
691
Teresa Charline89dd692021-09-01 16:30:34 +0100692std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateChannelShuffle(const ChannelShuffleQueueDescriptor& descriptor,
693 const WorkloadInfo& info) const
694{
695 return std::make_unique<NeonChannelShuffleWorkload>(descriptor, info);
696}
697
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100698std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateComparison(const ComparisonQueueDescriptor& descriptor,
699 const WorkloadInfo& info) const
700{
Teresa Charlincedd34f2020-03-30 11:17:30 +0100701 return std::make_unique<NeonComparisonWorkload>(descriptor, info);
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100702}
703
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100704std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateConcat(const ConcatQueueDescriptor& descriptor,
telsoa014fcda012018-03-09 14:13:49 +0000705 const WorkloadInfo& info) const
706{
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100707 return std::make_unique<NeonConcatWorkload>(descriptor, info);
telsoa014fcda012018-03-09 14:13:49 +0000708}
709
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100710std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateConstant(const ConstantQueueDescriptor& descriptor,
711 const WorkloadInfo& info) const
telsoa014fcda012018-03-09 14:13:49 +0000712{
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100713 return std::make_unique<NeonConstantWorkload>(descriptor, info);
telsoa014fcda012018-03-09 14:13:49 +0000714}
715
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100716std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateConvertFp16ToFp32(
717 const ConvertFp16ToFp32QueueDescriptor& descriptor,
718 const WorkloadInfo& info) const
telsoa014fcda012018-03-09 14:13:49 +0000719{
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100720 return std::make_unique<NeonConvertFp16ToFp32Workload>(descriptor, info);
telsoa014fcda012018-03-09 14:13:49 +0000721}
722
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100723std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateConvertFp32ToFp16(
724 const ConvertFp32ToFp16QueueDescriptor& descriptor,
725 const WorkloadInfo& info) const
telsoa014fcda012018-03-09 14:13:49 +0000726{
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100727 return std::make_unique<NeonConvertFp32ToFp16Workload>(descriptor, info);
Nikhil Raj9b461482019-07-03 15:58:31 +0100728}
729
telsoa014fcda012018-03-09 14:13:49 +0000730std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateConvolution2d(
731 const Convolution2dQueueDescriptor& descriptor, const WorkloadInfo& info) const
732{
Sadik Armagan04a72972020-09-14 15:44:18 +0100733 bool isFastMathEnabled = false;
734 if (m_ModelContextPtr)
735 {
736 if (m_ModelContextPtr.get() != nullptr)
737 {
738 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
739 if (modelOptions)
740 {
741 isFastMathEnabled = modelOptions->IsFastMathEnabled();
742 }
743 }
744 }
745 return std::make_unique<NeonConvolution2dWorkload>(descriptor,
746 info,
747 m_MemoryManager->GetIntraLayerManager(),
748 isFastMathEnabled);
telsoa014fcda012018-03-09 14:13:49 +0000749}
750
Teresa Charlinec5f7d12021-10-22 17:15:00 +0100751std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateConvolution3d(
752 const Convolution3dQueueDescriptor& descriptor, const WorkloadInfo& info) const
753{
754 bool isFastMathEnabled = false;
755 if (m_ModelContextPtr)
756 {
757 if (m_ModelContextPtr.get() != nullptr)
758 {
759 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
760 if (modelOptions)
761 {
762 isFastMathEnabled = modelOptions->IsFastMathEnabled();
763 }
764 }
765 }
766 return std::make_unique<NeonConvolution3dWorkload>(descriptor,
767 info,
768 m_MemoryManager->GetIntraLayerManager(),
769 isFastMathEnabled);
770}
771
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100772std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateDebug(const DebugQueueDescriptor& descriptor,
773 const WorkloadInfo& info) const
774{
775 return MakeWorkloadHelper<NullWorkload, NullWorkload>(descriptor, info);
776}
777
Aron Virginas-Tar2f00b742019-09-30 13:28:08 +0100778std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateDepthToSpace(const DepthToSpaceQueueDescriptor& descriptor,
779 const WorkloadInfo& info) const
780{
781 return std::make_unique<NeonDepthToSpaceWorkload>(descriptor, info);
782}
783
telsoa014fcda012018-03-09 14:13:49 +0000784std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateDepthwiseConvolution2d(
785 const DepthwiseConvolution2dQueueDescriptor& descriptor, const WorkloadInfo& info) const
786{
Nattapat Chaimanowong77140882018-10-17 11:12:19 +0100787 return std::make_unique<NeonDepthwiseConvolutionWorkload>(descriptor, info);
telsoa014fcda012018-03-09 14:13:49 +0000788}
789
Narumol Prangnawarat01961a72019-05-30 16:47:12 +0100790std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateDequantize(const DequantizeQueueDescriptor& descriptor,
791 const WorkloadInfo& info) const
792{
793 return std::make_unique<NeonDequantizeWorkload>(descriptor, info);
794}
795
Narumol Prangnawarat94dd5d82019-01-23 18:06:26 +0000796std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateDetectionPostProcess(
797 const armnn::DetectionPostProcessQueueDescriptor& descriptor, const armnn::WorkloadInfo& info) const
798{
James Conroyd9fb6e22020-02-21 16:52:44 +0000799 return MakeWorkloadHelper<NullWorkload, NullWorkload>(descriptor, info);
Narumol Prangnawarat94dd5d82019-01-23 18:06:26 +0000800}
801
Francis Murtaghe7a86a42018-08-29 12:42:10 +0100802std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateDivision(
803 const DivisionQueueDescriptor& descriptor, const WorkloadInfo& info) const
804{
Pablo Telloe61f0712020-01-23 10:37:17 +0000805 return std::make_unique<NeonDivisionWorkload>(descriptor, info);
Francis Murtaghe7a86a42018-08-29 12:42:10 +0100806}
807
Sadik Armaganac472102020-03-24 09:54:36 +0000808std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateElementwiseUnary(
809 const ElementwiseUnaryQueueDescriptor& descriptor, const WorkloadInfo& info) const
josh minor4a3c6102020-01-06 16:40:46 -0600810{
Derek Lambertic77874a2020-04-28 13:34:56 +0100811 switch(descriptor.m_Parameters.m_Operation)
josh minor4a3c6102020-01-06 16:40:46 -0600812 {
Derek Lambertic77874a2020-04-28 13:34:56 +0100813 case UnaryOperation::Abs:
James Conroy177df1e2020-11-13 10:18:51 +0000814 {
815 AbsQueueDescriptor absQueueDescriptor;
816 absQueueDescriptor.m_Inputs = descriptor.m_Inputs;
817 absQueueDescriptor.m_Outputs = descriptor.m_Outputs;
josh minor4a3c6102020-01-06 16:40:46 -0600818
James Conroy177df1e2020-11-13 10:18:51 +0000819 return std::make_unique<NeonAbsWorkload>(absQueueDescriptor, info);
820 }
Teresa Charlin50de4fa2021-05-31 18:47:33 +0100821 case UnaryOperation::Exp:
822 return std::make_unique<NeonExpWorkload>(descriptor, info);
823 case UnaryOperation::LogicalNot:
824 return std::make_unique<NeonLogicalNotWorkload>(descriptor, info);
825 case UnaryOperation::Log:
826 return std::make_unique<NeonLogWorkload>(descriptor, info);
827 case UnaryOperation::Neg:
828 return std::make_unique<NeonNegWorkload>(descriptor, info);
Derek Lambertic77874a2020-04-28 13:34:56 +0100829 case UnaryOperation::Rsqrt:
James Conroy177df1e2020-11-13 10:18:51 +0000830 {
831 RsqrtQueueDescriptor rsqrtQueueDescriptor;
832 rsqrtQueueDescriptor.m_Inputs = descriptor.m_Inputs;
833 rsqrtQueueDescriptor.m_Outputs = descriptor.m_Outputs;
josh minor4a3c6102020-01-06 16:40:46 -0600834
James Conroy177df1e2020-11-13 10:18:51 +0000835 return std::make_unique<NeonRsqrtWorkload>(rsqrtQueueDescriptor, info);
836 }
Teresa Charlin50de4fa2021-05-31 18:47:33 +0100837 case UnaryOperation::Sin:
838 return std::make_unique<NeonSinWorkload>(descriptor, info);
Derek Lambertic77874a2020-04-28 13:34:56 +0100839 default:
840 return nullptr;
josh minor4a3c6102020-01-06 16:40:46 -0600841 }
josh minor4a3c6102020-01-06 16:40:46 -0600842}
843
Sadik Armagana792a052020-06-23 16:22:23 +0100844std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateFill(const FillQueueDescriptor& descriptor,
845 const WorkloadInfo& info) const
846{
847 return std::make_unique<NeonFillWorkload>(descriptor, info);
848}
849
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100850std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateFloor(const FloorQueueDescriptor& descriptor,
851 const WorkloadInfo& info) const
852{
853 return MakeWorkloadHelper<NeonFloorFloatWorkload, NullWorkload>(descriptor, info);
854}
855
856std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateFullyConnected(
857 const FullyConnectedQueueDescriptor& descriptor, const WorkloadInfo& info) const
858{
Kevin Maybe7e35c2020-04-29 17:05:05 +0100859 return std::make_unique<NeonFullyConnectedWorkload>(descriptor, info, m_MemoryManager->GetIntraLayerManager());
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100860}
861
862std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateGather(const armnn::GatherQueueDescriptor& descriptor,
863 const armnn::WorkloadInfo& info) const
864{
Teresa Charlinf540eb82020-04-10 19:24:55 +0100865 return std::make_unique<NeonGatherWorkload>(descriptor, info);
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100866}
867
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100868std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateInput(const InputQueueDescriptor& descriptor,
869 const WorkloadInfo& info) const
870{
871 return std::make_unique<CopyMemGenericWorkload>(descriptor, info);
872}
873
874std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateInstanceNormalization(
875 const InstanceNormalizationQueueDescriptor& descriptor,
876 const WorkloadInfo& info) const
877{
878 return std::make_unique<NeonInstanceNormalizationWorkload>(descriptor, info);
879}
880
881std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateL2Normalization(const L2NormalizationQueueDescriptor& descriptor,
882 const WorkloadInfo& info) const
883{
884 return MakeWorkloadHelper<NeonL2NormalizationFloatWorkload, NullWorkload>(descriptor, info,
885 m_MemoryManager->GetIntraLayerManager());
886}
887
Keith Davis69e653f2020-07-02 11:49:26 +0100888std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateLogSoftmax(const LogSoftmaxQueueDescriptor& descriptor,
889 const WorkloadInfo& info) const
890{
891 return std::make_unique<NeonLogSoftmaxWorkload>(descriptor, info, m_MemoryManager->GetIntraLayerManager());
892}
893
James Conroy177df1e2020-11-13 10:18:51 +0000894std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateLogicalBinary(const LogicalBinaryQueueDescriptor& descriptor,
895 const WorkloadInfo& info) const
896{
897 switch(descriptor.m_Parameters.m_Operation)
898 {
899 case LogicalBinaryOperation::LogicalAnd:
900 return std::make_unique<NeonLogicalAndWorkload>(descriptor, info);
901 case LogicalBinaryOperation::LogicalOr:
902 return std::make_unique<NeonLogicalOrWorkload>(descriptor, info);
903 default:
904 return nullptr;
905 }
906}
907
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100908std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateLstm(const LstmQueueDescriptor& descriptor,
909 const WorkloadInfo& info) const
910{
911 return MakeWorkloadHelper<NeonLstmFloatWorkload, NullWorkload>(descriptor, info);
912}
913
914std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateMaximum(const MaximumQueueDescriptor& descriptor,
915 const WorkloadInfo& info) const
916{
917 return std::make_unique<NeonMaximumWorkload>(descriptor, info);
918}
919
920std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateMean(const MeanQueueDescriptor& descriptor,
921 const WorkloadInfo& info) const
922{
923 return std::make_unique<NeonMeanWorkload>(descriptor, info);
telsoa014fcda012018-03-09 14:13:49 +0000924}
925
926std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateMemCopy(const MemCopyQueueDescriptor& descriptor,
927 const WorkloadInfo& info) const
928{
929 if (descriptor.m_Inputs.empty() || !descriptor.m_Inputs[0])
930 {
931 throw InvalidArgumentException("NeonWorkloadFactory: Invalid null input for MemCopy workload");
932 }
933
Aron Virginas-Tara8e06ed2018-10-19 16:46:15 +0100934 return MakeWorkloadHelper<CopyMemGenericWorkload, CopyMemGenericWorkload>(descriptor, info);
telsoa014fcda012018-03-09 14:13:49 +0000935}
936
Derek Lambertif674aa02019-08-01 15:56:25 +0100937std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateMemImport(const MemImportQueueDescriptor& descriptor,
938 const WorkloadInfo& info) const
939{
940 if (descriptor.m_Inputs.empty() || !descriptor.m_Inputs[0])
941 {
942 throw InvalidArgumentException("NeonWorkloadFactory: Invalid null input for MemImport workload");
943 }
944
945 return std::make_unique<ImportMemGenericWorkload>(descriptor, info);
946}
947
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100948std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateMinimum(const MinimumQueueDescriptor& descriptor,
949 const WorkloadInfo& info) const
950{
951 return std::make_unique<NeonMinimumWorkload>(descriptor, info);
952}
953
954std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateMultiplication(
955 const MultiplicationQueueDescriptor& descriptor, const WorkloadInfo& info) const
956{
957 return std::make_unique<NeonMultiplicationWorkload>(descriptor, info);
958}
959
960std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateNormalization(
961 const NormalizationQueueDescriptor& descriptor, const WorkloadInfo& info) const
962{
963 return MakeWorkloadHelper<NeonNormalizationFloatWorkload, NullWorkload>(descriptor, info,
964 m_MemoryManager->GetIntraLayerManager());
965}
966
967std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateOutput(const OutputQueueDescriptor& descriptor,
Keith Davis69e653f2020-07-02 11:49:26 +0100968 const WorkloadInfo& info) const
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100969{
970 return std::make_unique<CopyMemGenericWorkload>(descriptor, info);
971}
972
973std::unique_ptr<IWorkload> NeonWorkloadFactory::CreatePad(const PadQueueDescriptor& descriptor,
974 const WorkloadInfo& info) const
975{
976 return std::make_unique<NeonPadWorkload>(descriptor, info);
977}
978
979std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreatePermute(const PermuteQueueDescriptor& descriptor,
Keith Davis69e653f2020-07-02 11:49:26 +0100980 const WorkloadInfo& info) const
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100981{
982 return std::make_unique<NeonPermuteWorkload>(descriptor, info);
983}
984
985std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreatePooling2d(const Pooling2dQueueDescriptor& descriptor,
Keith Davis69e653f2020-07-02 11:49:26 +0100986 const WorkloadInfo& info) const
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100987{
988 return std::make_unique<NeonPooling2dWorkload>(descriptor, info);
989}
990
991std::unique_ptr<IWorkload> NeonWorkloadFactory::CreatePreCompiled(const PreCompiledQueueDescriptor& descriptor,
992 const WorkloadInfo& info) const
993{
994 return MakeWorkloadHelper<NullWorkload, NullWorkload>(descriptor, info);
995}
996
997std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreatePrelu(const armnn::PreluQueueDescriptor &descriptor,
998 const armnn::WorkloadInfo &info) const
999{
1000 return std::make_unique<NeonPreluWorkload>(descriptor, info);
1001}
1002
James Conroycc340932020-05-12 18:08:52 +01001003std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateQLstm(const QLstmQueueDescriptor& descriptor,
1004 const WorkloadInfo& info) const
1005{
1006 return std::make_unique<NeonQLstmWorkload>(descriptor, info);
1007}
1008
Sadik Armagan0d4863d2019-10-09 14:26:32 +01001009std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateQuantize(const QuantizeQueueDescriptor& descriptor,
1010 const WorkloadInfo& info) const
1011{
Kevin May90774732020-03-03 12:10:10 +00001012 return std::make_unique<NeonQuantizeWorkload>(descriptor, info);
Sadik Armagan0d4863d2019-10-09 14:26:32 +01001013}
1014
1015std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateQuantizedLstm(const QuantizedLstmQueueDescriptor& descriptor,
1016 const WorkloadInfo& info) const
1017{
1018 return std::make_unique<NeonQuantizedLstmWorkload>(descriptor, info);
1019}
1020
David Monahan97451b42020-12-03 09:48:06 +00001021std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateRank(const RankQueueDescriptor& descriptor,
1022 const WorkloadInfo& info) const
1023{
1024 return std::make_unique<NeonRankWorkload>(descriptor, info);
1025}
1026
Sadik Armagana2747482021-02-09 10:28:54 +00001027std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateReduce(const ReduceQueueDescriptor& descriptor,
1028 const WorkloadInfo& info) const
1029{
1030 return std::make_unique<NeonReduceWorkload>(descriptor, info);
1031}
1032
Sadik Armagan0d4863d2019-10-09 14:26:32 +01001033std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateReshape(const ReshapeQueueDescriptor& descriptor,
1034 const WorkloadInfo& info) const
1035{
1036 return std::make_unique<NeonReshapeWorkload>(descriptor, info);
1037}
1038
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01001039std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateResize(const ResizeQueueDescriptor& descriptor,
1040 const WorkloadInfo& info) const
1041{
Ellen Norris-Thompson37e68682019-07-15 14:23:30 +01001042 return std::make_unique<NeonResizeWorkload>(descriptor, info);
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01001043}
1044
josh minor036f02d2019-11-15 14:53:22 -06001045std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateSlice(const SliceQueueDescriptor& descriptor,
1046 const WorkloadInfo& info) const
1047{
1048 return std::make_unique<NeonSliceWorkload>(descriptor, info);
1049}
1050
Sadik Armagan0d4863d2019-10-09 14:26:32 +01001051std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateSoftmax(const SoftmaxQueueDescriptor& descriptor,
1052 const WorkloadInfo& info) const
Sadik Armagan581742d2019-08-12 14:11:37 +01001053{
Sadik Armaganbe88a572020-04-30 11:39:37 +01001054 return std::make_unique<NeonSoftmaxWorkload>(descriptor, info, m_MemoryManager->GetIntraLayerManager());
Sadik Armagan581742d2019-08-12 14:11:37 +01001055}
1056
Mike Kelly0be3a882020-01-24 11:27:50 +00001057std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateSpaceToBatchNd(const SpaceToBatchNdQueueDescriptor& descriptor,
1058 const WorkloadInfo& info) const
1059{
1060 return std::make_unique<NeonSpaceToBatchNdWorkload>(descriptor, info);
1061}
1062
1063std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateSpaceToDepth(const SpaceToDepthQueueDescriptor& descriptor,
1064 const WorkloadInfo& info) const
narpra01b89b05f2019-01-16 09:53:09 +00001065{
Sadik Armagan0d4863d2019-10-09 14:26:32 +01001066 return std::make_unique<NeonSpaceToDepthWorkload>(descriptor, info);
1067}
1068
1069std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateSplitter(const SplitterQueueDescriptor& descriptor,
1070 const WorkloadInfo& info) const
1071{
1072 return std::make_unique<NeonSplitterWorkload>(descriptor, info);
narpra01b89b05f2019-01-16 09:53:09 +00001073}
1074
Matthew Jackson87f65ea2019-08-01 10:01:34 +01001075std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateStack(const StackQueueDescriptor& descriptor,
1076 const WorkloadInfo& info) const
1077{
1078 return std::make_unique<NeonStackWorkload>(descriptor, info);
1079}
1080
Sadik Armagan0d4863d2019-10-09 14:26:32 +01001081std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateStridedSlice(const StridedSliceQueueDescriptor& descriptor,
1082 const WorkloadInfo& info) const
James Conroyd47a0642019-09-17 14:22:06 +01001083{
Sadik Armagan0d4863d2019-10-09 14:26:32 +01001084 return std::make_unique<NeonStridedSliceWorkload>(descriptor, info);
1085}
1086
1087std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateSubtraction(
1088 const SubtractionQueueDescriptor& descriptor, const WorkloadInfo& info) const
1089{
1090 return std::make_unique<NeonSubtractionWorkload>(descriptor, info);
1091}
1092
Mike Kellyc9ea45a2020-02-28 18:11:58 +00001093std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateTranspose(const TransposeQueueDescriptor& descriptor,
1094 const WorkloadInfo& info) const
1095{
1096 return std::make_unique<NeonTransposeWorkload>(descriptor, info);
1097}
1098
Sadik Armagan0d4863d2019-10-09 14:26:32 +01001099std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateTransposeConvolution2d(
1100 const TransposeConvolution2dQueueDescriptor &descriptor,
1101 const WorkloadInfo &info) const
1102{
1103 return std::make_unique<NeonTransposeConvolution2dWorkload>(descriptor, info,
1104 m_MemoryManager->GetIntraLayerManager());
James Conroyd47a0642019-09-17 14:22:06 +01001105}
1106
Aron Virginas-Tar56055192018-11-12 18:10:43 +00001107} // namespace armnn