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