blob: 6c4c1772b6e3979e794845c3342fcc18fd876710 [file] [log] [blame]
Narumol Prangnawarat0be43382019-05-27 11:29:59 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5#pragma once
6
7#include <ResolveType.hpp>
8
9#include <armnn/INetwork.hpp>
10
11#include <backendsCommon/test/CommonTestUtils.hpp>
12
13#include <boost/test/unit_test.hpp>
14
15#include <vector>
16
17namespace
18{
19
20template<typename armnn::DataType DataType>
21INetworkPtr CreateSplitterNetwork(const TensorShape& inputShape,
22 const std::vector<TensorShape>& outputShapes,
23 unsigned int splitAxis,
24 unsigned int numSplit,
25 const float qScale = 1.0f,
26 const int32_t qOffset = 0)
27{
28 using namespace armnn;
29 // Builds up the structure of the network.
30 INetworkPtr net(INetwork::Create());
31
32 TensorInfo inputTensorInfo(inputShape, DataType, qScale, qOffset);
33
34 std::vector<unsigned int> splitterDimSizes(inputShape.GetNumDimensions());
35
36 // Add current input shape to splitterDimSizes
37 for (unsigned int i = 0; i < inputShape.GetNumDimensions(); ++i)
38 {
39 splitterDimSizes[i] = inputTensorInfo.GetShape()[i];
40 }
41
42 if (splitterDimSizes[splitAxis] % numSplit != 0)
43 {
44 throw ParseException("Number of splits must evenly divide the dimension");
45 }
46 splitterDimSizes[splitAxis] /= numSplit;
47
Narumol Prangnawarat0f072ab2019-05-29 14:12:46 +010048 SplitterDescriptor splitDesc(numSplit, inputShape.GetNumDimensions());
Narumol Prangnawarat0be43382019-05-27 11:29:59 +010049 for (unsigned int g = 0; g < numSplit; ++g)
50 {
51 // Set the size of the views.
52 for (unsigned int dimIdx = 0; dimIdx < splitterDimSizes.size(); ++dimIdx)
53 {
54 splitDesc.SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]);
55 }
56 splitDesc.SetViewOriginCoord(g, splitAxis, splitterDimSizes[splitAxis] * g);
57 }
58
59 IConnectableLayer* splitter = net->AddSplitterLayer(splitDesc, "splitter");
60 IConnectableLayer* input = net->AddInputLayer(0, "input");
61 Connect(input, splitter, inputTensorInfo, 0, 0);
62
63 for (unsigned int i = 0; i < outputShapes.size(); ++i)
64 {
65 TensorInfo outputTensorInfo(outputShapes[i], DataType, qScale, qOffset);
66 IConnectableLayer* output = net->AddOutputLayer(boost::numeric_cast<LayerBindingId>(i));
67 Connect(splitter, output, outputTensorInfo, i, 0);
68 }
69
70 return net;
71}
72
73template<armnn::DataType ArmnnType>
Narumol Prangnawarat0f072ab2019-05-29 14:12:46 +010074void Splitter1dEndToEnd(const std::vector<BackendId>& backends)
75{
76 using namespace armnn;
77 using T = ResolveType<ArmnnType>;
78
79 unsigned int splitAxis = 0;
80 unsigned int numSplit = 2;
81 const TensorShape& inputShape = { 4 };
82 const std::vector<TensorShape> outputShapes{{ 2 }, { 2 }};
83
84 // Builds up the structure of the network
85 INetworkPtr net = CreateSplitterNetwork<ArmnnType>(inputShape, outputShapes, splitAxis, numSplit);
86
87 BOOST_TEST_CHECKPOINT("create a network");
88
89 // Creates structures for input & output.
90 std::vector<T> inputData{ 1, 2, 3, 4 };
91
92 std::vector<T> expectedOutput0{ 1, 2 };
93 std::vector<T> expectedOutput1{ 3, 4 };
94
95 std::map<int, std::vector<T>> inputTensorData = { { 0, inputData } };
96 std::map<int, std::vector<T>> expectedOutputData = { { 0, expectedOutput0 }, {1, expectedOutput1} };
97
98 EndToEndLayerTestImpl<ArmnnType, ArmnnType>(move(net), inputTensorData, expectedOutputData, backends);
99}
100
101template<armnn::DataType ArmnnType>
102void Splitter2dDim0EndToEnd(const std::vector<BackendId>& backends)
103{
104 using namespace armnn;
105 using T = ResolveType<ArmnnType>;
106
107 unsigned int splitAxis = 0;
108 unsigned int numSplit = 2;
109 const TensorShape& inputShape = { 4, 3 };
110 const std::vector<TensorShape> outputShapes{{ 2, 3 }, { 2, 3 }};
111
112 // Builds up the structure of the network
113 INetworkPtr net = CreateSplitterNetwork<ArmnnType>(inputShape, outputShapes, splitAxis, numSplit);
114
115 BOOST_TEST_CHECKPOINT("create a network");
116
117 // Creates structures for input & output.
118 std::vector<T> inputData{
119 1, 2,
120 3, 4,
121 5, 6,
122 7, 8,
123 9, 10,
124 11, 12
125 };
126
127 std::vector<T> expectedOutput0{ 1, 2, 3, 4, 5, 6 };
128 std::vector<T> expectedOutput1{ 7, 8, 9, 10, 11, 12 };
129
130 std::map<int, std::vector<T>> inputTensorData = { { 0, inputData } };
131 std::map<int, std::vector<T>> expectedOutputData = { { 0, expectedOutput0 }, {1, expectedOutput1} };
132
133 EndToEndLayerTestImpl<ArmnnType, ArmnnType>(move(net), inputTensorData, expectedOutputData, backends);
134}
135
136template<armnn::DataType ArmnnType>
137void Splitter2dDim1EndToEnd(const std::vector<BackendId>& backends)
138{
139 using namespace armnn;
140 using T = ResolveType<ArmnnType>;
141
142 unsigned int splitAxis = 1;
143 unsigned int numSplit = 3;
144 const TensorShape& inputShape = { 4, 3 };
145 const std::vector<TensorShape> outputShapes{{ 4, 1 }, { 4, 1 }, { 4, 1 }};
146
147 // Builds up the structure of the network
148 INetworkPtr net = CreateSplitterNetwork<ArmnnType>(inputShape, outputShapes, splitAxis, numSplit);
149
150 BOOST_TEST_CHECKPOINT("create a network");
151
152 // Creates structures for input & output.
153 std::vector<T> inputData{
154 1, 2,
155 3, 4,
156 5, 6,
157 7, 8,
158 9, 10,
159 11, 12
160 };
161
162 std::vector<T> expectedOutput0{ 1, 4, 7, 10 };
163 std::vector<T> expectedOutput1{ 2, 5, 8, 11 };
164 std::vector<T> expectedOutput2{ 3, 6, 9, 12 };
165
166 std::map<int, std::vector<T>> inputTensorData = { { 0, inputData } };
167 std::map<int, std::vector<T>> expectedOutputData = { { 0, expectedOutput0 },
168 { 1, expectedOutput1 },
169 { 2, expectedOutput2 } };
170
171 EndToEndLayerTestImpl<ArmnnType, ArmnnType>(move(net), inputTensorData, expectedOutputData, backends);
172}
173
174template<armnn::DataType ArmnnType>
175void Splitter3dDim0EndToEnd(const std::vector<BackendId>& backends)
176{
177 using namespace armnn;
178 using T = ResolveType<ArmnnType>;
179
180 unsigned int splitAxis = 0;
181 unsigned int numSplit = 2;
182 const TensorShape& inputShape = { 2, 4, 3 };
183 const std::vector<TensorShape> outputShapes{{ 1, 4, 3 }, { 1, 4, 3 }};
184
185 // Builds up the structure of the network
186 INetworkPtr net = CreateSplitterNetwork<ArmnnType>(inputShape, outputShapes, splitAxis, numSplit);
187
188 BOOST_TEST_CHECKPOINT("create a network");
189
190 // Creates structures for input & output.
191 std::vector<T> inputData{
192 1, 2, 3,
193 4, 5, 6,
194 7, 8, 9,
195 10, 11, 12,
196 13, 14, 15,
197 16, 17, 18,
198 19, 20, 21,
199 22, 23, 24
200 };
201
202 std::vector<T> expectedOutput0{
203 1, 2, 3,
204 4, 5, 6,
205 7, 8, 9,
206 10, 11, 12
207 };
208 std::vector<T> expectedOutput1{
209 13, 14, 15,
210 16, 17, 18,
211 19, 20, 21,
212 22, 23, 24
213 };
214
215 std::map<int, std::vector<T>> inputTensorData = { { 0, inputData } };
216 std::map<int, std::vector<T>> expectedOutputData = { { 0, expectedOutput0 },
217 { 1, expectedOutput1 } };
218
219 EndToEndLayerTestImpl<ArmnnType, ArmnnType>(move(net), inputTensorData, expectedOutputData, backends);
220}
221
222template<armnn::DataType ArmnnType>
223void Splitter3dDim1EndToEnd(const std::vector<BackendId>& backends)
224{
225 using namespace armnn;
226 using T = ResolveType<ArmnnType>;
227
228 unsigned int splitAxis = 1;
229 unsigned int numSplit = 2;
230 const TensorShape& inputShape = { 2, 4, 3 };
231 const std::vector<TensorShape> outputShapes{{ 2, 2, 3 }, { 2, 2, 3 }};
232
233 // Builds up the structure of the network
234 INetworkPtr net = CreateSplitterNetwork<ArmnnType>(inputShape, outputShapes, splitAxis, numSplit);
235
236 BOOST_TEST_CHECKPOINT("create a network");
237
238 // Creates structures for input & output.
239 std::vector<T> inputData{
240 1, 2, 3,
241 4, 5, 6,
242 7, 8, 9,
243 10, 11, 12,
244 13, 14, 15,
245 16, 17, 18,
246 19, 20, 21,
247 22, 23, 24
248 };
249
250 std::vector<T> expectedOutput0{
251 1, 2, 3,
252 4, 5, 6,
253 13, 14, 15,
254 16, 17, 18
255 };
256 std::vector<T> expectedOutput1{
257 7, 8, 9,
258 10, 11, 12,
259 19, 20, 21,
260 22, 23, 24
261 };
262
263 std::map<int, std::vector<T>> inputTensorData = { { 0, inputData } };
264 std::map<int, std::vector<T>> expectedOutputData = { { 0, expectedOutput0 },
265 { 1, expectedOutput1 } };
266
267 EndToEndLayerTestImpl<ArmnnType, ArmnnType>(move(net), inputTensorData, expectedOutputData, backends);
268}
269
270template<armnn::DataType ArmnnType>
271void Splitter3dDim2EndToEnd(const std::vector<BackendId>& backends)
272{
273 using namespace armnn;
274 using T = ResolveType<ArmnnType>;
275
276 unsigned int splitAxis = 2;
277 unsigned int numSplit = 3;
278 const TensorShape& inputShape = { 2, 4, 3 };
279 const std::vector<TensorShape> outputShapes{{ 2, 4, 1 }, { 2, 4, 1 }, { 2, 4, 1 }};
280
281 // Builds up the structure of the network
282 INetworkPtr net = CreateSplitterNetwork<ArmnnType>(inputShape, outputShapes, splitAxis, numSplit);
283
284 BOOST_TEST_CHECKPOINT("create a network");
285
286 // Creates structures for input & output.
287 std::vector<T> inputData{
288 1, 2, 3,
289 4, 5, 6,
290 7, 8, 9,
291 10, 11, 12,
292 13, 14, 15,
293 16, 17, 18,
294 19, 20, 21,
295 22, 23, 24
296 };
297
298 std::vector<T> expectedOutput0{ 1, 4, 7, 10, 13, 16, 19, 22 };
299 std::vector<T> expectedOutput1{ 2, 5, 8, 11, 14, 17, 20, 23 };
300 std::vector<T> expectedOutput2{ 3, 6, 9, 12, 15, 18, 21, 24 };
301
302 std::map<int, std::vector<T>> inputTensorData = { { 0, inputData } };
303 std::map<int, std::vector<T>> expectedOutputData = { { 0, expectedOutput0 },
304 { 1, expectedOutput1 },
305 { 2, expectedOutput2 } };
306
307 EndToEndLayerTestImpl<ArmnnType, ArmnnType>(move(net), inputTensorData, expectedOutputData, backends);
308}
309
310template<armnn::DataType ArmnnType>
311void Splitter4dDim0EndToEnd(const std::vector<BackendId>& backends)
Narumol Prangnawarat0be43382019-05-27 11:29:59 +0100312{
313 using namespace armnn;
314 using T = ResolveType<ArmnnType>;
315
316 unsigned int splitAxis = 0;
317 unsigned int numSplit = 2;
318 const TensorShape& inputShape = { 4, 3, 2, 2 };
319 const std::vector<TensorShape> outputShapes{{ 2, 3, 2, 2 }, { 2, 3, 2, 2 }};
320
321 // Builds up the structure of the network
322 INetworkPtr net = CreateSplitterNetwork<ArmnnType>(inputShape, outputShapes, splitAxis, numSplit);
323
324 BOOST_TEST_CHECKPOINT("create a network");
325
326 // Creates structures for input & output.
327 std::vector<T> inputData{
328 1, 2,
329 3, 4,
330 5, 6,
331 7, 8,
332 9, 10,
333 11, 12,
334 13, 14,
335 15, 16,
336 17, 18,
337 19, 20,
338 21, 22,
339 23, 24,
340 25, 26,
341 27, 28,
342 29, 30,
343 31, 32,
344 33, 34,
345 35, 36,
346 37, 38,
347 39, 40,
348 41, 42,
349 43, 44,
350 45, 46,
351 47, 48
352 };
353
354 std::vector<T> expectedOutput0{
355 1, 2,
356 3, 4,
357 5, 6,
358 7, 8,
359 9, 10,
360 11, 12,
361 13, 14,
362 15, 16,
363 17, 18,
364 19, 20,
365 21, 22,
366 23, 24
367 };
368
369 std::vector<T> expectedOutput1{
370 25, 26,
371 27, 28,
372 29, 30,
373 31, 32,
374 33, 34,
375 35, 36,
376 37, 38,
377 39, 40,
378 41, 42,
379 43, 44,
380 45, 46,
381 47, 48
382 };
383
384 std::map<int, std::vector<T>> inputTensorData = {{ 0,inputData }};
385 std::map<int, std::vector<T>> expectedOutputData = {{ 0, expectedOutput0 }, { 1, expectedOutput1 }};
386
387 EndToEndLayerTestImpl<ArmnnType, ArmnnType>(move(net), inputTensorData, expectedOutputData, backends);
388}
389
390template<armnn::DataType ArmnnType>
Narumol Prangnawarat0f072ab2019-05-29 14:12:46 +0100391void Splitter4dDim1EndToEnd(const std::vector<BackendId>& backends)
Narumol Prangnawarat0be43382019-05-27 11:29:59 +0100392{
393 using namespace armnn;
394 using T = ResolveType<ArmnnType>;
395
396 unsigned int splitAxis = 1;
397 unsigned int numSplit = 2;
398 const TensorShape& inputShape = { 2, 6, 2, 2 };
399 const std::vector<TensorShape> outputShapes{{ 2, 3, 2, 2 }, { 2, 3, 2, 2 }};
400
401 // Builds up the structure of the network
402 INetworkPtr net = CreateSplitterNetwork<ArmnnType>(inputShape, outputShapes, splitAxis, numSplit);
403
404 BOOST_TEST_CHECKPOINT("create a network");
405
406 // Creates structures for input & output.
407 std::vector<T> inputData{
408 1, 2,
409 3, 4,
410 5, 6,
411 7, 8,
412 9, 10,
413 11, 12,
414 13, 14,
415 15, 16,
416 17, 18,
417 19, 20,
418 21, 22,
419 23, 24,
420 25, 26,
421 27, 28,
422 29, 30,
423 31, 32,
424 33, 34,
425 35, 36,
426 37, 38,
427 39, 40,
428 41, 42,
429 43, 44,
430 45, 46,
431 47, 48
432 };
433
434 std::vector<T> expectedOutput0{
435 1, 2,
436 3, 4,
437 5, 6,
438 7, 8,
439 9, 10,
440 11, 12,
441 25, 26,
442 27, 28,
443 29, 30,
444 31, 32,
445 33, 34,
446 35, 36
447 };
448
449 std::vector<T> expectedOutput1{
450 13, 14,
451 15, 16,
452 17, 18,
453 19, 20,
454 21, 22,
455 23, 24,
456 37, 38,
457 39, 40,
458 41, 42,
459 43, 44,
460 45, 46,
461 47, 48
462 };
463
464 std::map<int, std::vector<T>> inputTensorData = {{ 0,inputData }};
465 std::map<int, std::vector<T>> expectedOutputData = {{ 0, expectedOutput0 }, { 1, expectedOutput1 }};
466
467 EndToEndLayerTestImpl<ArmnnType, ArmnnType>(move(net), inputTensorData, expectedOutputData, backends);
468}
469
470template<armnn::DataType ArmnnType>
Narumol Prangnawarat0f072ab2019-05-29 14:12:46 +0100471void Splitter4dDim2EndToEnd(const std::vector<BackendId>& backends)
Narumol Prangnawarat0be43382019-05-27 11:29:59 +0100472{
473 using namespace armnn;
474 using T = ResolveType<ArmnnType>;
475
476 unsigned int splitAxis = 2;
477 unsigned int numSplit = 2;
478 const TensorShape& inputShape = { 2, 3, 4, 2 };
479 const std::vector<TensorShape> outputShapes{{ 2, 3, 2, 2 }, { 2, 3, 2, 2 }};
480
481 // Builds up the structure of the network
482 INetworkPtr net = CreateSplitterNetwork<ArmnnType>(inputShape, outputShapes, splitAxis, numSplit);
483
484 BOOST_TEST_CHECKPOINT("create a network");
485
486 // Creates structures for input & output.
487 std::vector<T> inputData{
488 1, 2,
489 3, 4,
490 5, 6,
491 7, 8,
492 9, 10,
493 11, 12,
494 13, 14,
495 15, 16,
496 17, 18,
497 19, 20,
498 21, 22,
499 23, 24,
500 25, 26,
501 27, 28,
502 29, 30,
503 31, 32,
504 33, 34,
505 35, 36,
506 37, 38,
507 39, 40,
508 41, 42,
509 43, 44,
510 45, 46,
511 47, 48
512 };
513
514 std::vector<T> expectedOutput0{
515 1, 2,
516 3, 4,
517 9, 10,
518 11, 12,
519 17, 18,
520 19, 20,
521 25, 26,
522 27, 28,
523 33, 34,
524 35, 36,
525 41, 42,
526 43, 44
527 };
528
529 std::vector<T> expectedOutput1{
530 5, 6,
531 7, 8,
532 13, 14,
533 15, 16,
534 21, 22,
535 23, 24,
536 29, 30,
537 31, 32,
538 37, 38,
539 39, 40,
540 45, 46,
541 47, 48
542 };
543
544 std::map<int, std::vector<T>> inputTensorData = {{ 0,inputData }};
545 std::map<int, std::vector<T>> expectedOutputData = {{ 0, expectedOutput0 }, { 1, expectedOutput1 }};
546
547 EndToEndLayerTestImpl<ArmnnType, ArmnnType>(move(net), inputTensorData, expectedOutputData, backends);
548}
549
550template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
Narumol Prangnawarat0f072ab2019-05-29 14:12:46 +0100551void Splitter4dDim3EndToEnd(const std::vector<BackendId>& backends)
Narumol Prangnawarat0be43382019-05-27 11:29:59 +0100552{
553 using namespace armnn;
554
555 unsigned int splitAxis = 3;
556 unsigned int numSplit = 2;
557 const TensorShape& inputShape = { 2, 3, 4, 2 };
558 const std::vector<TensorShape> outputShapes{{ 2, 3, 4, 1 }, { 2, 3, 4, 1 }};
559
560 // Builds up the structure of the network
561 INetworkPtr net = CreateSplitterNetwork<ArmnnType>(inputShape, outputShapes, splitAxis, numSplit);
562
563 BOOST_TEST_CHECKPOINT("create a network");
564
565 // Creates structures for input & output.
566 std::vector<T> inputData{
567 1, 2,
568 3, 4,
569 5, 6,
570 7, 8,
571 9, 10,
572 11, 12,
573 13, 14,
574 15, 16,
575 17, 18,
576 19, 20,
577 21, 22,
578 23, 24,
579 25, 26,
580 27, 28,
581 29, 30,
582 31, 32,
583 33, 34,
584 35, 36,
585 37, 38,
586 39, 40,
587 41, 42,
588 43, 44,
589 45, 46,
590 47, 48
591 };
592
593 std::vector<T> expectedOutput0{
594 1, 3, 5, 7,
595 9, 11, 13, 15,
596 17, 19, 21, 23,
597 25, 27, 29, 31,
598 33, 35, 37, 39,
599 41, 43, 45, 47
600 };
601
602 std::vector<T> expectedOutput1{
603 2, 4, 6, 8,
604 10, 12, 14, 16,
605 18, 20, 22, 24,
606 26, 28, 30, 32,
607 34, 36, 38, 40,
608 42, 44, 46, 48
609 };
610
611 std::map<int, std::vector<T>> inputTensorData = {{ 0,inputData }};
612 std::map<int, std::vector<T>> expectedOutputData = {{ 0, expectedOutput0 }, { 1, expectedOutput1 }};
613
614 EndToEndLayerTestImpl<ArmnnType, ArmnnType>(move(net), inputTensorData, expectedOutputData, backends);
615}
616
617} // anonymous namespace