Release 18.03
[platform/upstream/armnn.git] / src / armnn / backends / NeonWorkloadFactory.cpp
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // See LICENSE file in the project root for full license information.
4 //
5 #include "NeonWorkloadFactory.hpp"
6 #include "armnn/Utils.hpp"
7 #include "CpuTensorHandle.hpp"
8 #include "Layer.hpp"
9 #include "Layers.hpp"
10
11 #ifdef ARMCOMPUTENEON_ENABLED
12 #include "MemCopyWorkload.hpp"
13 #include "NeonTensorHandle.hpp"
14 #include "NeonWorkloadUtils.hpp"
15 #include "NeonWorkloads.hpp"
16 #endif
17
18 #include "MakeWorkloadHelper.hpp"
19
20 #include <boost/polymorphic_cast.hpp>
21
22 namespace armnn
23 {
24
25 bool NeonWorkloadFactory::IsLayerSupported(const Layer& layer, DataType dataType, std::string& outReasonIfUnsupported)
26 {
27     return IWorkloadFactory::IsLayerSupported(Compute::CpuAcc, layer, dataType, outReasonIfUnsupported);
28 }
29
30 #ifdef ARMCOMPUTENEON_ENABLED
31
32 std::unique_ptr<ITensorHandle> NeonWorkloadFactory::CreateSubTensorHandle(ITensorHandle& parent,
33     TensorShape const& subTensorShape,
34     unsigned int const* subTensorOrigin) const
35 {
36     BOOST_ASSERT(parent.GetType() == ITensorHandle::Neon);
37
38     const arm_compute::TensorShape shape = armcomputetensorutils::BuildArmComputeTensorShape(subTensorShape);
39
40     arm_compute::Coordinates coords;
41     coords.set_num_dimensions(subTensorShape.GetNumDimensions());
42     for (unsigned int i = 0; i < subTensorShape.GetNumDimensions(); i++)
43     {
44         // arm compute indexes tensor coords in reverse order
45         unsigned int revertedIndex = subTensorShape.GetNumDimensions() - i - 1;
46         coords.set(i, boost::numeric_cast<int>(subTensorOrigin[revertedIndex]));
47     }
48
49     return std::make_unique<NeonSubTensorHandle>(boost::polymorphic_downcast<INeonTensorHandle*>(&parent)->GetTensor(),
50         shape, coords);
51 }
52
53 std::unique_ptr<ITensorHandle> NeonWorkloadFactory::CreateTensorHandle(const TensorInfo& tensorInfo) const
54 {
55     return std::make_unique<NeonTensorHandle>(tensorInfo);
56 }
57
58 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateInput(const InputQueueDescriptor& descriptor,
59                                                             const WorkloadInfo&        info) const
60 {
61     return MakeWorkload<CopyFromCpuToNeonFloat32Workload, CopyFromCpuToNeonUint8Workload>(descriptor, info);
62 }
63
64 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateOutput(const OutputQueueDescriptor& descriptor,
65                                                              const WorkloadInfo&        info) const
66 {
67     return MakeWorkload<CopyFromNeonToCpuFloat32Workload, CopyFromNeonToCpuUint8Workload>(descriptor, info);
68 }
69
70 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateActivation(const ActivationQueueDescriptor& descriptor,
71                                                                  const WorkloadInfo&              info) const
72 {
73     return MakeWorkload<NeonActivationFloat32Workload, NeonActivationUint8Workload>(descriptor, info);
74 }
75
76 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateSoftmax(const SoftmaxQueueDescriptor& descriptor,
77                                                               const WorkloadInfo&           info) const
78 {
79     return MakeWorkload<NeonSoftmaxFloat32Workload, NeonSoftmaxUint8Workload>(descriptor, info);
80 }
81
82 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateSplitter(const SplitterQueueDescriptor& descriptor,
83                                                                const WorkloadInfo&            info) const
84 {
85     return MakeWorkload<NeonSplitterFloat32Workload, NeonSplitterUint8Workload>(descriptor, info);
86 }
87
88 std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateMerger(const MergerQueueDescriptor& descriptor,
89                                                                     const WorkloadInfo&          info) const
90 {
91     return MakeWorkload<NeonMergerFloat32Workload, NeonMergerUint8Workload>(descriptor, info);
92 }
93
94 std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateFullyConnected(
95     const FullyConnectedQueueDescriptor& descriptor, const WorkloadInfo& info) const
96 {
97     return MakeWorkload<NeonFullyConnectedFloat32Workload, NullWorkload>(descriptor, info);
98 }
99
100 std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreatePermute(const PermuteQueueDescriptor& descriptor,
101                                                                      const WorkloadInfo&           info) const
102 {
103     return MakeWorkload<NeonPermuteFloat32Workload, NeonPermuteUint8Workload>(descriptor, info);
104 }
105
106 std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreatePooling2d(const Pooling2dQueueDescriptor& descriptor,
107                                                                        const WorkloadInfo&           info) const
108 {
109     return MakeWorkload<NeonPooling2dFloat32Workload, NeonPooling2dUint8Workload>(descriptor, info);
110 }
111
112 std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateConvolution2d(
113     const Convolution2dQueueDescriptor& descriptor, const WorkloadInfo& info) const
114 {
115     return MakeWorkload<NeonConvolution2dFloat32Workload, NeonConvolution2dUint8Workload>(descriptor, info);
116 }
117
118 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateDepthwiseConvolution2d(
119     const DepthwiseConvolution2dQueueDescriptor& descriptor, const WorkloadInfo& info) const
120 {
121     return MakeWorkload<NeonDepthwiseConvolutionFloat32Workload, NeonDepthwiseConvolutionUint8Workload>(
122         descriptor, info);
123 }
124
125 std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateNormalization(
126     const NormalizationQueueDescriptor& descriptor, const WorkloadInfo& info) const
127 {
128     return MakeWorkload<NeonNormalizationFloat32Workload, NullWorkload>(descriptor, info);
129 }
130
131 std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateAddition(const AdditionQueueDescriptor& descriptor,
132                                                                       const WorkloadInfo&            info) const
133 {
134     return MakeWorkload<NeonAdditionFloat32Workload, NullWorkload>(descriptor, info);
135 }
136
137 std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateMultiplication(
138     const MultiplicationQueueDescriptor& descriptor, const WorkloadInfo& info) const
139 {
140     return MakeWorkload<NeonMultiplicationFloat32Workload, NullWorkload>(descriptor, info);
141 }
142
143 std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateBatchNormalization(
144     const BatchNormalizationQueueDescriptor& descriptor, const WorkloadInfo& info) const
145 {
146     return MakeWorkload<NeonBatchNormalizationFloat32Workload, NullWorkload>(descriptor, info);
147 }
148
149 std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateMemCopy(const MemCopyQueueDescriptor& descriptor,
150                                                                      const WorkloadInfo&        info) const
151 {
152     if (descriptor.m_Inputs.empty() || !descriptor.m_Inputs[0])
153     {
154         throw InvalidArgumentException("NeonWorkloadFactory: Invalid null input for MemCopy workload");
155     }
156
157     // Create a workload that will copy tensor data from the inputs, which can have a number of different formats,
158     // to Neon tensors.
159     switch (descriptor.m_Inputs[0]->GetType())
160     {
161     case ITensorHandle::Cpu:
162         return MakeWorkload<CopyFromCpuToNeonFloat32Workload, CopyFromCpuToNeonUint8Workload>(descriptor, info);
163 #if ARMCOMPUTECL_ENABLED
164     case ITensorHandle::CL:
165     {
166         return MakeWorkload<CopyFromClToNeonFloat32Workload, CopyFromClToNeonUint8Workload>(descriptor, info);
167     }
168 #endif
169     default:
170         throw InvalidArgumentException("NeonWorkloadFactory: Destination type not supported for MemCopy Workload.");
171     }
172 }
173
174 std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateResizeBilinear(
175     const ResizeBilinearQueueDescriptor& descriptor,
176     const WorkloadInfo& info) const
177 {
178     return nullptr;
179 }
180
181 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateFakeQuantization(
182     const FakeQuantizationQueueDescriptor& descriptor,
183     const WorkloadInfo& info) const
184 {
185     return nullptr;
186 }
187
188 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateL2Normalization(const L2NormalizationQueueDescriptor& descriptor,
189     const WorkloadInfo& info) const
190 {
191     return MakeWorkload<NeonL2NormalizationFloat32Workload, NullWorkload>(descriptor, info);
192 }
193
194 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateConstant(const ConstantQueueDescriptor& descriptor,
195     const WorkloadInfo& info) const
196 {
197     return MakeWorkload<NeonConstantFloat32Workload, NeonConstantUint8Workload>(descriptor, info);
198 }
199
200 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateReshape(const ReshapeQueueDescriptor& descriptor,
201     const WorkloadInfo& info) const
202 {
203     return MakeWorkload<NeonReshapeFloat32Workload, NeonReshapeUint8Workload>(descriptor, info);
204 }
205
206 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateFloor(const FloorQueueDescriptor& descriptor,
207     const WorkloadInfo& info) const
208 {
209     return MakeWorkload<NeonFloorFloat32Workload, NullWorkload>(descriptor, info);
210 }
211
212 #else // Compiled without ArmCompute libs
213
214 std::unique_ptr<ITensorHandle> NeonWorkloadFactory::CreateSubTensorHandle(ITensorHandle& parent,
215     TensorShape const& subTensorShape,
216     unsigned int const* subTensorOrigin) const
217 {
218     return nullptr;
219 }
220
221 std::unique_ptr<ITensorHandle> NeonWorkloadFactory::CreateTensorHandle(const TensorInfo& tensorInfo) const
222 {
223     return nullptr;
224 }
225
226 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateInput(const InputQueueDescriptor& descriptor,
227                                                             const WorkloadInfo&        info) const
228 {
229     return nullptr;
230 }
231
232 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateOutput(const OutputQueueDescriptor& descriptor,
233                                                              const WorkloadInfo&        info) const
234 {
235     return nullptr;
236 }
237
238 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateActivation(const ActivationQueueDescriptor& descriptor,
239                                                                  const WorkloadInfo&              info) const
240 {
241     return nullptr;
242 }
243
244 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateSoftmax(const SoftmaxQueueDescriptor& descriptor,
245                                                               const WorkloadInfo&           info) const
246 {
247     return nullptr;
248 }
249
250 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateSplitter(const SplitterQueueDescriptor& descriptor,
251                                                                const WorkloadInfo&            info) const
252 {
253     return nullptr;
254 }
255
256 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateMerger(const MergerQueueDescriptor& descriptor,
257                                                              const WorkloadInfo&          info) const
258 {
259     return nullptr;
260 }
261
262 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateFullyConnected(const FullyConnectedQueueDescriptor& descriptor,
263                                                                      const WorkloadInfo&                  info) const
264 {
265     return nullptr;
266 }
267
268 std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreatePermute(const PermuteQueueDescriptor& descriptor,
269                                                                      const WorkloadInfo&           info) const
270 {
271     return nullptr;
272 }
273
274 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreatePooling2d(const Pooling2dQueueDescriptor& descriptor,
275                                                                 const WorkloadInfo&           info) const
276 {
277     return nullptr;
278 }
279
280 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateConvolution2d(const Convolution2dQueueDescriptor& descriptor,
281                                                                     const WorkloadInfo&               info) const
282 {
283     return nullptr;
284 }
285
286 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateDepthwiseConvolution2d(
287     const DepthwiseConvolution2dQueueDescriptor& descriptor, const WorkloadInfo& info) const
288 {
289     return nullptr;
290 }
291
292 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateNormalization(const NormalizationQueueDescriptor& descriptor,
293                                                                     const WorkloadInfo&                 info) const
294 {
295     return nullptr;
296 }
297
298 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateAddition(const AdditionQueueDescriptor& descriptor,
299                                                                const WorkloadInfo&            info) const
300 {
301     return nullptr;
302 }
303
304 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateBatchNormalization(const BatchNormalizationQueueDescriptor& data,
305                                                                          const WorkloadInfo& info) const
306 {
307     return nullptr;
308 }
309
310 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateMultiplication(const MultiplicationQueueDescriptor& data,
311                                                                      const WorkloadInfo&                  info) const
312 {
313     return nullptr;
314 }
315
316 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateMemCopy(const MemCopyQueueDescriptor& descriptor,
317                                                               const WorkloadInfo&        info) const
318 {
319     return nullptr;
320 }
321
322 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateResizeBilinear(const ResizeBilinearQueueDescriptor& descriptor,
323                                                                      const WorkloadInfo& info) const
324 {
325     return nullptr;
326 }
327
328 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateFakeQuantization(
329         const FakeQuantizationQueueDescriptor& descriptor, const WorkloadInfo& info) const
330 {
331     return nullptr;
332 }
333
334 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateL2Normalization(const L2NormalizationQueueDescriptor& descriptor,
335     const WorkloadInfo& info) const
336 {
337     return nullptr;
338 }
339
340 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateConstant(const ConstantQueueDescriptor& descriptor,
341     const WorkloadInfo& info) const
342 {
343     return nullptr;
344 }
345
346 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateReshape(const ReshapeQueueDescriptor& descriptor,
347     const WorkloadInfo&           info) const
348 {
349     return nullptr;
350 }
351
352 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateFloor(const FloorQueueDescriptor& descriptor,
353     const WorkloadInfo& info) const
354 {
355     return nullptr;
356 }
357
358 #endif
359
360 } //namespace armnn