blob: 6125e62cb21d8ae7c994a68e0606703f18f0e227 [file] [log] [blame]
Laurent Carlier749294b2020-06-01 09:03:17 +01001//
Teresa Charlinacb3ec52023-04-03 19:57:00 +01002// Copyright © 2017,2022-2023 Arm Ltd and Contributors. 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
Colm Donelan0c479742021-12-10 12:43:54 +00006#include <armnnTestUtils/WorkloadTestUtils.hpp>
telsoa014fcda012018-03-09 14:13:49 +00007
8#include <armnn/Exceptions.hpp>
9
Colm Donelan0c479742021-12-10 12:43:54 +000010#include <armnn/backends/TensorHandle.hpp>
11#include <armnn/backends/Workload.hpp>
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000012
13#include <reference/workloads/RefWorkloads.hpp>
14#include <reference/RefWorkloadFactory.hpp>
15
Sadik Armagan1625efc2021-06-10 18:24:34 +010016#include <doctest/doctest.h>
telsoa014fcda012018-03-09 14:13:49 +000017
18using namespace armnn;
19
Sadik Armagan1625efc2021-06-10 18:24:34 +010020TEST_SUITE("WorkloadInfoValidation")
21{
22TEST_CASE("BatchNormalizationQueueDescriptor_Validate_DifferentQuantizationData")
Mike Kelly1ced4642020-03-04 18:01:13 +000023{
24 TensorShape inputShape { 1, 3, 2, 2 };
25 TensorShape outputShape { 1, 3, 2, 2 };
telsoa014fcda012018-03-09 14:13:49 +000026
Mike Kelly1ced4642020-03-04 18:01:13 +000027 TensorInfo inputTensorInfo(inputShape, armnn::DataType::QAsymmU8, .1f, 125);
28 TensorInfo outputTensorInfo(outputShape, armnn::DataType::QAsymmU8, .2f, 120);
29
30 BatchNormalizationQueueDescriptor invalidData;
31 WorkloadInfo invalidInfo;
32
33 unsigned int sameShape[] = { 10 };
34 TensorInfo sameInfo = armnn::TensorInfo(1, sameShape, armnn::DataType::QAsymmU8);
James Conroy1f58f032021-04-27 17:13:27 +010035 ScopedTensorHandle sameTensor(sameInfo);
Mike Kelly1ced4642020-03-04 18:01:13 +000036
37 AddInputToWorkload(invalidData, invalidInfo, inputTensorInfo, nullptr);
38 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
39
40 invalidData.m_Mean = &sameTensor;
41 invalidData.m_Variance = &sameTensor;
42 invalidData.m_Beta= &sameTensor;
43 invalidData.m_Gamma = &sameTensor;
44
Sadik Armagan1625efc2021-06-10 18:24:34 +010045 CHECK_NOTHROW(RefBatchNormalizationWorkload(invalidData, invalidInfo));
Mike Kelly1ced4642020-03-04 18:01:13 +000046}
telsoa014fcda012018-03-09 14:13:49 +000047
Sadik Armagan1625efc2021-06-10 18:24:34 +010048TEST_CASE("QueueDescriptor_Validate_WrongNumOfInputsOutputs")
telsoa014fcda012018-03-09 14:13:49 +000049{
50 InputQueueDescriptor invalidData;
51 WorkloadInfo invalidInfo;
telsoa01c577f2c2018-08-31 09:22:23 +010052 //Invalid argument exception is expected, because no inputs and no outputs were defined.
Teresa Charlin611c7fb2022-01-07 09:47:29 +000053 CHECK_THROWS_AS(RefWorkloadFactory().CreateWorkload(LayerType::Input, invalidData, invalidInfo),
54 armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +000055}
56
Sadik Armagan1625efc2021-06-10 18:24:34 +010057TEST_CASE("RefPooling2dFloat32Workload_Validate_WrongDimTensor")
telsoa014fcda012018-03-09 14:13:49 +000058{
59 armnn::TensorInfo inputTensorInfo;
60 armnn::TensorInfo outputTensorInfo;
61
telsoa01c577f2c2018-08-31 09:22:23 +010062 unsigned int inputShape[] = {2, 3, 4}; // <- Invalid - input tensor has to be 4D.
telsoa014fcda012018-03-09 14:13:49 +000063 unsigned int outputShape[] = {2, 3, 4, 5};
64
65 outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32);
66 inputTensorInfo = armnn::TensorInfo(3, inputShape, armnn::DataType::Float32);
67
68 Pooling2dQueueDescriptor invalidData;
69 WorkloadInfo invalidInfo;
70
71 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
72 AddInputToWorkload(invalidData, invalidInfo, inputTensorInfo, nullptr);
73
telsoa01c577f2c2018-08-31 09:22:23 +010074 // Invalid argument exception is expected, input tensor has to be 4D.
Sadik Armagan1625efc2021-06-10 18:24:34 +010075 CHECK_THROWS_AS(RefPooling2dWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +000076}
77
Tamás Nyíri7b885b32021-10-26 14:47:57 +010078TEST_CASE("RefPooling3dFloat32Workload_Validate_WrongDimTensor")
79{
80 armnn::TensorInfo inputTensorInfo;
81 armnn::TensorInfo outputTensorInfo;
82
83 unsigned int inputShape[] = {2, 3, 4, 5}; // <- Invalid - input tensor has to be 5D.
84 unsigned int outputShape[] = {2, 3, 4, 5, 6};
85
86 outputTensorInfo = armnn::TensorInfo(5, outputShape, armnn::DataType::Float32);
87 inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32);
88
89 Pooling3dQueueDescriptor invalidData;
90 WorkloadInfo invalidInfo;
91
92 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
93 AddInputToWorkload(invalidData, invalidInfo, inputTensorInfo, nullptr);
94
95 // Invalid argument exception is expected, input tensor has to be 5D.
96 CHECK_THROWS_AS(RefPooling3dWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
97}
98
Sadik Armagan1625efc2021-06-10 18:24:34 +010099TEST_CASE("SoftmaxQueueDescriptor_Validate_WrongInputHeight")
telsoa014fcda012018-03-09 14:13:49 +0000100{
101 unsigned int inputHeight = 1;
102 unsigned int inputWidth = 1;
103 unsigned int inputChannels = 4;
104 unsigned int inputNum = 2;
105
106 unsigned int outputChannels = inputChannels;
telsoa01c577f2c2018-08-31 09:22:23 +0100107 unsigned int outputHeight = inputHeight + 1; //Makes data invalid - Softmax expects height and width to be 1.
telsoa014fcda012018-03-09 14:13:49 +0000108 unsigned int outputWidth = inputWidth;
109 unsigned int outputNum = inputNum;
110
111 armnn::TensorInfo inputTensorInfo;
112 armnn::TensorInfo outputTensorInfo;
113
114 unsigned int inputShape[] = { inputNum, inputChannels, inputHeight, inputWidth };
115 unsigned int outputShape[] = { outputNum, outputChannels, outputHeight, outputWidth };
116
117 inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32);
118 outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32);
119
120 SoftmaxQueueDescriptor invalidData;
121 WorkloadInfo invalidInfo;
122
123 AddInputToWorkload(invalidData, invalidInfo, inputTensorInfo, nullptr);
124 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
125
telsoa01c577f2c2018-08-31 09:22:23 +0100126 //Invalid argument exception is expected, because height != 1.
Sadik Armagan1625efc2021-06-10 18:24:34 +0100127 CHECK_THROWS_AS(RefSoftmaxWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000128}
129
Sadik Armagan1625efc2021-06-10 18:24:34 +0100130TEST_CASE("FullyConnectedQueueDescriptor_Validate_RequiredDataMissing")
telsoa014fcda012018-03-09 14:13:49 +0000131{
132 unsigned int inputWidth = 1;
133 unsigned int inputHeight = 1;
134 unsigned int inputChannels = 5;
135 unsigned int inputNum = 2;
136
137 unsigned int outputWidth = 1;
138 unsigned int outputHeight = 1;
139 unsigned int outputChannels = 3;
140 unsigned int outputNum = 2;
141
telsoa01c577f2c2018-08-31 09:22:23 +0100142 // Define the tensor descriptors.
telsoa014fcda012018-03-09 14:13:49 +0000143 armnn::TensorInfo inputTensorInfo;
144 armnn::TensorInfo outputTensorInfo;
145 armnn::TensorInfo weightsDesc;
146 armnn::TensorInfo biasesDesc;
147
148 unsigned int inputShape[] = { inputNum, inputChannels, inputHeight, inputWidth };
149 unsigned int outputShape[] = { outputNum, outputChannels, outputHeight, outputWidth };
150 unsigned int weightsShape[] = { 1, 1, inputChannels, outputChannels };
151 unsigned int biasShape[] = { 1, outputChannels, outputHeight, outputWidth };
152
153 inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32);
154 outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32);
155 weightsDesc = armnn::TensorInfo(4, weightsShape, armnn::DataType::Float32);
156 biasesDesc = armnn::TensorInfo(4, biasShape, armnn::DataType::Float32);
157
158 FullyConnectedQueueDescriptor invalidData;
159 WorkloadInfo invalidInfo;
160
telsoa014fcda012018-03-09 14:13:49 +0000161 AddInputToWorkload(invalidData, invalidInfo, inputTensorInfo, nullptr);
162 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000163 invalidData.m_Parameters.m_BiasEnabled = true;
164 invalidData.m_Parameters.m_TransposeWeightMatrix = false;
165
166
telsoa01c577f2c2018-08-31 09:22:23 +0100167 //Invalid argument exception is expected, because not all required fields have been provided.
168 //In particular inputsData[0], outputsData[0] and weightsData can not be null.
Sadik Armagan1625efc2021-06-10 18:24:34 +0100169 CHECK_THROWS_AS(RefFullyConnectedWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000170}
171
172
Sadik Armagan1625efc2021-06-10 18:24:34 +0100173TEST_CASE("NormalizationQueueDescriptor_Validate_WrongInputHeight")
telsoa014fcda012018-03-09 14:13:49 +0000174{
175 constexpr unsigned int inputNum = 5;
176 constexpr unsigned int inputHeight = 32;
177 constexpr unsigned int inputWidth = 24;
178 constexpr unsigned int inputChannels = 3;
179
180 constexpr unsigned int outputNum = inputNum;
181 constexpr unsigned int outputChannels = inputChannels;
telsoa01c577f2c2018-08-31 09:22:23 +0100182 constexpr unsigned int outputHeight = inputHeight + 1; //Makes data invalid - normalization requires.
183 //Input and output to have the same dimensions.
telsoa014fcda012018-03-09 14:13:49 +0000184 constexpr unsigned int outputWidth = inputWidth;
185
186
187 armnn::TensorInfo inputTensorInfo;
188 armnn::TensorInfo outputTensorInfo;
189
190 unsigned int inputShape[] = {inputNum, inputChannels, inputHeight, inputWidth};
191 unsigned int outputShape[] = {outputNum, outputChannels, outputHeight, outputWidth};
192
193 inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32);
194 outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32);
195
196
197 armnn::NormalizationAlgorithmMethod normMethod = armnn::NormalizationAlgorithmMethod::LocalBrightness;
198 armnn::NormalizationAlgorithmChannel normChannel = armnn::NormalizationAlgorithmChannel::Across;
199 float alpha = 1.f;
200 float beta = 1.f;
201 float kappa = 1.f;
202 uint32_t normSize = 5;
203
204 NormalizationQueueDescriptor invalidData;
205 WorkloadInfo invalidInfo;
206
207 AddInputToWorkload(invalidData, invalidInfo, inputTensorInfo, nullptr);
208 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
209 invalidData.m_Parameters.m_NormChannelType = normChannel;
210 invalidData.m_Parameters.m_NormMethodType = normMethod;
211 invalidData.m_Parameters.m_NormSize = normSize;
212 invalidData.m_Parameters.m_Alpha = alpha;
213 invalidData.m_Parameters.m_Beta = beta;
214 invalidData.m_Parameters.m_K = kappa;
215
telsoa01c577f2c2018-08-31 09:22:23 +0100216 //Invalid argument exception is expected, because input height != output height.
Sadik Armagan1625efc2021-06-10 18:24:34 +0100217 CHECK_THROWS_AS(RefNormalizationWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000218}
219
Sadik Armagan1625efc2021-06-10 18:24:34 +0100220TEST_CASE("SplitterQueueDescriptor_Validate_WrongWindow")
telsoa014fcda012018-03-09 14:13:49 +0000221{
222 constexpr unsigned int inputNum = 1;
223 constexpr unsigned int inputHeight = 32;
224 constexpr unsigned int inputWidth = 24;
225 constexpr unsigned int inputChannels = 3;
226
227 constexpr unsigned int outputNum = inputNum;
228 constexpr unsigned int outputChannels = inputChannels;
229 constexpr unsigned int outputHeight = 18;
230 constexpr unsigned int outputWidth = inputWidth;
231
232
233 armnn::TensorInfo inputTensorInfo;
234 armnn::TensorInfo outputTensorInfo;
235
236 unsigned int inputShape[] = {inputNum, inputChannels, inputHeight, inputWidth};
237 unsigned int outputShape[] = {outputNum, outputChannels, outputHeight, outputWidth};
238
239 inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32);
240 outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32);
241
242 SplitterQueueDescriptor invalidData;
243 WorkloadInfo invalidInfo;
244
245 AddInputToWorkload(invalidData, invalidInfo, inputTensorInfo, nullptr);
246 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
247
telsoa01c577f2c2018-08-31 09:22:23 +0100248 // Invalid, since it has only 3 dimensions while the input tensor is 4d.
telsoa014fcda012018-03-09 14:13:49 +0000249 std::vector<unsigned int> wOrigin = {0, 0, 0};
250 armnn::SplitterQueueDescriptor::ViewOrigin window(wOrigin);
251 invalidData.m_ViewOrigins.push_back(window);
252
Sadik Armagan1625efc2021-06-10 18:24:34 +0100253 INFO("Invalid argument exception is expected, because split window dimensionality does not match input.");
254 CHECK_THROWS_AS(RefSplitterWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000255
telsoa01c577f2c2018-08-31 09:22:23 +0100256 // Invalid, since window extends past the boundary of input tensor.
telsoa014fcda012018-03-09 14:13:49 +0000257 std::vector<unsigned int> wOrigin3 = {0, 0, 15, 0};
258 armnn::SplitterQueueDescriptor::ViewOrigin window3(wOrigin3);
259 invalidData.m_ViewOrigins[0] = window3;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100260 INFO("Invalid argument exception is expected (wOrigin3[2]+ outputHeight > inputHeight");
261 CHECK_THROWS_AS(RefSplitterWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000262
263
264 std::vector<unsigned int> wOrigin4 = {0, 0, 0, 0};
265 armnn::SplitterQueueDescriptor::ViewOrigin window4(wOrigin4);
266 invalidData.m_ViewOrigins[0] = window4;
267
268 std::vector<unsigned int> wOrigin5 = {1, 16, 20, 2};
269 armnn::SplitterQueueDescriptor::ViewOrigin window5(wOrigin4);
270 invalidData.m_ViewOrigins.push_back(window5);
271
Sadik Armagan1625efc2021-06-10 18:24:34 +0100272 INFO("Invalid exception due to number of split windows not matching number of outputs.");
273 CHECK_THROWS_AS(RefSplitterWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000274}
275
276
Sadik Armagan1625efc2021-06-10 18:24:34 +0100277TEST_CASE("ConcatQueueDescriptor_Validate_WrongWindow")
telsoa014fcda012018-03-09 14:13:49 +0000278{
279 constexpr unsigned int inputNum = 1;
280 constexpr unsigned int inputChannels = 3;
281 constexpr unsigned int inputHeight = 32;
282 constexpr unsigned int inputWidth = 24;
283
284 constexpr unsigned int outputNum = 1;
285 constexpr unsigned int outputChannels = 3;
286 constexpr unsigned int outputHeight = 32;
287 constexpr unsigned int outputWidth = 24;
288
289
290 armnn::TensorInfo inputTensorInfo;
291 armnn::TensorInfo outputTensorInfo;
292
293 unsigned int inputShape[] = {inputNum, inputChannels, inputHeight, inputWidth};
294 unsigned int outputShape[] = {outputNum, outputChannels, outputHeight, outputWidth};
295
296 inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32);
297 outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32);
298
Jim Flynne242f2d2019-05-22 14:24:13 +0100299 ConcatQueueDescriptor invalidData;
telsoa014fcda012018-03-09 14:13:49 +0000300 WorkloadInfo invalidInfo;
301
302 AddInputToWorkload(invalidData, invalidInfo, inputTensorInfo, nullptr);
303 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
304
telsoa01c577f2c2018-08-31 09:22:23 +0100305 // Invalid, since it has only 3 dimensions while the input tensor is 4d.
telsoa014fcda012018-03-09 14:13:49 +0000306 std::vector<unsigned int> wOrigin = {0, 0, 0};
Jim Flynne242f2d2019-05-22 14:24:13 +0100307 armnn::ConcatQueueDescriptor::ViewOrigin window(wOrigin);
telsoa014fcda012018-03-09 14:13:49 +0000308 invalidData.m_ViewOrigins.push_back(window);
309
Sadik Armagan1625efc2021-06-10 18:24:34 +0100310 INFO("Invalid argument exception is expected, because merge window dimensionality does not match input.");
311 CHECK_THROWS_AS(RefConcatWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000312
telsoa01c577f2c2018-08-31 09:22:23 +0100313 // Invalid, since window extends past the boundary of output tensor.
telsoa014fcda012018-03-09 14:13:49 +0000314 std::vector<unsigned int> wOrigin3 = {0, 0, 15, 0};
Jim Flynne242f2d2019-05-22 14:24:13 +0100315 armnn::ConcatQueueDescriptor::ViewOrigin window3(wOrigin3);
telsoa014fcda012018-03-09 14:13:49 +0000316 invalidData.m_ViewOrigins[0] = window3;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100317 INFO("Invalid argument exception is expected (wOrigin3[2]+ inputHeight > outputHeight");
318 CHECK_THROWS_AS(RefConcatWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000319
320
321 std::vector<unsigned int> wOrigin4 = {0, 0, 0, 0};
Jim Flynne242f2d2019-05-22 14:24:13 +0100322 armnn::ConcatQueueDescriptor::ViewOrigin window4(wOrigin4);
telsoa014fcda012018-03-09 14:13:49 +0000323 invalidData.m_ViewOrigins[0] = window4;
324
325 std::vector<unsigned int> wOrigin5 = {1, 16, 20, 2};
Jim Flynne242f2d2019-05-22 14:24:13 +0100326 armnn::ConcatQueueDescriptor::ViewOrigin window5(wOrigin4);
telsoa014fcda012018-03-09 14:13:49 +0000327 invalidData.m_ViewOrigins.push_back(window5);
328
Sadik Armagan1625efc2021-06-10 18:24:34 +0100329 INFO("Invalid exception due to number of merge windows not matching number of inputs.");
330 CHECK_THROWS_AS(RefConcatWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000331}
332
Sadik Armagan1625efc2021-06-10 18:24:34 +0100333TEST_CASE("AdditionQueueDescriptor_Validate_InputNumbers")
telsoa014fcda012018-03-09 14:13:49 +0000334{
335 armnn::TensorInfo input1TensorInfo;
336 armnn::TensorInfo input2TensorInfo;
337 armnn::TensorInfo input3TensorInfo;
338 armnn::TensorInfo outputTensorInfo;
339
340 unsigned int shape[] = {1, 1, 1, 1};
341
342 input1TensorInfo = armnn::TensorInfo(4, shape, armnn::DataType::Float32);
343 input2TensorInfo = armnn::TensorInfo(4, shape, armnn::DataType::Float32);
344 input3TensorInfo = armnn::TensorInfo(4, shape, armnn::DataType::Float32);
345 outputTensorInfo = armnn::TensorInfo(4, shape, armnn::DataType::Float32);
346
347 AdditionQueueDescriptor invalidData;
348 WorkloadInfo invalidInfo;
349
350 AddInputToWorkload(invalidData, invalidInfo, input1TensorInfo, nullptr);
351 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
352
telsoa01c577f2c2018-08-31 09:22:23 +0100353 // Too few inputs.
Sadik Armagan1625efc2021-06-10 18:24:34 +0100354 CHECK_THROWS_AS(RefAdditionWorkload<>(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000355
356 AddInputToWorkload(invalidData, invalidInfo, input2TensorInfo, nullptr);
357
telsoa01c577f2c2018-08-31 09:22:23 +0100358 // Correct.
Sadik Armagan1625efc2021-06-10 18:24:34 +0100359 CHECK_NOTHROW(RefAdditionWorkload<>(invalidData, invalidInfo));
telsoa014fcda012018-03-09 14:13:49 +0000360
361 AddInputToWorkload(invalidData, invalidInfo, input3TensorInfo, nullptr);
362
telsoa01c577f2c2018-08-31 09:22:23 +0100363 // Too many inputs.
Sadik Armagan1625efc2021-06-10 18:24:34 +0100364 CHECK_THROWS_AS(RefAdditionWorkload<>(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000365}
366
Sadik Armagan1625efc2021-06-10 18:24:34 +0100367TEST_CASE("AdditionQueueDescriptor_Validate_InputShapes")
telsoa014fcda012018-03-09 14:13:49 +0000368{
369 armnn::TensorInfo input1TensorInfo;
370 armnn::TensorInfo input2TensorInfo;
371 armnn::TensorInfo outputTensorInfo;
372
373 unsigned int shape1[] = {1, 1, 2, 1};
374 unsigned int shape2[] = {1, 1, 3, 2};
375
telsoa01c577f2c2018-08-31 09:22:23 +0100376 // Incompatible shapes even with broadcasting.
telsoa014fcda012018-03-09 14:13:49 +0000377 {
378 input1TensorInfo = armnn::TensorInfo(4, shape1, armnn::DataType::Float32);
379 input2TensorInfo = armnn::TensorInfo(4, shape2, armnn::DataType::Float32);
380 outputTensorInfo = armnn::TensorInfo(4, shape1, armnn::DataType::Float32);
381
382 AdditionQueueDescriptor invalidData;
383 WorkloadInfo invalidInfo;
384
385 AddInputToWorkload(invalidData, invalidInfo, input1TensorInfo, nullptr);
386 AddInputToWorkload(invalidData, invalidInfo, input2TensorInfo, nullptr);
387 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
388
Sadik Armagan1625efc2021-06-10 18:24:34 +0100389 CHECK_THROWS_AS(RefAdditionWorkload<>(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000390 }
391
telsoa01c577f2c2018-08-31 09:22:23 +0100392 // Output size not compatible with input sizes.
telsoa014fcda012018-03-09 14:13:49 +0000393 {
394 input1TensorInfo = armnn::TensorInfo(4, shape1, armnn::DataType::Float32);
395 input2TensorInfo = armnn::TensorInfo(4, shape1, armnn::DataType::Float32);
396 outputTensorInfo = armnn::TensorInfo(4, shape2, armnn::DataType::Float32);
397
398 AdditionQueueDescriptor invalidData;
399 WorkloadInfo invalidInfo;
400
401 AddInputToWorkload(invalidData, invalidInfo, input1TensorInfo, nullptr);
402 AddInputToWorkload(invalidData, invalidInfo, input2TensorInfo, nullptr);
403 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
404
telsoa01c577f2c2018-08-31 09:22:23 +0100405 // Output differs.
Sadik Armagan1625efc2021-06-10 18:24:34 +0100406 CHECK_THROWS_AS(RefAdditionWorkload<>(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000407 }
408}
409
Sadik Armagan1625efc2021-06-10 18:24:34 +0100410TEST_CASE("MultiplicationQueueDescriptor_Validate_InputTensorDimensionMismatch")
telsoa014fcda012018-03-09 14:13:49 +0000411{
412 armnn::TensorInfo input0TensorInfo;
413 armnn::TensorInfo input1TensorInfo;
414 armnn::TensorInfo outputTensorInfo;
415
416 constexpr unsigned int input0Shape[] = { 2, 2, 4, 4 };
417 constexpr std::size_t dimensionCount = std::extent<decltype(input0Shape)>::value;
418
telsoa01c577f2c2018-08-31 09:22:23 +0100419 // Checks dimension consistency for input tensors.
telsoa014fcda012018-03-09 14:13:49 +0000420 for (unsigned int dimIndex = 0; dimIndex < dimensionCount; ++dimIndex)
421 {
422 unsigned int input1Shape[dimensionCount];
423 for (unsigned int i = 0; i < dimensionCount; ++i)
424 {
425 input1Shape[i] = input0Shape[i];
426 }
427
428 ++input1Shape[dimIndex];
429
430 input0TensorInfo = armnn::TensorInfo(dimensionCount, input0Shape, armnn::DataType::Float32);
431 input1TensorInfo = armnn::TensorInfo(dimensionCount, input1Shape, armnn::DataType::Float32);
432 outputTensorInfo = armnn::TensorInfo(dimensionCount, input0Shape, armnn::DataType::Float32);
433
434 MultiplicationQueueDescriptor invalidData;
435 WorkloadInfo invalidInfo;
436
437 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
438 AddInputToWorkload(invalidData, invalidInfo, input0TensorInfo, nullptr);
439 AddInputToWorkload(invalidData, invalidInfo, input1TensorInfo, nullptr);
440
Sadik Armagan1625efc2021-06-10 18:24:34 +0100441 CHECK_THROWS_AS(RefMultiplicationWorkload<>(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000442 }
443
telsoa01c577f2c2018-08-31 09:22:23 +0100444 // Checks dimension consistency for input and output tensors.
telsoa014fcda012018-03-09 14:13:49 +0000445 for (unsigned int dimIndex = 0; dimIndex < dimensionCount; ++dimIndex)
446 {
447 unsigned int outputShape[dimensionCount];
448 for (unsigned int i = 0; i < dimensionCount; ++i)
449 {
450 outputShape[i] = input0Shape[i];
451 }
452
453 ++outputShape[dimIndex];
454
455 input0TensorInfo = armnn::TensorInfo(dimensionCount, input0Shape, armnn::DataType::Float32);
456 input1TensorInfo = armnn::TensorInfo(dimensionCount, input0Shape, armnn::DataType::Float32);
457 outputTensorInfo = armnn::TensorInfo(dimensionCount, outputShape, armnn::DataType::Float32);
458
459 MultiplicationQueueDescriptor invalidData;
460 WorkloadInfo invalidInfo;
461
462 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
463 AddInputToWorkload(invalidData, invalidInfo, input0TensorInfo, nullptr);
464 AddInputToWorkload(invalidData, invalidInfo, input1TensorInfo, nullptr);
465
Sadik Armagan1625efc2021-06-10 18:24:34 +0100466 CHECK_THROWS_AS(RefMultiplicationWorkload<>(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000467 }
468}
469
Sadik Armagan1625efc2021-06-10 18:24:34 +0100470TEST_CASE("ReshapeQueueDescriptor_Validate_MismatchingNumElements")
telsoa014fcda012018-03-09 14:13:49 +0000471{
472 armnn::TensorInfo inputTensorInfo;
473 armnn::TensorInfo outputTensorInfo;
474
telsoa01c577f2c2018-08-31 09:22:23 +0100475 // The input and output shapes should have the same number of elements, but these don't.
telsoa014fcda012018-03-09 14:13:49 +0000476 unsigned int inputShape[] = { 1, 1, 2, 3 };
477 unsigned int outputShape[] = { 1, 1, 1, 2 };
478
479 inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32);
480 outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32);
481
482 ReshapeQueueDescriptor invalidData;
483 WorkloadInfo invalidInfo;
484
485 AddInputToWorkload(invalidData, invalidInfo, inputTensorInfo, nullptr);
486 AddOutputToWorkload(invalidData, invalidInfo, outputTensorInfo, nullptr);
487
telsoa01c577f2c2018-08-31 09:22:23 +0100488 // InvalidArgumentException is expected, because the number of elements don't match.
Sadik Armagan1625efc2021-06-10 18:24:34 +0100489 CHECK_THROWS_AS(RefReshapeWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException);
telsoa014fcda012018-03-09 14:13:49 +0000490}
491
telsoa01c577f2c2018-08-31 09:22:23 +0100492
Sadik Armagan1625efc2021-06-10 18:24:34 +0100493TEST_CASE("LstmQueueDescriptor_Validate")
telsoa01c577f2c2018-08-31 09:22:23 +0100494{
Jan Eilers38e05bd2019-06-26 13:10:09 +0100495 armnn::DataType dataType = armnn::DataType::Float32;
telsoa01c577f2c2018-08-31 09:22:23 +0100496
Teresa Charlinacb3ec52023-04-03 19:57:00 +0100497 float qScale = 1.0f;
Jan Eilers38e05bd2019-06-26 13:10:09 +0100498 int32_t qOffset = 0;
telsoa01c577f2c2018-08-31 09:22:23 +0100499
Jan Eilers38e05bd2019-06-26 13:10:09 +0100500 unsigned int batchSize = 2;
501 unsigned int outputSize = 3;
502 unsigned int inputSize = 5;
503 unsigned numUnits = 4;
telsoa01c577f2c2018-08-31 09:22:23 +0100504
Jan Eilers38e05bd2019-06-26 13:10:09 +0100505 armnn::TensorInfo inputTensorInfo({batchSize , inputSize}, dataType, qScale, qOffset );
506 armnn::TensorInfo outputStateInTensorInfo({batchSize , outputSize}, dataType, qScale, qOffset);
507 armnn::TensorInfo cellStateInTensorInfo({batchSize , numUnits}, dataType, qScale, qOffset);
telsoa01c577f2c2018-08-31 09:22:23 +0100508
Jan Eilers38e05bd2019-06-26 13:10:09 +0100509 // Scratch buffer size with CIFG [batchSize, numUnits * 4]
510 armnn::TensorInfo scratchBufferTensorInfo({batchSize, numUnits * 4}, dataType, qScale, qOffset);
511 armnn::TensorInfo cellStateOutTensorInfo({batchSize, numUnits}, dataType, qScale, qOffset);
512 armnn::TensorInfo outputStateOutTensorInfo({batchSize, outputSize}, dataType, qScale, qOffset);
513 armnn::TensorInfo outputTensorInfo({batchSize, outputSize}, dataType, qScale, qOffset);
telsoa01c577f2c2018-08-31 09:22:23 +0100514
Jan Eilers38e05bd2019-06-26 13:10:09 +0100515 armnn::TensorInfo tensorInfo3({outputSize}, dataType, qScale, qOffset);
516 armnn::TensorInfo tensorInfo4({numUnits}, dataType, qScale, qOffset);
517 armnn::TensorInfo tensorInfo4x5({numUnits, inputSize}, dataType, qScale, qOffset);
518 armnn::TensorInfo tensorInfo4x3({numUnits, outputSize}, dataType, qScale, qOffset);
519 armnn::TensorInfo tensorInfo3x4({outputSize, numUnits}, dataType, qScale, qOffset);
520
521 LstmQueueDescriptor data;
522 WorkloadInfo info;
523
524 AddInputToWorkload(data, info, inputTensorInfo, nullptr);
525 AddInputToWorkload(data, info, outputStateInTensorInfo, nullptr);
526 AddInputToWorkload(data, info, cellStateInTensorInfo, nullptr);
527
528 AddOutputToWorkload(data, info, scratchBufferTensorInfo, nullptr);
529 AddOutputToWorkload(data, info, outputStateOutTensorInfo, nullptr);
530 AddOutputToWorkload(data, info, cellStateOutTensorInfo, nullptr);
531 // AddOutputToWorkload(data, info, outputTensorInfo, nullptr); is left out
532
James Conroy1f58f032021-04-27 17:13:27 +0100533 armnn::ScopedTensorHandle inputToInputWeightsTensor(tensorInfo4x5);
534 armnn::ScopedTensorHandle inputToForgetWeightsTensor(tensorInfo4x5);
535 armnn::ScopedTensorHandle inputToCellWeightsTensor(tensorInfo4x5);
536 armnn::ScopedTensorHandle inputToOutputWeightsTensor(tensorInfo4x5);
537 armnn::ScopedTensorHandle recurrentToForgetWeightsTensor(tensorInfo4x3);
538 armnn::ScopedTensorHandle recurrentToInputWeightsTensor(tensorInfo4x3);
539 armnn::ScopedTensorHandle recurrentToCellWeightsTensor(tensorInfo4x3);
540 armnn::ScopedTensorHandle recurrentToOutputWeightsTensor(tensorInfo4x3);
541 armnn::ScopedTensorHandle cellToInputWeightsTensor(tensorInfo4);
542 armnn::ScopedTensorHandle inputGateBiasTensor(tensorInfo4);
543 armnn::ScopedTensorHandle forgetGateBiasTensor(tensorInfo4);
544 armnn::ScopedTensorHandle cellBiasTensor(tensorInfo4);
545 armnn::ScopedTensorHandle outputGateBiasTensor(tensorInfo4);
546 armnn::ScopedTensorHandle cellToForgetWeightsTensor(tensorInfo4);
547 armnn::ScopedTensorHandle cellToOutputWeightsTensor(tensorInfo4);
548 armnn::ScopedTensorHandle projectionWeightsTensor(tensorInfo3x4);
549 armnn::ScopedTensorHandle projectionBiasTensor(tensorInfo3);
550 armnn::ScopedTensorHandle inputLayerNormWeightsTensor(tensorInfo4);
551 armnn::ScopedTensorHandle forgetLayerNormWeightsTensor(tensorInfo4);
552 armnn::ScopedTensorHandle cellLayerNormWeightsTensor(tensorInfo4);
553 armnn::ScopedTensorHandle outputLayerNormWeightsTensor(tensorInfo4);
Jan Eilers38e05bd2019-06-26 13:10:09 +0100554
555 data.m_InputToInputWeights = &inputToInputWeightsTensor;
556 data.m_InputToForgetWeights = &inputToForgetWeightsTensor;
557 data.m_InputToCellWeights = &inputToCellWeightsTensor;
558 data.m_InputToOutputWeights = &inputToOutputWeightsTensor;
559 data.m_RecurrentToInputWeights = &recurrentToInputWeightsTensor;
560 data.m_RecurrentToForgetWeights = &recurrentToForgetWeightsTensor;
561 data.m_RecurrentToCellWeights = &recurrentToCellWeightsTensor;
562 data.m_RecurrentToOutputWeights = &recurrentToOutputWeightsTensor;
563 data.m_CellToInputWeights = &cellToInputWeightsTensor;
564 data.m_InputGateBias = &inputGateBiasTensor;
565 data.m_ForgetGateBias = &forgetGateBiasTensor;
566 data.m_CellBias = &cellBiasTensor;
567 data.m_OutputGateBias = &outputGateBiasTensor;
568 data.m_CellToForgetWeights = &cellToForgetWeightsTensor;
569 data.m_CellToOutputWeights = &cellToOutputWeightsTensor;
570 data.m_ProjectionWeights = &projectionWeightsTensor;
571 data.m_ProjectionBias = &projectionBiasTensor;
572
573 data.m_InputLayerNormWeights = &inputLayerNormWeightsTensor;
574 data.m_ForgetLayerNormWeights = &forgetLayerNormWeightsTensor;
575 data.m_CellLayerNormWeights = &cellLayerNormWeightsTensor;
576 data.m_OutputLayerNormWeights = &outputLayerNormWeightsTensor;
577
578 // Flags to set test configuration
579 data.m_Parameters.m_ActivationFunc = 4;
580 data.m_Parameters.m_CifgEnabled = false;
581 data.m_Parameters.m_PeepholeEnabled = true;
582 data.m_Parameters.m_ProjectionEnabled = true;
583 data.m_Parameters.m_LayerNormEnabled = true;
584
585 // check wrong number of outputs
Sadik Armagan1625efc2021-06-10 18:24:34 +0100586 CHECK_THROWS_AS(data.Validate(info), armnn::InvalidArgumentException);
Jan Eilers38e05bd2019-06-26 13:10:09 +0100587 AddOutputToWorkload(data, info, outputTensorInfo, nullptr);
588
589 // check wrong cifg parameter configuration
590 data.m_Parameters.m_CifgEnabled = true;
591 armnn::TensorInfo scratchBufferTensorInfo2({batchSize, numUnits * 3}, dataType, qScale, qOffset);
592 SetWorkloadOutput(data, info, 0, scratchBufferTensorInfo2, nullptr);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100593 CHECK_THROWS_AS(data.Validate(info), armnn::InvalidArgumentException);
Jan Eilers38e05bd2019-06-26 13:10:09 +0100594 data.m_Parameters.m_CifgEnabled = false;
595 SetWorkloadOutput(data, info, 0, scratchBufferTensorInfo, nullptr);
596
597 // check wrong inputGateBias configuration
598 data.m_InputGateBias = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100599 CHECK_THROWS_AS(data.Validate(info), armnn::InvalidArgumentException);
Jan Eilers38e05bd2019-06-26 13:10:09 +0100600 data.m_InputGateBias = &inputGateBiasTensor;
601
602 // check inconsistant projection parameters
603 data.m_Parameters.m_ProjectionEnabled = false;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100604 CHECK_THROWS_AS(data.Validate(info), armnn::InvalidArgumentException);
Jan Eilers38e05bd2019-06-26 13:10:09 +0100605 data.m_Parameters.m_ProjectionEnabled = true;
606 data.m_ProjectionWeights = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100607 CHECK_THROWS_AS(data.Validate(info), armnn::InvalidArgumentException);
Jan Eilers38e05bd2019-06-26 13:10:09 +0100608 data.m_ProjectionWeights = &projectionWeightsTensor;
609
610 // check missing input layer normalisation weights
611 data.m_InputLayerNormWeights = nullptr;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100612 CHECK_THROWS_AS(data.Validate(info), armnn::InvalidArgumentException);
Jan Eilers38e05bd2019-06-26 13:10:09 +0100613 data.m_InputLayerNormWeights = &inputLayerNormWeightsTensor;
614
615 // layer norm disabled but normalisation weights are present
616 data.m_Parameters.m_LayerNormEnabled = false;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100617 CHECK_THROWS_AS(data.Validate(info), armnn::InvalidArgumentException);
Jan Eilers38e05bd2019-06-26 13:10:09 +0100618 data.m_Parameters.m_LayerNormEnabled = true;
619
620 // check invalid outputTensor shape
621 armnn::TensorInfo incorrectOutputTensorInfo({batchSize, outputSize + 1}, dataType, qScale, qOffset);
622 SetWorkloadOutput(data, info, 3, incorrectOutputTensorInfo, nullptr);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100623 CHECK_THROWS_AS(data.Validate(info), armnn::InvalidArgumentException);
Jan Eilers38e05bd2019-06-26 13:10:09 +0100624 SetWorkloadOutput(data, info, 3, outputTensorInfo, nullptr);
625
janeil0117d8d852019-11-15 15:00:16 +0000626 // check invalid cell clipping parameters
627 data.m_Parameters.m_ClippingThresCell = -1.0f;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100628 CHECK_THROWS_AS(data.Validate(info), armnn::InvalidArgumentException);
janeil0117d8d852019-11-15 15:00:16 +0000629 data.m_Parameters.m_ClippingThresCell = 0.0f;
630
631 // check invalid projection clipping parameters
632 data.m_Parameters.m_ClippingThresProj = -1.0f;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100633 CHECK_THROWS_AS(data.Validate(info), armnn::InvalidArgumentException);
janeil0117d8d852019-11-15 15:00:16 +0000634 data.m_Parameters.m_ClippingThresProj = 0.0f;
635
Jan Eilers38e05bd2019-06-26 13:10:09 +0100636 // check correct configuration
Sadik Armagan1625efc2021-06-10 18:24:34 +0100637 CHECK_NOTHROW(data.Validate(info));
telsoa01c577f2c2018-08-31 09:22:23 +0100638}
639
Keith Davisb4dd5cc2022-04-07 11:32:00 +0100640TEST_CASE("BiasPerAxisQuantization_ValidateCorrectValues")
Aron Virginas-Tard9053072019-10-30 16:03:19 +0000641{
642 constexpr unsigned int nInput = 1u;
643 constexpr unsigned int cInput = 3u;
644 constexpr unsigned int hInput = 3u;
645 constexpr unsigned int wInput = 3u;
646
647 constexpr unsigned int nOutput = nInput;
648 constexpr unsigned int cOutput = cInput;
649 constexpr unsigned int hOutput = 1u;
650 constexpr unsigned int wOutput = 1u;
651
652 const TensorShape inputShape { nInput, cInput, hInput, wInput };
653 const TensorShape outputShape{ nOutput, cOutput, hOutput, wOutput };
654 const TensorShape weightShape{ cOutput, cInput, hInput, wInput };
655 const TensorShape biasShape { cOutput };
656
Derek Lambertif90c56d2020-01-10 17:14:08 +0000657 constexpr DataType inputType = DataType::QAsymmU8;
Derek Lambertid466a542020-01-22 15:37:29 +0000658 constexpr DataType weightType = DataType::QSymmS8;
Aron Virginas-Tar5edc8812019-11-05 18:00:21 +0000659 constexpr DataType biasType = DataType::Signed32;
Aron Virginas-Tard9053072019-10-30 16:03:19 +0000660
661 constexpr float perTensorScale = 1.5f;
Aron Virginas-Tar5edc8812019-11-05 18:00:21 +0000662 const TensorInfo inputInfo (inputShape, inputType, perTensorScale);
663 const TensorInfo outputInfo(outputShape, inputType, perTensorScale);
Aron Virginas-Tard9053072019-10-30 16:03:19 +0000664
665 const std::vector<float> weightPerAxisScales = { 2.50f, 3.50f };
Aron Virginas-Tar5edc8812019-11-05 18:00:21 +0000666 const TensorInfo weightInfo(weightShape, weightType, weightPerAxisScales, 0);
Aron Virginas-Tard9053072019-10-30 16:03:19 +0000667
668 Convolution2dQueueDescriptor queueDescriptor;
669 queueDescriptor.m_Parameters.m_BiasEnabled = true;
670
671 WorkloadInfo workloadInfo;
672 AddInputToWorkload(queueDescriptor, workloadInfo, inputInfo, nullptr);
Keith Davisb4dd5cc2022-04-07 11:32:00 +0100673 AddInputToWorkload(queueDescriptor, workloadInfo, weightInfo, nullptr);
Aron Virginas-Tard9053072019-10-30 16:03:19 +0000674 AddOutputToWorkload(queueDescriptor, workloadInfo, outputInfo, nullptr);
675
Aron Virginas-Tard9053072019-10-30 16:03:19 +0000676 // Test 1: correct per-axis quantization values
677 const std::vector<float> biasPerAxisScales1 = { 3.75f, 5.25f };
678 const TensorInfo biasInfo1(biasShape, biasType, biasPerAxisScales1, 0);
679
Keith Davisb4dd5cc2022-04-07 11:32:00 +0100680 AddInputToWorkload(queueDescriptor, workloadInfo, biasInfo1, nullptr);
Aron Virginas-Tard9053072019-10-30 16:03:19 +0000681
Keith Davisb4dd5cc2022-04-07 11:32:00 +0100682 CHECK_NOTHROW(queueDescriptor.Validate(workloadInfo));
683}
684
685TEST_CASE("BiasPerAxisQuantization_ValidateIncorrectValues")
686{
687 constexpr unsigned int nInput = 1u;
688 constexpr unsigned int cInput = 3u;
689 constexpr unsigned int hInput = 3u;
690 constexpr unsigned int wInput = 3u;
691
692 constexpr unsigned int nOutput = nInput;
693 constexpr unsigned int cOutput = cInput;
694 constexpr unsigned int hOutput = 1u;
695 constexpr unsigned int wOutput = 1u;
696
697 const TensorShape inputShape { nInput, cInput, hInput, wInput };
698 const TensorShape outputShape{ nOutput, cOutput, hOutput, wOutput };
699 const TensorShape weightShape{ cOutput, cInput, hInput, wInput };
700 const TensorShape biasShape { cOutput };
701
702 constexpr DataType inputType = DataType::QAsymmU8;
703 constexpr DataType weightType = DataType::QSymmS8;
704 constexpr DataType biasType = DataType::Signed32;
705
706 constexpr float perTensorScale = 1.5f;
707 const TensorInfo inputInfo (inputShape, inputType, perTensorScale);
708 const TensorInfo outputInfo(outputShape, inputType, perTensorScale);
709
710 const std::vector<float> weightPerAxisScales = { 2.50f, 3.50f };
711 const TensorInfo weightInfo(weightShape, weightType, weightPerAxisScales, 0);
712
713 Convolution2dQueueDescriptor queueDescriptor;
714 queueDescriptor.m_Parameters.m_BiasEnabled = true;
715
716 WorkloadInfo workloadInfo;
717 AddInputToWorkload(queueDescriptor, workloadInfo, inputInfo, nullptr);
718 AddInputToWorkload(queueDescriptor, workloadInfo, weightInfo, nullptr);
719 AddOutputToWorkload(queueDescriptor, workloadInfo, outputInfo, nullptr);
720
Mike Kellyec67a0f2022-11-25 13:55:24 +0000721 // Test 2: wrong per-axis quantization values
Aron Virginas-Tard9053072019-10-30 16:03:19 +0000722 const std::vector<float> biasPerAxisScales2 = { 4.00f, 5.00f };
723 const TensorInfo biasInfo2(biasShape, biasType, biasPerAxisScales2, 0);
724
Keith Davisb4dd5cc2022-04-07 11:32:00 +0100725 AddInputToWorkload(queueDescriptor, workloadInfo, biasInfo2, nullptr);
726
Sadik Armagan1625efc2021-06-10 18:24:34 +0100727 CHECK_NOTHROW(queueDescriptor.Validate(workloadInfo));
Aron Virginas-Tard9053072019-10-30 16:03:19 +0000728
Keith Davisb4dd5cc2022-04-07 11:32:00 +0100729}
730
731TEST_CASE("BiasPerAxisQuantization_ValidateInvalidArgumentException")
732{
733 constexpr unsigned int nInput = 1u;
734 constexpr unsigned int cInput = 3u;
735 constexpr unsigned int hInput = 3u;
736 constexpr unsigned int wInput = 3u;
737
738 constexpr unsigned int nOutput = nInput;
739 constexpr unsigned int cOutput = cInput;
740 constexpr unsigned int hOutput = 1u;
741 constexpr unsigned int wOutput = 1u;
742
743 const TensorShape inputShape { nInput, cInput, hInput, wInput };
744 const TensorShape outputShape{ nOutput, cOutput, hOutput, wOutput };
745 const TensorShape weightShape{ cOutput, cInput, hInput, wInput };
746 const TensorShape biasShape { cOutput };
747
748 constexpr DataType inputType = DataType::QAsymmU8;
749 constexpr DataType weightType = DataType::QSymmS8;
750 constexpr DataType biasType = DataType::Signed32;
751
752 constexpr float perTensorScale = 1.5f;
753 const TensorInfo inputInfo (inputShape, inputType, perTensorScale);
754 const TensorInfo outputInfo(outputShape, inputType, perTensorScale);
755
756 const std::vector<float> weightPerAxisScales = { 2.50f, 3.50f };
757 const TensorInfo weightInfo(weightShape, weightType, weightPerAxisScales, 0);
758
759 Convolution2dQueueDescriptor queueDescriptor;
760 queueDescriptor.m_Parameters.m_BiasEnabled = true;
761
762 WorkloadInfo workloadInfo;
763 AddInputToWorkload(queueDescriptor, workloadInfo, inputInfo, nullptr);
764 AddInputToWorkload(queueDescriptor, workloadInfo, weightInfo, nullptr);
765 AddOutputToWorkload(queueDescriptor, workloadInfo, outputInfo, nullptr);
766
Aron Virginas-Tard9053072019-10-30 16:03:19 +0000767 // Test 3: mismatched number of quantization scales
768 const std::vector<float> biasPerAxisScales3 = { 3.75f, 5.25f, 5.25f };
769 const TensorInfo biasInfo3(biasShape, biasType, biasPerAxisScales3, 0);
770
Keith Davisb4dd5cc2022-04-07 11:32:00 +0100771 AddInputToWorkload(queueDescriptor, workloadInfo, biasInfo3, nullptr);
772
Sadik Armagan1625efc2021-06-10 18:24:34 +0100773 CHECK_THROWS_AS(queueDescriptor.Validate(workloadInfo), InvalidArgumentException);
Aron Virginas-Tard9053072019-10-30 16:03:19 +0000774}
775
Keith Davisb4dd5cc2022-04-07 11:32:00 +0100776
Sadik Armagan1625efc2021-06-10 18:24:34 +0100777}