blob: 9b74f750f9099a06a13eaa172d311d89d9238743 [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
Cian McGriskin7894ef92023-08-01 14:04:09 +0100175 = PolymorphicDowncast<const BatchNormalizationQueueDescriptor*>(&descriptor);
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000176 return std::make_unique<NeonBatchNormalizationWorkload>(*batchNormalizationQueueDescriptor, info);
177 }
178 case LayerType::BatchToSpaceNd :
179 {
180 auto batchToSpaceNdQueueDescriptor
Cian McGriskin7894ef92023-08-01 14:04:09 +0100181 = PolymorphicDowncast<const BatchToSpaceNdQueueDescriptor*>(&descriptor);
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000182 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
Cian McGriskin7894ef92023-08-01 14:04:09 +0100212 = PolymorphicDowncast<const ConvertFp16ToFp32QueueDescriptor*>(&descriptor);
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000213 return std::make_unique<NeonConvertFp16ToFp32Workload>(*convertFp16ToFp32QueueDescriptor, info);
214 }
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000215 case LayerType::ConvertFp32ToFp16 :
216 {
217 auto convertFp32ToFp16QueueDescriptor
Cian McGriskin7894ef92023-08-01 14:04:09 +0100218 = PolymorphicDowncast<const ConvertFp32ToFp16QueueDescriptor*>(&descriptor);
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000219 return std::make_unique<NeonConvertFp32ToFp16Workload>(*convertFp32ToFp16QueueDescriptor, info);
220 }
221 case LayerType::Convolution2d :
222 {
223 auto convolution2dQueueDescriptor = PolymorphicDowncast<const Convolution2dQueueDescriptor*>(&descriptor);
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000224 bool isFastMathEnabled = false;
225 if (m_ModelContextPtr)
226 {
227 if (m_ModelContextPtr.get() != nullptr)
228 {
229 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
230 if (modelOptions)
231 {
232 isFastMathEnabled = modelOptions->IsFastMathEnabled();
233 }
234 }
235 }
236 return std::make_unique<NeonConvolution2dWorkload>(*convolution2dQueueDescriptor,
237 info,
238 m_MemoryManager->GetIntraLayerManager(),
239 isFastMathEnabled);
240 }
241 case LayerType::Convolution3d :
242 {
243 auto convolution3dQueueDescriptor = PolymorphicDowncast<const Convolution3dQueueDescriptor*>(&descriptor);
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000244 bool isFastMathEnabled = false;
245 if (m_ModelContextPtr)
246 {
247 if (m_ModelContextPtr.get() != nullptr)
248 {
249 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
250 if (modelOptions)
251 {
252 isFastMathEnabled = modelOptions->IsFastMathEnabled();
253 }
254 }
255 }
256 return std::make_unique<NeonConvolution3dWorkload>(*convolution3dQueueDescriptor,
257 info,
258 m_MemoryManager->GetIntraLayerManager(),
259 isFastMathEnabled);
260 }
261 case LayerType::Debug :
262 {
263 auto debugQueueDescriptor = PolymorphicDowncast<const DebugQueueDescriptor*>(&descriptor);
264 return MakeWorkloadHelper<NullWorkload, NullWorkload>(*debugQueueDescriptor, info);
265 }
266 case LayerType::DepthToSpace :
267 {
268 auto depthToSpaceQueueDescriptor = PolymorphicDowncast<const DepthToSpaceQueueDescriptor*>(&descriptor);
269 return std::make_unique<NeonDepthToSpaceWorkload>(*depthToSpaceQueueDescriptor, info);
270 }
271 case LayerType::DepthwiseConvolution2d :
272 {
273 auto depthwiseConvolution2dQueueDescriptor
Cian McGriskin7894ef92023-08-01 14:04:09 +0100274 = PolymorphicDowncast<const DepthwiseConvolution2dQueueDescriptor*>(&descriptor);
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000275 return std::make_unique<NeonDepthwiseConvolutionWorkload>(*depthwiseConvolution2dQueueDescriptor, info);
276 }
277 case LayerType::Dequantize :
278 {
279 auto dequantizeQueueDescriptor = PolymorphicDowncast<const DequantizeQueueDescriptor*>(&descriptor);
280 return std::make_unique<NeonDequantizeWorkload>(*dequantizeQueueDescriptor, info);
281 }
282 case LayerType::DetectionPostProcess :
283 {
284 auto detectionPostProcessQueueDescriptor
Cian McGriskin7894ef92023-08-01 14:04:09 +0100285 = PolymorphicDowncast<const DetectionPostProcessQueueDescriptor*>(&descriptor);
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000286 return MakeWorkloadHelper<NullWorkload, NullWorkload>(*detectionPostProcessQueueDescriptor, info);
287 }
288 case LayerType::Division :
289 {
290 auto divisionQueueDescriptor = PolymorphicDowncast<const DivisionQueueDescriptor*>(&descriptor);
291 return std::make_unique<NeonDivisionWorkload>(*divisionQueueDescriptor, info);
292 }
Mike Kelly3ec30772023-03-08 13:47:17 +0000293 case LayerType::ElementwiseBinary :
294 {
295 auto elementwiseBinaryQueueDescriptor
Cian McGriskin7894ef92023-08-01 14:04:09 +0100296 = PolymorphicDowncast<const ElementwiseBinaryQueueDescriptor*>(&descriptor);
Mike Kelly3ec30772023-03-08 13:47:17 +0000297 switch (elementwiseBinaryQueueDescriptor->m_Parameters.m_Operation)
298 {
299 case BinaryOperation::Add:
300 {
301 AdditionQueueDescriptor additionQueueDescriptor;
302 additionQueueDescriptor.m_Inputs = descriptor.m_Inputs;
303 additionQueueDescriptor.m_Outputs = descriptor.m_Outputs;
304 return std::make_unique<NeonAdditionWorkload>(additionQueueDescriptor, info);
305 }
306 case BinaryOperation::Div:
307 {
308 DivisionQueueDescriptor divisionQueueDescriptor;
309 divisionQueueDescriptor.m_Inputs = descriptor.m_Inputs;
310 divisionQueueDescriptor.m_Outputs = descriptor.m_Outputs;
311 return std::make_unique<NeonDivisionWorkload>(divisionQueueDescriptor, info);
312 }
313 case BinaryOperation::Maximum:
314 {
315 MaximumQueueDescriptor maximumQueueDescriptor;
316 maximumQueueDescriptor.m_Inputs = descriptor.m_Inputs;
317 maximumQueueDescriptor.m_Outputs = descriptor.m_Outputs;
318 return std::make_unique<NeonMaximumWorkload>(maximumQueueDescriptor, info);
319 }
320 case BinaryOperation::Minimum:
321 {
322 MinimumQueueDescriptor minimumQueueDescriptor;
323 minimumQueueDescriptor.m_Inputs = descriptor.m_Inputs;
324 minimumQueueDescriptor.m_Outputs = descriptor.m_Outputs;
325 return std::make_unique<NeonMinimumWorkload>(minimumQueueDescriptor, info);
326 }
327 case BinaryOperation::Mul:
328 {
329 MultiplicationQueueDescriptor multiplicationQueueDescriptor;
330 multiplicationQueueDescriptor.m_Inputs = descriptor.m_Inputs;
331 multiplicationQueueDescriptor.m_Outputs = descriptor.m_Outputs;
332 return std::make_unique<NeonMultiplicationWorkload>(multiplicationQueueDescriptor, info);
333 }
John Mcloughlin34c1c382023-05-17 15:08:36 +0100334 case BinaryOperation::Power:
335 case BinaryOperation::SqDiff:
336 {
337 return std::make_unique<NeonElementwiseBinaryWorkload>(*elementwiseBinaryQueueDescriptor, info);
338 }
Mike Kelly3ec30772023-03-08 13:47:17 +0000339 case BinaryOperation::Sub:
340 {
341 SubtractionQueueDescriptor subtractionQueueDescriptor;
342 subtractionQueueDescriptor.m_Inputs = descriptor.m_Inputs;
343 subtractionQueueDescriptor.m_Outputs = descriptor.m_Outputs;
344 return std::make_unique<NeonSubtractionWorkload>(subtractionQueueDescriptor, info);
345 }
346 default:
347 return nullptr;
348 }
349 }
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000350 case LayerType::ElementwiseUnary :
351 {
352 auto elementwiseUnaryQueueDescriptor
Cian McGriskin7894ef92023-08-01 14:04:09 +0100353 = PolymorphicDowncast<const ElementwiseUnaryQueueDescriptor*>(&descriptor);
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000354 switch(elementwiseUnaryQueueDescriptor->m_Parameters.m_Operation)
355 {
356 case UnaryOperation::Abs:
357 {
358 AbsQueueDescriptor absQueueDescriptor;
359 absQueueDescriptor.m_Inputs = elementwiseUnaryQueueDescriptor->m_Inputs;
360 absQueueDescriptor.m_Outputs = elementwiseUnaryQueueDescriptor->m_Outputs;
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000361 return std::make_unique<NeonAbsWorkload>(absQueueDescriptor, info);
362 }
363 case UnaryOperation::Exp:
364 return std::make_unique<NeonExpWorkload>(*elementwiseUnaryQueueDescriptor, info);
365 case UnaryOperation::LogicalNot:
366 return std::make_unique<NeonLogicalNotWorkload>(*elementwiseUnaryQueueDescriptor, info);
367 case UnaryOperation::Log:
368 return std::make_unique<NeonLogWorkload>(*elementwiseUnaryQueueDescriptor, info);
369 case UnaryOperation::Neg:
370 return std::make_unique<NeonNegWorkload>(*elementwiseUnaryQueueDescriptor, info);
371 case UnaryOperation::Rsqrt:
372 {
373 RsqrtQueueDescriptor rsqrtQueueDescriptor;
374 rsqrtQueueDescriptor.m_Inputs = elementwiseUnaryQueueDescriptor->m_Inputs;
375 rsqrtQueueDescriptor.m_Outputs = elementwiseUnaryQueueDescriptor->m_Outputs;
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000376 return std::make_unique<NeonRsqrtWorkload>(rsqrtQueueDescriptor, info);
377 }
378 case UnaryOperation::Sin:
379 return std::make_unique<NeonSinWorkload>(*elementwiseUnaryQueueDescriptor, info);
Teresa Charlin03027232022-05-09 17:27:08 +0100380 case UnaryOperation::Sqrt:
381 return std::make_unique<NeonSqrtWorkload>(*elementwiseUnaryQueueDescriptor, info);
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000382 default:
383 return nullptr;
384 }
385 }
386 case LayerType::Fill :
387 {
388 auto fillQueueDescriptor = PolymorphicDowncast<const FillQueueDescriptor*>(&descriptor);
389 return std::make_unique<NeonFillWorkload>(*fillQueueDescriptor, info);
390 }
391 case LayerType::Floor :
392 {
393 auto floorQueueDescriptor = PolymorphicDowncast<const FloorQueueDescriptor*>(&descriptor);
394 return MakeWorkloadHelper<NeonFloorFloatWorkload, NullWorkload>(*floorQueueDescriptor, info);
395 }
396 case LayerType::FullyConnected :
397 {
398 auto fullyConnectedQueueDescriptor = PolymorphicDowncast<const FullyConnectedQueueDescriptor*>(&descriptor);
399 return std::make_unique<NeonFullyConnectedWorkload>(*fullyConnectedQueueDescriptor,
400 info,
401 m_MemoryManager->GetIntraLayerManager());
402 }
Teresa Charlin9145e382023-08-17 18:44:58 +0100403 case LayerType::Fused :
404 {
405 auto fusedQueueDescriptor = PolymorphicDowncast<const FusedQueueDescriptor*>(&descriptor);
406 return std::make_unique<NeonFusedWorkload>(*fusedQueueDescriptor, info);
407 }
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000408 case LayerType::Gather :
409 {
410 auto gatherQueueDescriptor = PolymorphicDowncast<const GatherQueueDescriptor*>(&descriptor);
411 return std::make_unique<NeonGatherWorkload>(*gatherQueueDescriptor, info);
412 }
Teresa Charlinbd22c7d2022-04-26 18:14:12 +0100413 case LayerType::GatherNd :
414 {
415 auto gatherNdQueueDescriptor = PolymorphicDowncast<const GatherNdQueueDescriptor*>(&descriptor);
416 return std::make_unique<NeonGatherNdWorkload>(*gatherNdQueueDescriptor, info);
417 }
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000418 case LayerType::Input :
419 {
420 auto inputQueueDescriptor = PolymorphicDowncast<const InputQueueDescriptor*>(&descriptor);
421 return std::make_unique<CopyMemGenericWorkload>(*inputQueueDescriptor, info);
422 }
423 case LayerType::InstanceNormalization :
424 {
425 auto instanceNormalizationQueueDescriptor
Cian McGriskin7894ef92023-08-01 14:04:09 +0100426 = PolymorphicDowncast<const InstanceNormalizationQueueDescriptor*>(&descriptor);
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000427 return std::make_unique<NeonInstanceNormalizationWorkload>(*instanceNormalizationQueueDescriptor, info);
428 }
429 case LayerType::L2Normalization :
430 {
431 auto l2NormalizationQueueDescriptor
Cian McGriskin7894ef92023-08-01 14:04:09 +0100432 = PolymorphicDowncast<const L2NormalizationQueueDescriptor*>(&descriptor);
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000433 return MakeWorkloadHelper<NeonL2NormalizationFloatWorkload, NullWorkload>
Cian McGriskin7894ef92023-08-01 14:04:09 +0100434 (*l2NormalizationQueueDescriptor, info, m_MemoryManager->GetIntraLayerManager());
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000435 }
436 case LayerType::LogSoftmax :
437 {
438 auto logSoftmaxQueueDescriptor = PolymorphicDowncast<const LogSoftmaxQueueDescriptor*>(&descriptor);
439 return std::make_unique<NeonLogSoftmaxWorkload>(*logSoftmaxQueueDescriptor,
440 info,
441 m_MemoryManager->GetIntraLayerManager());
442 }
443 case LayerType::LogicalBinary :
444 {
445 auto logicalBinaryQueueDescriptor = PolymorphicDowncast<const LogicalBinaryQueueDescriptor*>(&descriptor);
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000446 switch(logicalBinaryQueueDescriptor->m_Parameters.m_Operation)
447 {
448 case LogicalBinaryOperation::LogicalAnd:
449 return std::make_unique<NeonLogicalAndWorkload>(*logicalBinaryQueueDescriptor, info);
450 case LogicalBinaryOperation::LogicalOr:
451 return std::make_unique<NeonLogicalOrWorkload>(*logicalBinaryQueueDescriptor, info);
452 default:
453 return nullptr;
454 }
455 }
456 case LayerType::Lstm :
457 {
458 auto lstmQueueDescriptor = PolymorphicDowncast<const LstmQueueDescriptor*>(&descriptor);
459 return MakeWorkloadHelper<NeonLstmFloatWorkload, NullWorkload>(*lstmQueueDescriptor, info);
460 }
461 case LayerType::Maximum :
462 {
463 auto maximumQueueDescriptor = PolymorphicDowncast<const MaximumQueueDescriptor*>(&descriptor);
464 return std::make_unique<NeonMaximumWorkload>(*maximumQueueDescriptor, info);
465 }
466 case LayerType::Mean :
467 {
468 auto meanQueueDescriptor = PolymorphicDowncast<const MeanQueueDescriptor*>(&descriptor);
469 return std::make_unique<NeonMeanWorkload>(*meanQueueDescriptor, info);
470 }
471 case LayerType::MemCopy :
472 {
473 auto memCopyQueueDescriptor = PolymorphicDowncast<const MemCopyQueueDescriptor*>(&descriptor);
474 if (memCopyQueueDescriptor->m_Inputs.empty() || !memCopyQueueDescriptor->m_Inputs[0])
475 {
476 throw InvalidArgumentException("NeonWorkloadFactory: Invalid null input for MemCopy workload");
477 }
478 return MakeWorkloadHelper<CopyMemGenericWorkload, CopyMemGenericWorkload>(*memCopyQueueDescriptor, info);
479 }
480 case LayerType::MemImport :
481 {
482 auto memImportQueueDescriptor = PolymorphicDowncast<const MemImportQueueDescriptor*>(&descriptor);
483 if (memImportQueueDescriptor->m_Inputs.empty() || !memImportQueueDescriptor->m_Inputs[0])
484 {
485 throw InvalidArgumentException("NeonWorkloadFactory: Invalid null input for MemImport workload");
486 }
487 return std::make_unique<ImportMemGenericWorkload>(*memImportQueueDescriptor, info);
488 }
489 case LayerType::Minimum :
490 {
491 auto minimumQueueDescriptor = PolymorphicDowncast<const MinimumQueueDescriptor*>(&descriptor);
492 return std::make_unique<NeonMinimumWorkload>(*minimumQueueDescriptor, info);
493 }
494 case LayerType::Multiplication :
495 {
496 auto multiplicationQueueDescriptor = PolymorphicDowncast<const MultiplicationQueueDescriptor*>(&descriptor);
497 return std::make_unique<NeonMultiplicationWorkload>(*multiplicationQueueDescriptor, info);
498 }
499 case LayerType::Normalization :
500 {
501 auto normalizationQueueDescriptor = PolymorphicDowncast<const NormalizationQueueDescriptor*>(&descriptor);
502 return MakeWorkloadHelper<NeonNormalizationFloatWorkload, NullWorkload>
Cian McGriskin7894ef92023-08-01 14:04:09 +0100503 (*normalizationQueueDescriptor, info, m_MemoryManager->GetIntraLayerManager());
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000504 }
505 case LayerType::Output :
506 {
507 auto outputQueueDescriptor = PolymorphicDowncast<const OutputQueueDescriptor*>(&descriptor);
508 return std::make_unique<CopyMemGenericWorkload>(*outputQueueDescriptor, info);
509 }
510 case LayerType::Pad :
511 {
512 auto padQueueDescriptor = PolymorphicDowncast<const PadQueueDescriptor*>(&descriptor);
513 return std::make_unique<NeonPadWorkload>(*padQueueDescriptor, info);
514 }
515 case LayerType::Permute :
516 {
517 auto permuteQueueDescriptor = PolymorphicDowncast<const PermuteQueueDescriptor*>(&descriptor);
518 return std::make_unique<NeonPermuteWorkload>(*permuteQueueDescriptor, info);
519 }
520 case LayerType::Pooling2d :
521 {
522 auto pooling2dQueueDescriptor = PolymorphicDowncast<const Pooling2dQueueDescriptor*>(&descriptor);
523 return std::make_unique<NeonPooling2dWorkload>(*pooling2dQueueDescriptor, info);
524 }
Ryan OShea19e79422022-05-04 00:38:03 +0100525 case LayerType::Pooling3d :
526 {
527 auto pooling3dQueueDescriptor = PolymorphicDowncast<const Pooling3dQueueDescriptor*>(&descriptor);
528 return std::make_unique<NeonPooling3dWorkload>(*pooling3dQueueDescriptor, info);
529 }
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000530 case LayerType::PreCompiled :
531 {
532 auto preCompiledQueueDescriptor = PolymorphicDowncast<const PreCompiledQueueDescriptor*>(&descriptor);
533 return MakeWorkloadHelper<NullWorkload, NullWorkload>(*preCompiledQueueDescriptor, info);
534 }
535 case LayerType::Prelu :
536 {
537 auto preluQueueDescriptor = PolymorphicDowncast<const PreluQueueDescriptor*>(&descriptor);
538 return std::make_unique<NeonPreluWorkload>(*preluQueueDescriptor, info);
539 }
540 case LayerType::QLstm :
541 {
542 auto qLstmQueueDescriptor = PolymorphicDowncast<const QLstmQueueDescriptor*>(&descriptor);
543 return std::make_unique<NeonQLstmWorkload>(*qLstmQueueDescriptor, info);
544 }
545 case LayerType::Quantize :
546 {
547 auto quantizeQueueDescriptor = PolymorphicDowncast<const QuantizeQueueDescriptor*>(&descriptor);
548 return std::make_unique<NeonQuantizeWorkload>(*quantizeQueueDescriptor, info);
549 }
550 case LayerType::QuantizedLstm :
551 {
552 auto quantizedLstmQueueDescriptor = PolymorphicDowncast<const QuantizedLstmQueueDescriptor*>(&descriptor);
553 return std::make_unique<NeonQuantizedLstmWorkload>(*quantizedLstmQueueDescriptor, info);
554 }
555 case LayerType::Rank :
556 {
557 auto rankQueueDescriptor = PolymorphicDowncast<const RankQueueDescriptor*>(&descriptor);
558 return std::make_unique<NeonRankWorkload>(*rankQueueDescriptor, info);
559 }
560 case LayerType::Reduce :
561 {
562 auto reduceQueueDescriptor = PolymorphicDowncast<const ReduceQueueDescriptor*>(&descriptor);
563 return std::make_unique<NeonReduceWorkload>(*reduceQueueDescriptor, info);
564 }
565 case LayerType::Reshape :
566 {
567 auto reshapeQueueDescriptor = PolymorphicDowncast<const ReshapeQueueDescriptor*>(&descriptor);
568 return std::make_unique<NeonReshapeWorkload>(*reshapeQueueDescriptor, info);
569 }
570 case LayerType::Resize :
571 {
572 auto resizeQueueDescriptor = PolymorphicDowncast<const ResizeQueueDescriptor*>(&descriptor);
573 return std::make_unique<NeonResizeWorkload>(*resizeQueueDescriptor, info);
574 }
Tianle Cheng21a9f332023-11-09 13:56:53 +0000575 case LayerType::ReverseV2 :
576 {
577 auto reverseV2QueueDescriptor = PolymorphicDowncast<const ReverseV2QueueDescriptor*>(&descriptor);
578 return std::make_unique<NeonReverseV2Workload>(*reverseV2QueueDescriptor, info);
579 }
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000580 case LayerType::Slice :
581 {
582 auto sliceQueueDescriptor = PolymorphicDowncast<const SliceQueueDescriptor*>(&descriptor);
583 return std::make_unique<NeonSliceWorkload>(*sliceQueueDescriptor, info);
584 }
585 case LayerType::Softmax :
586 {
587 auto softmaxQueueDescriptor = PolymorphicDowncast<const SoftmaxQueueDescriptor*>(&descriptor);
588 return std::make_unique<NeonSoftmaxWorkload>(*softmaxQueueDescriptor,
589 info,
590 m_MemoryManager->GetIntraLayerManager());
591 }
592 case LayerType::SpaceToBatchNd :
593 {
594 auto spaceToBatchNdQueueDescriptor
Cian McGriskin7894ef92023-08-01 14:04:09 +0100595 = PolymorphicDowncast<const SpaceToBatchNdQueueDescriptor*>(&descriptor);
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000596 return std::make_unique<NeonSpaceToBatchNdWorkload>(*spaceToBatchNdQueueDescriptor, info);
597 }
598 case LayerType::SpaceToDepth :
599 {
600 auto spaceToDepthQueueDescriptor = PolymorphicDowncast<const SpaceToDepthQueueDescriptor*>(&descriptor);
601 return std::make_unique<NeonSpaceToDepthWorkload>(*spaceToDepthQueueDescriptor, info);
602 }
603 case LayerType::Splitter :
604 {
605 auto splitterQueueDescriptor = PolymorphicDowncast<const SplitterQueueDescriptor*>(&descriptor);
606 return std::make_unique<NeonSplitterWorkload>(*splitterQueueDescriptor, info);
607 }
608 case LayerType::Stack :
609 {
610 auto stackQueueDescriptor = PolymorphicDowncast<const StackQueueDescriptor*>(&descriptor);
611 return std::make_unique<NeonStackWorkload>(*stackQueueDescriptor, info);
612 }
613 case LayerType::StridedSlice :
614 {
615 auto stridedSliceQueueDescriptor = PolymorphicDowncast<const StridedSliceQueueDescriptor*>(&descriptor);
616 return std::make_unique<NeonStridedSliceWorkload>(*stridedSliceQueueDescriptor, info);
617 }
618 case LayerType::Subtraction :
619 {
620 auto subtractionQueueDescriptor = PolymorphicDowncast<const SubtractionQueueDescriptor*>(&descriptor);
621 return std::make_unique<NeonSubtractionWorkload>(*subtractionQueueDescriptor, info);
622 }
David Monahan36e6eae2023-07-26 18:37:45 +0100623 case LayerType::Tile:
624 {
625 auto tileQueueDescriptor = PolymorphicDowncast<const TileQueueDescriptor*>(&descriptor);
626 return std::make_unique<NeonTileWorkload>(*tileQueueDescriptor, info);
627 }
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000628 case LayerType::Transpose :
629 {
630 auto transposeQueueDescriptor = PolymorphicDowncast<const TransposeQueueDescriptor*>(&descriptor);
631 return std::make_unique<NeonTransposeWorkload>(*transposeQueueDescriptor, info);
632 }
633 case LayerType::TransposeConvolution2d :
634 {
635 auto transposeConvolution2dQueueDescriptor
Cian McGriskin7894ef92023-08-01 14:04:09 +0100636 = PolymorphicDowncast<const TransposeConvolution2dQueueDescriptor*>(&descriptor);
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000637 return std::make_unique<NeonTransposeConvolution2dWorkload>(*transposeConvolution2dQueueDescriptor,
638 info,
639 m_MemoryManager->GetIntraLayerManager());
640 }
Cathal Corbettfd5bec42022-03-03 15:13:23 +0000641 case LayerType::UnidirectionalSequenceLstm :
642 {
643 auto desc = PolymorphicDowncast<const UnidirectionalSequenceLstmQueueDescriptor*>(&descriptor);
Mike Kelly12994962022-04-21 11:57:09 +0100644 if ((info.m_InputTensorInfos[0].GetDataType() == armnn::DataType::Float32) &&
645 (info.m_InputTensorInfos[1].GetDataType() == armnn::DataType::Float32) &&
646 (info.m_InputTensorInfos[2].GetDataType() == armnn::DataType::Float32) &&
647 (info.m_OutputTensorInfos[0].GetDataType() == armnn::DataType::Float32) &&
648 (info.m_OutputTensorInfos[1].GetDataType() == armnn::DataType::Float32) &&
649 (info.m_OutputTensorInfos[2].GetDataType() == armnn::DataType::Float32))
650 {
651 return std::make_unique<NeonUnidirectionalSequenceLstmFloatWorkload>(*desc, info);
652 }
653 else
654 {
655 return std::make_unique<NeonUnidirectionalSequenceLstmWorkload>(*desc, info);
656 }
Cathal Corbettfd5bec42022-03-03 15:13:23 +0000657 }
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000658 default:
659 return nullptr;
660 }
661}
662
Aron Virginas-Tar56055192018-11-12 18:10:43 +0000663} // namespace armnn