1 //
2 // Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include "StackTestImpl.hpp"
7 #include "LayerTestResult.hpp"
8
9 #include <ResolveType.hpp>
10
11
12 #include <armnn/backends/IBackendInternal.hpp>
13 #include <backendsCommon/WorkloadFactory.hpp>
14
15 #include <backendsCommon/test/TensorCopyUtils.hpp>
16 #include <backendsCommon/test/WorkloadTestUtils.hpp>
17
18 #include <test/TensorHelpers.hpp>
19
20 namespace
21 {
22
23 template<armnn::DataType ArmnnType, typename T, std::size_t outputDimLength>
StackTestHelper(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,const armnn::ITensorHandleFactory & tensorHandleFactory,const armnn::TensorInfo & inputTensorInfo,const armnn::TensorInfo & outputTensorInfo,unsigned int axis,const std::vector<std::vector<T>> & inputData,const std::vector<T> & outputExpectedData)24 LayerTestResult<T, outputDimLength> StackTestHelper(
25 armnn::IWorkloadFactory& workloadFactory,
26 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
27 const armnn::ITensorHandleFactory& tensorHandleFactory,
28 const armnn::TensorInfo& inputTensorInfo,
29 const armnn::TensorInfo& outputTensorInfo,
30 unsigned int axis,
31 const std::vector<std::vector<T>>& inputData,
32 const std::vector<T>& outputExpectedData)
33 {
34 IgnoreUnused(memoryManager);
35 unsigned int numInputs = static_cast<unsigned int>(inputData.size());
36 std::vector<boost::multi_array<T, outputDimLength-1>> inputs;
37 for (unsigned int i = 0; i < numInputs; ++i)
38 {
39 inputs.push_back(MakeTensor<T, outputDimLength-1>(inputTensorInfo, inputData[i]));
40 }
41
42 LayerTestResult<T, outputDimLength> result(outputTensorInfo);
43 result.outputExpected = MakeTensor<T, outputDimLength>(outputTensorInfo, outputExpectedData);
44
45 std::vector<std::unique_ptr<armnn::ITensorHandle>> inputHandles;
46 for (unsigned int i = 0; i < numInputs; ++i)
47 {
48 inputHandles.push_back(tensorHandleFactory.CreateTensorHandle(inputTensorInfo));
49 }
50 std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
51
52 armnn::StackQueueDescriptor descriptor;
53 descriptor.m_Parameters.m_Axis = axis;
54 descriptor.m_Parameters.m_InputShape = inputTensorInfo.GetShape();
55 descriptor.m_Parameters.m_NumInputs = numInputs;
56
57 armnn::WorkloadInfo info;
58 for (unsigned int i = 0; i < numInputs; ++i)
59 {
60 std::unique_ptr<armnn::ITensorHandle>& inputHandle = inputHandles[i];
61 AddInputToWorkload(descriptor, info, inputTensorInfo, inputHandle.get());
62 inputHandle->Allocate();
63 CopyDataToITensorHandle(inputHandle.get(), inputs[i].origin());
64 }
65
66 AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
67 outputHandle->Allocate();
68
69 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateStack(descriptor, info);
70
71 workload->Execute();
72
73 CopyDataFromITensorHandle(result.output.origin(), outputHandle.get());
74
75 return result;
76 }
77
78 } // anonymous namespace
79
80 //
81 // Implementation templates
82 //
83
84 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
StackAxis0TestImpl(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,const armnn::ITensorHandleFactory & tensorHandleFactory)85 LayerTestResult<T, 4> StackAxis0TestImpl(
86 armnn::IWorkloadFactory& workloadFactory,
87 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
88 const armnn::ITensorHandleFactory& tensorHandleFactory)
89 {
90 armnn::TensorInfo inputTensorInfo ({ 3, 2, 3 }, ArmnnType);
91 armnn::TensorInfo outputTensorInfo({ 2, 3, 2, 3 }, ArmnnType);
92
93 std::vector<std::vector<T>> inputData;
94
95 inputData.push_back(
96 {
97 1, 2, 3,
98 4, 5, 6,
99
100 7, 8, 9,
101 10, 11, 12,
102
103 13, 14, 15,
104 16, 17, 18
105 });
106
107 inputData.push_back(
108 {
109 19, 20, 21,
110 22, 23, 24,
111
112 25, 26, 27,
113 28, 29, 30,
114
115 31, 32, 33,
116 34, 35, 36
117 });
118
119 std::vector<T> outputExpectedData =
120 {
121 1, 2, 3,
122 4, 5, 6,
123
124 7, 8, 9,
125 10, 11, 12,
126
127 13, 14, 15,
128 16, 17, 18,
129
130
131 19, 20, 21,
132 22, 23, 24,
133
134 25, 26, 27,
135 28, 29, 30,
136
137 31, 32, 33,
138 34, 35, 36
139 };
140
141 return StackTestHelper<ArmnnType, T, 4>(
142 workloadFactory,
143 memoryManager,
144 tensorHandleFactory,
145 inputTensorInfo,
146 outputTensorInfo,
147 0U,
148 inputData,
149 outputExpectedData
150 );
151 }
152
153 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
StackOutput4DAxis1TestImpl(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,const armnn::ITensorHandleFactory & tensorHandleFactory)154 LayerTestResult<T, 4> StackOutput4DAxis1TestImpl(
155 armnn::IWorkloadFactory& workloadFactory,
156 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
157 const armnn::ITensorHandleFactory& tensorHandleFactory)
158 {
159 armnn::TensorInfo inputTensorInfo ({ 3, 2, 3 }, ArmnnType);
160 armnn::TensorInfo outputTensorInfo({ 3, 2, 2, 3 }, ArmnnType);
161
162 std::vector<std::vector<T>> inputData;
163
164 inputData.push_back(
165 {
166 1, 2, 3,
167 4, 5, 6,
168
169 7, 8, 9,
170 10, 11, 12,
171
172 13, 14, 15,
173 16, 17, 18
174 });
175
176 inputData.push_back(
177 {
178 19, 20, 21,
179 22, 23, 24,
180
181 25, 26, 27,
182 28, 29, 30,
183
184 31, 32, 33,
185 34, 35, 36
186 });
187
188 std::vector<T> outputExpectedData =
189 {
190 1, 2, 3,
191 4, 5, 6,
192
193 19, 20, 21,
194 22, 23, 24,
195
196
197 7, 8, 9,
198 10, 11, 12,
199
200 25, 26, 27,
201 28, 29, 30,
202
203
204 13, 14, 15,
205 16, 17, 18,
206
207 31, 32, 33,
208 34, 35, 36
209 };
210
211 return StackTestHelper<ArmnnType, T, 4>(
212 workloadFactory,
213 memoryManager,
214 tensorHandleFactory,
215 inputTensorInfo,
216 outputTensorInfo,
217 1U,
218 inputData,
219 outputExpectedData
220 );
221 }
222
223 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
StackOutput4DAxis2TestImpl(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,const armnn::ITensorHandleFactory & tensorHandleFactory)224 LayerTestResult<T, 4> StackOutput4DAxis2TestImpl(
225 armnn::IWorkloadFactory& workloadFactory,
226 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
227 const armnn::ITensorHandleFactory& tensorHandleFactory)
228 {
229 armnn::TensorInfo inputTensorInfo ({ 3, 2, 3 }, ArmnnType);
230 armnn::TensorInfo outputTensorInfo({ 3, 2, 2, 3 }, ArmnnType);
231
232 std::vector<std::vector<T>> inputData;
233
234 inputData.push_back(
235 {
236 1, 2, 3,
237 4, 5, 6,
238
239 7, 8, 9,
240 10, 11, 12,
241
242 13, 14, 15,
243 16, 17, 18
244 });
245
246 inputData.push_back(
247 {
248 19, 20, 21,
249 22, 23, 24,
250
251 25, 26, 27,
252 28, 29, 30,
253
254 31, 32, 33,
255 34, 35, 36
256 });
257
258 std::vector<T> outputExpectedData =
259 {
260 1, 2, 3,
261 19, 20, 21,
262
263 4, 5, 6,
264 22, 23, 24,
265
266 7, 8, 9,
267 25, 26, 27,
268
269 10, 11, 12,
270 28, 29, 30,
271
272 13, 14, 15,
273 31, 32, 33,
274
275 16, 17, 18,
276 34, 35, 36
277 };
278
279 return StackTestHelper<ArmnnType, T, 4>(
280 workloadFactory,
281 memoryManager,
282 tensorHandleFactory,
283 inputTensorInfo,
284 outputTensorInfo,
285 2U,
286 inputData,
287 outputExpectedData
288 );
289 }
290
291 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
StackOutput4DAxis3TestImpl(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,const armnn::ITensorHandleFactory & tensorHandleFactory)292 LayerTestResult<T, 4> StackOutput4DAxis3TestImpl(
293 armnn::IWorkloadFactory& workloadFactory,
294 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
295 const armnn::ITensorHandleFactory& tensorHandleFactory)
296 {
297 armnn::TensorInfo inputTensorInfo ({ 3, 2, 3 }, ArmnnType);
298 armnn::TensorInfo outputTensorInfo({ 3, 2, 3, 2 }, ArmnnType);
299
300 std::vector<std::vector<T>> inputData;
301
302 inputData.push_back(
303 {
304 1, 2, 3,
305 4, 5, 6,
306
307 7, 8, 9,
308 10, 11, 12,
309
310 13, 14, 15,
311 16, 17, 18
312 });
313
314 inputData.push_back(
315 {
316 19, 20, 21,
317 22, 23, 24,
318
319 25, 26, 27,
320 28, 29, 30,
321
322 31, 32, 33,
323 34, 35, 36
324 });
325
326 std::vector<T> outputExpectedData =
327 {
328 1, 19,
329 2, 20,
330 3, 21,
331
332 4, 22,
333 5, 23,
334 6, 24,
335
336
337 7, 25,
338 8, 26,
339 9, 27,
340
341 10, 28,
342 11, 29,
343 12, 30,
344
345
346 13, 31,
347 14, 32,
348 15, 33,
349
350 16, 34,
351 17, 35,
352 18, 36
353 };
354
355 return StackTestHelper<ArmnnType, T, 4>(
356 workloadFactory,
357 memoryManager,
358 tensorHandleFactory,
359 inputTensorInfo,
360 outputTensorInfo,
361 3U,
362 inputData,
363 outputExpectedData
364 );
365 }
366
367 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
StackOutput3DInputs3TestImpl(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,const armnn::ITensorHandleFactory & tensorHandleFactory)368 LayerTestResult<T, 3> StackOutput3DInputs3TestImpl(
369 armnn::IWorkloadFactory& workloadFactory,
370 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
371 const armnn::ITensorHandleFactory& tensorHandleFactory)
372 {
373 armnn::TensorInfo inputTensorInfo ({ 3, 3 }, ArmnnType);
374 armnn::TensorInfo outputTensorInfo({ 3, 3, 3 }, ArmnnType);
375
376 std::vector<std::vector<T>> inputData;
377
378 inputData.push_back(
379 {
380 1, 2, 3,
381 4, 5, 6,
382 7, 8, 9
383 });
384
385 inputData.push_back(
386 {
387 10, 11, 12,
388 13, 14, 15,
389 16, 17, 18
390 });
391
392 inputData.push_back(
393 {
394 19, 20, 21,
395 22, 23, 24,
396 25, 26, 27
397 });
398
399 std::vector<T> outputExpectedData =
400 {
401 1, 2, 3,
402 10, 11, 12,
403 19, 20, 21,
404
405 4, 5, 6,
406 13, 14, 15,
407 22, 23, 24,
408
409 7, 8, 9,
410 16, 17, 18,
411 25, 26, 27
412 };
413
414 return StackTestHelper<ArmnnType, T, 3>(
415 workloadFactory,
416 memoryManager,
417 tensorHandleFactory,
418 inputTensorInfo,
419 outputTensorInfo,
420 1U,
421 inputData,
422 outputExpectedData
423 );
424 }
425
426 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
StackOutput5DTestImpl(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,const armnn::ITensorHandleFactory & tensorHandleFactory)427 LayerTestResult<T, 5> StackOutput5DTestImpl(
428 armnn::IWorkloadFactory& workloadFactory,
429 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
430 const armnn::ITensorHandleFactory& tensorHandleFactory)
431 {
432 armnn::TensorInfo inputTensorInfo ({ 2, 2, 2, 3 }, ArmnnType);
433 armnn::TensorInfo outputTensorInfo({ 2, 2, 2, 2, 3 }, ArmnnType);
434
435 std::vector<std::vector<T>> inputData;
436
437 inputData.push_back(
438 {
439 1, 2, 3,
440 4, 5, 6,
441
442 7, 8, 9,
443 10, 11, 12,
444
445
446 13, 14, 15,
447 16, 17, 18,
448
449 19, 20, 21,
450 22, 23, 24
451 });
452
453 inputData.push_back(
454 {
455 25, 26, 27,
456 28, 29, 30,
457
458 31, 32, 33,
459 34, 35, 36,
460
461
462 37, 38, 39,
463 40, 41, 42,
464
465 43, 44, 45,
466 46, 47, 48
467 });
468
469 std::vector<T> outputExpectedData =
470 {
471 1, 2, 3,
472 4, 5, 6,
473
474 7, 8, 9,
475 10, 11, 12,
476
477
478 25, 26, 27,
479 28, 29, 30,
480
481 31, 32, 33,
482 34, 35, 36,
483
484
485
486 13, 14, 15,
487 16, 17, 18,
488
489 19, 20, 21,
490 22, 23, 24,
491
492
493 37, 38, 39,
494 40, 41, 42,
495
496 43, 44, 45,
497 46, 47, 48
498
499 };
500
501 return StackTestHelper<ArmnnType, T, 5>(
502 workloadFactory,
503 memoryManager,
504 tensorHandleFactory,
505 inputTensorInfo,
506 outputTensorInfo,
507 1U,
508 inputData,
509 outputExpectedData
510 );
511 }
512
513 //
514 // Implementation functions
515 //
516
StackAxis0Float32Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,const armnn::ITensorHandleFactory & tensorHandleFactory)517 LayerTestResult<float, 4> StackAxis0Float32Test(
518 armnn::IWorkloadFactory& workloadFactory,
519 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
520 const armnn::ITensorHandleFactory& tensorHandleFactory)
521 {
522 return StackAxis0TestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager, tensorHandleFactory);
523 }
524
StackOutput4DAxis1Float32Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,const armnn::ITensorHandleFactory & tensorHandleFactory)525 LayerTestResult<float, 4> StackOutput4DAxis1Float32Test(
526 armnn::IWorkloadFactory& workloadFactory,
527 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
528 const armnn::ITensorHandleFactory& tensorHandleFactory)
529 {
530 return StackOutput4DAxis1TestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager, tensorHandleFactory);
531 }
532
StackOutput4DAxis2Float32Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,const armnn::ITensorHandleFactory & tensorHandleFactory)533 LayerTestResult<float, 4> StackOutput4DAxis2Float32Test(
534 armnn::IWorkloadFactory& workloadFactory,
535 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
536 const armnn::ITensorHandleFactory& tensorHandleFactory)
537 {
538 return StackOutput4DAxis2TestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager, tensorHandleFactory);
539 }
540
StackOutput4DAxis3Float32Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,const armnn::ITensorHandleFactory & tensorHandleFactory)541 LayerTestResult<float, 4> StackOutput4DAxis3Float32Test(
542 armnn::IWorkloadFactory& workloadFactory,
543 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
544 const armnn::ITensorHandleFactory& tensorHandleFactory)
545 {
546 return StackOutput4DAxis3TestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager, tensorHandleFactory);
547 }
548
StackOutput3DInputs3Float32Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,const armnn::ITensorHandleFactory & tensorHandleFactory)549 LayerTestResult<float, 3> StackOutput3DInputs3Float32Test(
550 armnn::IWorkloadFactory& workloadFactory,
551 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
552 const armnn::ITensorHandleFactory& tensorHandleFactory)
553 {
554 return StackOutput3DInputs3TestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager, tensorHandleFactory);
555 }
556
StackOutput5DFloat32Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,const armnn::ITensorHandleFactory & tensorHandleFactory)557 LayerTestResult<float, 5> StackOutput5DFloat32Test(
558 armnn::IWorkloadFactory& workloadFactory,
559 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
560 const armnn::ITensorHandleFactory& tensorHandleFactory)
561 {
562 return StackOutput5DTestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager, tensorHandleFactory);
563 }
564
StackFloat16Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,const armnn::ITensorHandleFactory & tensorHandleFactory)565 LayerTestResult<armnn::Half, 4> StackFloat16Test(
566 armnn::IWorkloadFactory& workloadFactory,
567 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
568 const armnn::ITensorHandleFactory& tensorHandleFactory)
569 {
570 using namespace half_float::literal;
571
572 armnn::TensorInfo inputTensorInfo ({ 3, 2, 3 }, armnn::DataType::Float16);
573 armnn::TensorInfo outputTensorInfo({ 3, 2, 2, 3 }, armnn::DataType::Float16);
574
575 std::vector<std::vector<armnn::Half>> inputData;
576
577 inputData.push_back(
578 {
579 1.0_h, 2.0_h, 3.0_h,
580 4.0_h, 5.0_h, 6.0_h,
581
582 7.0_h, 8.0_h, 9.0_h,
583 10.0_h, 11.0_h, 12.0_h,
584
585 13.0_h, 14.0_h, 15.0_h,
586 16.0_h, 17.0_h, 18.0_h
587 });
588
589 inputData.push_back(
590 {
591 19.0_h, 20.0_h, 21.0_h,
592 22.0_h, 23.0_h, 24.0_h,
593
594 25.0_h, 26.0_h, 27.0_h,
595 28.0_h, 29.0_h, 30.0_h,
596
597 31.0_h, 32.0_h, 33.0_h,
598 34.0_h, 35.0_h, 36.0_h
599 });
600
601 std::vector<armnn::Half> outputExpectedData =
602 {
603 1.0_h, 2.0_h, 3.0_h,
604 19.0_h, 20.0_h, 21.0_h,
605
606 4.0_h, 5.0_h, 6.0_h,
607 22.0_h, 23.0_h, 24.0_h,
608
609 7.0_h, 8.0_h, 9.0_h,
610 25.0_h, 26.0_h, 27.0_h,
611
612 10.0_h, 11.0_h, 12.0_h,
613 28.0_h, 29.0_h, 30.0_h,
614
615 13.0_h, 14.0_h, 15.0_h,
616 31.0_h, 32.0_h, 33.0_h,
617
618 16.0_h, 17.0_h, 18.0_h,
619 34.0_h, 35.0_h, 36.0_h
620 };
621
622 return StackTestHelper<armnn::DataType::Float16, armnn::Half, 4>(
623 workloadFactory,
624 memoryManager,
625 tensorHandleFactory,
626 inputTensorInfo,
627 outputTensorInfo,
628 2U,
629 inputData,
630 outputExpectedData
631 );
632 }