2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
6 #include <backendsCommon/MemCopyWorkload.hpp>
8 #include <aclCommon/test/CreateWorkloadClNeon.hpp>
10 #include <neon/NeonWorkloadFactory.hpp>
11 #include <neon/NeonTensorHandle.hpp>
12 #include <neon/workloads/NeonWorkloadUtils.hpp>
13 #include <neon/workloads/NeonWorkloads.hpp>
15 BOOST_AUTO_TEST_SUITE(CreateWorkloadNeon)
20 bool TestNeonTensorHandleInfo(armnn::INeonTensorHandle* handle, const armnn::TensorInfo& expectedInfo)
22 using namespace armnn::armcomputetensorutils;
24 const arm_compute::ITensorInfo* handleInfo = handle->GetTensor().info();
25 const arm_compute::TensorInfo expectedAclInfo = BuildArmComputeTensorInfo(expectedInfo);
27 if (handleInfo->data_type() != expectedAclInfo.data_type())
32 if (handleInfo->num_dimensions() != expectedAclInfo.num_dimensions())
37 if (handleInfo->quantization_info() != expectedAclInfo.quantization_info())
42 for (std::size_t d = 0; d < expectedAclInfo.num_dimensions(); ++d)
44 if (handleInfo->dimension(d) != expectedAclInfo.dimension(d))
55 template <typename armnn::DataType DataType>
56 static void NeonCreateActivationWorkloadTest()
59 NeonWorkloadFactory factory;
60 auto workload = CreateActivationWorkloadTest<NeonActivationWorkload, DataType>(factory, graph);
62 // Checks that inputs/outputs are as we expect them (see definition of CreateActivationWorkloadTest).
63 ActivationQueueDescriptor queueDescriptor = workload->GetData();
64 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
65 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
66 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({1, 1}, DataType)));
67 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({1, 1}, DataType)));
70 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
71 BOOST_AUTO_TEST_CASE(CreateActivationFloat16Workload)
73 NeonCreateActivationWorkloadTest<DataType::Float16>();
77 BOOST_AUTO_TEST_CASE(CreateActivationFloatWorkload)
79 NeonCreateActivationWorkloadTest<DataType::Float32>();
82 template <typename WorkloadType,
83 typename DescriptorType,
85 armnn::DataType DataType>
86 static void NeonCreateArithmethicWorkloadTest()
89 NeonWorkloadFactory factory;
90 auto workload = CreateArithmeticWorkloadTest<WorkloadType, DescriptorType, LayerType, DataType>(factory, graph);
92 DescriptorType queueDescriptor = workload->GetData();
93 auto inputHandle1 = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
94 auto inputHandle2 = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[1]);
95 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
96 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle1, TensorInfo({2, 3}, DataType)));
97 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle2, TensorInfo({2, 3}, DataType)));
98 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({2, 3}, DataType)));
101 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
102 BOOST_AUTO_TEST_CASE(CreateAdditionFloat16Workload)
104 NeonCreateArithmethicWorkloadTest<NeonAdditionFloatWorkload,
105 AdditionQueueDescriptor,
107 DataType::Float16>();
111 BOOST_AUTO_TEST_CASE(CreateAdditionFloatWorkload)
113 NeonCreateArithmethicWorkloadTest<NeonAdditionFloatWorkload,
114 AdditionQueueDescriptor,
116 DataType::Float32>();
119 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
120 BOOST_AUTO_TEST_CASE(CreateSubtractionFloat16Workload)
122 NeonCreateArithmethicWorkloadTest<NeonSubtractionFloatWorkload,
123 SubtractionQueueDescriptor,
125 DataType::Float16>();
129 BOOST_AUTO_TEST_CASE(CreateSubtractionFloatWorkload)
131 NeonCreateArithmethicWorkloadTest<NeonSubtractionFloatWorkload,
132 SubtractionQueueDescriptor,
134 DataType::Float32>();
137 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
138 BOOST_AUTO_TEST_CASE(CreateMultiplicationFloat16Workload)
140 NeonCreateArithmethicWorkloadTest<NeonMultiplicationFloatWorkload,
141 MultiplicationQueueDescriptor,
143 DataType::Float16>();
147 BOOST_AUTO_TEST_CASE(CreateMultiplicationFloatWorkload)
149 NeonCreateArithmethicWorkloadTest<NeonMultiplicationFloatWorkload,
150 MultiplicationQueueDescriptor,
152 DataType::Float32>();
155 template <typename BatchNormalizationWorkloadType, typename armnn::DataType DataType>
156 static void NeonCreateBatchNormalizationWorkloadTest(DataLayout dataLayout)
159 NeonWorkloadFactory factory;
160 auto workload = CreateBatchNormalizationWorkloadTest<BatchNormalizationWorkloadType, DataType>
161 (factory, graph, dataLayout);
163 // Checks that outputs and inputs are as we expect them (see definition of CreateBatchNormalizationWorkloadTest).
164 BatchNormalizationQueueDescriptor queueDescriptor = workload->GetData();
165 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
166 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
168 TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{2, 3, 4, 4} : TensorShape{2, 4, 4, 3};
169 TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{2, 3, 4, 4} : TensorShape{2, 4, 4, 3};
171 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo(inputShape, DataType)));
172 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, DataType)));
175 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
176 BOOST_AUTO_TEST_CASE(CreateBatchNormalizationFloat16NchwWorkload)
178 NeonCreateBatchNormalizationWorkloadTest<NeonBatchNormalizationFloatWorkload, DataType::Float16>(DataLayout::NCHW);
181 BOOST_AUTO_TEST_CASE(CreateBatchNormalizationFloat16NhwcWorkload)
183 NeonCreateBatchNormalizationWorkloadTest<NeonBatchNormalizationFloatWorkload, DataType::Float16>(DataLayout::NHWC);
187 BOOST_AUTO_TEST_CASE(CreateBatchNormalizationFloatNchwWorkload)
189 NeonCreateBatchNormalizationWorkloadTest<NeonBatchNormalizationFloatWorkload, DataType::Float32>(DataLayout::NCHW);
192 BOOST_AUTO_TEST_CASE(CreateBatchNormalizationFloatNhwcWorkload)
194 NeonCreateBatchNormalizationWorkloadTest<NeonBatchNormalizationFloatWorkload, DataType::Float32>(DataLayout::NHWC);
197 template <typename armnn::DataType DataType>
198 static void NeonCreateConvolution2dWorkloadTest(DataLayout dataLayout = DataLayout::NCHW)
201 NeonWorkloadFactory factory;
202 auto workload = CreateConvolution2dWorkloadTest<NeonConvolution2dWorkload,
203 DataType>(factory, graph, dataLayout);
205 TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{2, 3, 8, 16} : TensorShape{2, 8, 16, 3};
206 TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{2, 2, 2, 10} : TensorShape{2, 2, 10, 2};
208 // Checks that outputs and inputs are as we expect them (see definition of CreateConvolution2dWorkloadTest).
209 Convolution2dQueueDescriptor queueDescriptor = workload->GetData();
210 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
211 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
212 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo(inputShape, DataType)));
213 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, DataType)));
216 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
217 BOOST_AUTO_TEST_CASE(CreateConvolution2dFloat16NchwWorkload)
219 NeonCreateConvolution2dWorkloadTest<DataType::Float16>();
222 BOOST_AUTO_TEST_CASE(CreateConvolution2dFloat16NhwcWorkload)
224 NeonCreateConvolution2dWorkloadTest<DataType::Float16>(DataLayout::NHWC);
228 BOOST_AUTO_TEST_CASE(CreateConvolution2dFloatNchwWorkload)
230 NeonCreateConvolution2dWorkloadTest<DataType::Float32>();
233 BOOST_AUTO_TEST_CASE(CreateConvolution2dFloatNhwcWorkload)
235 NeonCreateConvolution2dWorkloadTest<DataType::Float32>(DataLayout::NHWC);
238 template <typename armnn::DataType DataType>
239 static void NeonCreateDepthWiseConvolutionWorkloadTest(DataLayout dataLayout)
242 NeonWorkloadFactory factory;
244 auto workload = CreateDepthwiseConvolution2dWorkloadTest<NeonDepthwiseConvolutionWorkload,
245 DataType>(factory, graph, dataLayout);
247 // Checks that inputs/outputs are as we expect them (see definition of CreateNormalizationWorkloadTest).
248 DepthwiseConvolution2dQueueDescriptor queueDescriptor = workload->GetData();
249 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
250 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
252 std::initializer_list<unsigned int> inputShape = (dataLayout == DataLayout::NCHW)
253 ? std::initializer_list<unsigned int>({ 2, 2, 5, 5 })
254 : std::initializer_list<unsigned int>({ 2, 5, 5, 2 });
255 std::initializer_list<unsigned int> outputShape = (dataLayout == DataLayout::NCHW)
256 ? std::initializer_list<unsigned int>({ 2, 2, 5, 5 })
257 : std::initializer_list<unsigned int>({ 2, 5, 5, 2 });
259 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo(inputShape, DataType)));
260 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, DataType)));
263 BOOST_AUTO_TEST_CASE(CreateDepthWiseConvolution2dFloat32NhwcWorkload)
265 NeonCreateDepthWiseConvolutionWorkloadTest<DataType::Float32>(DataLayout::NHWC);
268 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
269 BOOST_AUTO_TEST_CASE(CreateDepthWiseConvolution2dFloat16NhwcWorkload)
271 NeonCreateDepthWiseConvolutionWorkloadTest<DataType::Float16>(DataLayout::NHWC);
275 template <typename FullyConnectedWorkloadType, typename armnn::DataType DataType>
276 static void NeonCreateFullyConnectedWorkloadTest()
279 NeonWorkloadFactory factory;
280 auto workload = CreateFullyConnectedWorkloadTest<FullyConnectedWorkloadType,
281 DataType>(factory, graph);
283 // Checks that outputs and inputs are as we expect them (see definition of CreateFullyConnectedWorkloadTest).
284 FullyConnectedQueueDescriptor queueDescriptor = workload->GetData();
285 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
286 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
287 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({3, 1, 4, 5}, DataType)));
288 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({3, 7}, DataType)));
291 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
292 BOOST_AUTO_TEST_CASE(CreateFullyConnectedFloat16Workload)
294 NeonCreateFullyConnectedWorkloadTest<NeonFullyConnectedWorkload, DataType::Float16>();
298 BOOST_AUTO_TEST_CASE(CreateFullyConnectedFloatWorkload)
300 NeonCreateFullyConnectedWorkloadTest<NeonFullyConnectedWorkload, DataType::Float32>();
303 template <typename NormalizationWorkloadType, typename armnn::DataType DataType>
304 static void NeonCreateNormalizationWorkloadTest(DataLayout dataLayout)
307 NeonWorkloadFactory factory;
308 auto workload = CreateNormalizationWorkloadTest<NormalizationWorkloadType, DataType>(factory, graph, dataLayout);
310 // Checks that outputs and inputs are as we expect them (see definition of CreateNormalizationWorkloadTest).
311 NormalizationQueueDescriptor queueDescriptor = workload->GetData();
312 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
313 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
315 TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{3, 5, 5, 1} : TensorShape{3, 1, 5, 5};
316 TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{3, 5, 5, 1} : TensorShape{3, 1, 5, 5};
318 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo(inputShape, DataType)));
319 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, DataType)));
322 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
323 BOOST_AUTO_TEST_CASE(CreateNormalizationFloat16NchwWorkload)
325 NeonCreateNormalizationWorkloadTest<NeonNormalizationFloatWorkload, DataType::Float16>(DataLayout::NCHW);
328 BOOST_AUTO_TEST_CASE(CreateNormalizationFloat16NhwcWorkload)
330 NeonCreateNormalizationWorkloadTest<NeonNormalizationFloatWorkload, DataType::Float16>(DataLayout::NHWC);
334 BOOST_AUTO_TEST_CASE(CreateNormalizationFloatNchwWorkload)
336 NeonCreateNormalizationWorkloadTest<NeonNormalizationFloatWorkload, DataType::Float32>(DataLayout::NCHW);
339 BOOST_AUTO_TEST_CASE(CreateNormalizationFloatNhwcWorkload)
341 NeonCreateNormalizationWorkloadTest<NeonNormalizationFloatWorkload, DataType::Float32>(DataLayout::NHWC);
345 template <typename armnn::DataType DataType>
346 static void NeonCreatePooling2dWorkloadTest(DataLayout dataLayout = DataLayout::NCHW)
349 NeonWorkloadFactory factory;
350 auto workload = CreatePooling2dWorkloadTest<NeonPooling2dWorkload, DataType>
351 (factory, graph, dataLayout);
353 TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{3, 2, 5, 5} : TensorShape{3, 5, 5, 2};
354 TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{3, 2, 2, 4} : TensorShape{3, 2, 4, 2};
356 // Checks that outputs and inputs are as we expect them (see definition of CreatePooling2dWorkloadTest).
357 Pooling2dQueueDescriptor queueDescriptor = workload->GetData();
358 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
359 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
360 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo(inputShape, DataType)));
361 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, DataType)));
364 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
365 BOOST_AUTO_TEST_CASE(CreatePooling2dFloat16Workload)
367 NeonCreatePooling2dWorkloadTest<DataType::Float16>();
371 BOOST_AUTO_TEST_CASE(CreatePooling2dFloatNchwWorkload)
373 NeonCreatePooling2dWorkloadTest<DataType::Float32>(DataLayout::NCHW);
376 BOOST_AUTO_TEST_CASE(CreatePooling2dFloatNhwcWorkload)
378 NeonCreatePooling2dWorkloadTest<DataType::Float32>(DataLayout::NHWC);
381 BOOST_AUTO_TEST_CASE(CreatePooling2dUint8NchwWorkload)
383 NeonCreatePooling2dWorkloadTest<DataType::QuantisedAsymm8>(DataLayout::NCHW);
386 BOOST_AUTO_TEST_CASE(CreatePooling2dUint8NhwcWorkload)
388 NeonCreatePooling2dWorkloadTest<DataType::QuantisedAsymm8>(DataLayout::NHWC);
391 template <typename armnn::DataType DataType>
392 static void NeonCreateReshapeWorkloadTest()
395 NeonWorkloadFactory factory;
396 auto workload = CreateReshapeWorkloadTest<NeonReshapeWorkload, DataType>(factory, graph);
398 // Checks that outputs and inputs are as we expect them (see definition of CreateReshapeWorkloadTest).
399 ReshapeQueueDescriptor queueDescriptor = workload->GetData();
400 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
401 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
402 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({4, 1}, DataType)));
403 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({1, 4}, DataType)));
406 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
407 BOOST_AUTO_TEST_CASE(CreateReshapeFloat16Workload)
409 NeonCreateReshapeWorkloadTest<DataType::Float16>();
413 BOOST_AUTO_TEST_CASE(CreateReshapeFloatWorkload)
415 NeonCreateReshapeWorkloadTest<DataType::Float32>();
418 BOOST_AUTO_TEST_CASE(CreateReshapeUint8Workload)
420 NeonCreateReshapeWorkloadTest<DataType::QuantisedAsymm8>();
423 template <typename SoftmaxWorkloadType, typename armnn::DataType DataType>
424 static void NeonCreateSoftmaxWorkloadTest()
427 NeonWorkloadFactory factory;
428 auto workload = CreateSoftmaxWorkloadTest<SoftmaxWorkloadType, DataType>(factory, graph);
430 // Checks that outputs and inputs are as we expect them (see definition of CreateSoftmaxWorkloadTest).
431 SoftmaxQueueDescriptor queueDescriptor = workload->GetData();
432 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
433 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
434 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({4, 1}, DataType)));
435 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({4, 1}, DataType)));
438 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
439 BOOST_AUTO_TEST_CASE(CreateSoftmaxFloat16Workload)
441 NeonCreateSoftmaxWorkloadTest<NeonSoftmaxFloatWorkload, DataType::Float16>();
445 BOOST_AUTO_TEST_CASE(CreateSoftmaxFloatWorkload)
447 NeonCreateSoftmaxWorkloadTest<NeonSoftmaxFloatWorkload, DataType::Float32>();
450 BOOST_AUTO_TEST_CASE(CreateSplitterWorkload)
453 NeonWorkloadFactory factory;
454 auto workload = CreateSplitterWorkloadTest<NeonSplitterWorkload, DataType::Float32>(factory, graph);
456 // Checks that outputs are as we expect them (see definition of CreateSplitterWorkloadTest).
457 SplitterQueueDescriptor queueDescriptor = workload->GetData();
458 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
459 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({5, 7, 7}, DataType::Float32)));
461 auto outputHandle0 = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
462 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle0, TensorInfo({1, 7, 7}, DataType::Float32)));
464 auto outputHandle1 = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[1]);
465 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle1, TensorInfo({2, 7, 7}, DataType::Float32)));
467 auto outputHandle2 = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[2]);
468 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle2, TensorInfo({2, 7, 7}, DataType::Float32)));
471 BOOST_AUTO_TEST_CASE(CreateSplitterMerger)
473 // Tests that it is possible to decide which output of the splitter layer
474 // should be lined to which input of the merger layer.
475 // We tested that is is possible to specify 0th output
476 // of the splitter to be the 1st input to the merger, and the 1st output of the splitter to be 0th input
480 NeonWorkloadFactory factory;
483 CreateSplitterMergerWorkloadTest<NeonSplitterWorkload, NeonMergerWorkload,
484 DataType::Float32>(factory, graph);
486 auto wlSplitter = std::move(workloads.first);
487 auto wlMerger = std::move(workloads.second);
489 //Checks that the index of inputs/outputs matches what we declared on InputDescriptor construction.
490 armnn::INeonTensorHandle* sOut0 = dynamic_cast<armnn::INeonTensorHandle*>(wlSplitter->GetData().m_Outputs[0]);
491 armnn::INeonTensorHandle* sOut1 = dynamic_cast<armnn::INeonTensorHandle*>(wlSplitter->GetData().m_Outputs[1]);
492 armnn::INeonTensorHandle* mIn0 = dynamic_cast<armnn::INeonTensorHandle*>(wlMerger->GetData().m_Inputs[0]);
493 armnn::INeonTensorHandle* mIn1 = dynamic_cast<armnn::INeonTensorHandle*>(wlMerger->GetData().m_Inputs[1]);
500 bool validDataPointers = (sOut0 == mIn1) && (sOut1 == mIn0);
502 BOOST_TEST(validDataPointers);
505 BOOST_AUTO_TEST_CASE(CreateSingleOutputMultipleInputs)
507 // Tests that it is possible to assign multiple (two) different layers to each of the outputs of a splitter layer.
508 // We created a splitter with two outputs. That each of those outputs is used by two different activation layers
511 NeonWorkloadFactory factory;
512 std::unique_ptr<NeonSplitterWorkload> wlSplitter;
513 std::unique_ptr<NeonActivationWorkload> wlActiv0_0;
514 std::unique_ptr<NeonActivationWorkload> wlActiv0_1;
515 std::unique_ptr<NeonActivationWorkload> wlActiv1_0;
516 std::unique_ptr<NeonActivationWorkload> wlActiv1_1;
518 CreateSplitterMultipleInputsOneOutputWorkloadTest<NeonSplitterWorkload,
519 NeonActivationWorkload, DataType::Float32>(factory, graph, wlSplitter, wlActiv0_0, wlActiv0_1,
520 wlActiv1_0, wlActiv1_1);
522 armnn::INeonTensorHandle* sOut0 = dynamic_cast<armnn::INeonTensorHandle*>(wlSplitter->GetData().m_Outputs[0]);
523 armnn::INeonTensorHandle* sOut1 = dynamic_cast<armnn::INeonTensorHandle*>(wlSplitter->GetData().m_Outputs[1]);
524 armnn::INeonTensorHandle* activ0_0Im = dynamic_cast<armnn::INeonTensorHandle*>(wlActiv0_0->GetData().m_Inputs[0]);
525 armnn::INeonTensorHandle* activ0_1Im = dynamic_cast<armnn::INeonTensorHandle*>(wlActiv0_1->GetData().m_Inputs[0]);
526 armnn::INeonTensorHandle* activ1_0Im = dynamic_cast<armnn::INeonTensorHandle*>(wlActiv1_0->GetData().m_Inputs[0]);
527 armnn::INeonTensorHandle* activ1_1Im = dynamic_cast<armnn::INeonTensorHandle*>(wlActiv1_1->GetData().m_Inputs[0]);
532 BOOST_TEST(activ0_0Im);
533 BOOST_TEST(activ0_1Im);
534 BOOST_TEST(activ1_0Im);
535 BOOST_TEST(activ1_1Im);
537 bool validDataPointers = (sOut0 == activ0_0Im) && (sOut0 == activ0_1Im) &&
538 (sOut1 == activ1_0Im) && (sOut1 == activ1_1Im);
540 BOOST_TEST(validDataPointers);
543 BOOST_AUTO_TEST_CASE(CreateMemCopyWorkloadsNeon)
545 NeonWorkloadFactory factory;
546 CreateMemCopyWorkloads<INeonTensorHandle>(factory);
549 template <typename L2NormalizationWorkloadType, typename armnn::DataType DataType>
550 static void NeonCreateL2NormalizationWorkloadTest(DataLayout dataLayout)
553 NeonWorkloadFactory factory;
555 CreateL2NormalizationWorkloadTest<L2NormalizationWorkloadType, DataType>(factory, graph, dataLayout);
557 // Checks that inputs/outputs are as we expect them (see definition of CreateNormalizationWorkloadTest).
558 L2NormalizationQueueDescriptor queueDescriptor = workload->GetData();
559 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
560 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
562 TensorShape inputShape = (dataLayout == DataLayout::NCHW) ?
563 TensorShape{ 5, 20, 50, 67 } : TensorShape{ 5, 50, 67, 20 };
564 TensorShape outputShape = (dataLayout == DataLayout::NCHW) ?
565 TensorShape{ 5, 20, 50, 67 } : TensorShape{ 5, 50, 67, 20 };
567 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo(inputShape, DataType)));
568 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, DataType)));
571 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
572 BOOST_AUTO_TEST_CASE(CreateL2NormalizationFloat16NchwWorkload)
574 NeonCreateL2NormalizationWorkloadTest<NeonL2NormalizationFloatWorkload, DataType::Float16>(DataLayout::NCHW);
577 BOOST_AUTO_TEST_CASE(CreateL2NormalizationFloat16NhwcWorkload)
579 NeonCreateL2NormalizationWorkloadTest<NeonL2NormalizationFloatWorkload, DataType::Float16>(DataLayout::NHWC);
583 BOOST_AUTO_TEST_CASE(CreateL2NormalizationNchwWorkload)
585 NeonCreateL2NormalizationWorkloadTest<NeonL2NormalizationFloatWorkload, DataType::Float32>(DataLayout::NCHW);
588 BOOST_AUTO_TEST_CASE(CreateL2NormalizationNhwcWorkload)
590 NeonCreateL2NormalizationWorkloadTest<NeonL2NormalizationFloatWorkload, DataType::Float32>(DataLayout::NHWC);
593 BOOST_AUTO_TEST_SUITE_END()