• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #include "ClWorkloadFactory.hpp"
6 #include "ClBackendId.hpp"
7 #include "ClBackendModelContext.hpp"
8 
9 #include <Layer.hpp>
10 
11 #include <armnn/Exceptions.hpp>
12 #include <armnn/Utils.hpp>
13 #include <armnn/utility/IgnoreUnused.hpp>
14 #include <armnn/utility/NumericCast.hpp>
15 #include <armnn/utility/PolymorphicDowncast.hpp>
16 
17 #include <backendsCommon/CpuTensorHandle.hpp>
18 #include <backendsCommon/MakeWorkloadHelper.hpp>
19 #include <backendsCommon/MemCopyWorkload.hpp>
20 #include <backendsCommon/MemImportWorkload.hpp>
21 
22 #include <cl/ClTensorHandle.hpp>
23 #include <cl/workloads/ClWorkloads.hpp>
24 #include <cl/workloads/ClWorkloadUtils.hpp>
25 
26 #include <arm_compute/core/CL/CLKernelLibrary.h>
27 #include <arm_compute/runtime/CL/CLBufferAllocator.h>
28 #include <arm_compute/runtime/CL/CLScheduler.h>
29 
30 #include <Filesystem.hpp>
31 
32 namespace armnn
33 {
34 
35 namespace
36 {
37 static const BackendId s_Id{ClBackendId()};
38 }
39 
IsLayerSupported(const Layer & layer,Optional<DataType> dataType,std::string & outReasonIfUnsupported)40 bool ClWorkloadFactory::IsLayerSupported(const Layer& layer,
41                                          Optional<DataType> dataType,
42                                          std::string& outReasonIfUnsupported)
43 {
44     return IWorkloadFactory::IsLayerSupported(s_Id, layer, dataType, outReasonIfUnsupported);
45 }
46 
IsLayerSupported(const IConnectableLayer & layer,Optional<DataType> dataType,std::string & outReasonIfUnsupported,const ModelOptions & modelOptions)47 bool ClWorkloadFactory::IsLayerSupported(const IConnectableLayer& layer,
48                                          Optional<DataType> dataType,
49                                          std::string& outReasonIfUnsupported,
50                                          const ModelOptions& modelOptions)
51 {
52     return IWorkloadFactory::IsLayerSupported(s_Id, layer, dataType, outReasonIfUnsupported, modelOptions);
53 }
54 
GetBackendId() const55 const BackendId& ClWorkloadFactory::GetBackendId() const
56 {
57     return s_Id;
58 }
59 
AfterWorkloadsCreated()60 void ClWorkloadFactory::AfterWorkloadsCreated()
61 {
62     if(m_ModelContextPtr)
63     {
64         auto modelOptions = dynamic_cast<ClBackendModelContext*>(m_ModelContextPtr.get());
65         if (modelOptions->SaveCachedNetwork())
66         {
67             // Save map to a filepath provided in ModelOptions
68             auto filePath = modelOptions->GetCachedNetworkFilePath();
69             if (filePath != "" && fs::exists(filePath) && fs::is_regular_file(filePath))
70             {
71                 ///  Saving will be implemented within IVGCVSW-5483 story.
72             }
73         }
74     }
75 }
76 
77 template <typename FloatWorkload, typename Uint8Workload, typename QueueDescriptorType, typename... Args>
MakeWorkload(const QueueDescriptorType & descriptor,const WorkloadInfo & info,Args &&...args)78 std::unique_ptr<IWorkload> ClWorkloadFactory::MakeWorkload(const QueueDescriptorType& descriptor,
79                                                            const WorkloadInfo& info,
80                                                            Args&&... args)
81 {
82     try
83     {
84         return MakeWorkloadHelper<FloatWorkload, Uint8Workload>(descriptor, info, std::forward<Args>(args)...);
85     }
86     catch (const cl::Error& clError)
87     {
88         throw WrapClError(clError, CHECK_LOCATION());
89     }
90 }
91 
92 template <typename Workload, typename QueueDescriptorType, typename... Args>
MakeWorkload(const QueueDescriptorType & descriptor,const WorkloadInfo & info,Args &&...args)93 std::unique_ptr<IWorkload> ClWorkloadFactory::MakeWorkload(const QueueDescriptorType& descriptor,
94                                                            const WorkloadInfo& info,
95                                                            Args&&... args)
96 {
97     try
98     {
99         return std::make_unique<Workload>(descriptor, info, std::forward<Args>(args)...);
100     }
101     catch (const cl::Error& clError)
102     {
103         throw WrapClError(clError, CHECK_LOCATION());
104     }
105 }
106 
InitializeCLCompileContext()107 void ClWorkloadFactory::InitializeCLCompileContext()
108 {
109     // Initialize our m_CLCompileContext using default device and context
110     cl::Device device = cl::Device::getDefault();
111     cl::Context context = cl::Context(device);
112 
113     m_CLCompileContext = arm_compute::CLCompileContext(context, device);
114 
115     if (m_ModelContextPtr)
116     {
117         // Load saved programs if the user has set a filepath
118         auto modelOptions = dynamic_cast<ClBackendModelContext*>(m_ModelContextPtr.get());
119         auto filePath = modelOptions->GetCachedNetworkFilePath();
120         if (filePath != ""
121             && fs::exists(filePath)
122             && fs::is_regular_file(filePath)
123             && !(modelOptions->SaveCachedNetwork()))
124         {
125             ///  Loading will be implemented within IVGCVSW-5483 story.
126         }
127     }
128 }
129 
ClWorkloadFactory(const std::shared_ptr<ClMemoryManager> & memoryManager)130 ClWorkloadFactory::ClWorkloadFactory(const std::shared_ptr<ClMemoryManager>& memoryManager)
131     : m_MemoryManager(memoryManager), m_ModelContextPtr(IBackendInternal::IBackendSpecificModelContextPtr{})
132 {
133     InitializeCLCompileContext();
134 }
135 
ClWorkloadFactory(const std::shared_ptr<ClMemoryManager> & memoryManager,const IBackendInternal::IBackendSpecificModelContextPtr & modelContextPtr)136 ClWorkloadFactory::ClWorkloadFactory(const std::shared_ptr<ClMemoryManager>& memoryManager,
137                                      const IBackendInternal::IBackendSpecificModelContextPtr& modelContextPtr)
138     : m_MemoryManager(memoryManager), m_ModelContextPtr(modelContextPtr)
139 {
140     InitializeCLCompileContext();
141 }
142 
CreateTensorHandle(const TensorInfo & tensorInfo,const bool IsMemoryManaged) const143 std::unique_ptr<ITensorHandle> ClWorkloadFactory::CreateTensorHandle(const TensorInfo& tensorInfo,
144                                                                      const bool IsMemoryManaged) const
145 {
146     IgnoreUnused(IsMemoryManaged);
147     std::unique_ptr<ClTensorHandle> tensorHandle = std::make_unique<ClTensorHandle>(tensorInfo);
148     tensorHandle->SetMemoryGroup(m_MemoryManager->GetInterLayerMemoryGroup());
149 
150     return tensorHandle;
151 }
152 
CreateTensorHandle(const TensorInfo & tensorInfo,DataLayout dataLayout,const bool IsMemoryManaged) const153 std::unique_ptr<ITensorHandle> ClWorkloadFactory::CreateTensorHandle(const TensorInfo& tensorInfo,
154                                                                      DataLayout dataLayout,
155                                                                      const bool IsMemoryManaged) const
156 {
157     IgnoreUnused(IsMemoryManaged);
158     std::unique_ptr<ClTensorHandle> tensorHandle = std::make_unique<ClTensorHandle>(tensorInfo, dataLayout);
159     tensorHandle->SetMemoryGroup(m_MemoryManager->GetInterLayerMemoryGroup());
160 
161     return tensorHandle;
162 }
163 
CreateSubTensorHandle(ITensorHandle & parent,TensorShape const & subTensorShape,unsigned int const * subTensorOrigin) const164 std::unique_ptr<ITensorHandle> ClWorkloadFactory::CreateSubTensorHandle(ITensorHandle& parent,
165                                                                         TensorShape const& subTensorShape,
166                                                                         unsigned int const* subTensorOrigin) const
167 {
168     arm_compute::Coordinates coords;
169     arm_compute::TensorShape shape = armcomputetensorutils::BuildArmComputeTensorShape(subTensorShape);
170 
171     coords.set_num_dimensions(subTensorShape.GetNumDimensions());
172     for (unsigned int i = 0; i < subTensorShape.GetNumDimensions(); i++)
173     {
174         // Arm compute indexes tensor coords in reverse order.
175         unsigned int revertedIndex = subTensorShape.GetNumDimensions() - i - 1;
176         coords.set(i, armnn::numeric_cast<int>(subTensorOrigin[revertedIndex]));
177     }
178 
179     const arm_compute::TensorShape parentShape = armcomputetensorutils::BuildArmComputeTensorShape(parent.GetShape());
180     if (!::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, parentShape, coords, shape))
181     {
182         return nullptr;
183     }
184 
185     return std::make_unique<ClSubTensorHandle>(
186         PolymorphicDowncast<IClTensorHandle*>(&parent), shape, coords);
187 }
188 
CreateAbs(const AbsQueueDescriptor & descriptor,const WorkloadInfo & info) const189 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateAbs(const AbsQueueDescriptor& descriptor,
190                                                         const WorkloadInfo& info) const
191 {
192     IgnoreUnused(descriptor);
193 
194     ElementwiseUnaryQueueDescriptor elementwiseUnaryDescriptor;
195     elementwiseUnaryDescriptor.m_Parameters = ElementwiseUnaryDescriptor(UnaryOperation::Abs);
196 
197     return CreateElementwiseUnary(elementwiseUnaryDescriptor, info);
198 }
199 
CreateActivation(const ActivationQueueDescriptor & descriptor,const WorkloadInfo & info) const200 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateActivation(const ActivationQueueDescriptor& descriptor,
201                                                                const WorkloadInfo& info) const
202 {
203     return MakeWorkload<ClActivationWorkload>(descriptor, info);
204 }
205 
CreateAddition(const AdditionQueueDescriptor & descriptor,const WorkloadInfo & info) const206 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateAddition(const AdditionQueueDescriptor& descriptor,
207                                                              const WorkloadInfo& info) const
208 {
209     return MakeWorkload<ClAdditionWorkload>(descriptor, info);
210 }
211 
CreateArgMinMax(const ArgMinMaxQueueDescriptor & descriptor,const WorkloadInfo & info) const212 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateArgMinMax(const ArgMinMaxQueueDescriptor& descriptor,
213                                                               const WorkloadInfo& info) const
214 {
215     return std::make_unique<ClArgMinMaxWorkload>(descriptor, info);
216 }
217 
CreateBatchNormalization(const BatchNormalizationQueueDescriptor & descriptor,const WorkloadInfo & info) const218 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateBatchNormalization(
219     const BatchNormalizationQueueDescriptor& descriptor,
220     const WorkloadInfo& info) const
221 {
222     return MakeWorkload<ClBatchNormalizationFloatWorkload, NullWorkload>(descriptor, info);
223 }
224 
CreateBatchToSpaceNd(const BatchToSpaceNdQueueDescriptor & descriptor,const WorkloadInfo & info) const225 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateBatchToSpaceNd(const BatchToSpaceNdQueueDescriptor& descriptor,
226                                                                    const WorkloadInfo& info) const
227 {
228     return MakeWorkload<ClBatchToSpaceNdWorkload>(descriptor, info);
229 }
230 
CreateComparison(const ComparisonQueueDescriptor & descriptor,const WorkloadInfo & info) const231 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateComparison(const ComparisonQueueDescriptor& descriptor,
232                                                                const WorkloadInfo& info) const
233 {
234     return MakeWorkload<ClComparisonWorkload>(descriptor, info);
235 }
236 
CreateConcat(const ConcatQueueDescriptor & descriptor,const WorkloadInfo & info) const237 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateConcat(const ConcatQueueDescriptor& descriptor,
238                                                            const WorkloadInfo& info) const
239 {
240     return MakeWorkload<ClConcatWorkload>(descriptor, info);
241 }
242 
CreateConstant(const ConstantQueueDescriptor & descriptor,const WorkloadInfo & info) const243 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateConstant(const ConstantQueueDescriptor& descriptor,
244                                                              const WorkloadInfo& info) const
245 {
246     return MakeWorkload<ClConstantWorkload>(descriptor, info);
247 }
248 
CreateConvertFp16ToFp32(const ConvertFp16ToFp32QueueDescriptor & descriptor,const WorkloadInfo & info) const249 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateConvertFp16ToFp32(
250     const ConvertFp16ToFp32QueueDescriptor& descriptor,
251     const WorkloadInfo& info) const
252 {
253     return MakeWorkload<ClConvertFp16ToFp32Workload>(descriptor, info);
254 }
255 
CreateConvertFp32ToFp16(const ConvertFp32ToFp16QueueDescriptor & descriptor,const WorkloadInfo & info) const256 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateConvertFp32ToFp16(
257     const ConvertFp32ToFp16QueueDescriptor& descriptor,
258     const WorkloadInfo& info) const
259 {
260     return MakeWorkload<ClConvertFp32ToFp16Workload>(descriptor, info);
261 }
262 
CreateConvolution2d(const Convolution2dQueueDescriptor & descriptor,const WorkloadInfo & info) const263 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateConvolution2d(const Convolution2dQueueDescriptor& descriptor,
264                                                                   const WorkloadInfo& info) const
265 {
266     bool isFastMathEnabled = false;
267     if (m_ModelContextPtr)
268     {
269         if (m_ModelContextPtr.get() != nullptr)
270         {
271             auto modelOptions = dynamic_cast<ClBackendModelContext*>(m_ModelContextPtr.get());
272             if (modelOptions)
273             {
274                 isFastMathEnabled = modelOptions->IsFastMathEnabled();
275             }
276         }
277     }
278     return MakeWorkload<ClConvolution2dWorkload>(descriptor,
279                                                  info,
280                                                  m_MemoryManager->GetIntraLayerManager(),
281                                                  isFastMathEnabled);
282 }
283 
CreateDebug(const DebugQueueDescriptor & descriptor,const WorkloadInfo & info) const284 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateDebug(const DebugQueueDescriptor& descriptor,
285                                                           const WorkloadInfo& info) const
286 {
287     return MakeWorkload<NullWorkload, NullWorkload>(descriptor, info);
288 }
289 
CreateDepthToSpace(const DepthToSpaceQueueDescriptor & descriptor,const WorkloadInfo & info) const290 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateDepthToSpace(const DepthToSpaceQueueDescriptor& descriptor,
291                                                                  const WorkloadInfo& info) const
292 {
293     return MakeWorkload<ClDepthToSpaceWorkload>(descriptor, info);
294 }
295 
CreateDepthwiseConvolution2d(const DepthwiseConvolution2dQueueDescriptor & descriptor,const WorkloadInfo & info) const296 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateDepthwiseConvolution2d(
297     const DepthwiseConvolution2dQueueDescriptor& descriptor,
298     const WorkloadInfo& info) const
299 {
300     return MakeWorkload<ClDepthwiseConvolutionWorkload>(descriptor, info);
301 }
302 
CreateDequantize(const DequantizeQueueDescriptor & descriptor,const WorkloadInfo & info) const303 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateDequantize(const DequantizeQueueDescriptor& descriptor,
304                                                                const WorkloadInfo& info) const
305 {
306     return MakeWorkload<ClDequantizeWorkload>(descriptor, info);
307 }
308 
CreateDetectionPostProcess(const DetectionPostProcessQueueDescriptor & descriptor,const WorkloadInfo & info) const309 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateDetectionPostProcess(
310     const DetectionPostProcessQueueDescriptor& descriptor,
311     const WorkloadInfo& info) const
312 {
313     return MakeWorkload<NullWorkload, NullWorkload>(descriptor, info);
314 }
315 
CreateDivision(const DivisionQueueDescriptor & descriptor,const WorkloadInfo & info) const316 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateDivision(const DivisionQueueDescriptor& descriptor,
317                                                              const WorkloadInfo& info) const
318 {
319     return MakeWorkload<ClDivisionFloatWorkload, NullWorkload>(descriptor, info);
320 }
321 
CreateElementwiseUnary(const ElementwiseUnaryQueueDescriptor & descriptor,const WorkloadInfo & info) const322 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateElementwiseUnary(const ElementwiseUnaryQueueDescriptor& descriptor,
323                                                                      const WorkloadInfo& info) const
324 {
325     switch(descriptor.m_Parameters.m_Operation)
326     {
327         case UnaryOperation::Abs:
328         {
329             AbsQueueDescriptor absQueueDescriptor;
330             absQueueDescriptor.m_Inputs  = descriptor.m_Inputs;
331             absQueueDescriptor.m_Outputs = descriptor.m_Outputs;
332 
333             return  std::make_unique<ClAbsWorkload>(absQueueDescriptor, info);
334         }
335         case UnaryOperation::Exp:
336             return std::make_unique<ClExpWorkload>(descriptor, info);
337         case UnaryOperation::Neg:
338             return std::make_unique<ClNegWorkload>(descriptor, info);
339         case UnaryOperation::Rsqrt:
340         {
341             RsqrtQueueDescriptor rsqrtQueueDescriptor;
342             rsqrtQueueDescriptor.m_Inputs  = descriptor.m_Inputs;
343             rsqrtQueueDescriptor.m_Outputs = descriptor.m_Outputs;
344 
345             return std::make_unique<ClRsqrtWorkload>(rsqrtQueueDescriptor, info);
346         }
347         case UnaryOperation::LogicalNot:
348             return std::make_unique<ClLogicalNotWorkload>(descriptor, info);
349         default:
350             return nullptr;
351     }
352 }
353 
CreateEqual(const EqualQueueDescriptor & descriptor,const WorkloadInfo & info) const354 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateEqual(const EqualQueueDescriptor& descriptor,
355                                                           const WorkloadInfo& info) const
356 {
357     IgnoreUnused(descriptor);
358 
359     ComparisonQueueDescriptor comparisonDescriptor;
360     comparisonDescriptor.m_Parameters = ComparisonDescriptor(ComparisonOperation::Equal);
361 
362     return CreateComparison(comparisonDescriptor, info);
363 }
364 
CreateFill(const FillQueueDescriptor & descriptor,const WorkloadInfo & info) const365 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateFill(const FillQueueDescriptor& descriptor,
366                                                          const WorkloadInfo& info) const
367 {
368     return std::make_unique<ClFillWorkload>(descriptor, info);
369 }
370 
CreateFloor(const FloorQueueDescriptor & descriptor,const WorkloadInfo & info) const371 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateFloor(const FloorQueueDescriptor& descriptor,
372                                                           const WorkloadInfo& info) const
373 {
374     return MakeWorkload<ClFloorFloatWorkload, NullWorkload>(descriptor, info);
375 }
376 
CreateFullyConnected(const FullyConnectedQueueDescriptor & descriptor,const WorkloadInfo & info) const377 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateFullyConnected(const FullyConnectedQueueDescriptor& descriptor,
378                                                                    const WorkloadInfo& info) const
379 {
380     return MakeWorkload<ClFullyConnectedWorkload>(descriptor, info, m_MemoryManager->GetIntraLayerManager());
381 }
382 
CreateGather(const GatherQueueDescriptor & descriptor,const WorkloadInfo & info) const383 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateGather(const GatherQueueDescriptor& descriptor,
384                                                            const WorkloadInfo& info) const
385 {
386     return MakeWorkload<ClGatherWorkload>(descriptor, info);
387 }
388 
CreateGreater(const GreaterQueueDescriptor & descriptor,const WorkloadInfo & info) const389 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateGreater(const GreaterQueueDescriptor& descriptor,
390                                                             const WorkloadInfo& info) const
391 {
392     IgnoreUnused(descriptor);
393 
394     ComparisonQueueDescriptor comparisonDescriptor;
395     comparisonDescriptor.m_Parameters = ComparisonDescriptor(ComparisonOperation::Greater);
396 
397     return CreateComparison(comparisonDescriptor, info);
398 }
399 
CreateInput(const InputQueueDescriptor & descriptor,const WorkloadInfo & info) const400 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateInput(const InputQueueDescriptor& descriptor,
401                                                           const WorkloadInfo& info) const
402 {
403     return std::make_unique<CopyMemGenericWorkload>(descriptor, info);
404 }
405 
CreateInstanceNormalization(const InstanceNormalizationQueueDescriptor & descriptor,const WorkloadInfo & info) const406 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateInstanceNormalization(
407     const InstanceNormalizationQueueDescriptor& descriptor,
408     const WorkloadInfo& info) const
409 {
410     return MakeWorkload<ClInstanceNormalizationWorkload>(descriptor, info);
411 }
412 
CreateL2Normalization(const L2NormalizationQueueDescriptor & descriptor,const WorkloadInfo & info) const413 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateL2Normalization(const L2NormalizationQueueDescriptor& descriptor,
414                                                                     const WorkloadInfo& info) const
415 {
416     return MakeWorkload<ClL2NormalizationFloatWorkload, NullWorkload>(descriptor, info);
417 }
418 
CreateLogicalBinary(const LogicalBinaryQueueDescriptor & descriptor,const WorkloadInfo & info) const419 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateLogicalBinary(const LogicalBinaryQueueDescriptor& descriptor,
420                                                                   const WorkloadInfo& info) const
421 {
422     switch(descriptor.m_Parameters.m_Operation)
423     {
424         case LogicalBinaryOperation::LogicalAnd:
425             return std::make_unique<ClLogicalAndWorkload>(descriptor, info);
426         case LogicalBinaryOperation::LogicalOr:
427             return std::make_unique<ClLogicalOrWorkload>(descriptor, info);
428         default:
429             return nullptr;
430     }
431 }
432 
CreateLogSoftmax(const LogSoftmaxQueueDescriptor & descriptor,const WorkloadInfo & info) const433 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateLogSoftmax(const LogSoftmaxQueueDescriptor& descriptor,
434                                                                const WorkloadInfo& info) const
435 {
436     return MakeWorkload<ClLogSoftmaxWorkload>(descriptor, info, m_MemoryManager->GetIntraLayerManager());
437 }
438 
CreateLstm(const LstmQueueDescriptor & descriptor,const WorkloadInfo & info) const439 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateLstm(const LstmQueueDescriptor& descriptor,
440                                                          const WorkloadInfo& info) const
441 {
442     return MakeWorkload<ClLstmFloatWorkload, NullWorkload>(descriptor, info);
443 }
444 
CreateMaximum(const MaximumQueueDescriptor & descriptor,const WorkloadInfo & info) const445 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateMaximum(const MaximumQueueDescriptor& descriptor,
446                                                             const WorkloadInfo& info) const
447 {
448     return MakeWorkload<ClMaximumWorkload>(descriptor, info);
449 }
450 
CreateMean(const MeanQueueDescriptor & descriptor,const WorkloadInfo & info) const451 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateMean(const MeanQueueDescriptor& descriptor,
452                                                          const WorkloadInfo& info) const
453 {
454     return MakeWorkload<ClMeanWorkload>(descriptor, info);
455 }
456 
CreateMemCopy(const MemCopyQueueDescriptor & descriptor,const WorkloadInfo & info) const457 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateMemCopy(const MemCopyQueueDescriptor& descriptor,
458                                                             const WorkloadInfo& info) const
459 {
460     if (descriptor.m_Inputs.empty() || !descriptor.m_Inputs[0])
461     {
462         throw InvalidArgumentException("ClWorkloadFactory: Invalid null input for MemCopy workload");
463     }
464 
465     return MakeWorkload<CopyMemGenericWorkload>(descriptor, info);
466 }
467 
CreateMemImport(const MemImportQueueDescriptor & descriptor,const WorkloadInfo & info) const468 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateMemImport(const MemImportQueueDescriptor& descriptor,
469                                                               const WorkloadInfo& info) const
470 {
471     if (descriptor.m_Inputs.empty() || !descriptor.m_Inputs[0])
472     {
473         throw InvalidArgumentException("ClWorkloadFactory: Invalid null input for MemImport workload");
474     }
475 
476     return std::make_unique<ImportMemGenericWorkload>(descriptor, info);
477 }
478 
CreateMerger(const MergerQueueDescriptor & descriptor,const WorkloadInfo & info) const479 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateMerger(const MergerQueueDescriptor& descriptor,
480                                                            const WorkloadInfo& info) const
481 {
482     return CreateConcat(descriptor, info);
483 }
484 
CreateMinimum(const MinimumQueueDescriptor & descriptor,const WorkloadInfo & info) const485 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateMinimum(const MinimumQueueDescriptor& descriptor,
486                                                             const WorkloadInfo& info) const
487 {
488     return MakeWorkload<ClMinimumWorkload>(descriptor, info);
489 }
490 
CreateMultiplication(const MultiplicationQueueDescriptor & descriptor,const WorkloadInfo & info) const491 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateMultiplication(const MultiplicationQueueDescriptor& descriptor,
492                                                                    const WorkloadInfo& info) const
493 {
494     return MakeWorkload<ClMultiplicationWorkload>(descriptor, info);
495 }
496 
CreateNormalization(const NormalizationQueueDescriptor & descriptor,const WorkloadInfo & info) const497 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateNormalization(const NormalizationQueueDescriptor& descriptor,
498                                                                   const WorkloadInfo& info) const
499 {
500     return MakeWorkload<ClNormalizationFloatWorkload, NullWorkload>(descriptor, info);
501 }
502 
CreateOutput(const OutputQueueDescriptor & descriptor,const WorkloadInfo & info) const503 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateOutput(const OutputQueueDescriptor& descriptor,
504                                                            const WorkloadInfo& info) const
505 {
506     return std::make_unique<CopyMemGenericWorkload>(descriptor, info);
507 }
508 
CreatePad(const PadQueueDescriptor & descriptor,const WorkloadInfo & info) const509 std::unique_ptr<IWorkload> ClWorkloadFactory::CreatePad(const PadQueueDescriptor& descriptor,
510                                                         const WorkloadInfo& info) const
511 {
512     return MakeWorkload<ClPadWorkload>(descriptor, info);
513 }
514 
CreatePermute(const PermuteQueueDescriptor & descriptor,const WorkloadInfo & info) const515 std::unique_ptr<IWorkload> ClWorkloadFactory::CreatePermute(const PermuteQueueDescriptor& descriptor,
516                                                             const WorkloadInfo& info) const
517 {
518     return MakeWorkload<ClPermuteWorkload>(descriptor, info);
519 }
520 
CreatePooling2d(const Pooling2dQueueDescriptor & descriptor,const WorkloadInfo & info) const521 std::unique_ptr<IWorkload> ClWorkloadFactory::CreatePooling2d(const Pooling2dQueueDescriptor& descriptor,
522                                                               const WorkloadInfo& info) const
523 {
524     return MakeWorkload<ClPooling2dWorkload>(descriptor, info);
525 }
526 
CreatePreCompiled(const PreCompiledQueueDescriptor & descriptor,const WorkloadInfo & info) const527 std::unique_ptr<IWorkload> ClWorkloadFactory::CreatePreCompiled(const PreCompiledQueueDescriptor& descriptor,
528                                                                 const WorkloadInfo& info) const
529 {
530     return MakeWorkload<NullWorkload, NullWorkload>(descriptor, info);
531 }
532 
CreatePrelu(const PreluQueueDescriptor & descriptor,const WorkloadInfo & info) const533 std::unique_ptr<IWorkload> ClWorkloadFactory::CreatePrelu(const PreluQueueDescriptor &descriptor,
534                                                           const WorkloadInfo &info) const
535 {
536     return MakeWorkload<ClPreluWorkload>(descriptor, info);
537 }
538 
CreateQLstm(const QLstmQueueDescriptor & descriptor,const WorkloadInfo & info) const539 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateQLstm(const QLstmQueueDescriptor& descriptor,
540                                                           const WorkloadInfo& info) const
541 {
542     return std::make_unique<ClQLstmWorkload>(descriptor, info);
543 }
544 
CreateQuantize(const QuantizeQueueDescriptor & descriptor,const WorkloadInfo & info) const545 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateQuantize(const QuantizeQueueDescriptor& descriptor,
546                                                              const WorkloadInfo& info) const
547 {
548     return MakeWorkload<ClQuantizeWorkload>(descriptor, info);
549 }
550 
CreateQuantizedLstm(const QuantizedLstmQueueDescriptor & descriptor,const WorkloadInfo & info) const551 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateQuantizedLstm(const QuantizedLstmQueueDescriptor& descriptor,
552                                                                   const WorkloadInfo& info) const
553 {
554     return MakeWorkload<ClQuantizedLstmWorkload>(descriptor, info);
555 }
556 
CreateReshape(const ReshapeQueueDescriptor & descriptor,const WorkloadInfo & info) const557 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateReshape(const ReshapeQueueDescriptor& descriptor,
558                                                             const WorkloadInfo& info) const
559 {
560     return MakeWorkload<ClReshapeWorkload>(descriptor, info);
561 }
562 
CreateResize(const ResizeQueueDescriptor & descriptor,const WorkloadInfo & info) const563 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateResize(const ResizeQueueDescriptor& descriptor,
564                                                            const WorkloadInfo& info) const
565 {
566     return MakeWorkload<ClResizeWorkload>(descriptor, info);
567 }
568 
CreateResizeBilinear(const ResizeBilinearQueueDescriptor & descriptor,const WorkloadInfo & info) const569 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateResizeBilinear(const ResizeBilinearQueueDescriptor& descriptor,
570                                                                    const WorkloadInfo& info) const
571 {
572     ResizeQueueDescriptor resizeDescriptor;
573     resizeDescriptor.m_Inputs  = descriptor.m_Inputs;
574     resizeDescriptor.m_Outputs = descriptor.m_Outputs;
575 
576     resizeDescriptor.m_Parameters.m_Method       = ResizeMethod::Bilinear;
577     resizeDescriptor.m_Parameters.m_DataLayout   = descriptor.m_Parameters.m_DataLayout;
578     resizeDescriptor.m_Parameters.m_TargetHeight = descriptor.m_Parameters.m_TargetHeight;
579     resizeDescriptor.m_Parameters.m_TargetWidth  = descriptor.m_Parameters.m_TargetWidth;
580 
581     return CreateResize(resizeDescriptor, info);
582 }
583 
CreateRsqrt(const RsqrtQueueDescriptor & descriptor,const WorkloadInfo & info) const584 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateRsqrt(const RsqrtQueueDescriptor& descriptor,
585                                                           const WorkloadInfo& info) const
586 {
587     IgnoreUnused(descriptor);
588 
589     ElementwiseUnaryQueueDescriptor elementwiseUnaryDescriptor;
590     elementwiseUnaryDescriptor.m_Parameters = ElementwiseUnaryDescriptor(UnaryOperation::Rsqrt);
591 
592     return CreateElementwiseUnary(elementwiseUnaryDescriptor, info);
593 }
594 
CreateSlice(const SliceQueueDescriptor & descriptor,const WorkloadInfo & info) const595 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateSlice(const SliceQueueDescriptor& descriptor,
596                                                           const WorkloadInfo& info) const
597 {
598     return MakeWorkload<ClSliceWorkload>(descriptor, info);
599 }
600 
CreateSoftmax(const SoftmaxQueueDescriptor & descriptor,const WorkloadInfo & info) const601 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateSoftmax(const SoftmaxQueueDescriptor& descriptor,
602                                                             const WorkloadInfo& info) const
603 {
604     return std::make_unique<ClSoftmaxWorkload>(descriptor, info, m_MemoryManager->GetIntraLayerManager());
605 }
606 
CreateSpaceToBatchNd(const SpaceToBatchNdQueueDescriptor & descriptor,const WorkloadInfo & info) const607 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateSpaceToBatchNd(const SpaceToBatchNdQueueDescriptor& descriptor,
608                                                                    const WorkloadInfo& info) const
609 {
610     return MakeWorkload<ClSpaceToBatchNdWorkload>(descriptor, info);
611 }
612 
CreateSpaceToDepth(const SpaceToDepthQueueDescriptor & descriptor,const WorkloadInfo & info) const613 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateSpaceToDepth(const SpaceToDepthQueueDescriptor& descriptor,
614                                                                  const WorkloadInfo& info) const
615 {
616     return MakeWorkload<ClSpaceToDepthWorkload>(descriptor, info);
617 }
618 
CreateSplitter(const SplitterQueueDescriptor & descriptor,const WorkloadInfo & info) const619 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateSplitter(const SplitterQueueDescriptor& descriptor,
620                                                              const WorkloadInfo& info) const
621 {
622     return MakeWorkload<ClSplitterWorkload>(descriptor, info);
623 }
624 
CreateStack(const StackQueueDescriptor & descriptor,const WorkloadInfo & info) const625 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateStack(const StackQueueDescriptor& descriptor,
626                                                           const WorkloadInfo& info) const
627 {
628     return MakeWorkload<ClStackWorkload>(descriptor, info);
629 }
630 
CreateStridedSlice(const StridedSliceQueueDescriptor & descriptor,const WorkloadInfo & info) const631 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateStridedSlice(const StridedSliceQueueDescriptor& descriptor,
632                                                                  const WorkloadInfo& info) const
633 {
634     return MakeWorkload<ClStridedSliceWorkload>(descriptor, info);
635 }
636 
CreateSubtraction(const SubtractionQueueDescriptor & descriptor,const WorkloadInfo & info) const637 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateSubtraction(const SubtractionQueueDescriptor& descriptor,
638                                                                 const WorkloadInfo& info) const
639 {
640     return MakeWorkload<ClSubtractionWorkload>(descriptor, info);
641 }
642 
CreateTranspose(const TransposeQueueDescriptor & descriptor,const WorkloadInfo & info) const643 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateTranspose(const TransposeQueueDescriptor& descriptor,
644                                                               const WorkloadInfo& info) const
645 {
646     return MakeWorkload<ClTransposeWorkload>(descriptor, info);
647 }
648 
CreateTransposeConvolution2d(const TransposeConvolution2dQueueDescriptor & descriptor,const WorkloadInfo & info) const649 std::unique_ptr<IWorkload> ClWorkloadFactory::CreateTransposeConvolution2d(
650     const TransposeConvolution2dQueueDescriptor& descriptor,
651     const WorkloadInfo& info) const
652 {
653     return MakeWorkload<ClTransposeConvolution2dWorkload>(descriptor, info, m_MemoryManager->GetIntraLayerManager());
654 }
655 
656 } // namespace armnn
657