blob: ff9ef268ecc1b6ac5dd4cbf6ec35116ebfd50198 [file] [log] [blame]
Laurent Carlier749294b2020-06-01 09:03:17 +01001//
Keith Davis69e653f2020-07-02 11:49:26 +01002// Copyright © 2017 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 }
155 case LayerType::BatchNormalization :
156 {
157 auto batchNormalizationQueueDescriptor
158 = PolymorphicDowncast<const BatchNormalizationQueueDescriptor*>(&descriptor);
159 return std::make_unique<NeonBatchNormalizationWorkload>(*batchNormalizationQueueDescriptor, info);
160 }
161 case LayerType::BatchToSpaceNd :
162 {
163 auto batchToSpaceNdQueueDescriptor
164 = PolymorphicDowncast<const BatchToSpaceNdQueueDescriptor*>(&descriptor);
165 return std::make_unique<NeonBatchToSpaceNdWorkload>(*batchToSpaceNdQueueDescriptor, info);
166 }
167 case LayerType::Cast :
168 {
169 auto castQueueDescriptor = PolymorphicDowncast<const CastQueueDescriptor*>(&descriptor);
170 return std::make_unique<NeonCastWorkload>(*castQueueDescriptor, info);
171 }
172 case LayerType::ChannelShuffle :
173 {
174 auto channelShuffleQueueDescriptor = PolymorphicDowncast<const ChannelShuffleQueueDescriptor*>(&descriptor);
175 return std::make_unique<NeonChannelShuffleWorkload>(*channelShuffleQueueDescriptor, info);
176 }
177 case LayerType::Comparison :
178 {
179 auto comparisonQueueDescriptor = PolymorphicDowncast<const ComparisonQueueDescriptor*>(&descriptor);
180 return std::make_unique<NeonComparisonWorkload>(*comparisonQueueDescriptor, info);
181 }
182 case LayerType::Concat :
183 {
184 auto concatQueueDescriptor = PolymorphicDowncast<const ConcatQueueDescriptor*>(&descriptor);
185 return std::make_unique<NeonConcatWorkload>(*concatQueueDescriptor, info);
186 }
187 case LayerType::Constant :
188 {
189 auto constantQueueDescriptor = PolymorphicDowncast<const ConstantQueueDescriptor*>(&descriptor);
190 return std::make_unique<NeonConstantWorkload>(*constantQueueDescriptor, info);
191 }
192 case LayerType::ConvertBf16ToFp32 :
193 {
194 auto convertBf16ToFp32QueueDescriptor
195 = PolymorphicDowncast<const ConvertBf16ToFp32QueueDescriptor*>(&descriptor);
196 return std::make_unique<NeonConvertBf16ToFp32Workload>(*convertBf16ToFp32QueueDescriptor, info);
197 }
198 case LayerType::ConvertFp16ToFp32 :
199 {
200 auto convertFp16ToFp32QueueDescriptor
201 = PolymorphicDowncast<const ConvertFp16ToFp32QueueDescriptor*>(&descriptor);
202 return std::make_unique<NeonConvertFp16ToFp32Workload>(*convertFp16ToFp32QueueDescriptor, info);
203 }
204 case LayerType::ConvertFp32ToBf16 :
205 {
206 auto convertFp32ToBf16QueueDescriptor
207 = PolymorphicDowncast<const ConvertFp32ToBf16QueueDescriptor*>(&descriptor);
208 return std::make_unique<NeonConvertFp32ToBf16Workload>(*convertFp32ToBf16QueueDescriptor, info);
209 }
210 case LayerType::ConvertFp32ToFp16 :
211 {
212 auto convertFp32ToFp16QueueDescriptor
213 = PolymorphicDowncast<const ConvertFp32ToFp16QueueDescriptor*>(&descriptor);
214 return std::make_unique<NeonConvertFp32ToFp16Workload>(*convertFp32ToFp16QueueDescriptor, info);
215 }
216 case LayerType::Convolution2d :
217 {
218 auto convolution2dQueueDescriptor = PolymorphicDowncast<const Convolution2dQueueDescriptor*>(&descriptor);
219
220 bool isFastMathEnabled = false;
221 if (m_ModelContextPtr)
222 {
223 if (m_ModelContextPtr.get() != nullptr)
224 {
225 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
226 if (modelOptions)
227 {
228 isFastMathEnabled = modelOptions->IsFastMathEnabled();
229 }
230 }
231 }
232 return std::make_unique<NeonConvolution2dWorkload>(*convolution2dQueueDescriptor,
233 info,
234 m_MemoryManager->GetIntraLayerManager(),
235 isFastMathEnabled);
236 }
237 case LayerType::Convolution3d :
238 {
239 auto convolution3dQueueDescriptor = PolymorphicDowncast<const Convolution3dQueueDescriptor*>(&descriptor);
240
241 bool isFastMathEnabled = false;
242 if (m_ModelContextPtr)
243 {
244 if (m_ModelContextPtr.get() != nullptr)
245 {
246 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
247 if (modelOptions)
248 {
249 isFastMathEnabled = modelOptions->IsFastMathEnabled();
250 }
251 }
252 }
253 return std::make_unique<NeonConvolution3dWorkload>(*convolution3dQueueDescriptor,
254 info,
255 m_MemoryManager->GetIntraLayerManager(),
256 isFastMathEnabled);
257 }
258 case LayerType::Debug :
259 {
260 auto debugQueueDescriptor = PolymorphicDowncast<const DebugQueueDescriptor*>(&descriptor);
261 return MakeWorkloadHelper<NullWorkload, NullWorkload>(*debugQueueDescriptor, info);
262 }
263 case LayerType::DepthToSpace :
264 {
265 auto depthToSpaceQueueDescriptor = PolymorphicDowncast<const DepthToSpaceQueueDescriptor*>(&descriptor);
266 return std::make_unique<NeonDepthToSpaceWorkload>(*depthToSpaceQueueDescriptor, info);
267 }
268 case LayerType::DepthwiseConvolution2d :
269 {
270 auto depthwiseConvolution2dQueueDescriptor
271 = PolymorphicDowncast<const DepthwiseConvolution2dQueueDescriptor*>(&descriptor);
272 return std::make_unique<NeonDepthwiseConvolutionWorkload>(*depthwiseConvolution2dQueueDescriptor, info);
273 }
274 case LayerType::Dequantize :
275 {
276 auto dequantizeQueueDescriptor = PolymorphicDowncast<const DequantizeQueueDescriptor*>(&descriptor);
277 return std::make_unique<NeonDequantizeWorkload>(*dequantizeQueueDescriptor, info);
278 }
279 case LayerType::DetectionPostProcess :
280 {
281 auto detectionPostProcessQueueDescriptor
282 = PolymorphicDowncast<const DetectionPostProcessQueueDescriptor*>(&descriptor);
283 return MakeWorkloadHelper<NullWorkload, NullWorkload>(*detectionPostProcessQueueDescriptor, info);
284 }
285 case LayerType::Division :
286 {
287 auto divisionQueueDescriptor = PolymorphicDowncast<const DivisionQueueDescriptor*>(&descriptor);
288 return std::make_unique<NeonDivisionWorkload>(*divisionQueueDescriptor, info);
289 }
290 case LayerType::ElementwiseUnary :
291 {
292 auto elementwiseUnaryQueueDescriptor
293 = PolymorphicDowncast<const ElementwiseUnaryQueueDescriptor*>(&descriptor);
294
295 switch(elementwiseUnaryQueueDescriptor->m_Parameters.m_Operation)
296 {
297 case UnaryOperation::Abs:
298 {
299 AbsQueueDescriptor absQueueDescriptor;
300 absQueueDescriptor.m_Inputs = elementwiseUnaryQueueDescriptor->m_Inputs;
301 absQueueDescriptor.m_Outputs = elementwiseUnaryQueueDescriptor->m_Outputs;
302
303 return std::make_unique<NeonAbsWorkload>(absQueueDescriptor, info);
304 }
305 case UnaryOperation::Exp:
306 return std::make_unique<NeonExpWorkload>(*elementwiseUnaryQueueDescriptor, info);
307 case UnaryOperation::LogicalNot:
308 return std::make_unique<NeonLogicalNotWorkload>(*elementwiseUnaryQueueDescriptor, info);
309 case UnaryOperation::Log:
310 return std::make_unique<NeonLogWorkload>(*elementwiseUnaryQueueDescriptor, info);
311 case UnaryOperation::Neg:
312 return std::make_unique<NeonNegWorkload>(*elementwiseUnaryQueueDescriptor, info);
313 case UnaryOperation::Rsqrt:
314 {
315 RsqrtQueueDescriptor rsqrtQueueDescriptor;
316 rsqrtQueueDescriptor.m_Inputs = elementwiseUnaryQueueDescriptor->m_Inputs;
317 rsqrtQueueDescriptor.m_Outputs = elementwiseUnaryQueueDescriptor->m_Outputs;
318
319 return std::make_unique<NeonRsqrtWorkload>(rsqrtQueueDescriptor, info);
320 }
321 case UnaryOperation::Sin:
322 return std::make_unique<NeonSinWorkload>(*elementwiseUnaryQueueDescriptor, info);
Teresa Charlin03027232022-05-09 17:27:08 +0100323 case UnaryOperation::Sqrt:
324 return std::make_unique<NeonSqrtWorkload>(*elementwiseUnaryQueueDescriptor, info);
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000325 default:
326 return nullptr;
327 }
328 }
329 case LayerType::Fill :
330 {
331 auto fillQueueDescriptor = PolymorphicDowncast<const FillQueueDescriptor*>(&descriptor);
332 return std::make_unique<NeonFillWorkload>(*fillQueueDescriptor, info);
333 }
334 case LayerType::Floor :
335 {
336 auto floorQueueDescriptor = PolymorphicDowncast<const FloorQueueDescriptor*>(&descriptor);
337 return MakeWorkloadHelper<NeonFloorFloatWorkload, NullWorkload>(*floorQueueDescriptor, info);
338 }
339 case LayerType::FullyConnected :
340 {
341 auto fullyConnectedQueueDescriptor = PolymorphicDowncast<const FullyConnectedQueueDescriptor*>(&descriptor);
342 return std::make_unique<NeonFullyConnectedWorkload>(*fullyConnectedQueueDescriptor,
343 info,
344 m_MemoryManager->GetIntraLayerManager());
345 }
346 case LayerType::Gather :
347 {
348 auto gatherQueueDescriptor = PolymorphicDowncast<const GatherQueueDescriptor*>(&descriptor);
349 return std::make_unique<NeonGatherWorkload>(*gatherQueueDescriptor, info);
350 }
Teresa Charlinbd22c7d2022-04-26 18:14:12 +0100351 case LayerType::GatherNd :
352 {
353 auto gatherNdQueueDescriptor = PolymorphicDowncast<const GatherNdQueueDescriptor*>(&descriptor);
354 return std::make_unique<NeonGatherNdWorkload>(*gatherNdQueueDescriptor, info);
355 }
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000356 case LayerType::Input :
357 {
358 auto inputQueueDescriptor = PolymorphicDowncast<const InputQueueDescriptor*>(&descriptor);
359 return std::make_unique<CopyMemGenericWorkload>(*inputQueueDescriptor, info);
360 }
361 case LayerType::InstanceNormalization :
362 {
363 auto instanceNormalizationQueueDescriptor
364 = PolymorphicDowncast<const InstanceNormalizationQueueDescriptor*>(&descriptor);
365 return std::make_unique<NeonInstanceNormalizationWorkload>(*instanceNormalizationQueueDescriptor, info);
366 }
367 case LayerType::L2Normalization :
368 {
369 auto l2NormalizationQueueDescriptor
370 = PolymorphicDowncast<const L2NormalizationQueueDescriptor*>(&descriptor);
371 return MakeWorkloadHelper<NeonL2NormalizationFloatWorkload, NullWorkload>
372 (*l2NormalizationQueueDescriptor, info, m_MemoryManager->GetIntraLayerManager());
373 }
374 case LayerType::LogSoftmax :
375 {
376 auto logSoftmaxQueueDescriptor = PolymorphicDowncast<const LogSoftmaxQueueDescriptor*>(&descriptor);
377 return std::make_unique<NeonLogSoftmaxWorkload>(*logSoftmaxQueueDescriptor,
378 info,
379 m_MemoryManager->GetIntraLayerManager());
380 }
381 case LayerType::LogicalBinary :
382 {
383 auto logicalBinaryQueueDescriptor = PolymorphicDowncast<const LogicalBinaryQueueDescriptor*>(&descriptor);
384
385 switch(logicalBinaryQueueDescriptor->m_Parameters.m_Operation)
386 {
387 case LogicalBinaryOperation::LogicalAnd:
388 return std::make_unique<NeonLogicalAndWorkload>(*logicalBinaryQueueDescriptor, info);
389 case LogicalBinaryOperation::LogicalOr:
390 return std::make_unique<NeonLogicalOrWorkload>(*logicalBinaryQueueDescriptor, info);
391 default:
392 return nullptr;
393 }
394 }
395 case LayerType::Lstm :
396 {
397 auto lstmQueueDescriptor = PolymorphicDowncast<const LstmQueueDescriptor*>(&descriptor);
398 return MakeWorkloadHelper<NeonLstmFloatWorkload, NullWorkload>(*lstmQueueDescriptor, info);
399 }
400 case LayerType::Maximum :
401 {
402 auto maximumQueueDescriptor = PolymorphicDowncast<const MaximumQueueDescriptor*>(&descriptor);
403 return std::make_unique<NeonMaximumWorkload>(*maximumQueueDescriptor, info);
404 }
405 case LayerType::Mean :
406 {
407 auto meanQueueDescriptor = PolymorphicDowncast<const MeanQueueDescriptor*>(&descriptor);
408 return std::make_unique<NeonMeanWorkload>(*meanQueueDescriptor, info);
409 }
410 case LayerType::MemCopy :
411 {
412 auto memCopyQueueDescriptor = PolymorphicDowncast<const MemCopyQueueDescriptor*>(&descriptor);
413 if (memCopyQueueDescriptor->m_Inputs.empty() || !memCopyQueueDescriptor->m_Inputs[0])
414 {
415 throw InvalidArgumentException("NeonWorkloadFactory: Invalid null input for MemCopy workload");
416 }
417 return MakeWorkloadHelper<CopyMemGenericWorkload, CopyMemGenericWorkload>(*memCopyQueueDescriptor, info);
418 }
419 case LayerType::MemImport :
420 {
421 auto memImportQueueDescriptor = PolymorphicDowncast<const MemImportQueueDescriptor*>(&descriptor);
422 if (memImportQueueDescriptor->m_Inputs.empty() || !memImportQueueDescriptor->m_Inputs[0])
423 {
424 throw InvalidArgumentException("NeonWorkloadFactory: Invalid null input for MemImport workload");
425 }
426 return std::make_unique<ImportMemGenericWorkload>(*memImportQueueDescriptor, info);
427 }
428 case LayerType::Minimum :
429 {
430 auto minimumQueueDescriptor = PolymorphicDowncast<const MinimumQueueDescriptor*>(&descriptor);
431 return std::make_unique<NeonMinimumWorkload>(*minimumQueueDescriptor, info);
432 }
433 case LayerType::Multiplication :
434 {
435 auto multiplicationQueueDescriptor = PolymorphicDowncast<const MultiplicationQueueDescriptor*>(&descriptor);
436 return std::make_unique<NeonMultiplicationWorkload>(*multiplicationQueueDescriptor, info);
437 }
438 case LayerType::Normalization :
439 {
440 auto normalizationQueueDescriptor = PolymorphicDowncast<const NormalizationQueueDescriptor*>(&descriptor);
441 return MakeWorkloadHelper<NeonNormalizationFloatWorkload, NullWorkload>
442 (*normalizationQueueDescriptor, info, m_MemoryManager->GetIntraLayerManager());
443 }
444 case LayerType::Output :
445 {
446 auto outputQueueDescriptor = PolymorphicDowncast<const OutputQueueDescriptor*>(&descriptor);
447 return std::make_unique<CopyMemGenericWorkload>(*outputQueueDescriptor, info);
448 }
449 case LayerType::Pad :
450 {
451 auto padQueueDescriptor = PolymorphicDowncast<const PadQueueDescriptor*>(&descriptor);
452 return std::make_unique<NeonPadWorkload>(*padQueueDescriptor, info);
453 }
454 case LayerType::Permute :
455 {
456 auto permuteQueueDescriptor = PolymorphicDowncast<const PermuteQueueDescriptor*>(&descriptor);
457 return std::make_unique<NeonPermuteWorkload>(*permuteQueueDescriptor, info);
458 }
459 case LayerType::Pooling2d :
460 {
461 auto pooling2dQueueDescriptor = PolymorphicDowncast<const Pooling2dQueueDescriptor*>(&descriptor);
462 return std::make_unique<NeonPooling2dWorkload>(*pooling2dQueueDescriptor, info);
463 }
Ryan OShea19e79422022-05-04 00:38:03 +0100464 case LayerType::Pooling3d :
465 {
466 auto pooling3dQueueDescriptor = PolymorphicDowncast<const Pooling3dQueueDescriptor*>(&descriptor);
467 return std::make_unique<NeonPooling3dWorkload>(*pooling3dQueueDescriptor, info);
468 }
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000469 case LayerType::PreCompiled :
470 {
471 auto preCompiledQueueDescriptor = PolymorphicDowncast<const PreCompiledQueueDescriptor*>(&descriptor);
472 return MakeWorkloadHelper<NullWorkload, NullWorkload>(*preCompiledQueueDescriptor, info);
473 }
474 case LayerType::Prelu :
475 {
476 auto preluQueueDescriptor = PolymorphicDowncast<const PreluQueueDescriptor*>(&descriptor);
477 return std::make_unique<NeonPreluWorkload>(*preluQueueDescriptor, info);
478 }
479 case LayerType::QLstm :
480 {
481 auto qLstmQueueDescriptor = PolymorphicDowncast<const QLstmQueueDescriptor*>(&descriptor);
482 return std::make_unique<NeonQLstmWorkload>(*qLstmQueueDescriptor, info);
483 }
484 case LayerType::Quantize :
485 {
486 auto quantizeQueueDescriptor = PolymorphicDowncast<const QuantizeQueueDescriptor*>(&descriptor);
487 return std::make_unique<NeonQuantizeWorkload>(*quantizeQueueDescriptor, info);
488 }
489 case LayerType::QuantizedLstm :
490 {
491 auto quantizedLstmQueueDescriptor = PolymorphicDowncast<const QuantizedLstmQueueDescriptor*>(&descriptor);
492 return std::make_unique<NeonQuantizedLstmWorkload>(*quantizedLstmQueueDescriptor, info);
493 }
494 case LayerType::Rank :
495 {
496 auto rankQueueDescriptor = PolymorphicDowncast<const RankQueueDescriptor*>(&descriptor);
497 return std::make_unique<NeonRankWorkload>(*rankQueueDescriptor, info);
498 }
499 case LayerType::Reduce :
500 {
501 auto reduceQueueDescriptor = PolymorphicDowncast<const ReduceQueueDescriptor*>(&descriptor);
502 return std::make_unique<NeonReduceWorkload>(*reduceQueueDescriptor, info);
503 }
504 case LayerType::Reshape :
505 {
506 auto reshapeQueueDescriptor = PolymorphicDowncast<const ReshapeQueueDescriptor*>(&descriptor);
507 return std::make_unique<NeonReshapeWorkload>(*reshapeQueueDescriptor, info);
508 }
509 case LayerType::Resize :
510 {
511 auto resizeQueueDescriptor = PolymorphicDowncast<const ResizeQueueDescriptor*>(&descriptor);
512 return std::make_unique<NeonResizeWorkload>(*resizeQueueDescriptor, info);
513 }
514 case LayerType::Slice :
515 {
516 auto sliceQueueDescriptor = PolymorphicDowncast<const SliceQueueDescriptor*>(&descriptor);
517 return std::make_unique<NeonSliceWorkload>(*sliceQueueDescriptor, info);
518 }
519 case LayerType::Softmax :
520 {
521 auto softmaxQueueDescriptor = PolymorphicDowncast<const SoftmaxQueueDescriptor*>(&descriptor);
522 return std::make_unique<NeonSoftmaxWorkload>(*softmaxQueueDescriptor,
523 info,
524 m_MemoryManager->GetIntraLayerManager());
525 }
526 case LayerType::SpaceToBatchNd :
527 {
528 auto spaceToBatchNdQueueDescriptor
529 = PolymorphicDowncast<const SpaceToBatchNdQueueDescriptor*>(&descriptor);
530 return std::make_unique<NeonSpaceToBatchNdWorkload>(*spaceToBatchNdQueueDescriptor, info);
531 }
532 case LayerType::SpaceToDepth :
533 {
534 auto spaceToDepthQueueDescriptor = PolymorphicDowncast<const SpaceToDepthQueueDescriptor*>(&descriptor);
535 return std::make_unique<NeonSpaceToDepthWorkload>(*spaceToDepthQueueDescriptor, info);
536 }
537 case LayerType::Splitter :
538 {
539 auto splitterQueueDescriptor = PolymorphicDowncast<const SplitterQueueDescriptor*>(&descriptor);
540 return std::make_unique<NeonSplitterWorkload>(*splitterQueueDescriptor, info);
541 }
542 case LayerType::Stack :
543 {
544 auto stackQueueDescriptor = PolymorphicDowncast<const StackQueueDescriptor*>(&descriptor);
545 return std::make_unique<NeonStackWorkload>(*stackQueueDescriptor, info);
546 }
547 case LayerType::StridedSlice :
548 {
549 auto stridedSliceQueueDescriptor = PolymorphicDowncast<const StridedSliceQueueDescriptor*>(&descriptor);
550 return std::make_unique<NeonStridedSliceWorkload>(*stridedSliceQueueDescriptor, info);
551 }
552 case LayerType::Subtraction :
553 {
554 auto subtractionQueueDescriptor = PolymorphicDowncast<const SubtractionQueueDescriptor*>(&descriptor);
555 return std::make_unique<NeonSubtractionWorkload>(*subtractionQueueDescriptor, info);
556 }
557 case LayerType::Transpose :
558 {
559 auto transposeQueueDescriptor = PolymorphicDowncast<const TransposeQueueDescriptor*>(&descriptor);
560 return std::make_unique<NeonTransposeWorkload>(*transposeQueueDescriptor, info);
561 }
562 case LayerType::TransposeConvolution2d :
563 {
564 auto transposeConvolution2dQueueDescriptor
565 = PolymorphicDowncast<const TransposeConvolution2dQueueDescriptor*>(&descriptor);
566 return std::make_unique<NeonTransposeConvolution2dWorkload>(*transposeConvolution2dQueueDescriptor,
567 info,
568 m_MemoryManager->GetIntraLayerManager());
569 }
Cathal Corbettfd5bec42022-03-03 15:13:23 +0000570 case LayerType::UnidirectionalSequenceLstm :
571 {
572 auto desc = PolymorphicDowncast<const UnidirectionalSequenceLstmQueueDescriptor*>(&descriptor);
Mike Kelly12994962022-04-21 11:57:09 +0100573
574 if ((info.m_InputTensorInfos[0].GetDataType() == armnn::DataType::Float32) &&
575 (info.m_InputTensorInfos[1].GetDataType() == armnn::DataType::Float32) &&
576 (info.m_InputTensorInfos[2].GetDataType() == armnn::DataType::Float32) &&
577 (info.m_OutputTensorInfos[0].GetDataType() == armnn::DataType::Float32) &&
578 (info.m_OutputTensorInfos[1].GetDataType() == armnn::DataType::Float32) &&
579 (info.m_OutputTensorInfos[2].GetDataType() == armnn::DataType::Float32))
580 {
581 return std::make_unique<NeonUnidirectionalSequenceLstmFloatWorkload>(*desc, info);
582 }
583 else
584 {
585 return std::make_unique<NeonUnidirectionalSequenceLstmWorkload>(*desc, info);
586 }
Cathal Corbettfd5bec42022-03-03 15:13:23 +0000587 }
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000588 default:
589 return nullptr;
590 }
591}
592
telsoa014fcda012018-03-09 14:13:49 +0000593std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateActivation(const ActivationQueueDescriptor& descriptor,
594 const WorkloadInfo& info) const
595{
Nattapat Chaimanowongd4b70592018-10-12 11:21:49 +0100596 return std::make_unique<NeonActivationWorkload>(descriptor, info);
telsoa014fcda012018-03-09 14:13:49 +0000597}
598
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100599std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateAddition(const AdditionQueueDescriptor& descriptor,
600 const WorkloadInfo& info) const
telsoa014fcda012018-03-09 14:13:49 +0000601{
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100602 return std::make_unique<NeonAdditionWorkload>(descriptor, info);
telsoa014fcda012018-03-09 14:13:49 +0000603}
604
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100605std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateArgMinMax(const ArgMinMaxQueueDescriptor& descriptor,
606 const WorkloadInfo& info) const
telsoa014fcda012018-03-09 14:13:49 +0000607{
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100608 return std::make_unique<NeonArgMinMaxWorkload>(descriptor, info);
telsoa014fcda012018-03-09 14:13:49 +0000609}
610
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100611std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateBatchNormalization(
612 const BatchNormalizationQueueDescriptor& descriptor, const WorkloadInfo& info) const
613{
614 return std::make_unique<NeonBatchNormalizationWorkload>(descriptor, info);
615}
616
617std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateBatchToSpaceNd(const BatchToSpaceNdQueueDescriptor& descriptor,
618 const WorkloadInfo& info) const
619{
Mike Kelly56858022020-01-27 12:14:47 +0000620 return std::make_unique<NeonBatchToSpaceNdWorkload>(descriptor, info);
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100621}
622
Sadik Armagan48f011e2021-04-21 10:50:34 +0100623std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateCast(const CastQueueDescriptor& descriptor,
624 const WorkloadInfo& info) const
625{
626 return std::make_unique<NeonCastWorkload>(descriptor, info);
627}
628
Teresa Charline89dd692021-09-01 16:30:34 +0100629std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateChannelShuffle(const ChannelShuffleQueueDescriptor& descriptor,
630 const WorkloadInfo& info) const
631{
632 return std::make_unique<NeonChannelShuffleWorkload>(descriptor, info);
633}
634
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100635std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateComparison(const ComparisonQueueDescriptor& descriptor,
636 const WorkloadInfo& info) const
637{
Teresa Charlincedd34f2020-03-30 11:17:30 +0100638 return std::make_unique<NeonComparisonWorkload>(descriptor, info);
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100639}
640
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100641std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateConcat(const ConcatQueueDescriptor& descriptor,
telsoa014fcda012018-03-09 14:13:49 +0000642 const WorkloadInfo& info) const
643{
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100644 return std::make_unique<NeonConcatWorkload>(descriptor, info);
telsoa014fcda012018-03-09 14:13:49 +0000645}
646
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100647std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateConstant(const ConstantQueueDescriptor& descriptor,
648 const WorkloadInfo& info) const
telsoa014fcda012018-03-09 14:13:49 +0000649{
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100650 return std::make_unique<NeonConstantWorkload>(descriptor, info);
telsoa014fcda012018-03-09 14:13:49 +0000651}
652
Narumol Prangnawarat250d3922020-03-30 16:11:04 +0100653std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateConvertBf16ToFp32(
654 const ConvertBf16ToFp32QueueDescriptor& descriptor,
655 const WorkloadInfo& info) const
656{
657 return std::make_unique<NeonConvertBf16ToFp32Workload>(descriptor, info);
658}
659
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100660std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateConvertFp16ToFp32(
661 const ConvertFp16ToFp32QueueDescriptor& descriptor,
662 const WorkloadInfo& info) const
telsoa014fcda012018-03-09 14:13:49 +0000663{
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100664 return std::make_unique<NeonConvertFp16ToFp32Workload>(descriptor, info);
telsoa014fcda012018-03-09 14:13:49 +0000665}
666
Narumol Prangnawarat250d3922020-03-30 16:11:04 +0100667std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateConvertFp32ToBf16(
668 const ConvertFp32ToBf16QueueDescriptor& descriptor,
669 const WorkloadInfo& info) const
670{
671 return std::make_unique<NeonConvertFp32ToBf16Workload>(descriptor, info);
672}
673
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100674std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateConvertFp32ToFp16(
675 const ConvertFp32ToFp16QueueDescriptor& descriptor,
676 const WorkloadInfo& info) const
telsoa014fcda012018-03-09 14:13:49 +0000677{
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100678 return std::make_unique<NeonConvertFp32ToFp16Workload>(descriptor, info);
Nikhil Raj9b461482019-07-03 15:58:31 +0100679}
680
telsoa014fcda012018-03-09 14:13:49 +0000681std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateConvolution2d(
682 const Convolution2dQueueDescriptor& descriptor, const WorkloadInfo& info) const
683{
Sadik Armagan04a72972020-09-14 15:44:18 +0100684 bool isFastMathEnabled = false;
685 if (m_ModelContextPtr)
686 {
687 if (m_ModelContextPtr.get() != nullptr)
688 {
689 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
690 if (modelOptions)
691 {
692 isFastMathEnabled = modelOptions->IsFastMathEnabled();
693 }
694 }
695 }
696 return std::make_unique<NeonConvolution2dWorkload>(descriptor,
697 info,
698 m_MemoryManager->GetIntraLayerManager(),
699 isFastMathEnabled);
telsoa014fcda012018-03-09 14:13:49 +0000700}
701
Teresa Charlinec5f7d12021-10-22 17:15:00 +0100702std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateConvolution3d(
703 const Convolution3dQueueDescriptor& descriptor, const WorkloadInfo& info) const
704{
705 bool isFastMathEnabled = false;
706 if (m_ModelContextPtr)
707 {
708 if (m_ModelContextPtr.get() != nullptr)
709 {
710 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
711 if (modelOptions)
712 {
713 isFastMathEnabled = modelOptions->IsFastMathEnabled();
714 }
715 }
716 }
717 return std::make_unique<NeonConvolution3dWorkload>(descriptor,
718 info,
719 m_MemoryManager->GetIntraLayerManager(),
720 isFastMathEnabled);
721}
722
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100723std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateDebug(const DebugQueueDescriptor& descriptor,
724 const WorkloadInfo& info) const
725{
726 return MakeWorkloadHelper<NullWorkload, NullWorkload>(descriptor, info);
727}
728
Aron Virginas-Tar2f00b742019-09-30 13:28:08 +0100729std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateDepthToSpace(const DepthToSpaceQueueDescriptor& descriptor,
730 const WorkloadInfo& info) const
731{
732 return std::make_unique<NeonDepthToSpaceWorkload>(descriptor, info);
733}
734
telsoa014fcda012018-03-09 14:13:49 +0000735std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateDepthwiseConvolution2d(
736 const DepthwiseConvolution2dQueueDescriptor& descriptor, const WorkloadInfo& info) const
737{
Nattapat Chaimanowong77140882018-10-17 11:12:19 +0100738 return std::make_unique<NeonDepthwiseConvolutionWorkload>(descriptor, info);
telsoa014fcda012018-03-09 14:13:49 +0000739}
740
Narumol Prangnawarat01961a72019-05-30 16:47:12 +0100741std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateDequantize(const DequantizeQueueDescriptor& descriptor,
742 const WorkloadInfo& info) const
743{
744 return std::make_unique<NeonDequantizeWorkload>(descriptor, info);
745}
746
Narumol Prangnawarat94dd5d82019-01-23 18:06:26 +0000747std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateDetectionPostProcess(
748 const armnn::DetectionPostProcessQueueDescriptor& descriptor, const armnn::WorkloadInfo& info) const
749{
James Conroyd9fb6e22020-02-21 16:52:44 +0000750 return MakeWorkloadHelper<NullWorkload, NullWorkload>(descriptor, info);
Narumol Prangnawarat94dd5d82019-01-23 18:06:26 +0000751}
752
Francis Murtaghe7a86a42018-08-29 12:42:10 +0100753std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateDivision(
754 const DivisionQueueDescriptor& descriptor, const WorkloadInfo& info) const
755{
Pablo Telloe61f0712020-01-23 10:37:17 +0000756 return std::make_unique<NeonDivisionWorkload>(descriptor, info);
Francis Murtaghe7a86a42018-08-29 12:42:10 +0100757}
758
Sadik Armaganac472102020-03-24 09:54:36 +0000759std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateElementwiseUnary(
760 const ElementwiseUnaryQueueDescriptor& descriptor, const WorkloadInfo& info) const
josh minor4a3c6102020-01-06 16:40:46 -0600761{
Derek Lambertic77874a2020-04-28 13:34:56 +0100762 switch(descriptor.m_Parameters.m_Operation)
josh minor4a3c6102020-01-06 16:40:46 -0600763 {
Derek Lambertic77874a2020-04-28 13:34:56 +0100764 case UnaryOperation::Abs:
James Conroy177df1e2020-11-13 10:18:51 +0000765 {
766 AbsQueueDescriptor absQueueDescriptor;
767 absQueueDescriptor.m_Inputs = descriptor.m_Inputs;
768 absQueueDescriptor.m_Outputs = descriptor.m_Outputs;
josh minor4a3c6102020-01-06 16:40:46 -0600769
James Conroy177df1e2020-11-13 10:18:51 +0000770 return std::make_unique<NeonAbsWorkload>(absQueueDescriptor, info);
771 }
Teresa Charlin50de4fa2021-05-31 18:47:33 +0100772 case UnaryOperation::Exp:
773 return std::make_unique<NeonExpWorkload>(descriptor, info);
774 case UnaryOperation::LogicalNot:
775 return std::make_unique<NeonLogicalNotWorkload>(descriptor, info);
776 case UnaryOperation::Log:
777 return std::make_unique<NeonLogWorkload>(descriptor, info);
778 case UnaryOperation::Neg:
779 return std::make_unique<NeonNegWorkload>(descriptor, info);
Derek Lambertic77874a2020-04-28 13:34:56 +0100780 case UnaryOperation::Rsqrt:
James Conroy177df1e2020-11-13 10:18:51 +0000781 {
782 RsqrtQueueDescriptor rsqrtQueueDescriptor;
783 rsqrtQueueDescriptor.m_Inputs = descriptor.m_Inputs;
784 rsqrtQueueDescriptor.m_Outputs = descriptor.m_Outputs;
josh minor4a3c6102020-01-06 16:40:46 -0600785
James Conroy177df1e2020-11-13 10:18:51 +0000786 return std::make_unique<NeonRsqrtWorkload>(rsqrtQueueDescriptor, info);
787 }
Teresa Charlin50de4fa2021-05-31 18:47:33 +0100788 case UnaryOperation::Sin:
789 return std::make_unique<NeonSinWorkload>(descriptor, info);
Derek Lambertic77874a2020-04-28 13:34:56 +0100790 default:
791 return nullptr;
josh minor4a3c6102020-01-06 16:40:46 -0600792 }
josh minor4a3c6102020-01-06 16:40:46 -0600793}
794
Sadik Armagana792a052020-06-23 16:22:23 +0100795std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateFill(const FillQueueDescriptor& descriptor,
796 const WorkloadInfo& info) const
797{
798 return std::make_unique<NeonFillWorkload>(descriptor, info);
799}
800
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100801std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateFloor(const FloorQueueDescriptor& descriptor,
802 const WorkloadInfo& info) const
803{
804 return MakeWorkloadHelper<NeonFloorFloatWorkload, NullWorkload>(descriptor, info);
805}
806
807std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateFullyConnected(
808 const FullyConnectedQueueDescriptor& descriptor, const WorkloadInfo& info) const
809{
Kevin Maybe7e35c2020-04-29 17:05:05 +0100810 return std::make_unique<NeonFullyConnectedWorkload>(descriptor, info, m_MemoryManager->GetIntraLayerManager());
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100811}
812
813std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateGather(const armnn::GatherQueueDescriptor& descriptor,
814 const armnn::WorkloadInfo& info) const
815{
Teresa Charlinf540eb82020-04-10 19:24:55 +0100816 return std::make_unique<NeonGatherWorkload>(descriptor, info);
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100817}
818
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100819std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateInput(const InputQueueDescriptor& descriptor,
820 const WorkloadInfo& info) const
821{
822 return std::make_unique<CopyMemGenericWorkload>(descriptor, info);
823}
824
825std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateInstanceNormalization(
826 const InstanceNormalizationQueueDescriptor& descriptor,
827 const WorkloadInfo& info) const
828{
829 return std::make_unique<NeonInstanceNormalizationWorkload>(descriptor, info);
830}
831
832std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateL2Normalization(const L2NormalizationQueueDescriptor& descriptor,
833 const WorkloadInfo& info) const
834{
835 return MakeWorkloadHelper<NeonL2NormalizationFloatWorkload, NullWorkload>(descriptor, info,
836 m_MemoryManager->GetIntraLayerManager());
837}
838
Keith Davis69e653f2020-07-02 11:49:26 +0100839std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateLogSoftmax(const LogSoftmaxQueueDescriptor& descriptor,
840 const WorkloadInfo& info) const
841{
842 return std::make_unique<NeonLogSoftmaxWorkload>(descriptor, info, m_MemoryManager->GetIntraLayerManager());
843}
844
James Conroy177df1e2020-11-13 10:18:51 +0000845std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateLogicalBinary(const LogicalBinaryQueueDescriptor& descriptor,
846 const WorkloadInfo& info) const
847{
848 switch(descriptor.m_Parameters.m_Operation)
849 {
850 case LogicalBinaryOperation::LogicalAnd:
851 return std::make_unique<NeonLogicalAndWorkload>(descriptor, info);
852 case LogicalBinaryOperation::LogicalOr:
853 return std::make_unique<NeonLogicalOrWorkload>(descriptor, info);
854 default:
855 return nullptr;
856 }
857}
858
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100859std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateLstm(const LstmQueueDescriptor& descriptor,
860 const WorkloadInfo& info) const
861{
862 return MakeWorkloadHelper<NeonLstmFloatWorkload, NullWorkload>(descriptor, info);
863}
864
865std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateMaximum(const MaximumQueueDescriptor& descriptor,
866 const WorkloadInfo& info) const
867{
868 return std::make_unique<NeonMaximumWorkload>(descriptor, info);
869}
870
871std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateMean(const MeanQueueDescriptor& descriptor,
872 const WorkloadInfo& info) const
873{
874 return std::make_unique<NeonMeanWorkload>(descriptor, info);
telsoa014fcda012018-03-09 14:13:49 +0000875}
876
877std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateMemCopy(const MemCopyQueueDescriptor& descriptor,
878 const WorkloadInfo& info) const
879{
880 if (descriptor.m_Inputs.empty() || !descriptor.m_Inputs[0])
881 {
882 throw InvalidArgumentException("NeonWorkloadFactory: Invalid null input for MemCopy workload");
883 }
884
Aron Virginas-Tara8e06ed2018-10-19 16:46:15 +0100885 return MakeWorkloadHelper<CopyMemGenericWorkload, CopyMemGenericWorkload>(descriptor, info);
telsoa014fcda012018-03-09 14:13:49 +0000886}
887
Derek Lambertif674aa02019-08-01 15:56:25 +0100888std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateMemImport(const MemImportQueueDescriptor& descriptor,
889 const WorkloadInfo& info) const
890{
891 if (descriptor.m_Inputs.empty() || !descriptor.m_Inputs[0])
892 {
893 throw InvalidArgumentException("NeonWorkloadFactory: Invalid null input for MemImport workload");
894 }
895
896 return std::make_unique<ImportMemGenericWorkload>(descriptor, info);
897}
898
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100899std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateMinimum(const MinimumQueueDescriptor& descriptor,
900 const WorkloadInfo& info) const
901{
902 return std::make_unique<NeonMinimumWorkload>(descriptor, info);
903}
904
905std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateMultiplication(
906 const MultiplicationQueueDescriptor& descriptor, const WorkloadInfo& info) const
907{
908 return std::make_unique<NeonMultiplicationWorkload>(descriptor, info);
909}
910
911std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateNormalization(
912 const NormalizationQueueDescriptor& descriptor, const WorkloadInfo& info) const
913{
914 return MakeWorkloadHelper<NeonNormalizationFloatWorkload, NullWorkload>(descriptor, info,
915 m_MemoryManager->GetIntraLayerManager());
916}
917
918std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateOutput(const OutputQueueDescriptor& descriptor,
Keith Davis69e653f2020-07-02 11:49:26 +0100919 const WorkloadInfo& info) const
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100920{
921 return std::make_unique<CopyMemGenericWorkload>(descriptor, info);
922}
923
924std::unique_ptr<IWorkload> NeonWorkloadFactory::CreatePad(const PadQueueDescriptor& descriptor,
925 const WorkloadInfo& info) const
926{
927 return std::make_unique<NeonPadWorkload>(descriptor, info);
928}
929
930std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreatePermute(const PermuteQueueDescriptor& descriptor,
Keith Davis69e653f2020-07-02 11:49:26 +0100931 const WorkloadInfo& info) const
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100932{
933 return std::make_unique<NeonPermuteWorkload>(descriptor, info);
934}
935
936std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreatePooling2d(const Pooling2dQueueDescriptor& descriptor,
Keith Davis69e653f2020-07-02 11:49:26 +0100937 const WorkloadInfo& info) const
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100938{
939 return std::make_unique<NeonPooling2dWorkload>(descriptor, info);
940}
941
942std::unique_ptr<IWorkload> NeonWorkloadFactory::CreatePreCompiled(const PreCompiledQueueDescriptor& descriptor,
943 const WorkloadInfo& info) const
944{
945 return MakeWorkloadHelper<NullWorkload, NullWorkload>(descriptor, info);
946}
947
948std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreatePrelu(const armnn::PreluQueueDescriptor &descriptor,
949 const armnn::WorkloadInfo &info) const
950{
951 return std::make_unique<NeonPreluWorkload>(descriptor, info);
952}
953
James Conroycc340932020-05-12 18:08:52 +0100954std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateQLstm(const QLstmQueueDescriptor& descriptor,
955 const WorkloadInfo& info) const
956{
957 return std::make_unique<NeonQLstmWorkload>(descriptor, info);
958}
959
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100960std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateQuantize(const QuantizeQueueDescriptor& descriptor,
961 const WorkloadInfo& info) const
962{
Kevin May90774732020-03-03 12:10:10 +0000963 return std::make_unique<NeonQuantizeWorkload>(descriptor, info);
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100964}
965
966std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateQuantizedLstm(const QuantizedLstmQueueDescriptor& descriptor,
967 const WorkloadInfo& info) const
968{
969 return std::make_unique<NeonQuantizedLstmWorkload>(descriptor, info);
970}
971
David Monahan97451b42020-12-03 09:48:06 +0000972std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateRank(const RankQueueDescriptor& descriptor,
973 const WorkloadInfo& info) const
974{
975 return std::make_unique<NeonRankWorkload>(descriptor, info);
976}
977
Sadik Armagana2747482021-02-09 10:28:54 +0000978std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateReduce(const ReduceQueueDescriptor& descriptor,
979 const WorkloadInfo& info) const
980{
981 return std::make_unique<NeonReduceWorkload>(descriptor, info);
982}
983
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100984std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateReshape(const ReshapeQueueDescriptor& descriptor,
985 const WorkloadInfo& info) const
986{
987 return std::make_unique<NeonReshapeWorkload>(descriptor, info);
988}
989
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +0100990std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateResize(const ResizeQueueDescriptor& descriptor,
991 const WorkloadInfo& info) const
992{
Ellen Norris-Thompson37e68682019-07-15 14:23:30 +0100993 return std::make_unique<NeonResizeWorkload>(descriptor, info);
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +0100994}
995
josh minor036f02d2019-11-15 14:53:22 -0600996std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateSlice(const SliceQueueDescriptor& descriptor,
997 const WorkloadInfo& info) const
998{
999 return std::make_unique<NeonSliceWorkload>(descriptor, info);
1000}
1001
Sadik Armagan0d4863d2019-10-09 14:26:32 +01001002std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateSoftmax(const SoftmaxQueueDescriptor& descriptor,
1003 const WorkloadInfo& info) const
Sadik Armagan581742d2019-08-12 14:11:37 +01001004{
Sadik Armaganbe88a572020-04-30 11:39:37 +01001005 return std::make_unique<NeonSoftmaxWorkload>(descriptor, info, m_MemoryManager->GetIntraLayerManager());
Sadik Armagan581742d2019-08-12 14:11:37 +01001006}
1007
Mike Kelly0be3a882020-01-24 11:27:50 +00001008std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateSpaceToBatchNd(const SpaceToBatchNdQueueDescriptor& descriptor,
1009 const WorkloadInfo& info) const
1010{
1011 return std::make_unique<NeonSpaceToBatchNdWorkload>(descriptor, info);
1012}
1013
1014std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateSpaceToDepth(const SpaceToDepthQueueDescriptor& descriptor,
1015 const WorkloadInfo& info) const
narpra01b89b05f2019-01-16 09:53:09 +00001016{
Sadik Armagan0d4863d2019-10-09 14:26:32 +01001017 return std::make_unique<NeonSpaceToDepthWorkload>(descriptor, info);
1018}
1019
1020std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateSplitter(const SplitterQueueDescriptor& descriptor,
1021 const WorkloadInfo& info) const
1022{
1023 return std::make_unique<NeonSplitterWorkload>(descriptor, info);
narpra01b89b05f2019-01-16 09:53:09 +00001024}
1025
Matthew Jackson87f65ea2019-08-01 10:01:34 +01001026std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateStack(const StackQueueDescriptor& descriptor,
1027 const WorkloadInfo& info) const
1028{
1029 return std::make_unique<NeonStackWorkload>(descriptor, info);
1030}
1031
Sadik Armagan0d4863d2019-10-09 14:26:32 +01001032std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateStridedSlice(const StridedSliceQueueDescriptor& descriptor,
1033 const WorkloadInfo& info) const
James Conroyd47a0642019-09-17 14:22:06 +01001034{
Sadik Armagan0d4863d2019-10-09 14:26:32 +01001035 return std::make_unique<NeonStridedSliceWorkload>(descriptor, info);
1036}
1037
1038std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateSubtraction(
1039 const SubtractionQueueDescriptor& descriptor, const WorkloadInfo& info) const
1040{
1041 return std::make_unique<NeonSubtractionWorkload>(descriptor, info);
1042}
1043
Mike Kellyc9ea45a2020-02-28 18:11:58 +00001044std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateTranspose(const TransposeQueueDescriptor& descriptor,
1045 const WorkloadInfo& info) const
1046{
1047 return std::make_unique<NeonTransposeWorkload>(descriptor, info);
1048}
1049
Sadik Armagan0d4863d2019-10-09 14:26:32 +01001050std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateTransposeConvolution2d(
1051 const TransposeConvolution2dQueueDescriptor &descriptor,
1052 const WorkloadInfo &info) const
1053{
1054 return std::make_unique<NeonTransposeConvolution2dWorkload>(descriptor, info,
1055 m_MemoryManager->GetIntraLayerManager());
James Conroyd47a0642019-09-17 14:22:06 +01001056}
1057
Aron Virginas-Tar56055192018-11-12 18:10:43 +00001058} // namespace armnn