ArmNN
 20.02
SplitterEndToEndTestImpl.hpp
Go to the documentation of this file.
1 //
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 
12 
13 #include <boost/test/unit_test.hpp>
14 
15 #include <vector>
16 
17 namespace
18 {
19 
20 template<typename armnn::DataType DataType>
21 INetworkPtr 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.
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 
48  SplitterDescriptor splitDesc(numSplit, inputShape.GetNumDimensions());
49  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 
73 template<armnn::DataType ArmnnType>
74 void 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 
101 template<armnn::DataType ArmnnType>
102 void 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 
136 template<armnn::DataType ArmnnType>
137 void 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 
174 template<armnn::DataType ArmnnType>
175 void 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 
222 template<armnn::DataType ArmnnType>
223 void 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 
270 template<armnn::DataType ArmnnType>
271 void 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 
310 template<armnn::DataType ArmnnType>
311 void Splitter4dDim0EndToEnd(const std::vector<BackendId>& backends)
312 {
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 
390 template<armnn::DataType ArmnnType>
391 void Splitter4dDim1EndToEnd(const std::vector<BackendId>& backends)
392 {
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 
470 template<armnn::DataType ArmnnType>
471 void Splitter4dDim2EndToEnd(const std::vector<BackendId>& backends)
472 {
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 
550 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
551 void Splitter4dDim3EndToEnd(const std::vector<BackendId>& backends)
552 {
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
A ViewsDescriptor for the SplitterLayer.
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:61
typename ResolveTypeImpl< DT >::Type ResolveType
Definition: ResolveType.hpp:73
Copyright (c) 2020 ARM Limited.
DataType
Definition: Types.hpp:32
Status SetViewSize(uint32_t view, uint32_t coord, uint32_t value)
Set the size of the views.
void Connect(armnn::IConnectableLayer *from, armnn::IConnectableLayer *to, const armnn::TensorInfo &tensorInfo, unsigned int fromIndex, unsigned int toIndex)
Definition: TestUtils.cpp:12
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
Definition: INetwork.hpp:101
static INetworkPtr Create()
Definition: Network.cpp:49