ArmNN
 20.02
ClCreateWorkloadTests.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
8 
10 
13 
14 #include <cl/ClTensorHandle.hpp>
15 #include <cl/ClWorkloadFactory.hpp>
18 
19 boost::test_tools::predicate_result CompareIClTensorHandleShape(IClTensorHandle* tensorHandle,
20  std::initializer_list<unsigned int> expectedDimensions)
21 {
22  return CompareTensorHandleShape<IClTensorHandle>(tensorHandle, expectedDimensions);
23 }
24 
25 BOOST_FIXTURE_TEST_SUITE(CreateWorkloadCl, ClContextControlFixture)
26 
27 template <armnn::DataType DataType>
28 static void ClCreateActivationWorkloadTest()
29 {
30  Graph graph;
31  ClWorkloadFactory factory =
32  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
33 
34  auto workload = CreateActivationWorkloadTest<ClActivationWorkload, DataType>(factory, graph);
35 
36  // Checks that inputs/outputs are as we expect them (see definition of CreateActivationWorkloadTest).
37  ActivationQueueDescriptor queueDescriptor = workload->GetData();
38  auto inputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
39  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
40 
41  BOOST_TEST(CompareIClTensorHandleShape(inputHandle, {1, 1}));
42  BOOST_TEST(CompareIClTensorHandleShape(outputHandle, {1, 1}));
43 }
44 
45 BOOST_AUTO_TEST_CASE(CreateActivationFloatWorkload)
46 {
47  ClCreateActivationWorkloadTest<armnn::DataType::Float32>();
48 }
49 
50 BOOST_AUTO_TEST_CASE(CreateActivationFloat16Workload)
51 {
52  ClCreateActivationWorkloadTest<armnn::DataType::Float16>();
53 }
54 
55 template <typename WorkloadType,
56  typename DescriptorType,
57  typename LayerType,
59 static void ClCreateElementwiseWorkloadTest()
60 {
61  Graph graph;
62  ClWorkloadFactory factory =
63  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
64 
65  auto workload = CreateElementwiseWorkloadTest<WorkloadType, DescriptorType, LayerType, DataType>(factory, graph);
66 
67  // Checks that inputs/outputs are as we expect them (see definition of CreateElementwiseWorkloadTest).
68  DescriptorType queueDescriptor = workload->GetData();
69  auto inputHandle1 = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
70  auto inputHandle2 = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[1]);
71  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
72  BOOST_TEST(CompareIClTensorHandleShape(inputHandle1, {2, 3}));
73  BOOST_TEST(CompareIClTensorHandleShape(inputHandle2, {2, 3}));
74  BOOST_TEST(CompareIClTensorHandleShape(outputHandle, {2, 3}));
75 }
76 
77 BOOST_AUTO_TEST_CASE(CreateAdditionFloatWorkload)
78 {
79  ClCreateElementwiseWorkloadTest<ClAdditionWorkload,
83 }
84 
85 BOOST_AUTO_TEST_CASE(CreateAdditionFloat16Workload)
86 {
87  ClCreateElementwiseWorkloadTest<ClAdditionWorkload,
91 }
92 
93 BOOST_AUTO_TEST_CASE(CreateSubtractionFloatWorkload)
94 {
95  ClCreateElementwiseWorkloadTest<ClSubtractionWorkload,
99 }
100 
101 BOOST_AUTO_TEST_CASE(CreateSubtractionFloat16Workload)
102 {
103  ClCreateElementwiseWorkloadTest<ClSubtractionWorkload,
107 }
108 
109 BOOST_AUTO_TEST_CASE(CreateMultiplicationFloatWorkloadTest)
110 {
111  ClCreateElementwiseWorkloadTest<ClMultiplicationWorkload,
115 }
116 
117 BOOST_AUTO_TEST_CASE(CreateMultiplicationFloat16WorkloadTest)
118 {
119  ClCreateElementwiseWorkloadTest<ClMultiplicationWorkload,
123 }
124 
125 BOOST_AUTO_TEST_CASE(CreateMultiplicationUint8WorkloadTest)
126 {
127  ClCreateElementwiseWorkloadTest<ClMultiplicationWorkload,
131 }
132 
133 BOOST_AUTO_TEST_CASE(CreateDivisionFloatWorkloadTest)
134 {
135  ClCreateElementwiseWorkloadTest<ClDivisionFloatWorkload,
139 }
140 
141 BOOST_AUTO_TEST_CASE(CreateDivisionFloat16WorkloadTest)
142 {
143  ClCreateElementwiseWorkloadTest<ClDivisionFloatWorkload,
147 }
148 
149 template <typename WorkloadType,
150  typename DescriptorType,
152 static void ClCreateElementwiseUnaryWorkloadTest(armnn::UnaryOperation op)
153 {
154  Graph graph;
155  ClWorkloadFactory factory =
156  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
157 
158  auto workload = CreateElementwiseUnaryWorkloadTest<WorkloadType, DescriptorType, DataType>(factory, graph, op);
159 
160  DescriptorType queueDescriptor = workload->GetData();
161 
162  auto inputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
163  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
164 
165  BOOST_TEST(CompareIClTensorHandleShape(inputHandle, {2, 3}));
166  BOOST_TEST(CompareIClTensorHandleShape(outputHandle, {2, 3}));
167 }
168 
169 BOOST_AUTO_TEST_CASE(CreateRsqrtFloat32WorkloadTest)
170 {
171  ClCreateElementwiseUnaryWorkloadTest<ClRsqrtWorkload, RsqrtQueueDescriptor, armnn::DataType::Float32>(
172  UnaryOperation::Rsqrt);
173 }
174 
175 template <typename BatchNormalizationWorkloadType, armnn::DataType DataType>
176 static void ClCreateBatchNormalizationWorkloadTest(DataLayout dataLayout)
177 {
178  Graph graph;
179  ClWorkloadFactory factory =
180  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
181 
182  auto workload = CreateBatchNormalizationWorkloadTest<BatchNormalizationWorkloadType, DataType>
183  (factory, graph, dataLayout);
184 
185  // Checks that inputs/outputs are as we expect them (see definition of CreateBatchNormalizationWorkloadTest).
186  BatchNormalizationQueueDescriptor queueDescriptor = workload->GetData();
187  auto inputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
188  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
189 
190  switch (dataLayout)
191  {
192  case DataLayout::NHWC:
193  BOOST_TEST(CompareIClTensorHandleShape(inputHandle, { 2, 4, 4, 3 }));
194  BOOST_TEST(CompareIClTensorHandleShape(outputHandle, { 2, 4, 4, 3 }));
195  break;
196  default: // NCHW
197  BOOST_TEST(CompareIClTensorHandleShape(inputHandle, { 2, 3, 4, 4 }));
198  BOOST_TEST(CompareIClTensorHandleShape(outputHandle, { 2, 3, 4, 4 }));
199  }
200 }
201 
202 BOOST_AUTO_TEST_CASE(CreateBatchNormalizationFloatNchwWorkload)
203 {
204  ClCreateBatchNormalizationWorkloadTest<ClBatchNormalizationFloatWorkload,
205  armnn::DataType::Float32>(DataLayout::NCHW);
206 }
207 
208 BOOST_AUTO_TEST_CASE(CreateBatchNormalizationFloat16NchwWorkload)
209 {
210  ClCreateBatchNormalizationWorkloadTest<ClBatchNormalizationFloatWorkload,
211  armnn::DataType::Float16>(DataLayout::NCHW);
212 }
213 
214 BOOST_AUTO_TEST_CASE(CreateBatchNormalizationFloatNhwcWorkload)
215 {
216  ClCreateBatchNormalizationWorkloadTest<ClBatchNormalizationFloatWorkload,
217  armnn::DataType::Float32>(DataLayout::NHWC);
218 }
219 
220 BOOST_AUTO_TEST_CASE(CreateBatchNormalizationNhwcFloat16NhwcWorkload)
221 {
222  ClCreateBatchNormalizationWorkloadTest<ClBatchNormalizationFloatWorkload,
223  armnn::DataType::Float16>(DataLayout::NHWC);
224 }
225 
226 BOOST_AUTO_TEST_CASE(CreateConvertFp16ToFp32Workload)
227 {
228  Graph graph;
229  ClWorkloadFactory factory =
230  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
231 
232  auto workload = CreateConvertFp16ToFp32WorkloadTest<ClConvertFp16ToFp32Workload>(factory, graph);
233 
234  ConvertFp16ToFp32QueueDescriptor queueDescriptor = workload->GetData();
235  auto inputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
236  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
237 
238  BOOST_TEST(CompareIClTensorHandleShape(inputHandle, {1, 3, 2, 3}));
239  BOOST_TEST(CompareIClTensorHandleShape(outputHandle, {1, 3, 2, 3}));
240  BOOST_TEST((inputHandle->GetTensor().info()->data_type() == arm_compute::DataType::F16));
241  BOOST_TEST((outputHandle->GetTensor().info()->data_type() == arm_compute::DataType::F32));
242 }
243 
244 BOOST_AUTO_TEST_CASE(CreateConvertFp32ToFp16Workload)
245 {
246  Graph graph;
247  ClWorkloadFactory factory =
248  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
249 
250  auto workload = CreateConvertFp32ToFp16WorkloadTest<ClConvertFp32ToFp16Workload>(factory, graph);
251 
252  ConvertFp32ToFp16QueueDescriptor queueDescriptor = workload->GetData();
253  auto inputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
254  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
255 
256  BOOST_TEST(CompareIClTensorHandleShape(inputHandle, {1, 3, 2, 3}));
257  BOOST_TEST(CompareIClTensorHandleShape(outputHandle, {1, 3, 2, 3}));
258  BOOST_TEST((inputHandle->GetTensor().info()->data_type() == arm_compute::DataType::F32));
259  BOOST_TEST((outputHandle->GetTensor().info()->data_type() == arm_compute::DataType::F16));
260 }
261 
262 template <typename Convolution2dWorkloadType, typename armnn::DataType DataType>
263 static void ClConvolution2dWorkloadTest(DataLayout dataLayout)
264 {
265  Graph graph;
266  ClWorkloadFactory factory =
267  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
268 
269  auto workload = CreateConvolution2dWorkloadTest<ClConvolution2dWorkload, DataType>(factory,
270  graph,
271  dataLayout);
272 
273  TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? std::initializer_list<unsigned int>({2, 3, 8, 16})
274  : std::initializer_list<unsigned int>({2, 8, 16, 3});
275  TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? std::initializer_list<unsigned int>({2, 2, 2, 10})
276  : std::initializer_list<unsigned int>({2, 2, 10, 2});
277 
278  // Checks that outputs and inputs are as we expect them (see definition of CreateConvolution2dWorkloadTest).
279  Convolution2dQueueDescriptor queueDescriptor = workload->GetData();
280  auto inputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
281  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
282  BOOST_TEST((inputHandle->GetShape() == inputShape));
283  BOOST_TEST((outputHandle->GetShape() == outputShape));
284 }
285 
286 BOOST_AUTO_TEST_CASE(CreateConvolution2dFloatNchwWorkload)
287 {
288  ClConvolution2dWorkloadTest<ClConvolution2dWorkload, armnn::DataType::Float32>(DataLayout::NCHW);
289 }
290 
291 BOOST_AUTO_TEST_CASE(CreateConvolution2dFloatNhwcWorkload)
292 {
293  ClConvolution2dWorkloadTest<ClConvolution2dWorkload, armnn::DataType::Float32>(DataLayout::NHWC);
294 }
295 
296 BOOST_AUTO_TEST_CASE(CreateConvolution2dFloat16NchwWorkload)
297 {
298  ClConvolution2dWorkloadTest<ClConvolution2dWorkload, armnn::DataType::Float16>(DataLayout::NCHW);
299 }
300 
301 BOOST_AUTO_TEST_CASE(CreateConvolution2dFloat16NhwcWorkload)
302 {
303  ClConvolution2dWorkloadTest<ClConvolution2dWorkload, armnn::DataType::Float16>(DataLayout::NHWC);
304 }
305 
306 template <typename DepthwiseConvolutionWorkloadType, typename armnn::DataType DataType>
307 static void ClDepthwiseConvolutionWorkloadTest(DataLayout dataLayout)
308 {
309  Graph graph;
310  ClWorkloadFactory factory =
311  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
312 
313  auto workload = CreateDepthwiseConvolution2dWorkloadTest<DepthwiseConvolutionWorkloadType, DataType>
314  (factory, graph, dataLayout);
315 
316  // Checks that inputs/outputs are as we expect them (see definition of CreateDepthwiseConvolution2dWorkloadTest).
317  DepthwiseConvolution2dQueueDescriptor queueDescriptor = workload->GetData();
318  auto inputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
319  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
320 
321  TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? std::initializer_list<unsigned int>({ 2, 2, 5, 5 })
322  : std::initializer_list<unsigned int>({ 2, 5, 5, 2 });
323  TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? std::initializer_list<unsigned int>({ 2, 2, 5, 5 })
324  : std::initializer_list<unsigned int>({ 2, 5, 5, 2 });
325 
326  BOOST_TEST((inputHandle->GetShape() == inputShape));
327  BOOST_TEST((outputHandle->GetShape() == outputShape));
328 }
329 
330 BOOST_AUTO_TEST_CASE(CreateDepthwiseConvolutionFloat32NhwcWorkload)
331 {
332  ClDepthwiseConvolutionWorkloadTest<ClDepthwiseConvolutionWorkload, DataType::Float32>(DataLayout::NHWC);
333 }
334 
335 template <typename Convolution2dWorkloadType, typename armnn::DataType DataType>
336 static void ClDirectConvolution2dWorkloadTest()
337 {
338  Graph graph;
339  ClWorkloadFactory factory =
340  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
341 
342  auto workload = CreateDirectConvolution2dWorkloadTest<ClConvolution2dWorkload, DataType>(factory, graph);
343 
344  // Checks that outputs and inputs are as we expect them (see definition of CreateDirectConvolution2dWorkloadTest).
345  Convolution2dQueueDescriptor queueDescriptor = workload->GetData();
346  auto inputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
347  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
348  BOOST_TEST(CompareIClTensorHandleShape(inputHandle, {2, 3, 6, 6}));
349  BOOST_TEST(CompareIClTensorHandleShape(outputHandle, {2, 2, 6, 6}));
350 }
351 
352 BOOST_AUTO_TEST_CASE(CreateDirectConvolution2dFloatWorkload)
353 {
354  ClDirectConvolution2dWorkloadTest<ClConvolution2dWorkload, armnn::DataType::Float32>();
355 }
356 
357 BOOST_AUTO_TEST_CASE(CreateDirectConvolution2dFloat16Workload)
358 {
359  ClDirectConvolution2dWorkloadTest<ClConvolution2dWorkload, armnn::DataType::Float16>();
360 }
361 
362 BOOST_AUTO_TEST_CASE(CreateDirectConvolution2dUint8Workload)
363 {
364  ClDirectConvolution2dWorkloadTest<ClConvolution2dWorkload, armnn::DataType::QAsymmU8>();
365 }
366 
367 template <typename FullyConnectedWorkloadType, typename armnn::DataType DataType>
368 static void ClCreateFullyConnectedWorkloadTest()
369 {
370  Graph graph;
371  ClWorkloadFactory factory =
372  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
373 
374  auto workload =
375  CreateFullyConnectedWorkloadTest<FullyConnectedWorkloadType, DataType>(factory, graph);
376 
377  // Checks that outputs and inputs are as we expect them (see definition of CreateFullyConnectedWorkloadTest).
378  FullyConnectedQueueDescriptor queueDescriptor = workload->GetData();
379  auto inputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
380  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
381  BOOST_TEST(CompareIClTensorHandleShape(inputHandle, {3, 1, 4, 5}));
382  BOOST_TEST(CompareIClTensorHandleShape(outputHandle, {3, 7}));
383 }
384 
385 
386 BOOST_AUTO_TEST_CASE(CreateFullyConnectedFloatWorkloadTest)
387 {
388  ClCreateFullyConnectedWorkloadTest<ClFullyConnectedWorkload, armnn::DataType::Float32>();
389 }
390 
391 BOOST_AUTO_TEST_CASE(CreateFullyConnectedFloat16WorkloadTest)
392 {
393  ClCreateFullyConnectedWorkloadTest<ClFullyConnectedWorkload, armnn::DataType::Float16>();
394 }
395 
396 template <typename NormalizationWorkloadType, typename armnn::DataType DataType>
397 static void ClNormalizationWorkloadTest(DataLayout dataLayout)
398 {
399  Graph graph;
400  ClWorkloadFactory factory =
401  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
402 
403  auto workload = CreateNormalizationWorkloadTest<NormalizationWorkloadType, DataType>(factory, graph, dataLayout);
404 
405  // Checks that inputs/outputs are as we expect them (see definition of CreateNormalizationWorkloadTest).
406  NormalizationQueueDescriptor queueDescriptor = workload->GetData();
407  auto inputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
408  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
409 
410  TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? std::initializer_list<unsigned int>({3, 5, 5, 1})
411  : std::initializer_list<unsigned int>({3, 1, 5, 5});
412  TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? std::initializer_list<unsigned int>({3, 5, 5, 1})
413  : std::initializer_list<unsigned int>({3, 1, 5, 5});
414 
415  BOOST_TEST((inputHandle->GetShape() == inputShape));
416  BOOST_TEST((outputHandle->GetShape() == outputShape));
417 }
418 
419 BOOST_AUTO_TEST_CASE(CreateNormalizationFloat32NchwWorkload)
420 {
421  ClNormalizationWorkloadTest<ClNormalizationFloatWorkload, armnn::DataType::Float32>(DataLayout::NCHW);
422 }
423 
424 BOOST_AUTO_TEST_CASE(CreateNormalizationFloat16NchwWorkload)
425 {
426  ClNormalizationWorkloadTest<ClNormalizationFloatWorkload, armnn::DataType::Float16>(DataLayout::NCHW);
427 }
428 
429 BOOST_AUTO_TEST_CASE(CreateNormalizationFloat32NhwcWorkload)
430 {
431  ClNormalizationWorkloadTest<ClNormalizationFloatWorkload, armnn::DataType::Float32>(DataLayout::NHWC);
432 }
433 
434 BOOST_AUTO_TEST_CASE(CreateNormalizationFloat16NhwcWorkload)
435 {
436  ClNormalizationWorkloadTest<ClNormalizationFloatWorkload, armnn::DataType::Float16>(DataLayout::NHWC);
437 }
438 
439 template <typename armnn::DataType DataType>
440 static void ClPooling2dWorkloadTest(DataLayout dataLayout)
441 {
442  Graph graph;
443  ClWorkloadFactory factory =
444  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
445 
446  auto workload = CreatePooling2dWorkloadTest<ClPooling2dWorkload, DataType>(factory, graph, dataLayout);
447 
448  TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? std::initializer_list<unsigned int>({3, 2, 5, 5})
449  : std::initializer_list<unsigned int>({3, 5, 5, 2});
450  TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? std::initializer_list<unsigned int>({3, 2, 2, 4})
451  : std::initializer_list<unsigned int>({3, 2, 4, 2});
452 
453  // Check that inputs/outputs are as we expect them (see definition of CreatePooling2dWorkloadTest).
454  Pooling2dQueueDescriptor queueDescriptor = workload->GetData();
455  auto inputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
456  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
457 
458  BOOST_TEST((inputHandle->GetShape() == inputShape));
459  BOOST_TEST((outputHandle->GetShape() == outputShape));
460 }
461 
462 BOOST_AUTO_TEST_CASE(CreatePooling2dFloatNchwWorkload)
463 {
464  ClPooling2dWorkloadTest<armnn::DataType::Float32>(DataLayout::NCHW);
465 }
466 
467 BOOST_AUTO_TEST_CASE(CreatePooling2dFloatNhwcWorkload)
468 {
469  ClPooling2dWorkloadTest<armnn::DataType::Float32>(DataLayout::NHWC);
470 }
471 
472 BOOST_AUTO_TEST_CASE(CreatePooling2dFloat16NchwWorkload)
473 {
474  ClPooling2dWorkloadTest<armnn::DataType::Float16>(DataLayout::NCHW);
475 }
476 
477 BOOST_AUTO_TEST_CASE(CreatePooling2dFloat16NhwcWorkload)
478 {
479  ClPooling2dWorkloadTest<armnn::DataType::Float16>(DataLayout::NHWC);
480 }
481 
482 static void ClCreatePreluWorkloadTest(const armnn::TensorShape& inputShape,
483  const armnn::TensorShape& alphaShape,
484  const armnn::TensorShape& outputShape,
485  armnn::DataType dataType)
486 {
487  Graph graph;
488  ClWorkloadFactory factory =
489  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
490 
491  auto workload = CreatePreluWorkloadTest<ClPreluWorkload>(factory,
492  graph,
493  inputShape,
494  alphaShape,
495  outputShape,
496  dataType);
497 
498  // Checks that outputs and inputs are as we expect them (see definition of CreatePreluWorkloadTest).
499  PreluQueueDescriptor queueDescriptor = workload->GetData();
500  auto inputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
501  auto alphaHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[1]);
502  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
503 
504  BOOST_TEST((inputHandle->GetShape() == inputShape));
505  BOOST_TEST((alphaHandle->GetShape() == alphaShape));
506  BOOST_TEST((outputHandle->GetShape() == outputShape));
507 }
508 
509 BOOST_AUTO_TEST_CASE(CreatePreluFloat16Workload)
510 {
511  ClCreatePreluWorkloadTest({ 1, 4, 1, 2 }, { 5, 4, 3, 1 }, { 5, 4, 3, 2 }, DataType::Float16);
512 }
513 
514 BOOST_AUTO_TEST_CASE(CreatePreluFloatWorkload)
515 {
516  ClCreatePreluWorkloadTest({ 1, 4, 1, 2 }, { 5, 4, 3, 1 }, { 5, 4, 3, 2 }, DataType::Float32);
517 }
518 
519 BOOST_AUTO_TEST_CASE(CreatePreluUint8Workload)
520 {
521  ClCreatePreluWorkloadTest({ 1, 4, 1, 2 }, { 5, 4, 3, 1 }, { 5, 4, 3, 2 }, DataType::QAsymmU8);
522 }
523 
524 template <typename armnn::DataType DataType>
525 static void ClCreateReshapeWorkloadTest()
526 {
527  Graph graph;
528  ClWorkloadFactory factory =
529  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
530 
531  auto workload = CreateReshapeWorkloadTest<ClReshapeWorkload, DataType>(factory, graph);
532 
533  // Checks that outputs and inputs are as we expect them (see definition of CreateReshapeWorkloadTest).
534  ReshapeQueueDescriptor queueDescriptor = workload->GetData();
535  auto inputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
536  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
537 
538  BOOST_TEST(CompareIClTensorHandleShape(inputHandle, {4, 1}));
539  BOOST_TEST(CompareIClTensorHandleShape(outputHandle, {1, 4}));
540 }
541 
542 BOOST_AUTO_TEST_CASE(CreateReshapeFloatWorkload)
543 {
544  ClCreateReshapeWorkloadTest<armnn::DataType::Float32>();
545 }
546 
547 BOOST_AUTO_TEST_CASE(CreateReshapeFloat16Workload)
548 {
549  ClCreateReshapeWorkloadTest<armnn::DataType::Float16>();
550 }
551 
552 BOOST_AUTO_TEST_CASE(CreateReshapeUint8Workload)
553 {
554  ClCreateReshapeWorkloadTest<armnn::DataType::QAsymmU8>();
555 }
556 
557 template <typename SoftmaxWorkloadType, typename armnn::DataType DataType>
558 static void ClSoftmaxWorkloadTest()
559 {
560  Graph graph;
561  ClWorkloadFactory factory =
562  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
563 
564  auto workload = CreateSoftmaxWorkloadTest<SoftmaxWorkloadType, DataType>(factory, graph);
565 
566  // Checks that inputs/outputs are as we expect them (see definition of ClSoftmaxFloatWorkload).
567  SoftmaxQueueDescriptor queueDescriptor = workload->GetData();
568  auto inputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
569  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
570 
571  BOOST_TEST(CompareIClTensorHandleShape(inputHandle, {4, 1}));
572  BOOST_TEST(CompareIClTensorHandleShape(outputHandle, {4, 1}));
573 }
574 
575 
576 BOOST_AUTO_TEST_CASE(CreateSoftmaxFloatWorkloadTest)
577 {
578  ClSoftmaxWorkloadTest<ClSoftmaxFloatWorkload, armnn::DataType::Float32>();
579 }
580 
581 BOOST_AUTO_TEST_CASE(CreateSoftmaxFloat16WorkloadTest)
582 {
583  ClSoftmaxWorkloadTest<ClSoftmaxFloatWorkload, armnn::DataType::Float16>();
584 }
585 
586 template <typename armnn::DataType DataType>
587 static void ClSplitterWorkloadTest()
588 {
589  Graph graph;
590  ClWorkloadFactory factory =
591  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
592 
593  auto workload = CreateSplitterWorkloadTest<ClSplitterWorkload, DataType>(factory, graph);
594 
595  // Checks that outputs are as we expect them (see definition of CreateSplitterWorkloadTest).
596  SplitterQueueDescriptor queueDescriptor = workload->GetData();
597  auto inputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
598  BOOST_TEST(CompareIClTensorHandleShape(inputHandle, {5, 7, 7}));
599 
600  auto outputHandle1 = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[1]);
601  BOOST_TEST(CompareIClTensorHandleShape(outputHandle1, {2, 7, 7}));
602 
603  auto outputHandle2 = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[2]);
604  BOOST_TEST(CompareIClTensorHandleShape(outputHandle2, {2, 7, 7}));
605 
606  auto outputHandle0 = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
607  BOOST_TEST(CompareIClTensorHandleShape(outputHandle0, {1, 7, 7}));
608 }
609 
610 BOOST_AUTO_TEST_CASE(CreateSplitterFloatWorkload)
611 {
612  ClSplitterWorkloadTest<armnn::DataType::Float32>();
613 }
614 
615 BOOST_AUTO_TEST_CASE(CreateSplitterFloat16Workload)
616 {
617  ClSplitterWorkloadTest<armnn::DataType::Float16>();
618 }
619 
620 template <typename armnn::DataType DataType>
621 static void ClSplitterConcatTest()
622 {
623  // Tests that it is possible to decide which output of the splitter layer
624  // should be lined to which input of the concat layer.
625  // We test that is is possible to specify 0th output
626  // of the splitter to be the 1st input to the concat and the 1st output of the splitter to be 0th input
627  // of the concat.
628 
629  Graph graph;
630  ClWorkloadFactory factory =
631  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
632 
633  auto workloads =
634  CreateSplitterConcatWorkloadTest<ClSplitterWorkload, ClConcatWorkload, DataType>
635  (factory, graph);
636 
637  auto wlSplitter = std::move(workloads.first);
638  auto wlConcat = std::move(workloads.second);
639 
640  //Checks that the index of inputs/outputs matches what we declared on InputDescriptor construction.
641  armnn::ClSubTensorHandle* sOut0 = dynamic_cast<armnn::ClSubTensorHandle*>(wlSplitter->GetData().m_Outputs[0]);
642  armnn::ClSubTensorHandle* sOut1 = dynamic_cast<armnn::ClSubTensorHandle*>(wlSplitter->GetData().m_Outputs[1]);
643  armnn::ClSubTensorHandle* mIn0 = dynamic_cast<armnn::ClSubTensorHandle*>(wlConcat->GetData().m_Inputs[0]);
644  armnn::ClSubTensorHandle* mIn1 = dynamic_cast<armnn::ClSubTensorHandle*>(wlConcat->GetData().m_Inputs[1]);
645 
646  BOOST_TEST(sOut0);
647  BOOST_TEST(sOut1);
648  BOOST_TEST(mIn0);
649  BOOST_TEST(mIn1);
650 
651  //Fliped order of inputs/outputs.
652  bool validDataPointers = (sOut0 == mIn1) && (sOut1 == mIn0);
653  BOOST_TEST(validDataPointers);
654 
655 
656  //Also make sure that the inputs are subtensors of one tensor and outputs are sub tensors of another tensor.
657  bool validSubTensorParents = (mIn0->GetTensor().parent() == mIn1->GetTensor().parent())
658  && (sOut0->GetTensor().parent() == sOut1->GetTensor().parent());
659 
660  BOOST_TEST(validSubTensorParents);
661 }
662 
663 BOOST_AUTO_TEST_CASE(CreateSplitterConcatFloatWorkload)
664 {
665  ClSplitterConcatTest<armnn::DataType::Float32>();
666 }
667 
668 BOOST_AUTO_TEST_CASE(CreateSplitterConcatFloat16Workload)
669 {
670  ClSplitterConcatTest<armnn::DataType::Float16>();
671 }
672 
673 
674 BOOST_AUTO_TEST_CASE(CreateSingleOutputMultipleInputs)
675 {
676  // Test that it is possible to assign multiple (two) different layers to each of the outputs of a splitter layer.
677  // We create a splitter with two outputs. That each of those outputs is used by two different activation layers.
678 
679  Graph graph;
680  ClWorkloadFactory factory =
681  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
682 
683  std::unique_ptr<ClSplitterWorkload> wlSplitter;
684  std::unique_ptr<ClActivationWorkload> wlActiv0_0;
685  std::unique_ptr<ClActivationWorkload> wlActiv0_1;
686  std::unique_ptr<ClActivationWorkload> wlActiv1_0;
687  std::unique_ptr<ClActivationWorkload> wlActiv1_1;
688 
689  CreateSplitterMultipleInputsOneOutputWorkloadTest<ClSplitterWorkload,
690  ClActivationWorkload, armnn::DataType::Float32>(factory, graph, wlSplitter, wlActiv0_0, wlActiv0_1,
691  wlActiv1_0, wlActiv1_1);
692 
693  //Checks that the index of inputs/outputs matches what we declared on InputDescriptor construction.
694  armnn::ClSubTensorHandle* sOut0 = dynamic_cast<armnn::ClSubTensorHandle*>(wlSplitter->GetData().m_Outputs[0]);
695  armnn::ClSubTensorHandle* sOut1 = dynamic_cast<armnn::ClSubTensorHandle*>(wlSplitter->GetData().m_Outputs[1]);
696  armnn::ClSubTensorHandle* activ0_0Im = dynamic_cast<armnn::ClSubTensorHandle*>(wlActiv0_0->GetData().m_Inputs[0]);
697  armnn::ClSubTensorHandle* activ0_1Im = dynamic_cast<armnn::ClSubTensorHandle*>(wlActiv0_1->GetData().m_Inputs[0]);
698  armnn::ClSubTensorHandle* activ1_0Im = dynamic_cast<armnn::ClSubTensorHandle*>(wlActiv1_0->GetData().m_Inputs[0]);
699  armnn::ClSubTensorHandle* activ1_1Im = dynamic_cast<armnn::ClSubTensorHandle*>(wlActiv1_1->GetData().m_Inputs[0]);
700 
701 
702  BOOST_TEST(sOut0);
703  BOOST_TEST(sOut1);
704  BOOST_TEST(activ0_0Im);
705  BOOST_TEST(activ0_1Im);
706  BOOST_TEST(activ1_0Im);
707  BOOST_TEST(activ1_1Im);
708 
709  bool validDataPointers = (sOut0 == activ0_0Im) && (sOut0 == activ0_1Im) &&
710  (sOut1 == activ1_0Im) && (sOut1 == activ1_1Im);
711 
712  BOOST_TEST(validDataPointers);
713 }
714 
715 #if defined(ARMNNREF_ENABLED)
716 
717 // This test unit needs the reference backend, it's not available if the reference backend is not built
718 
719 BOOST_AUTO_TEST_CASE(CreateMemCopyWorkloadsCl)
720 {
721  ClWorkloadFactory factory =
722  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
723 
724  CreateMemCopyWorkloads<IClTensorHandle>(factory);
725 }
726 
727 #endif
728 
729 template <typename L2NormalizationWorkloadType, typename armnn::DataType DataType>
730 static void ClL2NormalizationWorkloadTest(DataLayout dataLayout)
731 {
732  Graph graph;
733  ClWorkloadFactory factory =
734  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
735 
736  auto workload =
737  CreateL2NormalizationWorkloadTest<L2NormalizationWorkloadType, DataType>(factory, graph, dataLayout);
738 
739  // Checks that inputs/outputs are as we expect them (see definition of CreateNormalizationWorkloadTest).
740  L2NormalizationQueueDescriptor queueDescriptor = workload->GetData();
741  auto inputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
742  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
743 
744  TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? std::initializer_list<unsigned int>({ 5, 20, 50, 67 })
745  : std::initializer_list<unsigned int>({ 5, 50, 67, 20 });
746  TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? std::initializer_list<unsigned int>({ 5, 20, 50, 67 })
747  : std::initializer_list<unsigned int>({ 5, 50, 67, 20 });
748 
749  BOOST_TEST((inputHandle->GetShape() == inputShape));
750  BOOST_TEST((outputHandle->GetShape() == outputShape));
751 }
752 
753 BOOST_AUTO_TEST_CASE(CreateL2NormalizationFloatNchwWorkload)
754 {
755  ClL2NormalizationWorkloadTest<ClL2NormalizationFloatWorkload, armnn::DataType::Float32>(DataLayout::NCHW);
756 }
757 
758 BOOST_AUTO_TEST_CASE(CreateL2NormalizationFloatNhwcWorkload)
759 {
760  ClL2NormalizationWorkloadTest<ClL2NormalizationFloatWorkload, armnn::DataType::Float32>(DataLayout::NHWC);
761 }
762 
763 BOOST_AUTO_TEST_CASE(CreateL2NormalizationFloat16NchwWorkload)
764 {
765  ClL2NormalizationWorkloadTest<ClL2NormalizationFloatWorkload, armnn::DataType::Float16>(DataLayout::NCHW);
766 }
767 
768 BOOST_AUTO_TEST_CASE(CreateL2NormalizationFloat16NhwcWorkload)
769 {
770  ClL2NormalizationWorkloadTest<ClL2NormalizationFloatWorkload, armnn::DataType::Float16>(DataLayout::NHWC);
771 }
772 
773 template <typename LstmWorkloadType>
774 static void ClCreateLstmWorkloadTest()
775 {
776  Graph graph;
777  ClWorkloadFactory factory =
778  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
779 
780  auto workload = CreateLstmWorkloadTest<LstmWorkloadType>(factory, graph);
781 
782  LstmQueueDescriptor queueDescriptor = workload->GetData();
783  auto inputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
784  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[1]);
785  BOOST_TEST(CompareIClTensorHandleShape(inputHandle, { 2, 2 }));
786  BOOST_TEST(CompareIClTensorHandleShape(outputHandle, { 2, 4 }));
787 }
788 
789 BOOST_AUTO_TEST_CASE(CreateLSTMWorkloadFloatWorkload)
790 {
791  ClCreateLstmWorkloadTest<ClLstmFloatWorkload>();
792 }
793 
794 template <typename ResizeWorkloadType, typename armnn::DataType DataType>
795 static void ClResizeWorkloadTest(DataLayout dataLayout)
796 {
797  Graph graph;
798  ClWorkloadFactory factory =
799  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
800 
801  auto workload = CreateResizeBilinearWorkloadTest<ResizeWorkloadType, DataType>(factory, graph, dataLayout);
802 
803  auto queueDescriptor = workload->GetData();
804 
805  auto inputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
806  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
807 
808  switch (dataLayout)
809  {
810  case DataLayout::NHWC:
811  BOOST_TEST(CompareIClTensorHandleShape(inputHandle, { 2, 4, 4, 3 }));
812  BOOST_TEST(CompareIClTensorHandleShape(outputHandle, { 2, 2, 2, 3 }));
813  break;
814  case DataLayout::NCHW:
815  default:
816  BOOST_TEST(CompareIClTensorHandleShape(inputHandle, { 2, 3, 4, 4 }));
817  BOOST_TEST(CompareIClTensorHandleShape(outputHandle, { 2, 3, 2, 2 }));
818  }
819 }
820 
821 BOOST_AUTO_TEST_CASE(CreateResizeFloat32NchwWorkload)
822 {
823  ClResizeWorkloadTest<ClResizeWorkload, armnn::DataType::Float32>(DataLayout::NCHW);
824 }
825 
826 BOOST_AUTO_TEST_CASE(CreateResizeFloat16NchwWorkload)
827 {
828  ClResizeWorkloadTest<ClResizeWorkload, armnn::DataType::Float16>(DataLayout::NCHW);
829 }
830 
831 BOOST_AUTO_TEST_CASE(CreateResizeUint8NchwWorkload)
832 {
833  ClResizeWorkloadTest<ClResizeWorkload, armnn::DataType::QAsymmU8>(DataLayout::NCHW);
834 }
835 
836 BOOST_AUTO_TEST_CASE(CreateResizeFloat32NhwcWorkload)
837 {
838  ClResizeWorkloadTest<ClResizeWorkload, armnn::DataType::Float32>(DataLayout::NHWC);
839 }
840 
841 BOOST_AUTO_TEST_CASE(CreateResizeFloat16NhwcWorkload)
842 {
843  ClResizeWorkloadTest<ClResizeWorkload, armnn::DataType::Float16>(DataLayout::NHWC);
844 }
845 
846 BOOST_AUTO_TEST_CASE(CreateResizeUint8NhwcWorkload)
847 {
848  ClResizeWorkloadTest<ClResizeWorkload, armnn::DataType::QAsymmU8>(DataLayout::NHWC);
849 }
850 
851 template <typename MeanWorkloadType, typename armnn::DataType DataType>
852 static void ClMeanWorkloadTest()
853 {
854  Graph graph;
855  ClWorkloadFactory factory =
856  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
857 
858  auto workload = CreateMeanWorkloadTest<MeanWorkloadType, DataType>(factory, graph);
859 
860  // Checks that inputs/outputs are as we expect them (see definition of CreateMeanWorkloadTest).
861  MeanQueueDescriptor queueDescriptor = workload->GetData();
862  auto inputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
863  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
864 
865  // The first dimension (batch size) in both input and output is singular thus it has been reduced by ACL.
866  BOOST_TEST(CompareIClTensorHandleShape(inputHandle, { 1, 3, 7, 4 }));
867  BOOST_TEST(CompareIClTensorHandleShape(outputHandle, { 1, 4 }));
868 }
869 
870 BOOST_AUTO_TEST_CASE(CreateMeanFloat32Workload)
871 {
872  ClMeanWorkloadTest<ClMeanWorkload, armnn::DataType::Float32>();
873 }
874 
875 BOOST_AUTO_TEST_CASE(CreateMeanFloat16Workload)
876 {
877  ClMeanWorkloadTest<ClMeanWorkload, armnn::DataType::Float16>();
878 }
879 
880 BOOST_AUTO_TEST_CASE(CreateMeanUint8Workload)
881 {
882  ClMeanWorkloadTest<ClMeanWorkload, armnn::DataType::QAsymmU8>();
883 }
884 
885 template <typename ConcatWorkloadType, armnn::DataType DataType>
886 static void ClCreateConcatWorkloadTest(std::initializer_list<unsigned int> outputShape,
887  unsigned int concatAxis)
888 {
889  Graph graph;
890  ClWorkloadFactory factory =
891  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
892 
893  auto workload = CreateConcatWorkloadTest<ConcatWorkloadType, DataType>(factory, graph, outputShape, concatAxis);
894 
895  ConcatQueueDescriptor queueDescriptor = workload->GetData();
896  auto inputHandle0 = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
897  auto inputHandle1 = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[1]);
898  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
899 
900  BOOST_TEST(CompareIClTensorHandleShape(inputHandle0, { 2, 3, 2, 5 }));
901  BOOST_TEST(CompareIClTensorHandleShape(inputHandle1, { 2, 3, 2, 5 }));
902  BOOST_TEST(CompareIClTensorHandleShape(outputHandle, outputShape));
903 }
904 
905 BOOST_AUTO_TEST_CASE(CreateConcatDim0Float32Workload)
906 {
907  ClCreateConcatWorkloadTest<ClConcatWorkload, armnn::DataType::Float32>({ 4, 3, 2, 5 }, 0);
908 }
909 
910 BOOST_AUTO_TEST_CASE(CreateConcatDim1Float32Workload)
911 {
912  ClCreateConcatWorkloadTest<ClConcatWorkload, armnn::DataType::Float32>({ 2, 6, 2, 5 }, 1);
913 }
914 
915 BOOST_AUTO_TEST_CASE(CreateConcatDim3Float32Workload)
916 {
917  ClCreateConcatWorkloadTest<ClConcatWorkload, armnn::DataType::Float32>({ 2, 3, 2, 10 }, 3);
918 }
919 
920 BOOST_AUTO_TEST_CASE(CreateConcatDim0Uint8Workload)
921 {
922  ClCreateConcatWorkloadTest<ClConcatWorkload, armnn::DataType::QAsymmU8>({ 4, 3, 2, 5 }, 0);
923 }
924 
925 BOOST_AUTO_TEST_CASE(CreateConcatDim1Uint8Workload)
926 {
927  ClCreateConcatWorkloadTest<ClConcatWorkload, armnn::DataType::QAsymmU8>({ 2, 6, 2, 5 }, 1);
928 }
929 
930 BOOST_AUTO_TEST_CASE(CreateConcatDim3Uint8Workload)
931 {
932  ClCreateConcatWorkloadTest<ClConcatWorkload, armnn::DataType::QAsymmU8>({ 2, 3, 2, 10 }, 3);
933 }
934 
935 template <typename SpaceToDepthWorkloadType, typename armnn::DataType DataType>
936 static void ClSpaceToDepthWorkloadTest()
937 {
938  Graph graph;
939  ClWorkloadFactory factory =
940  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
941 
942  auto workload = CreateSpaceToDepthWorkloadTest<SpaceToDepthWorkloadType, DataType>(factory, graph);
943 
944  SpaceToDepthQueueDescriptor queueDescriptor = workload->GetData();
945  auto inputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[0]);
946  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
947 
948  BOOST_TEST(CompareIClTensorHandleShape(inputHandle, { 1, 2, 2, 1 }));
949  BOOST_TEST(CompareIClTensorHandleShape(outputHandle, { 1, 1, 1, 4 }));
950 }
951 
952 BOOST_AUTO_TEST_CASE(CreateSpaceToDepthFloat32Workload)
953 {
954  ClSpaceToDepthWorkloadTest<ClSpaceToDepthWorkload, armnn::DataType::Float32>();
955 }
956 
957 BOOST_AUTO_TEST_CASE(CreateSpaceToDepthFloat16Workload)
958 {
959  ClSpaceToDepthWorkloadTest<ClSpaceToDepthWorkload, armnn::DataType::Float16>();
960 }
961 
962 BOOST_AUTO_TEST_CASE(CreateSpaceToDepthQAsymm8Workload)
963 {
964  ClSpaceToDepthWorkloadTest<ClSpaceToDepthWorkload, armnn::DataType::QAsymmU8>();
965 }
966 
967 BOOST_AUTO_TEST_CASE(CreateSpaceToDepthQSymm16Workload)
968 {
969  ClSpaceToDepthWorkloadTest<ClSpaceToDepthWorkload, armnn::DataType::QSymmS16>();
970 }
971 
972 template <armnn::DataType DataType>
973 static void ClCreateStackWorkloadTest(const std::initializer_list<unsigned int>& inputShape,
974  const std::initializer_list<unsigned int>& outputShape,
975  unsigned int axis,
976  unsigned int numInputs)
977 {
978  armnn::Graph graph;
979  ClWorkloadFactory factory =
980  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
981 
982  auto workload = CreateStackWorkloadTest<ClStackWorkload, DataType>(factory,
983  graph,
984  TensorShape(inputShape),
985  TensorShape(outputShape),
986  axis,
987  numInputs);
988 
989  // Check inputs and output are as expected
990  StackQueueDescriptor queueDescriptor = workload->GetData();
991  for (unsigned int i = 0; i < numInputs; ++i)
992  {
993  auto inputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Inputs[i]);
994  BOOST_TEST(CompareIClTensorHandleShape(inputHandle, inputShape));
995  }
996  auto outputHandle = boost::polymorphic_downcast<IClTensorHandle*>(queueDescriptor.m_Outputs[0]);
997  BOOST_TEST(CompareIClTensorHandleShape(outputHandle, outputShape));
998 }
999 
1000 BOOST_AUTO_TEST_CASE(CreateStackFloat32Workload)
1001 {
1002  ClCreateStackWorkloadTest<armnn::DataType::Float32>({ 3, 4, 5 }, { 3, 4, 2, 5 }, 2, 2);
1003 }
1004 
1005 BOOST_AUTO_TEST_CASE(CreateStackFloat16Workload)
1006 {
1007  ClCreateStackWorkloadTest<armnn::DataType::Float16>({ 3, 4, 5 }, { 3, 4, 2, 5 }, 2, 2);
1008 }
1009 
1010 BOOST_AUTO_TEST_CASE(CreateStackUint8Workload)
1011 {
1012  ClCreateStackWorkloadTest<armnn::DataType::QAsymmU8>({ 3, 4, 5 }, { 3, 4, 2, 5 }, 2, 2);
1013 }
1014 
1015 template <typename QuantizedLstmWorkloadType>
1016 static void ClCreateQuantizedLstmWorkloadTest()
1017 {
1018  using namespace armnn::armcomputetensorutils;
1020 
1021  Graph graph;
1022  ClWorkloadFactory factory =
1023  ClWorkloadFactoryHelper::GetFactory(ClWorkloadFactoryHelper::GetMemoryManager());
1024 
1025  auto workload = CreateQuantizedLstmWorkloadTest<QuantizedLstmWorkloadType>(factory, graph);
1026 
1027  QuantizedLstmQueueDescriptor queueDescriptor = workload->GetData();
1028 
1029  IAclTensorHandle* inputHandle = polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[0]);
1030  BOOST_TEST((inputHandle->GetShape() == TensorShape({2, 2})));
1031  BOOST_TEST((inputHandle->GetDataType() == arm_compute::DataType::QASYMM8));
1032 
1033  IAclTensorHandle* cellStateInHandle = polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[1]);
1034  BOOST_TEST((cellStateInHandle->GetShape() == TensorShape({2, 4})));
1035  BOOST_TEST((cellStateInHandle->GetDataType() == arm_compute::DataType::QSYMM16));
1036 
1037  IAclTensorHandle* outputStateInHandle = polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[2]);
1038  BOOST_TEST((outputStateInHandle->GetShape() == TensorShape({2, 4})));
1039  BOOST_TEST((outputStateInHandle->GetDataType() == arm_compute::DataType::QASYMM8));
1040 
1041  IAclTensorHandle* cellStateOutHandle = polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[0]);
1042  BOOST_TEST((cellStateOutHandle->GetShape() == TensorShape({2, 4})));
1043  BOOST_TEST((cellStateOutHandle->GetDataType() == arm_compute::DataType::QSYMM16));
1044 
1045  IAclTensorHandle* outputStateOutHandle = polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[1]);
1046  BOOST_TEST((outputStateOutHandle->GetShape() == TensorShape({2, 4})));
1047  BOOST_TEST((outputStateOutHandle->GetDataType() == arm_compute::DataType::QASYMM8));
1048 }
1049 
1050 BOOST_AUTO_TEST_CASE(CreateQuantizedLstmWorkload)
1051 {
1052  ClCreateQuantizedLstmWorkloadTest<ClQuantizedLstmWorkload>();
1053 }
1054 
DestType polymorphic_downcast(SourceType value)
DataLayout
Definition: Types.hpp:49
BOOST_AUTO_TEST_CASE(CreateActivationFloatWorkload)
virtual arm_compute::DataType GetDataType() const =0
DataType
Definition: Types.hpp:32
BOOST_AUTO_TEST_CASE(CheckConvolution2dLayer)
virtual TensorShape GetShape() const =0
Get the number of elements for each dimension ordered from slowest iterating dimension to fastest ite...
This layer represents an addition operation.
BOOST_AUTO_TEST_SUITE_END()
This layer represents a subtraction operation.
std::vector< ITensorHandle * > m_Outputs
boost::test_tools::predicate_result CompareIClTensorHandleShape(IClTensorHandle *tensorHandle, std::initializer_list< unsigned int > expectedDimensions)
This layer represents a division operation.
UnaryOperation
Definition: Types.hpp:87
std::vector< ITensorHandle * > m_Inputs
This layer represents a multiplication operation.
arm_compute::CLSubTensor & GetTensor() override