blob: 6c069a86b7e5da9a5b8dfcd3cfad3c0f973a56c3 [file] [log] [blame]
surmeh0149b9e102018-05-17 14:11:25 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// See LICENSE file in the project root for full license information.
4//
5#include "DriverTestHelpers.hpp"
6#include "TestTensor.hpp"
7#include <boost/test/unit_test.hpp>
8#include <log/log.h>
9
10
11BOOST_AUTO_TEST_SUITE(MergerTests)
12
13using ArmnnDriver = armnn_driver::ArmnnDriver;
14using DriverOptions = armnn_driver::DriverOptions;
15using namespace driverTestHelpers;
16
17namespace
18{
19
20void
21MergerTestImpl(const std::vector<const TestTensor*> & inputs,
22 int32_t concatAxis,
23 const TestTensor & expectedOutputTensor,
24 ErrorStatus expectedPrepareStatus=ErrorStatus::NONE,
25 ErrorStatus expectedExecStatus=ErrorStatus::NONE)
26{
27 std::unique_ptr<ArmnnDriver> driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
28 Model model{};
29
30 hidl_vec<uint32_t> modelInputIds;
31 modelInputIds.resize(inputs.size()+1);
32 for (uint32_t i = 0; i<inputs.size(); ++i)
33 {
34 modelInputIds[i] = i;
35 AddInputOperand(model, inputs[i]->GetDimensions());
36 }
37 modelInputIds[inputs.size()] = inputs.size(); // add an id for the axis too
38 AddIntOperand(model, concatAxis);
39 AddOutputOperand(model, expectedOutputTensor.GetDimensions());
40
41 // make the concat operation
42 model.operations.resize(1);
43 model.operations[0].type = OperationType::CONCATENATION;
44 model.operations[0].inputs = modelInputIds;
45 model.operations[0].outputs = hidl_vec<uint32_t>{static_cast<uint32_t>(inputs.size()+1)};
46
47 // make the prepared model
48 ErrorStatus prepareStatus=ErrorStatus::NONE;
49 android::sp<IPreparedModel> preparedModel = PrepareModelWithStatus(model,
50 *driver,
51 prepareStatus,
52 expectedPrepareStatus);
53 BOOST_TEST(prepareStatus == expectedPrepareStatus);
54 if (prepareStatus != ErrorStatus::NONE)
55 {
56 // prepare failed, we cannot continue
57 return;
58 }
59
60 BOOST_TEST(preparedModel.get() != nullptr);
61 if (preparedModel.get() == nullptr)
62 {
63 // don't spoil other tests if prepare failed
64 return;
65 }
66
67 // construct the request
68 hidl_vec<RequestArgument> inputArguments;
69 hidl_vec<RequestArgument> outputArguments;
70 inputArguments.resize(inputs.size());
71 outputArguments.resize(1);
72
73 // the request's memory pools will follow the same order as
74 // the inputs
75 for (uint32_t i = 0; i<inputs.size(); ++i)
76 {
77 DataLocation inloc = {};
78 inloc.poolIndex = i;
79 inloc.offset = 0;
80 inloc.length = inputs[i]->GetNumElements() * sizeof(float);
81 RequestArgument input = {};
82 input.location = inloc;
83 input.dimensions = inputs[i]->GetDimensions();
84 inputArguments[i] = input;
85 }
86
87 // and an additional memory pool is needed for the output
88 {
89 DataLocation outloc = {};
90 outloc.poolIndex = inputs.size();
91 outloc.offset = 0;
92 outloc.length = expectedOutputTensor.GetNumElements() * sizeof(float);
93 RequestArgument output = {};
94 output.location = outloc;
95 output.dimensions = expectedOutputTensor.GetDimensions();
96 outputArguments[0] = output;
97 }
98
99 // make the request based on the arguments
100 Request request = {};
101 request.inputs = inputArguments;
102 request.outputs = outputArguments;
103
104 // set the input data
105 for (uint32_t i = 0; i<inputs.size(); ++i)
106 {
107 AddPoolAndSetData(inputs[i]->GetNumElements(),
108 request,
109 inputs[i]->GetData());
110 }
111
112 // add memory for the output
113 android::sp<IMemory> outMemory = AddPoolAndGetData(expectedOutputTensor.GetNumElements(), request);
114 float* outdata = static_cast<float*>(static_cast<void*>(outMemory->getPointer()));
115
116 // run the execution
117 auto execStatus = Execute(preparedModel, request, expectedExecStatus);
118 BOOST_TEST(execStatus == expectedExecStatus);
119
120 if (execStatus == ErrorStatus::NONE)
121 {
122 // check the result if there was no error
123 const float * expectedOutput = expectedOutputTensor.GetData();
124 for (unsigned int i=0; i<expectedOutputTensor.GetNumElements();++i)
125 {
126 BOOST_TEST(outdata[i] == expectedOutput[i]);
127 }
128 }
129}
130
131} // namespace <anonymous>
132
133BOOST_AUTO_TEST_CASE(SimpleConcatAxis0)
134{
135 int32_t axis = 0;
136 TestTensor aIn{armnn::TensorShape{1,1,1,1},{0}};
137 TestTensor bIn{armnn::TensorShape{1,1,1,1},{1}};
138 TestTensor cIn{armnn::TensorShape{1,1,1,1},{2}};
139
140 TestTensor expected{armnn::TensorShape{3,1,1,1},{0,1,2}};
141
142 MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected);
143}
144
145BOOST_AUTO_TEST_CASE(ConcatAxis0_NoInterleave)
146{
147 int32_t axis = 0;
148 TestTensor aIn{armnn::TensorShape{2,1,2,1},{0, 1,
149 2, 3}};
150 TestTensor bIn{armnn::TensorShape{3,1,2,1},{4, 5,
151 6, 7,
152 8, 9}};
153 TestTensor cIn{armnn::TensorShape{1,1,2,1},{10, 11}};
154
155 TestTensor expected{armnn::TensorShape{6,1,2,1},{0, 1,
156 2, 3,
157 4, 5,
158 6, 7,
159 8, 9,
160 10, 11}};
161
162 MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected);
163}
164
165BOOST_AUTO_TEST_CASE(SimpleConcatAxis1)
166{
167 int32_t axis = 1;
168 TestTensor aIn{armnn::TensorShape{1,1,1,1},{0}};
169 TestTensor bIn{armnn::TensorShape{1,1,1,1},{1}};
170 TestTensor cIn{armnn::TensorShape{1,1,1,1},{2}};
171
172 TestTensor expected{armnn::TensorShape{1,3,1,1},{0,1,2}};
173
174 MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected);
175}
176
177BOOST_AUTO_TEST_CASE(ConcatAxis1_NoInterleave)
178{
179 int32_t axis = 1;
180 TestTensor aIn{armnn::TensorShape{1,2,2,1},{0, 1,
181 2, 3}};
182 TestTensor bIn{armnn::TensorShape{1,3,2,1},{4, 5,
183 6, 7,
184 8, 9}};
185 TestTensor cIn{armnn::TensorShape{1,1,2,1},{10, 11}};
186
187 TestTensor expected{armnn::TensorShape{1,6,2,1},{0, 1,
188 2, 3,
189 4, 5,
190 6, 7,
191 8, 9,
192 10, 11}};
193
194 MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected);
195}
196
197BOOST_AUTO_TEST_CASE(SimpleConcatAxis1_DoInterleave)
198{
199 int32_t axis = 1;
200 TestTensor aIn{armnn::TensorShape{2,2,1,1},{0, 1,
201 2, 3}};
202 TestTensor bIn{armnn::TensorShape{2,3,1,1},{4, 5, 6,
203 7, 8, 9}};
204 TestTensor cIn{armnn::TensorShape{2,1,1,1},{10,
205 11}};
206
207 TestTensor expected{armnn::TensorShape{2,6,1,1},{0, 1, 4, 5, 6, 10,
208 2, 3, 7, 8, 9, 11}};
209
210 MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected);
211}
212
213BOOST_AUTO_TEST_CASE(SimpleConcatAxis2)
214{
215 int32_t axis = 2;
216 TestTensor aIn{armnn::TensorShape{1,1,1,1},{0}};
217 TestTensor bIn{armnn::TensorShape{1,1,1,1},{1}};
218 TestTensor cIn{armnn::TensorShape{1,1,1,1},{2}};
219
220 TestTensor expected{armnn::TensorShape{1,1,3,1},{0,1,2}};
221
222 MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected);
223}
224
225BOOST_AUTO_TEST_CASE(ConcatAxis2_NoInterleave)
226{
227 int32_t axis = 2;
228 TestTensor aIn{armnn::TensorShape{1,1,2,2},{0, 1,
229 2, 3}};
230 TestTensor bIn{armnn::TensorShape{1,1,3,2},{4, 5,
231 6, 7,
232 8, 9}};
233 TestTensor cIn{armnn::TensorShape{1,1,1,2},{10, 11}};
234
235 TestTensor expected{armnn::TensorShape{1,1,6,2},{0, 1,
236 2, 3,
237 4, 5,
238 6, 7,
239 8, 9,
240 10, 11}};
241
242 MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected);
243}
244
245BOOST_AUTO_TEST_CASE(SimpleConcatAxis2_DoInterleave)
246{
247 int32_t axis = 2;
248 TestTensor aIn{armnn::TensorShape{1,2,2,1},{0, 1,
249 2, 3}};
250 TestTensor bIn{armnn::TensorShape{1,2,3,1},{4, 5, 6,
251 7, 8, 9}};
252 TestTensor cIn{armnn::TensorShape{1,2,1,1},{10,
253 11}};
254
255 TestTensor expected{armnn::TensorShape{1,2,6,1},{0, 1, 4, 5, 6, 10,
256 2, 3, 7, 8, 9, 11}};
257
258 MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected);
259}
260
261BOOST_AUTO_TEST_CASE(SimpleConcatAxis3)
262{
263 int32_t axis = 3;
264 TestTensor aIn{armnn::TensorShape{1,1,1,1},{0}};
265 TestTensor bIn{armnn::TensorShape{1,1,1,1},{1}};
266 TestTensor cIn{armnn::TensorShape{1,1,1,1},{2}};
267
268 TestTensor expected{armnn::TensorShape{1,1,1,3},{0,1,2}};
269
270 MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected);
271}
272
273BOOST_AUTO_TEST_CASE(SimpleConcatAxis3_DoInterleave)
274{
275 int32_t axis = 3;
276 TestTensor aIn{armnn::TensorShape{1,1,2,2},{0, 1,
277 2, 3}};
278 TestTensor bIn{armnn::TensorShape{1,1,2,3},{4, 5, 6,
279 7, 8, 9}};
280 TestTensor cIn{armnn::TensorShape{1,1,2,1},{10,
281 11}};
282
283 TestTensor expected{armnn::TensorShape{1,1,2,6},{0, 1, 4, 5, 6, 10,
284 2, 3, 7, 8, 9, 11}};
285
286 MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected);
287}
288
289BOOST_AUTO_TEST_CASE(AxisTooBig)
290{
291 int32_t axis = 4;
292 TestTensor aIn{armnn::TensorShape{1,1,1,1},{0}};
293 TestTensor bIn{armnn::TensorShape{1,1,1,1},{0}};
294
295 // The axis must be within the range of [-rank(values), rank(values))
296 // see: https://www.tensorflow.org/api_docs/python/tf/concat
297 TestTensor uncheckedOutput{armnn::TensorShape{1,1,1,1},{0}};
298 ErrorStatus expectedParserStatus = ErrorStatus::GENERAL_FAILURE;
299 MergerTestImpl({&aIn, &bIn}, axis, uncheckedOutput, expectedParserStatus);
300}
301
302BOOST_AUTO_TEST_CASE(AxisTooSmall)
303{
304 int32_t axis = -5;
305 TestTensor aIn{armnn::TensorShape{1,1,1,1},{0}};
306 TestTensor bIn{armnn::TensorShape{1,1,1,1},{0}};
307
308 // The axis must be within the range of [-rank(values), rank(values))
309 // see: https://www.tensorflow.org/api_docs/python/tf/concat
310 TestTensor uncheckedOutput{armnn::TensorShape{1,1,1,1},{0}};
311 ErrorStatus expectedParserStatus = ErrorStatus::GENERAL_FAILURE;
312 MergerTestImpl({&aIn, &bIn}, axis, uncheckedOutput, expectedParserStatus);
313}
314
315BOOST_AUTO_TEST_CASE(TooFewInputs)
316{
317 int32_t axis = 0;
318 TestTensor aIn{armnn::TensorShape{1,1,1,1},{0}};
319
320 // We need at least two tensors to concatenate
321 ErrorStatus expectedParserStatus = ErrorStatus::GENERAL_FAILURE;
322 MergerTestImpl({&aIn}, axis, aIn, expectedParserStatus);
323}
324
325BOOST_AUTO_TEST_CASE(MismatchedInputDimensions)
326{
327 int32_t axis = 3;
328 TestTensor aIn{armnn::TensorShape{1,1,2,2},{0, 1,
329 2, 3}};
330 TestTensor bIn{armnn::TensorShape{1,1,2,3},{4, 5, 6,
331 7, 8, 9}};
332 TestTensor mismatched{armnn::TensorShape{1,1,1,1},{10}};
333
334 TestTensor expected{armnn::TensorShape{1,1,2,6},{0, 1, 4, 5, 6, 10,
335 2, 3, 7, 8, 9, 11}};
336
337 // The input dimensions must be compatible
338 ErrorStatus expectedParserStatus = ErrorStatus::GENERAL_FAILURE;
339 MergerTestImpl({&aIn, &bIn, &mismatched}, axis, expected, expectedParserStatus);
340}
341
342BOOST_AUTO_TEST_CASE(MismatchedInputRanks)
343{
344 int32_t axis = 2;
345 TestTensor aIn{armnn::TensorShape{1,1,2},{0,1}};
346 TestTensor bIn{armnn::TensorShape{1,1},{4}};
347 TestTensor expected{armnn::TensorShape{1,1,3},{0,1,4}};
348
349 // The input dimensions must be compatible
350 ErrorStatus expectedParserStatus = ErrorStatus::GENERAL_FAILURE;
351 MergerTestImpl({&aIn, &bIn}, axis, expected, expectedParserStatus);
352}
353
354BOOST_AUTO_TEST_CASE(MismatchedOutputDimensions)
355{
356 int32_t axis = 3;
357 TestTensor aIn{armnn::TensorShape{1,1,2,2},{0, 1,
358 2, 3}};
359 TestTensor bIn{armnn::TensorShape{1,1,2,3},{4, 5, 6,
360 7, 8, 9}};
361 TestTensor cIn{armnn::TensorShape{1,1,2,1},{10,
362 11}};
363
364 TestTensor mismatched{armnn::TensorShape{1,1,6,2},{0, 1, 4, 5, 6, 10,
365 2, 3, 7, 8, 9, 11}};
366
367 // The input and output dimensions must be compatible
368 ErrorStatus expectedParserStatus = ErrorStatus::GENERAL_FAILURE;
369 MergerTestImpl({&aIn, &bIn, &cIn}, axis, mismatched, expectedParserStatus);
370}
371
372BOOST_AUTO_TEST_CASE(MismatchedOutputRank)
373{
374 int32_t axis = 3;
375 TestTensor aIn{armnn::TensorShape{1,1,2,2},{0, 1,
376 2, 3}};
377 TestTensor bIn{armnn::TensorShape{1,1,2,3},{4, 5, 6,
378 7, 8, 9}};
379 TestTensor cIn{armnn::TensorShape{1,1,2,1},{10,
380 11}};
381
382 TestTensor mismatched{armnn::TensorShape{6,2},{0, 1, 4, 5, 6, 10,
383 2, 3, 7, 8, 9, 11}};
384
385 // The input and output ranks must match
386 ErrorStatus expectedParserStatus = ErrorStatus::GENERAL_FAILURE;
387 MergerTestImpl({&aIn, &bIn, &cIn}, axis, mismatched, expectedParserStatus);
388}
389
390BOOST_AUTO_TEST_CASE(ValidNegativeAxis)
391{
392 // this is the same as 3
393 // see: https://www.tensorflow.org/api_docs/python/tf/concat
394 int32_t axis = -1;
395 TestTensor aIn{armnn::TensorShape{1,1,2,2},{0, 1,
396 2, 3}};
397 TestTensor bIn{armnn::TensorShape{1,1,2,3},{4, 5, 6,
398 7, 8, 9}};
399 TestTensor cIn{armnn::TensorShape{1,1,2,1},{10,
400 11}};
401
402 TestTensor expected{armnn::TensorShape{1,1,2,6},{0, 1, 4, 5, 6, 10,
403 2, 3, 7, 8, 9, 11}};
404
405 MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected);
406}
407
408BOOST_AUTO_TEST_SUITE_END()