blob: 3c47eab01f240ef260c17b31a6bffd667674a270 [file] [log] [blame]
telsoa014fcda012018-03-09 14:13:49 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
telsoa014fcda012018-03-09 14:13:49 +00004//
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +00005
6#include "WorkloadTestUtils.hpp"
telsoa014fcda012018-03-09 14:13:49 +00007
8#include <armnn/Exceptions.hpp>
9
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000010#include <backendsCommon/CpuTensorHandle.hpp>
11#include <backendsCommon/Workload.hpp>
12
13#include <reference/workloads/RefWorkloads.hpp>
14#include <reference/RefWorkloadFactory.hpp>
15
16#include <boost/test/unit_test.hpp>
telsoa014fcda012018-03-09 14:13:49 +000017
18using namespace armnn;
19
20BOOST_AUTO_TEST_SUITE(WorkloadInfoValidation)
21
22
23
24BOOST_AUTO_TEST_CASE(QueueDescriptor_Validate_WrongNumOfInputsOutputs)
25{
26 InputQueueDescriptor invalidData;
27 WorkloadInfo invalidInfo;
telsoa01c577f2c2018-08-31 09:22:23 +010028 //Invalid argument exception is expected, because no inputs and no outputs were defined.
telsoa014fcda012018-03-09 14:13:49 +000029 BOOST_CHECK_THROW(RefWorkloadFactory().CreateInput(invalidData, invalidInfo), armnn::InvalidArgumentException);
30}
31
32BOOST_AUTO_TEST_CASE(RefPooling2dFloat32Workload_Validate_WrongDimTensor)
33{
34 armnn::TensorInfo inputTensorInfo;
35 armnn::TensorInfo outputTensorInfo;
36
telsoa01c577f2c2018-08-31 09:22:23 +010037 unsigned int inputShape[] = {2, 3, 4}; // <- Invalid - input tensor has to be 4D.
telsoa014fcda012018-03-09 14:13:49 +000038 unsigned int outputShape[] = {2, 3, 4, 5};
39
40 outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32);
41 inputTensorInfo = armnn::TensorInfo(3, inputShape, armnn::DataType::Float32);
42
43 Pooling2dQueueDescriptor invalidData;
44 WorkloadInfo invalidInfo;
45
46 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
47 AddInputToWorkload(invalidData, invalidInfo, inputTensorInfo, nullptr);
48
telsoa01c577f2c2018-08-31 09:22:23 +010049 // Invalid argument exception is expected, input tensor has to be 4D.
Teresa Charlina3b20472019-06-06 11:12:32 +010050 BOOST_CHECK_THROW(RefPooling2dWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +000051}
52
53BOOST_AUTO_TEST_CASE(SoftmaxQueueDescriptor_Validate_WrongInputHeight)
54{
55 unsigned int inputHeight = 1;
56 unsigned int inputWidth = 1;
57 unsigned int inputChannels = 4;
58 unsigned int inputNum = 2;
59
60 unsigned int outputChannels = inputChannels;
telsoa01c577f2c2018-08-31 09:22:23 +010061 unsigned int outputHeight = inputHeight + 1; //Makes data invalid - Softmax expects height and width to be 1.
telsoa014fcda012018-03-09 14:13:49 +000062 unsigned int outputWidth = inputWidth;
63 unsigned int outputNum = inputNum;
64
65 armnn::TensorInfo inputTensorInfo;
66 armnn::TensorInfo outputTensorInfo;
67
68 unsigned int inputShape[] = { inputNum, inputChannels, inputHeight, inputWidth };
69 unsigned int outputShape[] = { outputNum, outputChannels, outputHeight, outputWidth };
70
71 inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32);
72 outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32);
73
74 SoftmaxQueueDescriptor invalidData;
75 WorkloadInfo invalidInfo;
76
77 AddInputToWorkload(invalidData, invalidInfo, inputTensorInfo, nullptr);
78 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
79
telsoa01c577f2c2018-08-31 09:22:23 +010080 //Invalid argument exception is expected, because height != 1.
nikraj01a121de32019-05-29 10:51:05 +010081 BOOST_CHECK_THROW(RefSoftmaxWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +000082}
83
84BOOST_AUTO_TEST_CASE(FullyConnectedQueueDescriptor_Validate_RequiredDataMissing)
85{
86 unsigned int inputWidth = 1;
87 unsigned int inputHeight = 1;
88 unsigned int inputChannels = 5;
89 unsigned int inputNum = 2;
90
91 unsigned int outputWidth = 1;
92 unsigned int outputHeight = 1;
93 unsigned int outputChannels = 3;
94 unsigned int outputNum = 2;
95
telsoa01c577f2c2018-08-31 09:22:23 +010096 // Define the tensor descriptors.
telsoa014fcda012018-03-09 14:13:49 +000097 armnn::TensorInfo inputTensorInfo;
98 armnn::TensorInfo outputTensorInfo;
99 armnn::TensorInfo weightsDesc;
100 armnn::TensorInfo biasesDesc;
101
102 unsigned int inputShape[] = { inputNum, inputChannels, inputHeight, inputWidth };
103 unsigned int outputShape[] = { outputNum, outputChannels, outputHeight, outputWidth };
104 unsigned int weightsShape[] = { 1, 1, inputChannels, outputChannels };
105 unsigned int biasShape[] = { 1, outputChannels, outputHeight, outputWidth };
106
107 inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32);
108 outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32);
109 weightsDesc = armnn::TensorInfo(4, weightsShape, armnn::DataType::Float32);
110 biasesDesc = armnn::TensorInfo(4, biasShape, armnn::DataType::Float32);
111
112 FullyConnectedQueueDescriptor invalidData;
113 WorkloadInfo invalidInfo;
114
115 ScopedCpuTensorHandle weightTensor(weightsDesc);
116 ScopedCpuTensorHandle biasTensor(biasesDesc);
117
118 AddInputToWorkload(invalidData, invalidInfo, inputTensorInfo, nullptr);
119 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
120 invalidData.m_Weight = &weightTensor;
121 invalidData.m_Bias = &biasTensor;
122 invalidData.m_Parameters.m_BiasEnabled = true;
123 invalidData.m_Parameters.m_TransposeWeightMatrix = false;
124
125
telsoa01c577f2c2018-08-31 09:22:23 +0100126 //Invalid argument exception is expected, because not all required fields have been provided.
127 //In particular inputsData[0], outputsData[0] and weightsData can not be null.
Francis Murtagh43aec582019-05-27 12:14:10 +0100128 BOOST_CHECK_THROW(RefFullyConnectedWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000129}
130
131
132BOOST_AUTO_TEST_CASE(NormalizationQueueDescriptor_Validate_WrongInputHeight)
133{
134 constexpr unsigned int inputNum = 5;
135 constexpr unsigned int inputHeight = 32;
136 constexpr unsigned int inputWidth = 24;
137 constexpr unsigned int inputChannels = 3;
138
139 constexpr unsigned int outputNum = inputNum;
140 constexpr unsigned int outputChannels = inputChannels;
telsoa01c577f2c2018-08-31 09:22:23 +0100141 constexpr unsigned int outputHeight = inputHeight + 1; //Makes data invalid - normalization requires.
142 //Input and output to have the same dimensions.
telsoa014fcda012018-03-09 14:13:49 +0000143 constexpr unsigned int outputWidth = inputWidth;
144
145
146 armnn::TensorInfo inputTensorInfo;
147 armnn::TensorInfo outputTensorInfo;
148
149 unsigned int inputShape[] = {inputNum, inputChannels, inputHeight, inputWidth};
150 unsigned int outputShape[] = {outputNum, outputChannels, outputHeight, outputWidth};
151
152 inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32);
153 outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32);
154
155
156 armnn::NormalizationAlgorithmMethod normMethod = armnn::NormalizationAlgorithmMethod::LocalBrightness;
157 armnn::NormalizationAlgorithmChannel normChannel = armnn::NormalizationAlgorithmChannel::Across;
158 float alpha = 1.f;
159 float beta = 1.f;
160 float kappa = 1.f;
161 uint32_t normSize = 5;
162
163 NormalizationQueueDescriptor invalidData;
164 WorkloadInfo invalidInfo;
165
166 AddInputToWorkload(invalidData, invalidInfo, inputTensorInfo, nullptr);
167 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
168 invalidData.m_Parameters.m_NormChannelType = normChannel;
169 invalidData.m_Parameters.m_NormMethodType = normMethod;
170 invalidData.m_Parameters.m_NormSize = normSize;
171 invalidData.m_Parameters.m_Alpha = alpha;
172 invalidData.m_Parameters.m_Beta = beta;
173 invalidData.m_Parameters.m_K = kappa;
174
telsoa01c577f2c2018-08-31 09:22:23 +0100175 //Invalid argument exception is expected, because input height != output height.
Matteo Martincigh2fc70c52019-06-05 14:12:48 +0100176 BOOST_CHECK_THROW(RefNormalizationWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000177}
178
179BOOST_AUTO_TEST_CASE(SplitterQueueDescriptor_Validate_WrongWindow)
180{
181 constexpr unsigned int inputNum = 1;
182 constexpr unsigned int inputHeight = 32;
183 constexpr unsigned int inputWidth = 24;
184 constexpr unsigned int inputChannels = 3;
185
186 constexpr unsigned int outputNum = inputNum;
187 constexpr unsigned int outputChannels = inputChannels;
188 constexpr unsigned int outputHeight = 18;
189 constexpr unsigned int outputWidth = inputWidth;
190
191
192 armnn::TensorInfo inputTensorInfo;
193 armnn::TensorInfo outputTensorInfo;
194
195 unsigned int inputShape[] = {inputNum, inputChannels, inputHeight, inputWidth};
196 unsigned int outputShape[] = {outputNum, outputChannels, outputHeight, outputWidth};
197
198 inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32);
199 outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32);
200
201 SplitterQueueDescriptor invalidData;
202 WorkloadInfo invalidInfo;
203
204 AddInputToWorkload(invalidData, invalidInfo, inputTensorInfo, nullptr);
205 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
206
telsoa01c577f2c2018-08-31 09:22:23 +0100207 // Invalid, since it has only 3 dimensions while the input tensor is 4d.
telsoa014fcda012018-03-09 14:13:49 +0000208 std::vector<unsigned int> wOrigin = {0, 0, 0};
209 armnn::SplitterQueueDescriptor::ViewOrigin window(wOrigin);
210 invalidData.m_ViewOrigins.push_back(window);
211
212 BOOST_TEST_INFO("Invalid argument exception is expected, because split window dimensionality does not "
213 "match input.");
Ruomei Yan25339c32019-05-28 16:48:20 +0100214 BOOST_CHECK_THROW(RefSplitterWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000215
telsoa01c577f2c2018-08-31 09:22:23 +0100216 // Invalid, since window extends past the boundary of input tensor.
telsoa014fcda012018-03-09 14:13:49 +0000217 std::vector<unsigned int> wOrigin3 = {0, 0, 15, 0};
218 armnn::SplitterQueueDescriptor::ViewOrigin window3(wOrigin3);
219 invalidData.m_ViewOrigins[0] = window3;
220 BOOST_TEST_INFO("Invalid argument exception is expected (wOrigin3[2]+ outputHeight > inputHeight");
Ruomei Yan25339c32019-05-28 16:48:20 +0100221 BOOST_CHECK_THROW(RefSplitterWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000222
223
224 std::vector<unsigned int> wOrigin4 = {0, 0, 0, 0};
225 armnn::SplitterQueueDescriptor::ViewOrigin window4(wOrigin4);
226 invalidData.m_ViewOrigins[0] = window4;
227
228 std::vector<unsigned int> wOrigin5 = {1, 16, 20, 2};
229 armnn::SplitterQueueDescriptor::ViewOrigin window5(wOrigin4);
230 invalidData.m_ViewOrigins.push_back(window5);
231
232 BOOST_TEST_INFO("Invalid exception due to number of split windows not matching number of outputs.");
Ruomei Yan25339c32019-05-28 16:48:20 +0100233 BOOST_CHECK_THROW(RefSplitterWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000234}
235
236
Jim Flynne242f2d2019-05-22 14:24:13 +0100237BOOST_AUTO_TEST_CASE(ConcatQueueDescriptor_Validate_WrongWindow)
telsoa014fcda012018-03-09 14:13:49 +0000238{
239 constexpr unsigned int inputNum = 1;
240 constexpr unsigned int inputChannels = 3;
241 constexpr unsigned int inputHeight = 32;
242 constexpr unsigned int inputWidth = 24;
243
244 constexpr unsigned int outputNum = 1;
245 constexpr unsigned int outputChannels = 3;
246 constexpr unsigned int outputHeight = 32;
247 constexpr unsigned int outputWidth = 24;
248
249
250 armnn::TensorInfo inputTensorInfo;
251 armnn::TensorInfo outputTensorInfo;
252
253 unsigned int inputShape[] = {inputNum, inputChannels, inputHeight, inputWidth};
254 unsigned int outputShape[] = {outputNum, outputChannels, outputHeight, outputWidth};
255
256 inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32);
257 outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32);
258
Jim Flynne242f2d2019-05-22 14:24:13 +0100259 ConcatQueueDescriptor invalidData;
telsoa014fcda012018-03-09 14:13:49 +0000260 WorkloadInfo invalidInfo;
261
262 AddInputToWorkload(invalidData, invalidInfo, inputTensorInfo, nullptr);
263 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
264
telsoa01c577f2c2018-08-31 09:22:23 +0100265 // Invalid, since it has only 3 dimensions while the input tensor is 4d.
telsoa014fcda012018-03-09 14:13:49 +0000266 std::vector<unsigned int> wOrigin = {0, 0, 0};
Jim Flynne242f2d2019-05-22 14:24:13 +0100267 armnn::ConcatQueueDescriptor::ViewOrigin window(wOrigin);
telsoa014fcda012018-03-09 14:13:49 +0000268 invalidData.m_ViewOrigins.push_back(window);
269
270 BOOST_TEST_INFO("Invalid argument exception is expected, because merge window dimensionality does not "
271 "match input.");
Jim Flynn4ed34ed2019-05-17 15:32:17 +0100272 BOOST_CHECK_THROW(RefConcatWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000273
telsoa01c577f2c2018-08-31 09:22:23 +0100274 // Invalid, since window extends past the boundary of output tensor.
telsoa014fcda012018-03-09 14:13:49 +0000275 std::vector<unsigned int> wOrigin3 = {0, 0, 15, 0};
Jim Flynne242f2d2019-05-22 14:24:13 +0100276 armnn::ConcatQueueDescriptor::ViewOrigin window3(wOrigin3);
telsoa014fcda012018-03-09 14:13:49 +0000277 invalidData.m_ViewOrigins[0] = window3;
278 BOOST_TEST_INFO("Invalid argument exception is expected (wOrigin3[2]+ inputHeight > outputHeight");
Jim Flynn4ed34ed2019-05-17 15:32:17 +0100279 BOOST_CHECK_THROW(RefConcatWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000280
281
282 std::vector<unsigned int> wOrigin4 = {0, 0, 0, 0};
Jim Flynne242f2d2019-05-22 14:24:13 +0100283 armnn::ConcatQueueDescriptor::ViewOrigin window4(wOrigin4);
telsoa014fcda012018-03-09 14:13:49 +0000284 invalidData.m_ViewOrigins[0] = window4;
285
286 std::vector<unsigned int> wOrigin5 = {1, 16, 20, 2};
Jim Flynne242f2d2019-05-22 14:24:13 +0100287 armnn::ConcatQueueDescriptor::ViewOrigin window5(wOrigin4);
telsoa014fcda012018-03-09 14:13:49 +0000288 invalidData.m_ViewOrigins.push_back(window5);
289
290 BOOST_TEST_INFO("Invalid exception due to number of merge windows not matching number of inputs.");
Jim Flynn4ed34ed2019-05-17 15:32:17 +0100291 BOOST_CHECK_THROW(RefConcatWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000292}
293
294BOOST_AUTO_TEST_CASE(AdditionQueueDescriptor_Validate_InputNumbers)
295{
296 armnn::TensorInfo input1TensorInfo;
297 armnn::TensorInfo input2TensorInfo;
298 armnn::TensorInfo input3TensorInfo;
299 armnn::TensorInfo outputTensorInfo;
300
301 unsigned int shape[] = {1, 1, 1, 1};
302
303 input1TensorInfo = armnn::TensorInfo(4, shape, armnn::DataType::Float32);
304 input2TensorInfo = armnn::TensorInfo(4, shape, armnn::DataType::Float32);
305 input3TensorInfo = armnn::TensorInfo(4, shape, armnn::DataType::Float32);
306 outputTensorInfo = armnn::TensorInfo(4, shape, armnn::DataType::Float32);
307
308 AdditionQueueDescriptor invalidData;
309 WorkloadInfo invalidInfo;
310
311 AddInputToWorkload(invalidData, invalidInfo, input1TensorInfo, nullptr);
312 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
313
telsoa01c577f2c2018-08-31 09:22:23 +0100314 // Too few inputs.
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100315 BOOST_CHECK_THROW(RefAdditionWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000316
317 AddInputToWorkload(invalidData, invalidInfo, input2TensorInfo, nullptr);
318
telsoa01c577f2c2018-08-31 09:22:23 +0100319 // Correct.
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100320 BOOST_CHECK_NO_THROW(RefAdditionWorkload(invalidData, invalidInfo));
telsoa014fcda012018-03-09 14:13:49 +0000321
322 AddInputToWorkload(invalidData, invalidInfo, input3TensorInfo, nullptr);
323
telsoa01c577f2c2018-08-31 09:22:23 +0100324 // Too many inputs.
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100325 BOOST_CHECK_THROW(RefAdditionWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000326}
327
328BOOST_AUTO_TEST_CASE(AdditionQueueDescriptor_Validate_InputShapes)
329{
330 armnn::TensorInfo input1TensorInfo;
331 armnn::TensorInfo input2TensorInfo;
332 armnn::TensorInfo outputTensorInfo;
333
334 unsigned int shape1[] = {1, 1, 2, 1};
335 unsigned int shape2[] = {1, 1, 3, 2};
336
telsoa01c577f2c2018-08-31 09:22:23 +0100337 // Incompatible shapes even with broadcasting.
telsoa014fcda012018-03-09 14:13:49 +0000338 {
339 input1TensorInfo = armnn::TensorInfo(4, shape1, armnn::DataType::Float32);
340 input2TensorInfo = armnn::TensorInfo(4, shape2, armnn::DataType::Float32);
341 outputTensorInfo = armnn::TensorInfo(4, shape1, armnn::DataType::Float32);
342
343 AdditionQueueDescriptor invalidData;
344 WorkloadInfo invalidInfo;
345
346 AddInputToWorkload(invalidData, invalidInfo, input1TensorInfo, nullptr);
347 AddInputToWorkload(invalidData, invalidInfo, input2TensorInfo, nullptr);
348 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
349
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100350 BOOST_CHECK_THROW(RefAdditionWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000351 }
352
telsoa01c577f2c2018-08-31 09:22:23 +0100353 // Output size not compatible with input sizes.
telsoa014fcda012018-03-09 14:13:49 +0000354 {
355 input1TensorInfo = armnn::TensorInfo(4, shape1, armnn::DataType::Float32);
356 input2TensorInfo = armnn::TensorInfo(4, shape1, armnn::DataType::Float32);
357 outputTensorInfo = armnn::TensorInfo(4, shape2, armnn::DataType::Float32);
358
359 AdditionQueueDescriptor invalidData;
360 WorkloadInfo invalidInfo;
361
362 AddInputToWorkload(invalidData, invalidInfo, input1TensorInfo, nullptr);
363 AddInputToWorkload(invalidData, invalidInfo, input2TensorInfo, nullptr);
364 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
365
telsoa01c577f2c2018-08-31 09:22:23 +0100366 // Output differs.
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100367 BOOST_CHECK_THROW(RefAdditionWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000368 }
369}
370
371BOOST_AUTO_TEST_CASE(MultiplicationQueueDescriptor_Validate_InputTensorDimensionMismatch)
372{
373 armnn::TensorInfo input0TensorInfo;
374 armnn::TensorInfo input1TensorInfo;
375 armnn::TensorInfo outputTensorInfo;
376
377 constexpr unsigned int input0Shape[] = { 2, 2, 4, 4 };
378 constexpr std::size_t dimensionCount = std::extent<decltype(input0Shape)>::value;
379
telsoa01c577f2c2018-08-31 09:22:23 +0100380 // Checks dimension consistency for input tensors.
telsoa014fcda012018-03-09 14:13:49 +0000381 for (unsigned int dimIndex = 0; dimIndex < dimensionCount; ++dimIndex)
382 {
383 unsigned int input1Shape[dimensionCount];
384 for (unsigned int i = 0; i < dimensionCount; ++i)
385 {
386 input1Shape[i] = input0Shape[i];
387 }
388
389 ++input1Shape[dimIndex];
390
391 input0TensorInfo = armnn::TensorInfo(dimensionCount, input0Shape, armnn::DataType::Float32);
392 input1TensorInfo = armnn::TensorInfo(dimensionCount, input1Shape, armnn::DataType::Float32);
393 outputTensorInfo = armnn::TensorInfo(dimensionCount, input0Shape, armnn::DataType::Float32);
394
395 MultiplicationQueueDescriptor invalidData;
396 WorkloadInfo invalidInfo;
397
398 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
399 AddInputToWorkload(invalidData, invalidInfo, input0TensorInfo, nullptr);
400 AddInputToWorkload(invalidData, invalidInfo, input1TensorInfo, nullptr);
401
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100402 BOOST_CHECK_THROW(RefMultiplicationWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000403 }
404
telsoa01c577f2c2018-08-31 09:22:23 +0100405 // Checks dimension consistency for input and output tensors.
telsoa014fcda012018-03-09 14:13:49 +0000406 for (unsigned int dimIndex = 0; dimIndex < dimensionCount; ++dimIndex)
407 {
408 unsigned int outputShape[dimensionCount];
409 for (unsigned int i = 0; i < dimensionCount; ++i)
410 {
411 outputShape[i] = input0Shape[i];
412 }
413
414 ++outputShape[dimIndex];
415
416 input0TensorInfo = armnn::TensorInfo(dimensionCount, input0Shape, armnn::DataType::Float32);
417 input1TensorInfo = armnn::TensorInfo(dimensionCount, input0Shape, armnn::DataType::Float32);
418 outputTensorInfo = armnn::TensorInfo(dimensionCount, outputShape, armnn::DataType::Float32);
419
420 MultiplicationQueueDescriptor invalidData;
421 WorkloadInfo invalidInfo;
422
423 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
424 AddInputToWorkload(invalidData, invalidInfo, input0TensorInfo, nullptr);
425 AddInputToWorkload(invalidData, invalidInfo, input1TensorInfo, nullptr);
426
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100427 BOOST_CHECK_THROW(RefMultiplicationWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000428 }
429}
430
431BOOST_AUTO_TEST_CASE(ReshapeQueueDescriptor_Validate_MismatchingNumElements)
432{
433 armnn::TensorInfo inputTensorInfo;
434 armnn::TensorInfo outputTensorInfo;
435
telsoa01c577f2c2018-08-31 09:22:23 +0100436 // The input and output shapes should have the same number of elements, but these don't.
telsoa014fcda012018-03-09 14:13:49 +0000437 unsigned int inputShape[] = { 1, 1, 2, 3 };
438 unsigned int outputShape[] = { 1, 1, 1, 2 };
439
440 inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32);
441 outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32);
442
443 ReshapeQueueDescriptor invalidData;
444 WorkloadInfo invalidInfo;
445
446 AddInputToWorkload(invalidData, invalidInfo, inputTensorInfo, nullptr);
447 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
448
telsoa01c577f2c2018-08-31 09:22:23 +0100449 // InvalidArgumentException is expected, because the number of elements don't match.
Nina Drozd2f2778f2019-05-27 10:37:05 +0100450 BOOST_CHECK_THROW(RefReshapeWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000451}
452
telsoa01c577f2c2018-08-31 09:22:23 +0100453
454BOOST_AUTO_TEST_CASE(LstmQueueDescriptor_Validate)
455{
Jan Eilers38e05bd2019-06-26 13:10:09 +0100456 armnn::DataType dataType = armnn::DataType::Float32;
telsoa01c577f2c2018-08-31 09:22:23 +0100457
Jan Eilers38e05bd2019-06-26 13:10:09 +0100458 float qScale = 0.0f;
459 int32_t qOffset = 0;
telsoa01c577f2c2018-08-31 09:22:23 +0100460
Jan Eilers38e05bd2019-06-26 13:10:09 +0100461 unsigned int batchSize = 2;
462 unsigned int outputSize = 3;
463 unsigned int inputSize = 5;
464 unsigned numUnits = 4;
telsoa01c577f2c2018-08-31 09:22:23 +0100465
Jan Eilers38e05bd2019-06-26 13:10:09 +0100466 armnn::TensorInfo inputTensorInfo({batchSize , inputSize}, dataType, qScale, qOffset );
467 armnn::TensorInfo outputStateInTensorInfo({batchSize , outputSize}, dataType, qScale, qOffset);
468 armnn::TensorInfo cellStateInTensorInfo({batchSize , numUnits}, dataType, qScale, qOffset);
telsoa01c577f2c2018-08-31 09:22:23 +0100469
Jan Eilers38e05bd2019-06-26 13:10:09 +0100470 // Scratch buffer size with CIFG [batchSize, numUnits * 4]
471 armnn::TensorInfo scratchBufferTensorInfo({batchSize, numUnits * 4}, dataType, qScale, qOffset);
472 armnn::TensorInfo cellStateOutTensorInfo({batchSize, numUnits}, dataType, qScale, qOffset);
473 armnn::TensorInfo outputStateOutTensorInfo({batchSize, outputSize}, dataType, qScale, qOffset);
474 armnn::TensorInfo outputTensorInfo({batchSize, outputSize}, dataType, qScale, qOffset);
telsoa01c577f2c2018-08-31 09:22:23 +0100475
Jan Eilers38e05bd2019-06-26 13:10:09 +0100476 armnn::TensorInfo tensorInfo3({outputSize}, dataType, qScale, qOffset);
477 armnn::TensorInfo tensorInfo4({numUnits}, dataType, qScale, qOffset);
478 armnn::TensorInfo tensorInfo4x5({numUnits, inputSize}, dataType, qScale, qOffset);
479 armnn::TensorInfo tensorInfo4x3({numUnits, outputSize}, dataType, qScale, qOffset);
480 armnn::TensorInfo tensorInfo3x4({outputSize, numUnits}, dataType, qScale, qOffset);
481
482 LstmQueueDescriptor data;
483 WorkloadInfo info;
484
485 AddInputToWorkload(data, info, inputTensorInfo, nullptr);
486 AddInputToWorkload(data, info, outputStateInTensorInfo, nullptr);
487 AddInputToWorkload(data, info, cellStateInTensorInfo, nullptr);
488
489 AddOutputToWorkload(data, info, scratchBufferTensorInfo, nullptr);
490 AddOutputToWorkload(data, info, outputStateOutTensorInfo, nullptr);
491 AddOutputToWorkload(data, info, cellStateOutTensorInfo, nullptr);
492 // AddOutputToWorkload(data, info, outputTensorInfo, nullptr); is left out
493
494 armnn::ScopedCpuTensorHandle inputToInputWeightsTensor(tensorInfo4x5);
495 armnn::ScopedCpuTensorHandle inputToForgetWeightsTensor(tensorInfo4x5);
496 armnn::ScopedCpuTensorHandle inputToCellWeightsTensor(tensorInfo4x5);
497 armnn::ScopedCpuTensorHandle inputToOutputWeightsTensor(tensorInfo4x5);
498 armnn::ScopedCpuTensorHandle recurrentToForgetWeightsTensor(tensorInfo4x3);
499 armnn::ScopedCpuTensorHandle recurrentToInputWeightsTensor(tensorInfo4x3);
500 armnn::ScopedCpuTensorHandle recurrentToCellWeightsTensor(tensorInfo4x3);
501 armnn::ScopedCpuTensorHandle recurrentToOutputWeightsTensor(tensorInfo4x3);
502 armnn::ScopedCpuTensorHandle cellToInputWeightsTensor(tensorInfo4);
503 armnn::ScopedCpuTensorHandle inputGateBiasTensor(tensorInfo4);
504 armnn::ScopedCpuTensorHandle forgetGateBiasTensor(tensorInfo4);
505 armnn::ScopedCpuTensorHandle cellBiasTensor(tensorInfo4);
506 armnn::ScopedCpuTensorHandle outputGateBiasTensor(tensorInfo4);
507 armnn::ScopedCpuTensorHandle cellToForgetWeightsTensor(tensorInfo4);
508 armnn::ScopedCpuTensorHandle cellToOutputWeightsTensor(tensorInfo4);
509 armnn::ScopedCpuTensorHandle projectionWeightsTensor(tensorInfo3x4);
510 armnn::ScopedCpuTensorHandle projectionBiasTensor(tensorInfo3);
511 armnn::ScopedCpuTensorHandle inputLayerNormWeightsTensor(tensorInfo4);
512 armnn::ScopedCpuTensorHandle forgetLayerNormWeightsTensor(tensorInfo4);
513 armnn::ScopedCpuTensorHandle cellLayerNormWeightsTensor(tensorInfo4);
514 armnn::ScopedCpuTensorHandle outputLayerNormWeightsTensor(tensorInfo4);
515
516 data.m_InputToInputWeights = &inputToInputWeightsTensor;
517 data.m_InputToForgetWeights = &inputToForgetWeightsTensor;
518 data.m_InputToCellWeights = &inputToCellWeightsTensor;
519 data.m_InputToOutputWeights = &inputToOutputWeightsTensor;
520 data.m_RecurrentToInputWeights = &recurrentToInputWeightsTensor;
521 data.m_RecurrentToForgetWeights = &recurrentToForgetWeightsTensor;
522 data.m_RecurrentToCellWeights = &recurrentToCellWeightsTensor;
523 data.m_RecurrentToOutputWeights = &recurrentToOutputWeightsTensor;
524 data.m_CellToInputWeights = &cellToInputWeightsTensor;
525 data.m_InputGateBias = &inputGateBiasTensor;
526 data.m_ForgetGateBias = &forgetGateBiasTensor;
527 data.m_CellBias = &cellBiasTensor;
528 data.m_OutputGateBias = &outputGateBiasTensor;
529 data.m_CellToForgetWeights = &cellToForgetWeightsTensor;
530 data.m_CellToOutputWeights = &cellToOutputWeightsTensor;
531 data.m_ProjectionWeights = &projectionWeightsTensor;
532 data.m_ProjectionBias = &projectionBiasTensor;
533
534 data.m_InputLayerNormWeights = &inputLayerNormWeightsTensor;
535 data.m_ForgetLayerNormWeights = &forgetLayerNormWeightsTensor;
536 data.m_CellLayerNormWeights = &cellLayerNormWeightsTensor;
537 data.m_OutputLayerNormWeights = &outputLayerNormWeightsTensor;
538
539 // Flags to set test configuration
540 data.m_Parameters.m_ActivationFunc = 4;
541 data.m_Parameters.m_CifgEnabled = false;
542 data.m_Parameters.m_PeepholeEnabled = true;
543 data.m_Parameters.m_ProjectionEnabled = true;
544 data.m_Parameters.m_LayerNormEnabled = true;
545
546 // check wrong number of outputs
547 BOOST_CHECK_THROW(data.Validate(info), armnn::InvalidArgumentException);
548 AddOutputToWorkload(data, info, outputTensorInfo, nullptr);
549
550 // check wrong cifg parameter configuration
551 data.m_Parameters.m_CifgEnabled = true;
552 armnn::TensorInfo scratchBufferTensorInfo2({batchSize, numUnits * 3}, dataType, qScale, qOffset);
553 SetWorkloadOutput(data, info, 0, scratchBufferTensorInfo2, nullptr);
554 BOOST_CHECK_THROW(data.Validate(info), armnn::InvalidArgumentException);
555 data.m_Parameters.m_CifgEnabled = false;
556 SetWorkloadOutput(data, info, 0, scratchBufferTensorInfo, nullptr);
557
558 // check wrong inputGateBias configuration
559 data.m_InputGateBias = nullptr;
560 BOOST_CHECK_THROW(data.Validate(info), armnn::InvalidArgumentException);
561 data.m_InputGateBias = &inputGateBiasTensor;
562
563 // check inconsistant projection parameters
564 data.m_Parameters.m_ProjectionEnabled = false;
565 BOOST_CHECK_THROW(data.Validate(info), armnn::InvalidArgumentException);
566 data.m_Parameters.m_ProjectionEnabled = true;
567 data.m_ProjectionWeights = nullptr;
568 BOOST_CHECK_THROW(data.Validate(info), armnn::InvalidArgumentException);
569 data.m_ProjectionWeights = &projectionWeightsTensor;
570
571 // check missing input layer normalisation weights
572 data.m_InputLayerNormWeights = nullptr;
573 BOOST_CHECK_THROW(data.Validate(info), armnn::InvalidArgumentException);
574 data.m_InputLayerNormWeights = &inputLayerNormWeightsTensor;
575
576 // layer norm disabled but normalisation weights are present
577 data.m_Parameters.m_LayerNormEnabled = false;
578 BOOST_CHECK_THROW(data.Validate(info), armnn::InvalidArgumentException);
579 data.m_Parameters.m_LayerNormEnabled = true;
580
581 // check invalid outputTensor shape
582 armnn::TensorInfo incorrectOutputTensorInfo({batchSize, outputSize + 1}, dataType, qScale, qOffset);
583 SetWorkloadOutput(data, info, 3, incorrectOutputTensorInfo, nullptr);
584 BOOST_CHECK_THROW(data.Validate(info), armnn::InvalidArgumentException);
585 SetWorkloadOutput(data, info, 3, outputTensorInfo, nullptr);
586
janeil0117d8d852019-11-15 15:00:16 +0000587 // check invalid cell clipping parameters
588 data.m_Parameters.m_ClippingThresCell = -1.0f;
589 BOOST_CHECK_THROW(data.Validate(info), armnn::InvalidArgumentException);
590 data.m_Parameters.m_ClippingThresCell = 0.0f;
591
592 // check invalid projection clipping parameters
593 data.m_Parameters.m_ClippingThresProj = -1.0f;
594 BOOST_CHECK_THROW(data.Validate(info), armnn::InvalidArgumentException);
595 data.m_Parameters.m_ClippingThresProj = 0.0f;
596
Jan Eilers38e05bd2019-06-26 13:10:09 +0100597 // check correct configuration
598 BOOST_CHECK_NO_THROW(data.Validate(info));
telsoa01c577f2c2018-08-31 09:22:23 +0100599}
600
Aron Virginas-Tard9053072019-10-30 16:03:19 +0000601BOOST_AUTO_TEST_CASE(BiasPerAxisQuantization_Validate)
602{
603 constexpr unsigned int nInput = 1u;
604 constexpr unsigned int cInput = 3u;
605 constexpr unsigned int hInput = 3u;
606 constexpr unsigned int wInput = 3u;
607
608 constexpr unsigned int nOutput = nInput;
609 constexpr unsigned int cOutput = cInput;
610 constexpr unsigned int hOutput = 1u;
611 constexpr unsigned int wOutput = 1u;
612
613 const TensorShape inputShape { nInput, cInput, hInput, wInput };
614 const TensorShape outputShape{ nOutput, cOutput, hOutput, wOutput };
615 const TensorShape weightShape{ cOutput, cInput, hInput, wInput };
616 const TensorShape biasShape { cOutput };
617
Derek Lambertif90c56d2020-01-10 17:14:08 +0000618 constexpr DataType inputType = DataType::QAsymmU8;
Aron Virginas-Tar5edc8812019-11-05 18:00:21 +0000619 constexpr DataType weightType = DataType::QuantizedSymm8PerAxis;
620 constexpr DataType biasType = DataType::Signed32;
Aron Virginas-Tard9053072019-10-30 16:03:19 +0000621
622 constexpr float perTensorScale = 1.5f;
Aron Virginas-Tar5edc8812019-11-05 18:00:21 +0000623 const TensorInfo inputInfo (inputShape, inputType, perTensorScale);
624 const TensorInfo outputInfo(outputShape, inputType, perTensorScale);
Aron Virginas-Tard9053072019-10-30 16:03:19 +0000625
626 const std::vector<float> weightPerAxisScales = { 2.50f, 3.50f };
Aron Virginas-Tar5edc8812019-11-05 18:00:21 +0000627 const TensorInfo weightInfo(weightShape, weightType, weightPerAxisScales, 0);
Aron Virginas-Tard9053072019-10-30 16:03:19 +0000628
629 Convolution2dQueueDescriptor queueDescriptor;
630 queueDescriptor.m_Parameters.m_BiasEnabled = true;
631
632 WorkloadInfo workloadInfo;
633 AddInputToWorkload(queueDescriptor, workloadInfo, inputInfo, nullptr);
634 AddOutputToWorkload(queueDescriptor, workloadInfo, outputInfo, nullptr);
635
636 ScopedCpuTensorHandle weightTensor(weightInfo);
637 queueDescriptor.m_Weight = &weightTensor;
638
639 // Test 1: correct per-axis quantization values
640 const std::vector<float> biasPerAxisScales1 = { 3.75f, 5.25f };
641 const TensorInfo biasInfo1(biasShape, biasType, biasPerAxisScales1, 0);
642
643 ScopedCpuTensorHandle biasHandle1(biasInfo1);
644 queueDescriptor.m_Bias = &biasHandle1;
645
646 BOOST_CHECK_NO_THROW(queueDescriptor.Validate(workloadInfo));
647
648 // Test 2: wrong per-axis quantization values
649 const std::vector<float> biasPerAxisScales2 = { 4.00f, 5.00f };
650 const TensorInfo biasInfo2(biasShape, biasType, biasPerAxisScales2, 0);
651
652 ScopedCpuTensorHandle biasHandle2(biasInfo2);
653 queueDescriptor.m_Bias = &biasHandle2;
654
655 BOOST_CHECK_THROW(queueDescriptor.Validate(workloadInfo), InvalidArgumentException);
656
657 // Test 3: mismatched number of quantization scales
658 const std::vector<float> biasPerAxisScales3 = { 3.75f, 5.25f, 5.25f };
659 const TensorInfo biasInfo3(biasShape, biasType, biasPerAxisScales3, 0);
660
661 ScopedCpuTensorHandle biasHandle3(biasInfo3);
662 queueDescriptor.m_Bias = &biasHandle3;
663
664 BOOST_CHECK_THROW(queueDescriptor.Validate(workloadInfo), InvalidArgumentException);
665}
666
telsoa014fcda012018-03-09 14:13:49 +0000667BOOST_AUTO_TEST_SUITE_END()