• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright © 2017,2022 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #pragma once
6 
7 #include <CommonTestUtils.hpp>
8 
9 #include <ResolveType.hpp>
10 
11 #include <armnn/INetwork.hpp>
12 
13 #include <armnn/utility/NumericCast.hpp>
14 
15 #include <doctest/doctest.h>
16 
17 #include <vector>
18 
19 namespace
20 {
21 
22 template<typename armnn::DataType DataType>
CreateConcatNetwork(const std::vector<TensorShape> & inputShapes,const TensorShape & outputShape,unsigned int concatAxis,const float qScale=1.0f,const int32_t qOffset=0)23 INetworkPtr CreateConcatNetwork(const std::vector<TensorShape>& inputShapes,
24                                 const TensorShape &outputShape,
25                                 unsigned int concatAxis,
26                                 const float qScale = 1.0f,
27                                 const int32_t qOffset = 0)
28 {
29     using namespace armnn;
30     // Builds up the structure of the network.
31     INetworkPtr net(INetwork::Create());
32 
33     OriginsDescriptor descriptor;
34 
35     descriptor = CreateDescriptorForConcatenation(inputShapes.begin(),
36                                                   inputShapes.end(),
37                                                   concatAxis);
38     IConnectableLayer* concat = net->AddConcatLayer(descriptor, "concat");
39 
40     for (unsigned int i = 0; i < inputShapes.size(); ++i)
41     {
42         TensorInfo inputTensorInfo(inputShapes[i], DataType, qScale, qOffset, true);
43         IConnectableLayer* input = net->AddInputLayer(armnn::numeric_cast<LayerBindingId>(i));
44         Connect(input, concat, inputTensorInfo, 0, i);
45     }
46 
47     TensorInfo outputTensorInfo(outputShape, DataType, qScale, qOffset);
48     IConnectableLayer* output = net->AddOutputLayer(0, "output");
49     Connect(concat, output, outputTensorInfo, 0, 0);
50 
51     return net;
52 }
53 
54 template<armnn::DataType ArmnnType>
ConcatDim0EndToEnd(const std::vector<BackendId> & backends)55 void ConcatDim0EndToEnd(const std::vector<BackendId>& backends)
56 {
57     using namespace armnn;
58     using T = ResolveType<ArmnnType>;
59 
60     unsigned int concatAxis = 0;
61     const std::vector<TensorShape> inputShapes{{ 2, 3, 2, 2 }, { 2, 3, 2, 2 }};
62     const TensorShape& outputShape = { 4, 3, 2, 2 };
63 
64     // Builds up the structure of the network
65     INetworkPtr net = CreateConcatNetwork<ArmnnType>(inputShapes, outputShape, concatAxis);
66 
67     CHECK(net);
68 
69     // Creates structures for input & output.
70     std::vector<T> inputData{
71         1, 2,
72         3, 4,
73         5, 6,
74         7, 8,
75         9, 10,
76         11, 12,
77         1, 2,
78         3, 4,
79         5, 6,
80         7, 8,
81         9, 10,
82         11, 12
83     };
84 
85     std::vector<T> expectedOutput{
86         1, 2,
87         3, 4,
88         5, 6,
89         7, 8,
90         9, 10,
91         11, 12,
92         1, 2,
93         3, 4,
94         5, 6,
95         7, 8,
96         9, 10,
97         11, 12,
98         1, 2,
99         3, 4,
100         5, 6,
101         7, 8,
102         9, 10,
103         11, 12,
104         1, 2,
105         3, 4,
106         5, 6,
107         7, 8,
108         9, 10,
109         11, 12
110     };
111 
112     std::map<int, std::vector<T>> inputTensorData = {{ 0,inputData }, { 1,inputData }};
113     std::map<int, std::vector<T>> expectedOutputData = {{ 0,expectedOutput }};
114 
115     EndToEndLayerTestImpl<ArmnnType, ArmnnType>(std::move(net), inputTensorData, expectedOutputData, backends);
116 }
117 
118 template<armnn::DataType ArmnnType>
ConcatDim1EndToEnd(const std::vector<BackendId> & backends)119 void ConcatDim1EndToEnd(const std::vector<BackendId>& backends)
120 {
121     using namespace armnn;
122     using T = ResolveType<ArmnnType>;
123 
124     unsigned int concatAxis = 1;
125     const std::vector<TensorShape> inputShapes{{ 2, 3, 2, 2 }, { 2, 3, 2, 2 }};
126     const TensorShape& outputShape = { 2, 6, 2, 2 };
127 
128     // Builds up the structure of the network
129     INetworkPtr net = CreateConcatNetwork<ArmnnType>(inputShapes, outputShape, concatAxis);
130 
131     // Creates structures for input & output.
132     std::vector<T> inputData{
133         1, 2,
134         3, 4,
135         5, 6,
136         7, 8,
137         9, 10,
138         11, 12,
139         1, 2,
140         3, 4,
141         5, 6,
142         7, 8,
143         9, 10,
144         11, 12
145     };
146 
147     std::vector<T> expectedOutput{
148         1, 2,
149         3, 4,
150         5, 6,
151         7, 8,
152         9, 10,
153         11, 12,
154         1, 2,
155         3, 4,
156         5, 6,
157         7, 8,
158         9, 10,
159         11, 12,
160         1, 2,
161         3, 4,
162         5, 6,
163         7, 8,
164         9, 10,
165         11, 12,
166         1, 2,
167         3, 4,
168         5, 6,
169         7, 8,
170         9, 10,
171         11, 12
172     };
173 
174     std::map<int, std::vector<T>> inputTensorData = {{ 0,inputData }, { 1,inputData }};
175     std::map<int, std::vector<T>> expectedOutputData = {{ 0,expectedOutput }};
176 
177     EndToEndLayerTestImpl<ArmnnType, ArmnnType>(std::move(net), inputTensorData, expectedOutputData, backends);
178 }
179 
180 template<armnn::DataType ArmnnType>
ConcatDim2EndToEnd(const std::vector<BackendId> & backends)181 void ConcatDim2EndToEnd(const std::vector<BackendId>& backends)
182 {
183     using namespace armnn;
184     using T = ResolveType<ArmnnType>;
185 
186     unsigned int concatAxis = 2;
187     const std::vector<TensorShape> inputShapes{{ 2, 3, 2, 2 }, { 2, 3, 2, 2 }};
188     const TensorShape& outputShape = { 2, 3, 4, 2 };
189 
190     // Builds up the structure of the network
191     INetworkPtr net = CreateConcatNetwork<ArmnnType>(inputShapes, outputShape, concatAxis);
192 
193     // Creates structures for input & output.
194     std::vector<T> inputData{
195         1, 2,
196         3, 4,
197         5, 6,
198         7, 8,
199         9, 10,
200         11, 12,
201         1, 2,
202         3, 4,
203         5, 6,
204         7, 8,
205         9, 10,
206         11, 12
207     };
208 
209     std::vector<T> expectedOutput{
210         1, 2,
211         3, 4,
212         1, 2,
213         3, 4,
214         5, 6,
215         7, 8,
216         5, 6,
217         7, 8,
218         9, 10,
219         11, 12,
220         9, 10,
221         11, 12,
222         1, 2,
223         3, 4,
224         1, 2,
225         3, 4,
226         5, 6,
227         7, 8,
228         5, 6,
229         7, 8,
230         9, 10,
231         11, 12,
232         9, 10,
233         11, 12
234     };
235 
236     std::map<int, std::vector<T>> inputTensorData = {{ 0,inputData }, { 1,inputData }};
237     std::map<int, std::vector<T>> expectedOutputData = {{ 0,expectedOutput }};
238 
239     EndToEndLayerTestImpl<ArmnnType, ArmnnType>(std::move(net), inputTensorData, expectedOutputData, backends);
240 }
241 
242 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
ConcatDim3EndToEnd(const std::vector<BackendId> & backends)243 void ConcatDim3EndToEnd(const std::vector<BackendId>& backends)
244 {
245     using namespace armnn;
246 
247     unsigned int concatAxis = 3;
248     const std::vector<TensorShape> inputShapes{{ 2, 3, 2, 2 }, { 2, 3, 2, 2 }};
249     const TensorShape& outputShape = { 2, 3, 2, 4 };
250 
251     // Builds up the structure of the network
252     INetworkPtr net = CreateConcatNetwork<ArmnnType>(inputShapes, outputShape, concatAxis);
253 
254     // Creates structures for input & output.
255     std::vector<T> inputData{
256         1, 2,
257         3, 4,
258         5, 6,
259         7, 8,
260         9, 10,
261         11, 12,
262         1, 2,
263         3, 4,
264         5, 6,
265         7, 8,
266         9, 10,
267         11, 12
268     };
269 
270     std::vector<T> expectedOutput{
271         1, 2,
272         1, 2,
273         3, 4,
274         3, 4,
275         5, 6,
276         5, 6,
277         7, 8,
278         7, 8,
279         9, 10,
280         9, 10,
281         11, 12,
282         11, 12,
283         1, 2,
284         1, 2,
285         3, 4,
286         3, 4,
287         5, 6,
288         5, 6,
289         7, 8,
290         7, 8,
291         9, 10,
292         9, 10,
293         11, 12,
294         11, 12
295     };
296 
297     std::map<int, std::vector<T>> inputTensorData = {{ 0,inputData }, { 1,inputData }};
298     std::map<int, std::vector<T>> expectedOutputData = {{ 0,expectedOutput }};
299 
300     EndToEndLayerTestImpl<ArmnnType, ArmnnType>(std::move(net), inputTensorData, expectedOutputData, backends);
301 }
302 
303 } // anonymous namespace
304