blob: 251d3b96b8116a00d88e41a7b6e13ea91af1537d [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//
Matteo Martincighe011d202019-11-28 11:35:47 +00005
telsoa014fcda012018-03-09 14:13:49 +00006#include "WorkloadData.hpp"
7
8#include "CpuTensorHandle.hpp"
telsoa014fcda012018-03-09 14:13:49 +00009
Matteo Martincighe011d202019-11-28 11:35:47 +000010#include <armnnUtils/DataLayoutIndexed.hpp>
11#include <armnnUtils/TensorUtils.hpp>
Matthew Bentham8800c002018-11-19 13:19:28 +000012
telsoa014fcda012018-03-09 14:13:49 +000013#include <algorithm>
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000014#include <iomanip>
telsoa014fcda012018-03-09 14:13:49 +000015#include <string>
16#include <sstream>
telsoa014fcda012018-03-09 14:13:49 +000017
18#include <boost/format.hpp>
Aron Virginas-Tard4f0fea2019-04-09 14:08:06 +010019#include <boost/numeric/conversion/cast.hpp>
telsoa014fcda012018-03-09 14:13:49 +000020
Matteo Martincigh21350152018-11-28 16:22:22 +000021using namespace armnnUtils;
22
telsoa014fcda012018-03-09 14:13:49 +000023namespace armnn
24{
25
26//---------------------------------------------------------------
27DataType GetBiasDataType(DataType inputDataType)
28{
29 switch (inputDataType)
30 {
telsoa01c577f2c2018-08-31 09:22:23 +010031 case DataType::Float16:
32 return DataType::Float16;
telsoa014fcda012018-03-09 14:13:49 +000033 case DataType::Float32:
34 return DataType::Float32;
35 case DataType::QuantisedAsymm8:
36 return DataType::Signed32;
Ruomei Yan88d44b82019-05-23 14:29:06 +010037 case DataType::QuantisedSymm16:
38 return DataType::Signed32;
telsoa014fcda012018-03-09 14:13:49 +000039 default:
40 BOOST_ASSERT_MSG(false, "Invalid input data type");
41 return DataType::Float32;
42 }
43}
44
45namespace
46{
47
48//---------------------------------------------------------------
49//android ndk does not support std::to_string function.
50template <typename T>
51std::string to_string(T value)
52{
53 std::ostringstream os;
54 os << value;
55 return os.str();
56}
57
58//---------------------------------------------------------------
59void ValidatePointer(const void* ptr, std::string const& descName, std::string const& paramName)
60{
61 if (!ptr)
62 {
63 throw InvalidArgumentException(descName + ": Invalid null pointer. The " +
64 paramName + " parameter must be set.");
65 }
66}
67
68//---------------------------------------------------------------
69void ValidateTensorShapesMatch(const TensorInfo& first,
70 const TensorInfo& second,
71 std::string const& descName,
72 std::string const& firstName,
73 std::string const& secondName)
74{
75 if (first.GetShape() != second.GetShape())
76 {
77 throw InvalidArgumentException(descName + ": "
78 + firstName + " & " + secondName + " must have identical shapes");
79 }
80}
81
82//---------------------------------------------------------------
Sadik Armaganeff363d2019-04-05 15:25:46 +010083void ValidateNumInputs(const WorkloadInfo& workloadInfo, std::string const& descName, const unsigned int expectedSize)
telsoa014fcda012018-03-09 14:13:49 +000084{
Sadik Armaganeff363d2019-04-05 15:25:46 +010085 if (workloadInfo.m_InputTensorInfos.size() != expectedSize)
telsoa014fcda012018-03-09 14:13:49 +000086 {
87 throw InvalidArgumentException(descName +
Sadik Armaganeff363d2019-04-05 15:25:46 +010088 ": Requires exactly " + to_string(expectedSize) + "input(s). " +
telsoa014fcda012018-03-09 14:13:49 +000089 to_string(workloadInfo.m_InputTensorInfos.size()) + " have been provided.");
90 }
91}
92
93//---------------------------------------------------------------
Sadik Armaganeff363d2019-04-05 15:25:46 +010094void ValidateNumOutputs(const WorkloadInfo& workloadInfo, std::string const& descName, const unsigned int expectedSize)
telsoa014fcda012018-03-09 14:13:49 +000095{
Sadik Armaganeff363d2019-04-05 15:25:46 +010096 if (workloadInfo.m_OutputTensorInfos.size() != expectedSize)
telsoa014fcda012018-03-09 14:13:49 +000097 {
98 throw InvalidArgumentException(descName +
Sadik Armaganeff363d2019-04-05 15:25:46 +010099 ": Requires exactly " + to_string(expectedSize) + " output(s). " +
telsoa014fcda012018-03-09 14:13:49 +0000100 to_string(workloadInfo.m_OutputTensorInfos.size()) + " has been provided.");
101 }
102}
103
104//---------------------------------------------------------------
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100105void ValidateTensorNumDimensions(const TensorInfo& tensor,
telsoa014fcda012018-03-09 14:13:49 +0000106 std::string const& descName,
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100107 unsigned int numDimensions,
telsoa014fcda012018-03-09 14:13:49 +0000108 std::string const& tensorName)
109{
110 if (tensor.GetNumDimensions() != numDimensions)
111 {
112 throw InvalidArgumentException(descName + ": Expected " + to_string(numDimensions) + " but got " +
113 to_string(tensor.GetNumDimensions()) + " dimensions for " +
114 tensorName + " tensor.");
115 }
116}
117
118//---------------------------------------------------------------
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100119void ValidateTensorNumElements(const TensorInfo& tensor,
120 std::string const& descName,
121 unsigned int numElements,
122 std::string const& tensorName)
Jan Eilers38e05bd2019-06-26 13:10:09 +0100123{
124 if (tensor.GetNumElements() != numElements)
125 {
126 throw InvalidArgumentException(descName + ": Expected " + to_string(numElements) + " but got " +
James Conroyceda7852019-08-22 11:41:07 +0100127 to_string(tensor.GetNumElements()) + " elements for " +
Jan Eilers38e05bd2019-06-26 13:10:09 +0100128 tensorName + " tensor.");
129 }
130}
131
132//---------------------------------------------------------------
133void ValidateTensorNumDimNumElem(const TensorInfo& tensorInfo,
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100134 unsigned int numDimension,
135 unsigned int numElements,
136 std::string const& tensorName)
Jan Eilers38e05bd2019-06-26 13:10:09 +0100137{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100138 const std::string functionName{"ValidateTensorNumDimNumElem"};
139 ValidateTensorNumDimensions(tensorInfo, functionName, numDimension, tensorName);
140 ValidateTensorNumElements(tensorInfo, functionName, numElements, tensorName);
Jan Eilers38e05bd2019-06-26 13:10:09 +0100141}
142
143//---------------------------------------------------------------
telsoa014fcda012018-03-09 14:13:49 +0000144void ValidateTensorDataType(const TensorInfo& tensor, DataType dataType,
145 const std::string& descName, std::string const& tensorName)
146{
147 if (tensor.GetDataType() != dataType)
148 {
149 throw InvalidArgumentException(descName + ": Expected data type " + GetDataTypeName(dataType) + " but got " +
150 GetDataTypeName(tensor.GetDataType()) + " for " + tensorName + " tensor.");
151 }
152}
153
154//---------------------------------------------------------------
Matteo Martincighe851b3d2019-05-28 14:31:20 +0100155void ValidateTensorQuantizationSpace(const TensorInfo& first,
156 const TensorInfo& second,
157 const std::string& descName,
158 std::string const& firstName,
159 std::string const& secondName)
160{
161 if (!first.IsQuantized() ||
162 !second.IsQuantized())
163 {
164 // Not a quantized type, ignore the validation
165 return;
166 }
167
168 DataType firstDataType = first.GetDataType();
169 DataType secondDataType = second.GetDataType();
170
171 if (firstDataType != secondDataType)
172 {
173 throw InvalidArgumentException(descName + ": " + firstName + " and " + secondName +
174 " must be of the same quantized type, " +
175 firstName + " is " + GetDataTypeName(firstDataType) + ", " +
176 secondName + " is " + GetDataTypeName(secondDataType));
177 }
178
179 if (!first.IsTypeSpaceMatch(second))
180 {
181 throw InvalidArgumentException(descName + ": " + firstName + " and " + secondName +
182 " must have the same quantization space, " +
183 firstName + " has offset " + to_string(first.GetQuantizationOffset()) +
184 " and scale " + to_string(first.GetQuantizationScale()) + ", " +
185 secondName + " has offset " + to_string(second.GetQuantizationOffset()) +
186 " and scale " + to_string(second.GetQuantizationScale()));
187 }
188}
189
190//---------------------------------------------------------------
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100191void ValidateBiasTensorQuantization(const TensorInfo& biasTensor,
192 const TensorInfo& inputTensorInfo,
193 const TensorInfo& weightsTensorInfo,
194 const std::string& descName)
telsoa014fcda012018-03-09 14:13:49 +0000195{
Aron Virginas-Tard9053072019-10-30 16:03:19 +0000196 // Helper lambda function to validate a single bias quantization scale value
197 auto VerifyBiasQuantizationScale = [&descName](float biasScale, float expectedScale) -> void
198 {
ricbur013f4d7102019-10-31 16:22:18 +0000199 constexpr float tolerance = 0.000001f;
Aron Virginas-Tard9053072019-10-30 16:03:19 +0000200 if (std::abs(biasScale - expectedScale) > tolerance)
201 {
202 // Print the float values with extra precision to see very small differences
203 std::stringstream msg;
204 msg << std::setprecision(10) << descName << ": Expected " << expectedScale <<
205 " quantization scale for bias tensor (the product of the input and weight scales), but got " <<
206 biasScale;
207 throw InvalidArgumentException(msg.str(), CHECK_LOCATION());
208 }
209 };
210
telsoa014fcda012018-03-09 14:13:49 +0000211 if (biasTensor.GetQuantizationOffset() != 0)
212 {
213 throw InvalidArgumentException(descName + ": Expected zero quantization offset for bias tensor but got " +
214 to_string(biasTensor.GetQuantizationOffset()));
215 }
Aron Virginas-Tard9053072019-10-30 16:03:19 +0000216
217 if (biasTensor.HasMultipleQuantizationScales())
telsoa014fcda012018-03-09 14:13:49 +0000218 {
Aron Virginas-Tard9053072019-10-30 16:03:19 +0000219 // Validate per-axis quantization scales
220 const std::vector<float>& weightScales = weightsTensorInfo.GetQuantizationScales();
221 const std::vector<float>& biasScales = biasTensor.GetQuantizationScales();
222
223 if (weightScales.size() != biasScales.size())
224 {
225 std::stringstream msg;
226 msg << descName << ": Expected matchhing number of per-axis quantization scales, but got different "
227 << "values: weights=" << weightScales.size() << ", biases=" << biasScales.size();
228 throw InvalidArgumentException(msg.str(), CHECK_LOCATION());
229 }
230
231 for (size_t i = 0ul; i < biasScales.size(); ++i)
232 {
233 const float expectedScale = inputTensorInfo.GetQuantizationScale() * weightScales[i];
234 VerifyBiasQuantizationScale(biasScales[i], expectedScale);
235 }
236 }
237 else
238 {
239 // Validate per-tensor quantization scale
240 const float expectedScale = inputTensorInfo.GetQuantizationScale() * weightsTensorInfo.GetQuantizationScale();
241 VerifyBiasQuantizationScale(biasTensor.GetQuantizationScale(), expectedScale);
telsoa014fcda012018-03-09 14:13:49 +0000242 }
243}
244
245//---------------------------------------------------------------
246void ValidateTensors(const std::vector<ITensorHandle*>& vec,
247 unsigned int numExpected,
248 const std::string& descName,
249 const std::string& varName)
250{
251 if (vec.empty() && numExpected > 0)
252 {
253 throw InvalidArgumentException(descName + ": Invalid empty " + varName + " array.");
254 }
255
256 for (unsigned int i = 0; i < numExpected; ++i)
257 {
258 if (!vec[i])
259 {
260 throw InvalidArgumentException(descName + ": Invalid NULL for " + varName + to_string(i));
261 }
262 }
263}
264
265//---------------------------------------------------------------
266void ValidateBroadcastTensorShapesMatch(const TensorInfo& first,
267 const TensorInfo& second,
268 const TensorInfo& output,
269 std::string const& descName,
270 std::string const& firstName,
271 std::string const& secondName)
272{
273 // Tensors must have the same number of dimensions in order to be explicit about which dimensions will get
274 // broadcasted.
275 if (first.GetNumDimensions() != second.GetNumDimensions())
276 {
277 throw InvalidArgumentException(descName + ": Tensors "
278 + firstName + " & " + secondName
279 + " must have the same number of dimensions in order to be broadcasted");
280 }
281 uint32_t numDims = first.GetNumDimensions();
282 std::vector<uint32_t> outputDims(numDims, 0u);
283 for (uint32_t i = 0; i < numDims; i++)
284 {
285 const bool dimsNotEqual = first.GetShape()[i] != second.GetShape()[i];
286 const bool dimsNotOne = (first.GetShape()[i] != 1) && (second.GetShape()[i] != 1);
287 if (dimsNotEqual && dimsNotOne)
288 {
289 throw InvalidArgumentException("Broadcasting is not possible for incompatible shapes");
290 }
291 outputDims[i] = std::max(first.GetShape()[i], second.GetShape()[i]);
292 }
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100293 TensorShape broadcastShape = TensorShape(boost::numeric_cast<unsigned int>(outputDims.size()), outputDims.data());
telsoa014fcda012018-03-09 14:13:49 +0000294 if (broadcastShape != output.GetShape())
295 {
296 throw InvalidArgumentException(descName + ": The tensor shape resulting from adding "
297 + firstName + " & " + secondName
298 + " does not match the output shape");
299 }
300}
301
302//---------------------------------------------------------------
Sadik Armaganeff363d2019-04-05 15:25:46 +0100303void ValidateDataTypes(const TensorInfo& info,
304 const std::vector<armnn::DataType>& supportedTypes,
305 std::string const& descName)
306{
307 auto iterator = std::find(supportedTypes.begin(), supportedTypes.end(), info.GetDataType());
308 if (iterator == supportedTypes.end())
309 {
310 throw InvalidArgumentException(descName + ": " + " Tensor type is not supported.");
311 }
312}
313
James Conroy4d1ff582019-06-10 17:06:39 +0100314//---------------------------------------------------------------
315void ValidateTensorDataTypesMatch(const TensorInfo& first,
316 const TensorInfo& second,
317 std::string const& descName,
318 std::string const& firstName,
319 std::string const& secondName)
320{
321 if (first.GetDataType() != second.GetDataType())
322 {
323 throw InvalidArgumentException(descName + ": " + firstName + " & " + secondName +
324 " must have identical data types.");
325 }
326}
327
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100328//---------------------------------------------------------------
329void ValidateTensorNumElementsMatch(const TensorInfo& first,
330 const TensorInfo& second,
331 std::string const& descName,
332 std::string const& firstName,
333 std::string const& secondName)
334{
335 if (first.GetNumElements() != second.GetNumElements())
336 {
337 throw InvalidArgumentException(descName + ": " + firstName + " & " + secondName +
338 " must have the same number of elements.");
339 }
340}
341
Aron Virginas-Tar5edc8812019-11-05 18:00:21 +0000342void ValidateWeightDataType(const TensorInfo& inputInfo,
343 const TensorInfo& weightInfo,
344 const std::string& descName)
345{
346 const DataType inputType = inputInfo.GetDataType();
347 if (inputType == DataType::QuantisedAsymm8)
348 {
349 const std::vector<DataType> validTypes =
350 {
351 DataType::QuantisedAsymm8,
352 DataType::QuantizedSymm8PerAxis
353 };
354
355 ValidateDataTypes(weightInfo, validTypes, descName);
356 }
357 else
358 {
359 ValidateTensorDataTypesMatch(inputInfo, weightInfo, descName, "input", "weight");
360 }
361}
362
363void ValidatePerAxisQuantizationDimension(const TensorInfo& tensorInfo,
364 const std::string& descName,
365 const std::string& tensorName)
366{
367 const Optional<unsigned int>& quantizationDim = tensorInfo.GetQuantizationDim();
368 if (!quantizationDim.has_value())
369 {
370 throw InvalidArgumentException(boost::str(
371 boost::format("%1%: Quantization dimension for per-axis quantization not set on tensor %2%.")
372 % descName % tensorName));
373 }
374
375 if (quantizationDim.value() != 0)
376 {
377 throw InvalidArgumentException(boost::str(
378 boost::format("%1%: Quantization dimension for per-axis quantization expected to be 0 on tensor %2%, "
379 "but got: %3%") % descName % tensorName % quantizationDim.value()));
380 }
381}
382
383void ValidatePerAxisQuantizationOffset(const TensorInfo& tensorInfo,
384 const std::string& descName,
385 const std::string& tensorName)
386{
387 int32_t quantizationOffset = tensorInfo.GetQuantizationOffset();
388 if (quantizationOffset != 0)
389 {
390 throw InvalidArgumentException(boost::str(
391 boost::format("%1%: Quantization offset for per-axis quantization expected to be 0 on tensor %2%, "
392 "but got: %3%") % descName % tensorName % quantizationOffset));
393 }
394}
395
396void ValidatePerAxisQuantization(const TensorInfo& inputInfo,
397 const TensorInfo& outputInfo,
398 const TensorInfo& weightInfo,
399 const Optional<TensorInfo>& optionalBiasInfo,
400 const std::string& descName)
401{
402 if (weightInfo.HasPerAxisQuantization())
403 {
404 const DataType inputDataType = inputInfo.GetDataType();
405 const DataType outputDataType = outputInfo.GetDataType();
406
407 const bool canHavePerAxisQuantization =
408 inputDataType == DataType::QuantisedAsymm8 && inputDataType == outputDataType;
409
410 if (!canHavePerAxisQuantization)
411 {
412 throw InvalidArgumentException(boost::str(
413 boost::format("%1%: Per-axis quantization parameters set on tensor %2%, "
414 "but data type does not support per-axis quantization.") % descName % "weight"));
415 }
416
417 ValidateTensorDataType(weightInfo, DataType::QuantizedSymm8PerAxis, descName, "weight");
418 ValidatePerAxisQuantizationDimension(weightInfo, descName, "weight");
419 ValidatePerAxisQuantizationOffset(weightInfo, descName, "weight");
420
421 if (optionalBiasInfo.has_value())
422 {
423 const TensorInfo& biasInfo = optionalBiasInfo.value();
424 if (!biasInfo.HasPerAxisQuantization())
425 {
426 throw InvalidArgumentException(boost::str(
427 boost::format("%1%: Per-axis quantization parameters not set on bias tensor, despite being set on "
428 "weight tensor.") % descName));
429 }
430
431 ValidateTensorDataType(biasInfo, DataType::Signed32, descName, "bias");
432 ValidatePerAxisQuantizationDimension(biasInfo, descName, "bias");
433 ValidatePerAxisQuantizationOffset(biasInfo, descName, "bias");
434 }
435 }
436}
437
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100438} // anonymous namespace
telsoa014fcda012018-03-09 14:13:49 +0000439
440void QueueDescriptor::ValidateInputsOutputs(const std::string& descName,
441 unsigned int numExpectedIn, unsigned int numExpectedOut) const
442{
443 ValidateTensors(m_Inputs, numExpectedIn, descName, "input");
444 ValidateTensors(m_Outputs, numExpectedOut, descName, "output");
445}
446
447//---------------------------------------------------------------
448void MemCopyQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
449{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100450 const std::string descriptorName{"MemCopyQueueDescriptor"};
telsoa014fcda012018-03-09 14:13:49 +0000451
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100452 ValidateNumInputs(workloadInfo, descriptorName, 1);
453 ValidateNumOutputs(workloadInfo, descriptorName , 1);
telsoa014fcda012018-03-09 14:13:49 +0000454
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100455 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
456 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
457
458 ValidateTensorNumElementsMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
459 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
telsoa014fcda012018-03-09 14:13:49 +0000460
461 if (m_Inputs.size() != m_Outputs.size())
462 {
463 throw InvalidArgumentException(boost::str(
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100464 boost::format("%1%: Number of inputs (%2%) does not match the number of outputs (%3%).") %
465 descriptorName % m_Inputs.size() % m_Outputs.size()));
telsoa014fcda012018-03-09 14:13:49 +0000466 }
467
468 for (unsigned int i = 0; i < m_Inputs.size(); ++i)
469 {
470 if (!m_Inputs[i])
471 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100472 throw InvalidArgumentException(boost::str(boost::format("%1%: Invalid NULL input %2%.") %
473 descriptorName % i));
telsoa014fcda012018-03-09 14:13:49 +0000474 }
475
476 if (!m_Outputs[i])
477 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100478 throw InvalidArgumentException(boost::str(boost::format("%1%: Invalid NULL output %2%") %
479 descriptorName % i));
telsoa014fcda012018-03-09 14:13:49 +0000480 }
481 }
482}
483
Derek Lambertif674aa02019-08-01 15:56:25 +0100484//---------------------------------------------------------------
485void MemImportQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
486{
487 ValidateNumInputs(workloadInfo, "MemImportQueueDescriptor", 1);
488 ValidateNumOutputs(workloadInfo, "MemImportQueueDescriptor" , 1);
489
490 if (workloadInfo.m_InputTensorInfos.size() != 1)
491 {
492 throw InvalidArgumentException(boost::str(
493 boost::format("Number of input infos (%1%) is not 1.")
494 % workloadInfo.m_InputTensorInfos.size()));
495
496 }
497
498 if (workloadInfo.m_InputTensorInfos.size() != workloadInfo.m_OutputTensorInfos.size())
499 {
500 throw InvalidArgumentException(boost::str(
501 boost::format("Number of input infos (%1%) does not match the number of output infos (%2%)")
502 % workloadInfo.m_InputTensorInfos.size() % workloadInfo.m_OutputTensorInfos.size()));
503 }
504
505 for (std::size_t i = 0; i < workloadInfo.m_InputTensorInfos.size(); ++i)
506 {
507 if (workloadInfo.m_InputTensorInfos[i].GetNumElements() !=
508 workloadInfo.m_OutputTensorInfos[i].GetNumElements())
509 {
510 throw InvalidArgumentException(boost::str(
511 boost::format("Number of elements for tensor input and output %1% does not match")
512 % i ));
513 }
514 }
515
516 if (m_Inputs.size() != 1)
517 {
518 throw InvalidArgumentException(boost::str(
519 boost::format("Number of inputs (%1%) is not 1.")
520 % m_Inputs.size()));
521 }
522
523 if (m_Inputs.size() != m_Outputs.size())
524 {
525 throw InvalidArgumentException(boost::str(
526 boost::format("Number of inputs (%1%) does not match the number of outputs (%2%)")
527 % m_Inputs.size() % m_Outputs.size()));
528 }
529
530 for (unsigned int i = 0; i < m_Inputs.size(); ++i)
531 {
532 if (!m_Inputs[i])
533 {
534 throw InvalidArgumentException(boost::str(boost::format("Invalid null input %1%") % i));
535 }
536
537 if (!m_Outputs[i])
538 {
539 throw InvalidArgumentException(boost::str(boost::format("Invalid null output %1%") % i));
540 }
541 }
542}
543
544//---------------------------------------------------------------
545void MemSyncQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
546{
547 ValidateNumInputs(workloadInfo, "MemSyncQueueDescriptor", 1);
548 ValidateNumOutputs(workloadInfo, "MemSyncQueueDescriptor" , 1);
549
Derek Lambertif674aa02019-08-01 15:56:25 +0100550 if (m_Inputs.size() != 1)
551 {
552 throw InvalidArgumentException(boost::str(
553 boost::format("Number of inputs (%1%) is not 1.")
554 % m_Inputs.size()));
555 }
556
557 if (m_Outputs.size() != 0)
558 {
559 throw InvalidArgumentException(boost::str(
560 boost::format("Number of outputs (%1%) is not 0.")
561 % m_Inputs.size() % m_Outputs.size()));
562 }
563
564 if (!m_Inputs[0])
565 {
566 throw InvalidArgumentException(boost::str(boost::format("Invalid null input 0")));
567 }
568}
569
570//---------------------------------------------------------------
telsoa014fcda012018-03-09 14:13:49 +0000571void ActivationQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
572{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100573 const std::string descriptorName{"ActivationQueueDescriptor"};
Nattapat Chaimanowongae2c5f02019-04-24 16:19:57 +0100574
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100575 ValidateNumInputs(workloadInfo, descriptorName, 1);
576 ValidateNumOutputs(workloadInfo, descriptorName, 1);
Nattapat Chaimanowongae2c5f02019-04-24 16:19:57 +0100577
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100578 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
579 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
nikraj01248683f2019-05-29 16:46:50 +0100580
581 std::vector<DataType> supportedTypes =
582 {
James Conroyd47a0642019-09-17 14:22:06 +0100583 DataType::Float16,
584 DataType::Float32,
585 DataType::QuantisedAsymm8,
586 DataType::QuantisedSymm16
nikraj01248683f2019-05-29 16:46:50 +0100587 };
588
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100589 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
590 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
591 ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
telsoa014fcda012018-03-09 14:13:49 +0000592}
593
Nikhil Rajee391d52019-09-05 17:50:44 +0100594void ArgMinMaxQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
595{
596 const std::string descriptorName{"ArgMinMaxQueueDescriptor"};
597
598 ValidateNumInputs(workloadInfo, descriptorName, 1);
599 ValidateNumOutputs(workloadInfo, descriptorName, 1);
600
601 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
602 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
603
Nikhil Raj68c2c902019-09-19 11:21:11 +0100604 if (outputTensorInfo.GetDataType() != DataType::Signed32)
605 {
606 throw InvalidArgumentException(descriptorName + ": Output of ArgMinMax layer must be Int32.");
607 }
608
James Conroyd47a0642019-09-17 14:22:06 +0100609 std::vector<DataType> supportedInputTypes =
610 {
611 DataType::Float16,
612 DataType::Float32,
613 DataType::QuantisedAsymm8,
Francis Murtagh1939df52019-11-13 15:21:09 +0000614 DataType::QuantisedSymm16,
615 DataType::Signed32
James Conroyd47a0642019-09-17 14:22:06 +0100616 };
Nikhil Rajee391d52019-09-05 17:50:44 +0100617
James Conroyd47a0642019-09-17 14:22:06 +0100618 ValidateDataTypes(inputTensorInfo, supportedInputTypes, descriptorName);
James Conroyc8724c72019-10-08 15:41:34 +0100619
620 auto inputShape = inputTensorInfo.GetShape();
621 auto outputShape = outputTensorInfo.GetShape();
622
623 auto inputNumDimensions = inputShape.GetNumDimensions();
624 auto unsignedAxis = armnnUtils::GetUnsignedAxis(inputNumDimensions, m_Parameters.m_Axis);
625
626 const std::string outputShapeError{": Output tensor shape does not match shape inferred from input tensor."};
627
628 // 1D input shape results in scalar output shape
629 if (inputShape.GetNumDimensions() == 1)
630 {
631 if (outputShape.GetNumDimensions() != 1 && outputShape[0] != 1)
632 {
633 throw InvalidArgumentException(descriptorName + outputShapeError);
634 }
635 }
636 else
637 {
638 for (unsigned int i = 0; i < unsignedAxis; ++i)
639 {
640 if (outputShape[i] != inputShape[i])
641 {
642 throw InvalidArgumentException(descriptorName + outputShapeError);
643 }
644 }
645
646 for (auto i = unsignedAxis + 1; i < inputNumDimensions; ++i)
647 {
648 if (outputShape[i - 1] != inputShape[i])
649 {
650 throw InvalidArgumentException(descriptorName + outputShapeError);
651 }
652 }
653 }
Nikhil Rajee391d52019-09-05 17:50:44 +0100654}
655
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100656void SoftmaxQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
657{
658 const std::string descriptorName{"SoftmaxQueueDescriptor"};
659
660 ValidateNumInputs(workloadInfo, descriptorName, 1);
661 ValidateNumOutputs(workloadInfo, descriptorName, 1);
662
663 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
664 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
665
666 std::vector<DataType> supportedTypes =
667 {
James Conroyd47a0642019-09-17 14:22:06 +0100668 DataType::Float16,
669 DataType::Float32,
670 DataType::QuantisedAsymm8,
671 DataType::QuantisedSymm16
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100672 };
673
674 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
675 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
676 ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
677}
678
telsoa014fcda012018-03-09 14:13:49 +0000679void SplitterQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
680{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100681 const std::string descriptorName{"SplitterQueueDescriptor"};
682
683 ValidateNumInputs(workloadInfo, descriptorName, 1);
telsoa014fcda012018-03-09 14:13:49 +0000684
Ruomei Yan25339c32019-05-28 16:48:20 +0100685 // Check the supported data types
686 std::vector<DataType> supportedTypes =
687 {
James Conroyd47a0642019-09-17 14:22:06 +0100688 DataType::Float32,
689 DataType::Float16,
690 DataType::Boolean,
691 DataType::Signed32,
692 DataType::QuantisedAsymm8,
693 DataType::QuantisedSymm16
Ruomei Yan25339c32019-05-28 16:48:20 +0100694 };
695
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100696 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
697 for (unsigned long i = 0ul; i < workloadInfo.m_OutputTensorInfos.size(); ++i)
Ruomei Yan25339c32019-05-28 16:48:20 +0100698 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100699 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[i];
700 ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
701
702 const std::string outputName = "output_" + std::to_string(i);
703 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", outputName);
Ruomei Yan25339c32019-05-28 16:48:20 +0100704 }
Ruomei Yan25339c32019-05-28 16:48:20 +0100705
telsoa014fcda012018-03-09 14:13:49 +0000706 if (workloadInfo.m_OutputTensorInfos.size() <= 0)
707 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100708 throw InvalidArgumentException(descriptorName + ": At least one output needs to be provided.");
telsoa014fcda012018-03-09 14:13:49 +0000709 }
710
711 if (workloadInfo.m_OutputTensorInfos.size() != m_ViewOrigins.size())
712 {
713 throw InvalidArgumentException(
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100714 descriptorName + ": Number of split windows "
telsoa014fcda012018-03-09 14:13:49 +0000715 "has to match number of workloadInfo.m_OutputTensorInfos. "
716 "Number of windows: " +
717 to_string(m_ViewOrigins.size()) +
718 ". Number of workloadInfo.m_OutputTensorInfos: " + to_string(workloadInfo.m_OutputTensorInfos.size()));
719 }
720
telsoa01c577f2c2018-08-31 09:22:23 +0100721 //The dimensionality of all the windows has to match the dimensionality (not shape) of the input.
telsoa014fcda012018-03-09 14:13:49 +0000722 std::size_t inputDims = workloadInfo.m_InputTensorInfos[0].GetNumDimensions();
723 for(unsigned int w = 0; w < m_ViewOrigins.size(); ++w )
724 {
telsoa01c577f2c2018-08-31 09:22:23 +0100725 //Checks that the dimensionality of input is same as the split windows.
telsoa014fcda012018-03-09 14:13:49 +0000726 ViewOrigin const& e = m_ViewOrigins[w];
727 if (e.m_Origin.size() != inputDims)
728 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100729 throw InvalidArgumentException(descriptorName + ": Window origin have to "
telsoa014fcda012018-03-09 14:13:49 +0000730 "have the same dimensionality as the input tensor. "
731 "Window origin (index: " +
732 to_string(w) + ") has " + to_string(e.m_Origin.size()) +
733 " dimensions, the input "
734 "tensor has " +
735 to_string(inputDims) + " dimensions.");
736 }
737 for (unsigned int i = 0; i < e.m_Origin.size(); ++i)
738 {
739 if (e.m_Origin[i] + workloadInfo.m_OutputTensorInfos[w].GetShape()[i] >
740 workloadInfo.m_InputTensorInfos[0].GetShape()[i])
741 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100742 throw InvalidArgumentException(descriptorName + ": Window extent coordinates have to "
telsoa014fcda012018-03-09 14:13:49 +0000743 "be smaller or equal than the size of the input in that coord.");
744 }
745 }
746 }
747}
748
Jim Flynne242f2d2019-05-22 14:24:13 +0100749void ConcatQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
telsoa014fcda012018-03-09 14:13:49 +0000750{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100751 const std::string descriptorName{"ConcatQueueDescriptor"};
752
753 ValidateNumOutputs(workloadInfo, descriptorName, 1);
telsoa014fcda012018-03-09 14:13:49 +0000754
755 if (m_Inputs.size() <= 0)
756 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100757 throw InvalidArgumentException(descriptorName + ": At least one input needs to be provided.");
telsoa014fcda012018-03-09 14:13:49 +0000758 }
759 if (m_Outputs.size() <= 0)
760 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100761 throw InvalidArgumentException(descriptorName + ": At least one output needs to be provided.");
telsoa014fcda012018-03-09 14:13:49 +0000762 }
763
764 if (workloadInfo.m_InputTensorInfos.size() <= 0)
765 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100766 throw InvalidArgumentException(descriptorName + ": At least one TensorInfo input needs to be provided.");
telsoa014fcda012018-03-09 14:13:49 +0000767 }
768 if (workloadInfo.m_OutputTensorInfos.size() <= 0)
769 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100770 throw InvalidArgumentException(descriptorName + ": At least one TensorInfo output needs to be provided.");
telsoa014fcda012018-03-09 14:13:49 +0000771 }
772
Nikhil Raj8599a412018-11-19 14:51:07 +0000773 if(m_Parameters.GetConcatAxis() > workloadInfo.m_InputTensorInfos[0].GetShape().GetNumDimensions())
774 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100775 throw InvalidArgumentException(descriptorName + ": Invalid concatenation axis provided.");
Nikhil Raj8599a412018-11-19 14:51:07 +0000776 }
777
778 if (workloadInfo.m_InputTensorInfos[0].GetShape().GetNumDimensions() - m_Parameters.GetConcatAxis() == 1)
779 {
780 return;
781 }
782
telsoa014fcda012018-03-09 14:13:49 +0000783 if (workloadInfo.m_InputTensorInfos.size() != m_ViewOrigins.size())
784 {
785 throw InvalidArgumentException(
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100786 descriptorName + ": Number of split windows "
telsoa014fcda012018-03-09 14:13:49 +0000787 "has to match number of workloadInfo.m_InputTensorInfos. "
788 "Number of windows: " +
789 to_string(m_ViewOrigins.size()) +
790 ". Number of workloadInfo.m_InputTensorInfos: " + to_string(workloadInfo.m_InputTensorInfos.size()));
791 }
792
telsoa01c577f2c2018-08-31 09:22:23 +0100793 //The dimensionality of all the windows has to match the dimensionality (not shape) of the output.
telsoa014fcda012018-03-09 14:13:49 +0000794 std::size_t outputDims = workloadInfo.m_OutputTensorInfos[0].GetNumDimensions();
795 for(unsigned int w = 0; w < m_ViewOrigins.size(); ++w )
796 {
telsoa01c577f2c2018-08-31 09:22:23 +0100797 //Checks that the dimensionality of output is same as the split windows.
telsoa014fcda012018-03-09 14:13:49 +0000798 ViewOrigin const& e = m_ViewOrigins[w];
799 if (e.m_Origin.size() != outputDims)
800 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100801 throw InvalidArgumentException(descriptorName + ": Window origin have to "
telsoa014fcda012018-03-09 14:13:49 +0000802 "have the same dimensionality as the output tensor. "
803 "Window origin (index: " +
804 to_string(w) + ") has " + to_string(e.m_Origin.size()) +
805 " dimensions, the output "
806 "tensor has " +
807 to_string(outputDims) + " dimensions.");
808 }
telsoa01c577f2c2018-08-31 09:22:23 +0100809 //Checks that the merge windows are within the output tensor.
telsoa014fcda012018-03-09 14:13:49 +0000810 for (unsigned int i = 0; i < e.m_Origin.size(); ++i)
811 {
812 if (e.m_Origin[i] + workloadInfo.m_InputTensorInfos[w].GetShape()[i]
813 > workloadInfo.m_OutputTensorInfos[0].GetShape()[i])
814 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100815 throw InvalidArgumentException(descriptorName + ": Window extent coordinates have to "
telsoa014fcda012018-03-09 14:13:49 +0000816 "be smaller or equal than the size of the output in that coord.");
817 }
818 }
819 }
Jim Flynncbb66aa2019-05-15 13:03:54 +0100820
821 // Check the supported data types
822 std::vector<DataType> supportedTypes =
823 {
James Conroyd47a0642019-09-17 14:22:06 +0100824 DataType::Float32,
825 DataType::Float16,
826 DataType::Boolean,
827 DataType::Signed32,
828 DataType::QuantisedAsymm8,
829 DataType::QuantisedSymm16
Jim Flynncbb66aa2019-05-15 13:03:54 +0100830 };
831
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100832 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
833 for (unsigned long i = 0ul; i < workloadInfo.m_InputTensorInfos.size(); ++i)
Jim Flynncbb66aa2019-05-15 13:03:54 +0100834 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100835 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[i];
836 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
837
838 const std::string inputName = "input_" + std::to_string(i);
839 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, inputName, "output");
Jim Flynncbb66aa2019-05-15 13:03:54 +0100840 }
telsoa014fcda012018-03-09 14:13:49 +0000841}
842
Matthew Jackson2b8c1da2019-07-04 14:59:16 +0100843void StackQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
844{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100845 const std::string descriptorName{"StackQueueDescriptor"};
846
847 ValidateNumOutputs(workloadInfo, descriptorName, 1);
Matthew Jackson2b8c1da2019-07-04 14:59:16 +0100848
849 if (m_Parameters.m_NumInputs != workloadInfo.m_InputTensorInfos.size())
850 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100851 throw InvalidArgumentException(descriptorName + ": Must have the defined number of input tensors.");
Matthew Jackson2b8c1da2019-07-04 14:59:16 +0100852 }
853
854 // All inputs must have the same shape, which is defined in parameters
855 const TensorShape& inputShape = m_Parameters.m_InputShape;
856 for (unsigned int i = 0; i < workloadInfo.m_InputTensorInfos.size(); ++i)
857 {
858 if (workloadInfo.m_InputTensorInfos[i].GetShape() != inputShape)
859 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100860 throw InvalidArgumentException(descriptorName + ": All input tensor shapes must match the defined shape.");
Matthew Jackson2b8c1da2019-07-04 14:59:16 +0100861 }
862 }
863
Matthew Jacksondba634f2019-08-15 15:14:18 +0100864 if (inputShape.GetNumDimensions() > 4)
865 {
866 throw InvalidArgumentException(descriptorName + ": Input tensor may have up to 4 dimensions.");
867 }
868
Matthew Jackson2b8c1da2019-07-04 14:59:16 +0100869 // m_Axis is 0-based and may take values from 0 to the number of input dimensions (inclusive),
870 // since the output tensor has an additional dimension.
871 if (m_Parameters.m_Axis > inputShape.GetNumDimensions())
872 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100873 throw InvalidArgumentException(descriptorName + ": Axis may not be greater "
Matthew Jackson2b8c1da2019-07-04 14:59:16 +0100874 "than the number of input dimensions.");
875 }
876
877 // Output shape must be as inferred from the input shape
878 const TensorShape& outputShape = workloadInfo.m_OutputTensorInfos[0].GetShape();
879 for (unsigned int i = 0; i < m_Parameters.m_Axis; ++i)
880 {
881 if (outputShape[i] != inputShape[i])
882 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100883 throw InvalidArgumentException(descriptorName + ": Output tensor must "
Matthew Jackson2b8c1da2019-07-04 14:59:16 +0100884 "match shape inferred from input tensor.");
885 }
886 }
887
888 if (outputShape[m_Parameters.m_Axis] != m_Parameters.m_NumInputs)
889 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100890 throw InvalidArgumentException(descriptorName + ": Output tensor must "
Matthew Jackson2b8c1da2019-07-04 14:59:16 +0100891 "match shape inferred from input tensor.");
892 }
893
894 for (unsigned int i = m_Parameters.m_Axis + 1; i < inputShape.GetNumDimensions() + 1; ++i)
895 {
896 if (outputShape[i] != inputShape[i-1])
897 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100898 throw InvalidArgumentException(descriptorName + ": Output tensor must "
Matthew Jackson2b8c1da2019-07-04 14:59:16 +0100899 "match shape inferred from input tensor.");
900 }
901 }
902
Matthew Jacksondba634f2019-08-15 15:14:18 +0100903 if (outputShape.GetNumDimensions() > 5)
904 {
905 throw InvalidArgumentException(descriptorName + ": Output tensor may have up to 5 dimensions.");
906 }
907
Matthew Jackson2b8c1da2019-07-04 14:59:16 +0100908 // Check the supported data types
909 std::vector<DataType> supportedTypes =
910 {
James Conroyd47a0642019-09-17 14:22:06 +0100911 DataType::Float32,
912 DataType::Float16,
913 DataType::Boolean,
914 DataType::Signed32,
915 DataType::QuantisedAsymm8,
916 DataType::QuantisedSymm16
Matthew Jackson2b8c1da2019-07-04 14:59:16 +0100917 };
918
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100919 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0], supportedTypes, descriptorName);
Matthew Jackson2b8c1da2019-07-04 14:59:16 +0100920
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100921 for (unsigned int i = 1ul; i < workloadInfo.m_InputTensorInfos.size(); ++i)
Matthew Jackson2b8c1da2019-07-04 14:59:16 +0100922 {
923 ValidateTensorDataTypesMatch(workloadInfo.m_InputTensorInfos[0],
924 workloadInfo.m_InputTensorInfos[i],
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100925 descriptorName,
926 "input_0",
927 "input_" + std::to_string(i));
Matthew Jackson2b8c1da2019-07-04 14:59:16 +0100928 }
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100929
Matthew Jackson2b8c1da2019-07-04 14:59:16 +0100930 ValidateTensorDataTypesMatch(workloadInfo.m_InputTensorInfos[0],
931 workloadInfo.m_OutputTensorInfos[0],
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100932 descriptorName,
933 "input_0",
934 "output");
Matthew Jackson2b8c1da2019-07-04 14:59:16 +0100935}
936
telsoa014fcda012018-03-09 14:13:49 +0000937void FullyConnectedQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
938{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100939 const std::string descriptorName{"FullyConnectedQueueDescriptor"};
telsoa014fcda012018-03-09 14:13:49 +0000940
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100941 ValidateNumInputs(workloadInfo, descriptorName, 1);
942 ValidateNumOutputs(workloadInfo, descriptorName, 1);
943
944 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
945 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
946
947 ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 2, "output");
948
949 if (!(inputTensorInfo.GetNumDimensions() == 2 || inputTensorInfo.GetNumDimensions() == 4))
telsoa014fcda012018-03-09 14:13:49 +0000950 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100951 throw InvalidArgumentException(descriptorName + ": Input tensor must have 2 or 4 dimensions.");
telsoa014fcda012018-03-09 14:13:49 +0000952 }
953
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100954 ValidatePointer(m_Weight, descriptorName, "weight");
telsoa014fcda012018-03-09 14:13:49 +0000955
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100956 const TensorInfo& weightTensorInfo = m_Weight->GetTensorInfo();
957 ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 2, "weight");
telsoa014fcda012018-03-09 14:13:49 +0000958
959 if (m_Parameters.m_BiasEnabled)
960 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100961 ValidatePointer(m_Bias, descriptorName, "bias");
telsoa014fcda012018-03-09 14:13:49 +0000962
telsoa01c577f2c2018-08-31 09:22:23 +0100963 // Validates type and quantization values.
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100964 const TensorInfo& biasTensorInfo = m_Bias->GetTensorInfo();
965 ValidateBiasTensorQuantization(biasTensorInfo, inputTensorInfo, weightTensorInfo, descriptorName);
telsoa014fcda012018-03-09 14:13:49 +0000966
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100967 ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
968 ValidateTensorNumDimensions(biasTensorInfo, descriptorName, 1, "bias");
telsoa014fcda012018-03-09 14:13:49 +0000969 }
970
Francis Murtagh46c09d02019-05-28 08:15:28 +0100971 // Check the supported data types
972 std::vector<DataType> supportedTypes =
973 {
James Conroyd47a0642019-09-17 14:22:06 +0100974 DataType::Float32,
975 DataType::Float16,
976 DataType::QuantisedAsymm8,
977 DataType::QuantisedSymm16
Francis Murtagh46c09d02019-05-28 08:15:28 +0100978 };
979
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100980 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
981 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
telsoa014fcda012018-03-09 14:13:49 +0000982}
983
telsoa014fcda012018-03-09 14:13:49 +0000984void NormalizationQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
985{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +0100986 const std::string descriptorName{"NormalizationQueueDescriptor"};
987
988 ValidateNumInputs(workloadInfo, descriptorName, 1);
989 ValidateNumOutputs(workloadInfo, descriptorName, 1);
990
991 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
992 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
Matteo Martincigh2fc70c52019-06-05 14:12:48 +0100993
994 // Check the supported data types
995 std::vector<DataType> supportedTypes =
996 {
997 DataType::Float16,
998 DataType::Float32,
Matteo Martincigh6aeb7712019-06-05 17:23:29 +0100999 DataType::QuantisedAsymm8,
1000 DataType::QuantisedSymm16
Matteo Martincigh2fc70c52019-06-05 14:12:48 +01001001 };
1002
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001003 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
Matteo Martincigh2fc70c52019-06-05 14:12:48 +01001004
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001005 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
Matteo Martincigh2fc70c52019-06-05 14:12:48 +01001006
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001007 ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
telsoa014fcda012018-03-09 14:13:49 +00001008}
1009
1010void AdditionQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1011{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001012 const std::string descriptorName{"AdditionQueueDescriptor"};
telsoa014fcda012018-03-09 14:13:49 +00001013
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001014 ValidateNumInputs(workloadInfo, descriptorName, 2);
1015 ValidateNumOutputs(workloadInfo, descriptorName, 1);
1016
1017 const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
1018 const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
1019 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1020
1021 std::vector<DataType> supportedTypes =
1022 {
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01001023 DataType::Float32,
Sadik Armagan2999a022019-04-09 14:20:12 +01001024 DataType::QuantisedAsymm8,
Jim Flynn82fbe7c2019-04-02 15:19:08 +01001025 DataType::QuantisedSymm16,
1026 DataType::Float16
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01001027 };
1028
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001029 ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
1030 ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
1031 ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01001032
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001033 ValidateTensorDataTypesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
1034 ValidateTensorDataTypesMatch(inputTensorInfo1, outputTensorInfo, descriptorName, "input_1", "output");
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01001035
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001036 ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
1037 inputTensorInfo1,
1038 outputTensorInfo,
1039 descriptorName,
1040 "input_0",
1041 "input_1");
telsoa014fcda012018-03-09 14:13:49 +00001042}
1043
telsoa014fcda012018-03-09 14:13:49 +00001044void MultiplicationQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1045{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001046 const std::string descriptorName{"MultiplicationQueueDescriptor"};
surmeh01bceff2f2018-03-29 16:29:27 +01001047
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001048 ValidateNumInputs(workloadInfo, descriptorName, 2);
1049 ValidateNumOutputs(workloadInfo, descriptorName, 1);
1050
1051 const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
1052 const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
1053 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1054
1055 std::vector<DataType> supportedTypes =
1056 {
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01001057 DataType::Float32,
Sadik Armagan2999a022019-04-09 14:20:12 +01001058 DataType::QuantisedAsymm8,
Jim Flynn82fbe7c2019-04-02 15:19:08 +01001059 DataType::QuantisedSymm16,
1060 DataType::Float16
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01001061 };
1062
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001063 ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
1064 ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
1065 ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01001066
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001067 ValidateTensorDataTypesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
1068 ValidateTensorDataTypesMatch(inputTensorInfo1, outputTensorInfo, descriptorName, "input_1", "output");
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01001069
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001070 ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
1071 inputTensorInfo1,
1072 outputTensorInfo,
1073 descriptorName,
1074 "input_0",
1075 "input_1");
telsoa014fcda012018-03-09 14:13:49 +00001076}
1077
1078void BatchNormalizationQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1079{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001080 const std::string descriptorName{"BatchNormalizationQueueDescriptor"};
Matteo Martincigh3122bd52019-06-03 16:54:25 +01001081
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001082 ValidateNumInputs(workloadInfo, descriptorName, 1);
1083 ValidateNumOutputs(workloadInfo, descriptorName, 1);
1084
1085 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1086 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
Matteo Martincigh3122bd52019-06-03 16:54:25 +01001087
1088 std::vector<DataType> supportedTypes =
1089 {
1090 DataType::Float16,
1091 DataType::Float32,
Matteo Martincighf5507132019-06-04 10:59:47 +01001092 DataType::QuantisedAsymm8,
1093 DataType::QuantisedSymm16
Matteo Martincigh3122bd52019-06-03 16:54:25 +01001094 };
1095
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001096 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1097 ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
Matteo Martincigh3122bd52019-06-03 16:54:25 +01001098
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001099 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1100 ValidateTensorQuantizationSpace(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1101 ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
Matteo Martincigh3122bd52019-06-03 16:54:25 +01001102
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001103 ValidatePointer(m_Mean, descriptorName, "mean");
1104 ValidatePointer(m_Variance, descriptorName, "variance");
1105 ValidatePointer(m_Beta, descriptorName, "beta");
1106 ValidatePointer(m_Gamma, descriptorName, "gamma");
telsoa014fcda012018-03-09 14:13:49 +00001107
Matteo Martincigh3122bd52019-06-03 16:54:25 +01001108 const TensorInfo& mean = m_Mean->GetTensorInfo();
1109 const TensorInfo& variance = m_Variance->GetTensorInfo();
1110 const TensorInfo& beta = m_Beta->GetTensorInfo();
1111 const TensorInfo& gamma = m_Gamma->GetTensorInfo();
telsoa014fcda012018-03-09 14:13:49 +00001112
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001113 ValidateTensorNumDimensions(mean, descriptorName, 1, "mean");
1114 ValidateTensorNumDimensions(variance, descriptorName, 1, "variance");
1115 ValidateTensorNumDimensions(beta, descriptorName, 1, "beta");
1116 ValidateTensorNumDimensions(gamma, descriptorName, 1, "gamma");
telsoa014fcda012018-03-09 14:13:49 +00001117
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001118 ValidateTensorShapesMatch(mean, variance, descriptorName, "mean", "variance");
1119 ValidateTensorShapesMatch(mean, beta, descriptorName, "mean", "beta");
1120 ValidateTensorShapesMatch(mean, gamma, descriptorName, "mean", "gamma");
telsoa014fcda012018-03-09 14:13:49 +00001121}
1122
1123void Convolution2dQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1124{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001125 const std::string descriptorName{"Convolution2dQueueDescriptor"};
telsoa014fcda012018-03-09 14:13:49 +00001126
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001127 ValidateNumInputs(workloadInfo, descriptorName, 1);
1128 ValidateNumOutputs(workloadInfo, descriptorName, 1);
telsoa014fcda012018-03-09 14:13:49 +00001129
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001130 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1131 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
telsoa014fcda012018-03-09 14:13:49 +00001132
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001133 ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1134 ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
telsoa014fcda012018-03-09 14:13:49 +00001135
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001136 ValidatePointer(m_Weight, descriptorName, "weight");
telsoa014fcda012018-03-09 14:13:49 +00001137
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001138 const TensorInfo& weightTensorInfo = m_Weight->GetTensorInfo();
1139 ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 4, "weight");
telsoa014fcda012018-03-09 14:13:49 +00001140
Aron Virginas-Tar5edc8812019-11-05 18:00:21 +00001141 ValidateWeightDataType(inputTensorInfo, weightTensorInfo, descriptorName);
telsoa014fcda012018-03-09 14:13:49 +00001142
Aron Virginas-Tar5edc8812019-11-05 18:00:21 +00001143 Optional<TensorInfo> optionalBiasTensorInfo;
telsoa014fcda012018-03-09 14:13:49 +00001144 if (m_Parameters.m_BiasEnabled)
1145 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001146 ValidatePointer(m_Bias, descriptorName, "bias");
telsoa014fcda012018-03-09 14:13:49 +00001147
Aron Virginas-Tar5edc8812019-11-05 18:00:21 +00001148 optionalBiasTensorInfo = MakeOptional<TensorInfo>(m_Bias->GetTensorInfo());
1149 const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value();
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001150
1151 ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
1152 ValidateBiasTensorQuantization(biasTensorInfo, inputTensorInfo, weightTensorInfo, descriptorName);
telsoa014fcda012018-03-09 14:13:49 +00001153 }
1154
Aron Virginas-Tar5edc8812019-11-05 18:00:21 +00001155 ValidatePerAxisQuantization(inputTensorInfo,
1156 outputTensorInfo,
1157 weightTensorInfo,
1158 optionalBiasTensorInfo,
1159 descriptorName);
1160
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001161 std::vector<DataType> supportedTypes =
1162 {
Ruomei Yan88d44b82019-05-23 14:29:06 +01001163 DataType::Float32,
1164 DataType::QuantisedAsymm8,
1165 DataType::QuantisedSymm16,
1166 DataType::Float16
1167 };
1168
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001169 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1170 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1171}
Ruomei Yan88d44b82019-05-23 14:29:06 +01001172
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001173void DepthwiseConvolution2dQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1174{
1175 const std::string descriptorName{"DepthwiseConvolution2dQueueDescriptor"};
1176
1177 ValidateNumInputs(workloadInfo, descriptorName, 1);
1178 ValidateNumOutputs(workloadInfo, descriptorName, 1);
1179
1180 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1181 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1182
1183 ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1184 ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1185
1186 ValidatePointer(m_Weight, descriptorName, "weight");
1187
1188 const TensorInfo& weightTensorInfo = m_Weight->GetTensorInfo();
1189 ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 4, "weight");
1190
1191 if (m_Parameters.m_DilationX < 1 || m_Parameters.m_DilationY < 1 )
1192 {
1193 throw InvalidArgumentException(
1194 boost::str(boost::format("%1%: dilationX (provided %2%) and dilationY (provided %3%) "
1195 "cannot be smaller than 1.") % descriptorName %
1196 m_Parameters.m_DilationX % m_Parameters.m_DilationX));
1197 }
1198
1199 const unsigned int channelIndex = (m_Parameters.m_DataLayout == DataLayout::NCHW) ? 1 : 3;
1200
1201 // Expected weight shape: [ M, I, H, W ] - This shape does NOT depend on the data layout
1202 // inputChannels * channelMultiplier should be equal to outputChannels.
1203 const unsigned int numWeightChannelMultiplier = weightTensorInfo.GetShape()[0];
1204 const unsigned int numWeightInputChannels = weightTensorInfo.GetShape()[1];
1205 const unsigned int numWeightOutputChannels = outputTensorInfo.GetShape()[channelIndex];
1206 if (numWeightChannelMultiplier * numWeightInputChannels != numWeightOutputChannels)
1207 {
1208 throw InvalidArgumentException(
1209 boost::str(boost::format("%1%: output_channels (provided %2%) should be "
1210 "equal to input_channels (provided %3%) multiplied by channel_multiplier "
1211 "(provided %4%).") % descriptorName % numWeightOutputChannels %
1212 numWeightInputChannels % numWeightChannelMultiplier));
1213 }
1214
Teresa Charlind8df0262019-11-11 12:28:15 +00001215 ValidateWeightDataType(inputTensorInfo, weightTensorInfo, descriptorName);
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001216
Teresa Charlind8df0262019-11-11 12:28:15 +00001217 Optional<TensorInfo> optionalBiasTensorInfo;
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001218 if (m_Parameters.m_BiasEnabled)
1219 {
1220 ValidatePointer(m_Bias, descriptorName, "bias");
1221
Teresa Charlind8df0262019-11-11 12:28:15 +00001222 optionalBiasTensorInfo = MakeOptional<TensorInfo>(m_Bias->GetTensorInfo());
1223 const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value();
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001224
1225 ValidateBiasTensorQuantization(biasTensorInfo, inputTensorInfo, weightTensorInfo, descriptorName);
1226 ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
1227 }
Teresa Charlind8df0262019-11-11 12:28:15 +00001228 ValidatePerAxisQuantization(inputTensorInfo,
1229 outputTensorInfo,
1230 weightTensorInfo,
1231 optionalBiasTensorInfo,
1232 descriptorName);
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001233
1234 std::vector<DataType> supportedTypes =
1235 {
1236 DataType::Float32,
1237 DataType::QuantisedAsymm8,
1238 DataType::QuantisedSymm16,
1239 DataType::Float16
1240 };
1241
1242 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1243 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
telsoa014fcda012018-03-09 14:13:49 +00001244}
1245
1246void PermuteQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1247{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001248 const std::string descriptorName{"PermuteQueueDescriptor"};
1249
1250 ValidateNumInputs(workloadInfo, descriptorName, 1);
1251 ValidateNumOutputs(workloadInfo, descriptorName, 1);
telsoa014fcda012018-03-09 14:13:49 +00001252
1253 const PermutationVector& mapping = m_Parameters.m_DimMappings;
1254
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001255 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1256 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
telsoa014fcda012018-03-09 14:13:49 +00001257
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001258 ValidateTensorNumDimensions(inputTensorInfo, descriptorName, mapping.GetSize(), "input");
1259 ValidateTensorNumDimensions(outputTensorInfo, descriptorName, mapping.GetSize(), "output");
telsoa014fcda012018-03-09 14:13:49 +00001260
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001261 for (unsigned int i = 0u; i < mapping.GetSize(); ++i)
telsoa014fcda012018-03-09 14:13:49 +00001262 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001263 if (inputTensorInfo.GetShape()[i] != outputTensorInfo.GetShape()[mapping[i]])
telsoa014fcda012018-03-09 14:13:49 +00001264 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001265 throw InvalidArgumentException(descriptorName + ": src dimension " + to_string(i) +
1266 " (=" + to_string(inputTensorInfo.GetShape()[i]) + ") " +
1267 "must match dst dimension " + to_string(mapping[i]) +
1268 " (=" + to_string(outputTensorInfo.GetShape()[mapping[i]]) + ")");
telsoa014fcda012018-03-09 14:13:49 +00001269 }
1270 }
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001271
1272 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
telsoa014fcda012018-03-09 14:13:49 +00001273}
1274
1275void Pooling2dQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1276{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001277 const std::string descriptorName{"Pooling2dQueueDescriptor"};
telsoa014fcda012018-03-09 14:13:49 +00001278
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001279 ValidateNumInputs(workloadInfo, descriptorName, 1);
1280 ValidateNumOutputs(workloadInfo, descriptorName, 1);
1281
1282 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1283 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1284
1285 ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1286 ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
Teresa Charlina3b20472019-06-06 11:12:32 +01001287
1288 std::vector<DataType> supportedTypes =
1289 {
1290 DataType::Float32,
1291 DataType::Float16,
Teresa Charlin0434df62019-06-06 13:40:35 +01001292 DataType::QuantisedAsymm8,
1293 DataType::QuantisedSymm16
Teresa Charlina3b20472019-06-06 11:12:32 +01001294 };
1295
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001296 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1297 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
telsoa014fcda012018-03-09 14:13:49 +00001298}
1299
1300void ResizeBilinearQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1301{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001302 const std::string descriptorName{"ResizeBilinearQueueDescriptor"};
telsoa014fcda012018-03-09 14:13:49 +00001303
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001304 ValidateNumInputs(workloadInfo, descriptorName, 1);
1305 ValidateNumOutputs(workloadInfo, descriptorName, 1);
1306
1307 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1308 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1309
1310 ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1311 ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
telsoa014fcda012018-03-09 14:13:49 +00001312
Ellen Norris-Thompson3cb85f32019-06-17 11:32:49 +01001313 std::vector<DataType> supportedTypes =
Teresa Charlin970f43b2019-07-01 13:51:07 +01001314 {
1315 DataType::Float16,
1316 DataType::Float32,
1317 DataType::QuantisedAsymm8,
1318 DataType::QuantisedSymm16
1319 };
Ellen Norris-Thompson3cb85f32019-06-17 11:32:49 +01001320
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001321 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1322 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
Ellen Norris-Thompson3cb85f32019-06-17 11:32:49 +01001323
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001324 // ResizeBilinear only changes width and height: batch and channel count must match.
1325 const unsigned int inputBatchSize = inputTensorInfo.GetShape()[0];
1326 const unsigned int outputBatchSize = outputTensorInfo.GetShape()[0];
Teresa Charlin970f43b2019-07-01 13:51:07 +01001327 if (inputBatchSize != outputBatchSize)
telsoa014fcda012018-03-09 14:13:49 +00001328 {
Teresa Charlin970f43b2019-07-01 13:51:07 +01001329 throw InvalidArgumentException(
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001330 boost::str(boost::format("%1%: Input batch size (%2%) "
1331 "does not match output batch size (%3%)") %
1332 descriptorName % inputBatchSize % outputBatchSize));
telsoa014fcda012018-03-09 14:13:49 +00001333 }
1334
Teresa Charlin970f43b2019-07-01 13:51:07 +01001335 DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001336 const unsigned int inputChannelCount = inputTensorInfo.GetShape()[dimensionIndices.GetChannelsIndex()];
1337 const unsigned int outputChannelCount = outputTensorInfo.GetShape()[dimensionIndices.GetChannelsIndex()];
Teresa Charlin970f43b2019-07-01 13:51:07 +01001338 if (inputChannelCount != outputChannelCount)
telsoa014fcda012018-03-09 14:13:49 +00001339 {
Teresa Charlin970f43b2019-07-01 13:51:07 +01001340 throw InvalidArgumentException(
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001341 boost::str(boost::format("%1%: Input channel count (%2%) "
1342 "does not match output channel count (%3%)") %
1343 descriptorName % inputChannelCount % outputChannelCount));
Teresa Charlin970f43b2019-07-01 13:51:07 +01001344 }
1345}
1346
1347void ResizeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1348{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001349 const std::string descriptorName{"ResizeQueueDescriptor"};
Teresa Charlin970f43b2019-07-01 13:51:07 +01001350
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001351 ValidateNumInputs(workloadInfo, descriptorName, 1);
1352 ValidateNumOutputs(workloadInfo, descriptorName, 1);
1353
1354 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1355 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1356
1357 ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1358 ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
Teresa Charlin970f43b2019-07-01 13:51:07 +01001359
1360 std::vector<DataType> supportedTypes =
1361 {
1362 DataType::Float16,
1363 DataType::Float32,
1364 DataType::QuantisedAsymm8,
1365 DataType::QuantisedSymm16
1366 };
1367
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001368 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1369 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
Teresa Charlin970f43b2019-07-01 13:51:07 +01001370
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001371 // Resize only changes width and height: batch and channel count must match.
1372 const unsigned int inputBatchSize = inputTensorInfo.GetShape()[0];
1373 const unsigned int outputBatchSize = outputTensorInfo.GetShape()[0];
Teresa Charlin970f43b2019-07-01 13:51:07 +01001374 if (inputBatchSize != outputBatchSize)
1375 {
1376 throw InvalidArgumentException(
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001377 boost::str(boost::format("%1%: Input batch size (%2%) "
1378 "does not match output batch size (%3%)") %
1379 descriptorName % inputBatchSize % outputBatchSize));
Teresa Charlin970f43b2019-07-01 13:51:07 +01001380 }
1381
1382 DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001383 const unsigned int inputChannelCount = inputTensorInfo.GetShape()[dimensionIndices.GetChannelsIndex()];
1384 const unsigned int outputChannelCount = outputTensorInfo.GetShape()[dimensionIndices.GetChannelsIndex()];
Teresa Charlin970f43b2019-07-01 13:51:07 +01001385 if (inputChannelCount != outputChannelCount)
1386 {
1387 throw InvalidArgumentException(
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001388 boost::str(boost::format("%1%: Input channel count (%2%) "
1389 "does not match output channel count (%3%)") %
1390 descriptorName % inputChannelCount % outputChannelCount));
telsoa014fcda012018-03-09 14:13:49 +00001391 }
1392}
1393
1394void FakeQuantizationQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1395{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001396 const std::string descriptorName{"FakeQuantizationQueueDescriptor"};
telsoa014fcda012018-03-09 14:13:49 +00001397
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001398 ValidateNumInputs(workloadInfo, descriptorName, 1);
1399 ValidateNumOutputs(workloadInfo, descriptorName, 1);
1400
1401 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1402 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1403
1404 ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 2, "input");
1405 ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 2, "output");
1406
1407 ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1408
telsoa014fcda012018-03-09 14:13:49 +00001409 if (m_Parameters.m_Min > m_Parameters.m_Max)
1410 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001411 throw InvalidArgumentException(descriptorName + ": min cannot be greater than max");
telsoa014fcda012018-03-09 14:13:49 +00001412 }
telsoa014fcda012018-03-09 14:13:49 +00001413}
1414
Kevin Mayce5045a2019-10-02 14:07:47 +01001415void InstanceNormalizationQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1416{
1417 const std::string descriptorName{"InstanceNormalizationQueueDescriptor"};
1418
1419 ValidateNumInputs(workloadInfo, descriptorName, 1);
1420 ValidateNumOutputs(workloadInfo, descriptorName, 1);
1421
1422 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1423 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1424
1425 if (inputTensorInfo.GetNumDimensions() > 4)
1426 {
1427 throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
1428 }
1429
1430 ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1431
1432 // Check the supported data types
1433 std::vector<DataType> supportedTypes =
1434 {
1435 DataType::Float32,
1436 DataType::Float16
1437 };
1438
1439 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
Kevin Mayce5045a2019-10-02 14:07:47 +01001440 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
Kevin Mayce5045a2019-10-02 14:07:47 +01001441}
1442
telsoa014fcda012018-03-09 14:13:49 +00001443void L2NormalizationQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1444{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001445 const std::string descriptorName{"L2NormalizationQueueDescriptor"};
telsoa014fcda012018-03-09 14:13:49 +00001446
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001447 ValidateNumInputs(workloadInfo, descriptorName, 1);
Ferran Balaguerd73d14f2019-06-10 10:29:54 +01001448 ValidateNumOutputs(workloadInfo, descriptorName, 1);
1449
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001450 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1451 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1452
Matthew Jackson82b15ed2019-07-25 16:14:30 +01001453 if (inputTensorInfo.GetNumDimensions() > 4)
1454 {
1455 throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
1456 }
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001457
1458 ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
Ferran Balaguerd73d14f2019-06-10 10:29:54 +01001459
1460 // Check the supported data types
1461 std::vector<DataType> supportedTypes =
1462 {
1463 DataType::Float32,
1464 DataType::Float16,
1465 DataType::QuantisedAsymm8,
1466 DataType::QuantisedSymm16
1467 };
1468
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001469 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
Aron Virginas-Tarf982dea2019-10-11 14:07:53 +01001470 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1471}
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001472
Aron Virginas-Tarf982dea2019-10-11 14:07:53 +01001473void LogSoftmaxQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1474{
1475 const std::string descriptorName{"LogSoftmaxQueueDescriptor"};
1476
1477 ValidateNumInputs(workloadInfo, descriptorName, 1);
1478 ValidateNumOutputs(workloadInfo, descriptorName, 1);
1479
1480 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1481 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1482
1483 ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1484
1485 std::vector<DataType> supportedTypes =
1486 {
1487 DataType::Float32,
1488 DataType::Float16,
1489 };
1490
1491 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001492 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
telsoa014fcda012018-03-09 14:13:49 +00001493}
1494
1495void ConstantQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1496{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001497 const std::string descriptorName{"ConstantQueueDescriptor"};
1498
1499 ValidateNumInputs(workloadInfo, descriptorName, 0);
1500 ValidateNumOutputs(workloadInfo, descriptorName, 1);
telsoa014fcda012018-03-09 14:13:49 +00001501
1502 if (!m_LayerOutput)
1503 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001504 throw InvalidArgumentException(descriptorName + ": No const input specified.");
telsoa014fcda012018-03-09 14:13:49 +00001505 }
1506
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001507 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1508 ValidateTensorShapesMatch(m_LayerOutput->GetTensorInfo(), outputTensorInfo, descriptorName, "constant", "output");
Nina Drozd58ef2c62019-05-16 12:09:18 +01001509
1510 // Check the supported data types
1511 std::vector<DataType> supportedTypes =
Nina Drozd2f2778f2019-05-27 10:37:05 +01001512 {
1513 DataType::Float32,
1514 DataType::Float16,
1515 DataType::Signed32,
1516 DataType::QuantisedAsymm8,
1517 DataType::QuantisedSymm16
1518 };
Nina Drozd58ef2c62019-05-16 12:09:18 +01001519
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001520 ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
telsoa014fcda012018-03-09 14:13:49 +00001521}
1522
1523void ReshapeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1524{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001525 const std::string descriptorName{"ReshapeQueueDescriptor"};
telsoa014fcda012018-03-09 14:13:49 +00001526
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001527 ValidateNumInputs(workloadInfo, descriptorName, 1);
1528 ValidateNumOutputs(workloadInfo, descriptorName, 1);
1529
1530 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1531 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1532
1533 ValidateTensorNumElementsMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
Nina Drozd2f2778f2019-05-27 10:37:05 +01001534
1535 // Check the supported data types
1536 std::vector<DataType> supportedTypes =
1537 {
1538 DataType::Float32,
1539 DataType::Float16,
Narumol Prangnawarat0718ee92019-09-13 16:53:38 +01001540 DataType::Signed32,
Nina Drozd8ed4b8c2019-05-29 10:41:04 +01001541 DataType::QuantisedAsymm8,
1542 DataType::QuantisedSymm16
Nina Drozd2f2778f2019-05-27 10:37:05 +01001543 };
1544
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001545 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1546 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
telsoa014fcda012018-03-09 14:13:49 +00001547}
1548
Nattapat Chaimanowong207ef9a2018-11-02 10:57:25 +00001549void SpaceToBatchNdQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1550{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001551 const std::string descriptorName{"SpaceToBatchNdQueueDescriptor"};
Nattapat Chaimanowong207ef9a2018-11-02 10:57:25 +00001552
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001553 ValidateNumInputs(workloadInfo, descriptorName, 1);
1554 ValidateNumOutputs(workloadInfo, descriptorName, 1);
1555
1556 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1557 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1558
1559 ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1560 ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
Nattapat Chaimanowong207ef9a2018-11-02 10:57:25 +00001561
Nattapat Chaimanowong207ef9a2018-11-02 10:57:25 +00001562 if (m_Parameters.m_BlockShape.size() != 2)
1563 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001564 throw InvalidArgumentException(descriptorName + ": Block Shape must contain 2 spatial dimensions.");
Nattapat Chaimanowong207ef9a2018-11-02 10:57:25 +00001565 }
1566
1567 if (m_Parameters.m_BlockShape.size() != m_Parameters.m_PadList.size())
1568 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001569 throw InvalidArgumentException(descriptorName + ": Pad List must contain the same number of "
1570 "dimensions as Block Shape.");
Nattapat Chaimanowong207ef9a2018-11-02 10:57:25 +00001571 }
1572
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001573 const TensorShape& inputShape = inputTensorInfo.GetShape();
Nattapat Chaimanowong207ef9a2018-11-02 10:57:25 +00001574
1575 std::pair<unsigned int, unsigned int> heightPad = m_Parameters.m_PadList[0];
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001576 std::pair<unsigned int, unsigned int> widthPad = m_Parameters.m_PadList[1];
Nattapat Chaimanowong207ef9a2018-11-02 10:57:25 +00001577
Matthew Bentham8800c002018-11-19 13:19:28 +00001578 DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
Nattapat Chaimanowong3ea76d52018-11-09 14:10:38 +00001579
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001580 const unsigned int inputWidth = inputShape[dimensionIndices.GetWidthIndex()] +
1581 widthPad.first + widthPad.second;
1582 const unsigned int inputHeight = inputShape[dimensionIndices.GetHeightIndex()] +
1583 heightPad.first + heightPad.second;
Nattapat Chaimanowong3ea76d52018-11-09 14:10:38 +00001584
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001585 const unsigned int numInputElements = inputShape[0] * inputHeight * inputWidth *
1586 inputShape[dimensionIndices.GetChannelsIndex()];
1587 const unsigned int numOutputElements = outputTensorInfo.GetNumElements();
Nattapat Chaimanowong3ea76d52018-11-09 14:10:38 +00001588
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001589 if (numOutputElements != numInputElements)
Nattapat Chaimanowong3ea76d52018-11-09 14:10:38 +00001590 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001591 throw InvalidArgumentException(descriptorName + ": Input tensor has " +
Nattapat Chaimanowong3ea76d52018-11-09 14:10:38 +00001592 to_string(numInputElements) + " after padding but output tensor has " +
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001593 to_string(numOutputElements) + " elements.");
Nattapat Chaimanowong3ea76d52018-11-09 14:10:38 +00001594 }
1595
1596 if (inputHeight % m_Parameters.m_BlockShape[0] != 0 || inputWidth % m_Parameters.m_BlockShape[1] != 0)
Nattapat Chaimanowong207ef9a2018-11-02 10:57:25 +00001597 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001598 throw InvalidArgumentException(descriptorName + ": Input shape after padding must be "
1599 "divisible by Block Shape in all spatial dimensions");
Nattapat Chaimanowong207ef9a2018-11-02 10:57:25 +00001600 }
nikraj01120522a2019-05-31 11:33:07 +01001601
1602 std::vector<DataType> supportedTypes =
1603 {
1604 DataType::Float16,
1605 DataType::Float32,
1606 DataType::QuantisedAsymm8,
1607 DataType::QuantisedSymm16
1608 };
1609
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001610 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1611 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
Nattapat Chaimanowong207ef9a2018-11-02 10:57:25 +00001612}
1613
Keith Davisa57eccb2019-06-14 17:33:22 +01001614void SpaceToDepthQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1615{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001616 const std::string descriptorName{"SpaceToDepthQueueDescriptor"};
Keith Davisa57eccb2019-06-14 17:33:22 +01001617
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001618 ValidateNumInputs(workloadInfo, descriptorName, 1);
1619 ValidateNumOutputs(workloadInfo, descriptorName, 1);
Keith Davisa57eccb2019-06-14 17:33:22 +01001620
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001621 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1622 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1623
1624 ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1625 ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
Keith Davisa57eccb2019-06-14 17:33:22 +01001626
1627 std::vector<DataType> supportedTypes =
1628 {
1629 DataType::Float32,
1630 DataType::Float16,
James Conroyd2aa85e2019-07-01 17:12:40 +01001631 DataType::QuantisedAsymm8,
1632 DataType::QuantisedSymm16
Keith Davisa57eccb2019-06-14 17:33:22 +01001633 };
1634
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001635 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1636 ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
Keith Davisa57eccb2019-06-14 17:33:22 +01001637
Aron Virginas-Tar8a1b2182019-09-19 14:39:37 +01001638 ValidateTensorNumElementsMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1639
1640 if (m_Parameters.m_BlockSize == 0)
1641 {
1642 throw InvalidArgumentException(descriptorName + ": Block size cannot be 0.");
1643 }
1644
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001645 DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
1646 const unsigned int wIndex = dimensionIndices.GetWidthIndex();
1647 const unsigned int hIndex = dimensionIndices.GetHeightIndex();
1648 const unsigned int cIndex = dimensionIndices.GetChannelsIndex();
Keith Davisa57eccb2019-06-14 17:33:22 +01001649
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001650 const TensorShape& inputShape = inputTensorInfo.GetShape();
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001651 if (inputShape[hIndex] % m_Parameters.m_BlockSize != 0 || inputShape[wIndex] % m_Parameters.m_BlockSize != 0)
Keith Davisa57eccb2019-06-14 17:33:22 +01001652 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001653 throw InvalidArgumentException(descriptorName + ": Input shape must be divisible "
1654 "by block size in all spatial dimensions");
Keith Davisa57eccb2019-06-14 17:33:22 +01001655 }
Aron Virginas-Tar8a1b2182019-09-19 14:39:37 +01001656
1657 const TensorShape& outputShape = outputTensorInfo.GetShape();
1658 if (outputShape[cIndex] % (m_Parameters.m_BlockSize * m_Parameters.m_BlockSize) != 0)
1659 {
1660 throw InvalidArgumentException(descriptorName + ": The depth of the output tensor"
1661 "must be divisible by the square of block size." );
1662 }
Keith Davisa57eccb2019-06-14 17:33:22 +01001663}
1664
telsoa014fcda012018-03-09 14:13:49 +00001665void FloorQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1666{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001667 const std::string descriptorName{"FloorQueueDescriptor"};
James Conroy83735b12019-05-30 16:36:59 +01001668
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001669 ValidateNumInputs(workloadInfo, descriptorName, 1);
1670 ValidateNumOutputs(workloadInfo, descriptorName, 1);
1671
1672 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1673 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
James Conroy83735b12019-05-30 16:36:59 +01001674
1675 std::vector<DataType> supportedTypes =
1676 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001677 DataType::Float32,
Matthew Jackson9bff1442019-09-12 09:08:23 +01001678 DataType::Float16,
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001679 DataType::QuantisedSymm16
James Conroy83735b12019-05-30 16:36:59 +01001680 };
1681
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001682 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
telsoa014fcda012018-03-09 14:13:49 +00001683
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001684 if (inputTensorInfo != outputTensorInfo)
telsoa014fcda012018-03-09 14:13:49 +00001685 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001686 throw InvalidArgumentException(descriptorName + ": Input and output tensor infos do not match.");
telsoa014fcda012018-03-09 14:13:49 +00001687 }
1688}
1689
telsoa01c577f2c2018-08-31 09:22:23 +01001690void LstmQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1691{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001692 // ported from android/ml/nn/common/operations/LSTM.cpp CheckInputTensorDimensions()
1693
1694 const std::string descriptorName{"LstmQueueDescriptor"};
1695
1696 // check dimensions of all inputs and outputs
1697 if (workloadInfo.m_InputTensorInfos.size() != 3)
1698 {
1699 throw InvalidArgumentException(descriptorName + ": Invalid number of inputs.");
1700 }
1701 if (workloadInfo.m_OutputTensorInfos.size() != 4)
1702 {
1703 throw InvalidArgumentException(descriptorName + ": Invalid number of outputs.");
1704 }
1705
1706 std::vector<DataType> supportedTypes =
1707 {
Conor Kennedyb9971c92019-05-07 07:14:23 +01001708 DataType::Float16,
Nattapat Chaimanowongeb2b3292019-05-07 12:02:30 +01001709 DataType::Float32,
Conor Kennedyb9971c92019-05-07 07:14:23 +01001710 DataType::QuantisedSymm16
Nattapat Chaimanowongeb2b3292019-05-07 12:02:30 +01001711 };
1712
Jan Eilers38e05bd2019-06-26 13:10:09 +01001713 // check for supported type of one input and match them with all the other input and output
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001714 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0], supportedTypes, descriptorName);
1715
Jan Eilers38e05bd2019-06-26 13:10:09 +01001716 // type matches all other inputs
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001717 for (uint32_t i = 1u; i < workloadInfo.m_InputTensorInfos.size(); ++i)
Jan Eilers38e05bd2019-06-26 13:10:09 +01001718 {
1719 ValidateTensorDataTypesMatch(workloadInfo.m_InputTensorInfos[0],
1720 workloadInfo.m_InputTensorInfos[i],
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001721 descriptorName,
1722 "input_0",
1723 "input_" + std::to_string(i));
Jan Eilers38e05bd2019-06-26 13:10:09 +01001724 }
1725 // type matches all other outputs
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001726 for (uint32_t i = 0u; i < workloadInfo.m_OutputTensorInfos.size(); ++i)
Jan Eilers38e05bd2019-06-26 13:10:09 +01001727 {
1728 ValidateTensorDataTypesMatch(workloadInfo.m_InputTensorInfos[0],
1729 workloadInfo.m_OutputTensorInfos[i],
1730 "LstmQueueDescriptor",
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001731 "input_0",
1732 "output_" + std::to_string(i));
Jan Eilers38e05bd2019-06-26 13:10:09 +01001733 }
Nattapat Chaimanowongeb2b3292019-05-07 12:02:30 +01001734
janeil0117d8d852019-11-15 15:00:16 +00001735 // Making sure clipping parameters have valid values.
1736 // == 0 means no clipping
1737 // > 0 means clipping
1738 if (m_Parameters.m_ClippingThresCell < 0.0f)
1739 {
1740 throw InvalidArgumentException(descriptorName + ": negative cell clipping threshold is invalid");
1741 }
1742 if (m_Parameters.m_ClippingThresProj < 0.0f)
1743 {
1744 throw InvalidArgumentException(descriptorName + ": negative projection clipping threshold is invalid");
1745 }
1746
Jan Eilers38e05bd2019-06-26 13:10:09 +01001747
1748 // Inferring batch size, number of outputs and number of cells from the inputs.
Jan Eilers38e05bd2019-06-26 13:10:09 +01001749 const uint32_t n_input = workloadInfo.m_InputTensorInfos[0].GetShape()[1];
1750 const uint32_t n_batch = workloadInfo.m_InputTensorInfos[0].GetShape()[0];
1751 ValidatePointer(m_InputToOutputWeights, "Null pointer check", "InputToOutputWeights");
1752 const uint32_t n_cell = m_InputToOutputWeights->GetShape()[0];
1753 ValidatePointer(m_RecurrentToOutputWeights, "Null pointer check", "RecurrentToOutputWeights");
1754 const uint32_t n_output = m_RecurrentToOutputWeights->GetShape()[1];
1755
Jan Eilers38e05bd2019-06-26 13:10:09 +01001756 // input tensor
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001757 ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[0], 2, (n_batch * n_input),
1758 descriptorName + " input_0");
Jan Eilers38e05bd2019-06-26 13:10:09 +01001759 // outputStateInTensor
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001760 ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[1], 2, (n_batch * n_output),
1761 descriptorName + " input_1");
Jan Eilers38e05bd2019-06-26 13:10:09 +01001762 // outputStateInTensor
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001763 ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[2], 2, (n_batch * n_cell),
1764 descriptorName + " input_2");
Jan Eilers38e05bd2019-06-26 13:10:09 +01001765 // scratchBufferTensor
1766 unsigned int scratchBufferSize = m_Parameters.m_CifgEnabled ? n_cell * 3 : n_cell * 4;
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001767 ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[0], 2, (n_batch * scratchBufferSize),
1768 descriptorName + " output_0");
Jan Eilers38e05bd2019-06-26 13:10:09 +01001769 // outputStateOutTensor
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001770 ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[1], 2, (n_batch * n_output),
1771 descriptorName + " output_1");
Jan Eilers38e05bd2019-06-26 13:10:09 +01001772 // cellStateOutTensor
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001773 ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[2], 2, (n_batch * n_cell),
1774 descriptorName + " output_2");
Jan Eilers38e05bd2019-06-26 13:10:09 +01001775 // outputTensor
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001776 ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[3], 2, (n_batch * n_output),
1777 descriptorName + " output_3");
Jan Eilers38e05bd2019-06-26 13:10:09 +01001778
1779
1780 // check that dimensions of inputs/outputs and QueueDescriptor data match with each other
1781 if ( m_InputToInputWeights )
1782 {
1783 ValidateTensorNumDimNumElem(m_InputToInputWeights->GetTensorInfo(), 2,
1784 (n_cell * n_input), "InputLayerNormWeights");
1785 }
1786
1787 ValidatePointer(m_InputToForgetWeights, "Null pointer check", "InputToForgetWeights");
1788 ValidateTensorNumDimNumElem(m_InputToForgetWeights->GetTensorInfo(), 2,
1789 (n_cell * n_input), "InputToForgetWeights");
1790
1791 ValidatePointer(m_InputToCellWeights, "Null pointer check", "InputToCellWeights");
1792 ValidateTensorNumDimNumElem(m_InputToCellWeights->GetTensorInfo(), 2,
1793 (n_cell * n_input), "InputToCellWeights");
1794
1795 if ( m_RecurrentToInputWeights )
1796 {
1797 ValidateTensorNumDimNumElem(m_RecurrentToInputWeights->GetTensorInfo(), 2,
1798 (n_cell * n_output), "RecurrentToInputWeights");
1799 }
1800
1801 ValidatePointer(m_RecurrentToForgetWeights, "Null pointer check", "RecurrentToForgetWeights");
1802 ValidateTensorNumDimNumElem(m_RecurrentToForgetWeights->GetTensorInfo(), 2,
1803 (n_cell * n_output), "RecurrentToForgetWeights");
1804
1805 ValidatePointer(m_RecurrentToCellWeights, "Null pointer check", "RecurrentToCellWeights");
1806 ValidateTensorNumDimNumElem(m_RecurrentToCellWeights->GetTensorInfo(), 2,
1807 (n_cell * n_output), "RecurrentToCellWeights");
1808
1809 // Make sure the input-gate's parameters are either both present (regular
1810 // LSTM) or not at all (CIFG-LSTM). And CifgEnable is set accordingly.
1811 bool cifg_weights_all_or_none = ((m_InputToInputWeights && m_RecurrentToInputWeights &&
1812 !m_Parameters.m_CifgEnabled) ||
1813 (!m_InputToInputWeights && !m_RecurrentToInputWeights &&
1814 m_Parameters.m_CifgEnabled));
1815 if (!cifg_weights_all_or_none)
1816 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001817 throw InvalidArgumentException(descriptorName + ": Input-Gate's parameters InputToInputWeights and "
1818 "RecurrentToInputWeights must either both be present (regular LSTM) "
1819 "or both not present (CIFG-LSTM). In addition CifgEnable must be set "
1820 "accordingly.");
Jan Eilers38e05bd2019-06-26 13:10:09 +01001821 }
1822
1823 if ( m_CellToInputWeights )
1824 {
1825 ValidateTensorNumDimNumElem(m_CellToInputWeights->GetTensorInfo(), 1,
1826 n_cell, "CellToInputWeights");
1827 }
1828 if ( m_CellToForgetWeights )
1829 {
1830 ValidateTensorNumDimNumElem(m_CellToForgetWeights->GetTensorInfo(), 1,
1831 n_cell, "CellToForgetWeights");
1832 }
1833 if ( m_CellToOutputWeights )
1834 {
1835 ValidateTensorNumDimNumElem(m_CellToOutputWeights->GetTensorInfo(), 1,
1836 n_cell, "CellToOutputWeights");
1837 }
1838
1839 // Making sure the peephole weights are there all or none. And PeepholeEnable is set accordingly.
1840 bool peephole_weights_all_or_none =
1841 (((m_CellToInputWeights || m_Parameters.m_CifgEnabled) && m_CellToForgetWeights
1842 && m_CellToOutputWeights && m_Parameters.m_PeepholeEnabled)
1843 || ( !m_CellToInputWeights && !m_CellToForgetWeights
1844 && !m_CellToOutputWeights && !m_Parameters.m_PeepholeEnabled));
1845 if (!peephole_weights_all_or_none)
1846 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001847 throw InvalidArgumentException(descriptorName + ": Invalid combination of peephole parameters.");
Jan Eilers38e05bd2019-06-26 13:10:09 +01001848 }
1849
1850 // Make sure the input gate bias is present only when not a CIFG-LSTM.
1851 if (m_Parameters.m_CifgEnabled)
1852 {
1853 if (m_InputGateBias)
1854 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001855 throw InvalidArgumentException(descriptorName + ": InputGateBias is present and CIFG-LSTM is enabled.");
Jan Eilers38e05bd2019-06-26 13:10:09 +01001856 }
1857 }
1858 else
1859 {
1860 if (!m_InputGateBias)
1861 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001862 throw InvalidArgumentException(descriptorName + ": If CIFG-LSTM is disabled InputGateBias "
1863 "must be present.");
Jan Eilers38e05bd2019-06-26 13:10:09 +01001864 }
1865 ValidateTensorNumDimNumElem(m_InputGateBias->GetTensorInfo(), 1,
1866 n_cell, "InputGateBias");
1867 }
1868
1869 ValidatePointer(m_ForgetGateBias, "Null pointer check", "ForgetGateBias");
1870 ValidateTensorNumDimNumElem(m_ForgetGateBias->GetTensorInfo(), 1, n_cell, "ForgetGateBias");
1871
1872 ValidatePointer(m_CellBias, "Null pointer check", "CellBias");
1873 ValidateTensorNumDimNumElem(m_CellBias->GetTensorInfo(), 1, n_cell, "CellBias");
1874
1875 ValidatePointer(m_OutputGateBias, "Null pointer check", "OutputGateBias");
1876 ValidateTensorNumDimNumElem(m_OutputGateBias->GetTensorInfo(), 1, n_cell, "OutputGateBias");
1877
1878 if (m_ProjectionWeights)
1879 {
1880 ValidateTensorNumDimNumElem(m_ProjectionWeights->GetTensorInfo(), 2,
1881 (n_cell * n_output), "ProjectionWeights");
1882 }
1883 if (m_ProjectionBias)
1884 {
1885 ValidateTensorNumDimNumElem(m_ProjectionBias->GetTensorInfo(), 1, n_output, "ProjectionBias");
1886 }
1887
1888 // Making sure the projection tensors are consistent:
1889 // 1) If projection weight is not present, then projection bias should not be
1890 // present.
1891 // 2) If projection weight is present, then projection bias is optional.
1892 bool projecton_tensors_consistent = ((!m_ProjectionWeights && !m_ProjectionBias &&
1893 !m_Parameters.m_ProjectionEnabled)
1894 || (m_ProjectionWeights && !m_ProjectionBias &&
1895 m_Parameters.m_ProjectionEnabled)
1896 || (m_ProjectionWeights && m_ProjectionBias &&
1897 m_Parameters.m_ProjectionEnabled));
1898 if (!projecton_tensors_consistent)
1899 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001900 throw InvalidArgumentException(descriptorName + ": Projection tensors are inconsistent.");
Jan Eilers38e05bd2019-06-26 13:10:09 +01001901 }
1902
1903 // The four layer normalization weights either all have values or none of them have values. Additionally, if
1904 // CIFG is used, input layer normalization weights tensor is omitted and the other layer normalization weights
1905 // either all have values or none of them have values. Layer normalization is used when the values of all the
1906 // layer normalization weights are present
1907 if (m_InputLayerNormWeights)
1908 {
1909 ValidateTensorNumDimNumElem(m_InputLayerNormWeights->GetTensorInfo(), 1, n_cell, "InputLayerNormWeights");
1910 }
1911 if (m_ForgetLayerNormWeights)
1912 {
1913 ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
1914 }
1915 if (m_CellLayerNormWeights)
1916 {
1917 ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
1918 }
1919 if (m_OutputLayerNormWeights)
1920 {
1921 ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
1922 }
1923
Jan Eilers38e05bd2019-06-26 13:10:09 +01001924 if (m_Parameters.m_LayerNormEnabled)
1925 {
1926 if (!m_Parameters.m_CifgEnabled)
1927 {
1928 if (!m_InputLayerNormWeights)
1929 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001930 throw InvalidArgumentException(descriptorName + ": Layer normalisation is enabled and CIFG-LSTM is "
1931 "disabled but InputLayerNormWeights are not present");
Jan Eilers38e05bd2019-06-26 13:10:09 +01001932 }
1933 ValidateTensorNumDimNumElem(m_InputLayerNormWeights->GetTensorInfo(),
1934 1, n_cell, "InputLayerNormWeights");
1935 }
1936 else if (m_InputLayerNormWeights)
1937 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001938 throw InvalidArgumentException(descriptorName + ":InputLayerNormWeights are present while CIFG is "
1939 "enabled");
Jan Eilers38e05bd2019-06-26 13:10:09 +01001940 }
1941
1942 ValidatePointer(m_ForgetLayerNormWeights, "Null pointer check layer normalisation enabled",
1943 "ForgetLayerNormWeights");
1944 ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
1945
1946 ValidatePointer(m_OutputLayerNormWeights, "Null pointer check layer normalisation enabled",
1947 "OutputLayerNormWeights");
1948 ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
1949
1950 ValidatePointer(m_CellLayerNormWeights, "Null pointer check layer normalisation enabled",
1951 "CellLayerNormWeights");
1952 ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
1953 }
1954 else if (m_InputLayerNormWeights || m_ForgetLayerNormWeights || m_OutputLayerNormWeights || m_CellLayerNormWeights)
1955 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001956 throw InvalidArgumentException(descriptorName + ": Layer normalisation is disabled but one or more layer "
1957 "normalisation weights are present.");
Jan Eilers38e05bd2019-06-26 13:10:09 +01001958 }
telsoa01c577f2c2018-08-31 09:22:23 +01001959}
1960
1961void ConvertFp32ToFp16QueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1962{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001963 const std::string descriptorName{"ConvertFp32ToFp16QueueDescriptor"};
telsoa01c577f2c2018-08-31 09:22:23 +01001964
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001965 ValidateNumInputs(workloadInfo, descriptorName, 1);
1966 ValidateNumOutputs(workloadInfo, descriptorName, 1);
1967
1968 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1969 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1970
1971 if (inputTensorInfo.GetDataType() != DataType::Float32)
telsoa01c577f2c2018-08-31 09:22:23 +01001972 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001973 throw InvalidArgumentException(descriptorName + ": Input tensor type must be Float32.");
telsoa01c577f2c2018-08-31 09:22:23 +01001974 }
1975
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001976 if (outputTensorInfo.GetDataType() != DataType::Float16)
telsoa01c577f2c2018-08-31 09:22:23 +01001977 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001978 throw InvalidArgumentException(descriptorName + ": Output tensor type must be Float16.");
telsoa01c577f2c2018-08-31 09:22:23 +01001979 }
1980
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001981 ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
telsoa01c577f2c2018-08-31 09:22:23 +01001982}
1983
1984void ConvertFp16ToFp32QueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1985{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001986 const std::string descriptorName{"ConvertFp16ToFp32QueueDescriptor"};
telsoa01c577f2c2018-08-31 09:22:23 +01001987
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001988 ValidateNumInputs(workloadInfo, descriptorName, 1);
1989 ValidateNumOutputs(workloadInfo, descriptorName, 1);
1990
1991 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1992 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1993
1994 if (inputTensorInfo.GetDataType() != DataType::Float16)
telsoa01c577f2c2018-08-31 09:22:23 +01001995 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001996 throw InvalidArgumentException(descriptorName + ": Input tensor type must be Float16.");
telsoa01c577f2c2018-08-31 09:22:23 +01001997 }
1998
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01001999 if (outputTensorInfo.GetDataType() != DataType::Float32)
2000 {
2001 throw InvalidArgumentException(descriptorName + ": Output tensor type must be Float32.");
2002 }
2003
2004 ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
telsoa01c577f2c2018-08-31 09:22:23 +01002005}
2006
Francis Murtaghe7a86a42018-08-29 12:42:10 +01002007void DivisionQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2008{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002009 const std::string descriptorName{"DivisionQueueDescriptor"};
Francis Murtaghe7a86a42018-08-29 12:42:10 +01002010
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002011 ValidateNumInputs(workloadInfo, descriptorName, 2);
2012 ValidateNumOutputs(workloadInfo, descriptorName, 1);
2013
2014 const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2015 const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2016 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2017
2018 std::vector<DataType> supportedTypes =
2019 {
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01002020 DataType::Float32,
Sadik Armagan2999a022019-04-09 14:20:12 +01002021 DataType::QuantisedAsymm8,
Jim Flynn82fbe7c2019-04-02 15:19:08 +01002022 DataType::QuantisedSymm16,
2023 DataType::Float16
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01002024 };
2025
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002026 ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2027 ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2028 ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01002029
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002030 ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2031 inputTensorInfo1,
2032 outputTensorInfo,
2033 descriptorName,
2034 "input_0",
2035 "input_1");
Francis Murtaghe7a86a42018-08-29 12:42:10 +01002036}
2037
David Beckc2044fe2018-09-05 15:00:38 +01002038void SubtractionQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2039{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002040 const std::string descriptorName{"SubtractionQueueDescriptor"};
David Beckc2044fe2018-09-05 15:00:38 +01002041
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002042 ValidateNumInputs(workloadInfo, descriptorName, 2);
2043 ValidateNumOutputs(workloadInfo, descriptorName, 1);
2044
2045 const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2046 const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2047 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2048
2049 std::vector<DataType> supportedTypes =
2050 {
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01002051 DataType::Float32,
Sadik Armagan2999a022019-04-09 14:20:12 +01002052 DataType::QuantisedAsymm8,
Jim Flynn82fbe7c2019-04-02 15:19:08 +01002053 DataType::QuantisedSymm16,
2054 DataType::Float16
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01002055 };
2056
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002057 ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2058 ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2059 ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01002060
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002061 ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2062 inputTensorInfo1,
2063 outputTensorInfo,
2064 descriptorName,
2065 "input_0",
2066 "input_1");
David Beckc2044fe2018-09-05 15:00:38 +01002067}
2068
Nattapat Chaimanowong5a4304a2018-11-28 10:44:37 +00002069void MaximumQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2070{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002071 const std::string descriptorName{"MaximumQueueDescriptor"};
Nattapat Chaimanowong5a4304a2018-11-28 10:44:37 +00002072
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002073 ValidateNumInputs(workloadInfo, descriptorName, 2);
2074 ValidateNumOutputs(workloadInfo, descriptorName, 1);
2075
2076 const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2077 const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2078 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2079
2080 std::vector<DataType> supportedTypes =
2081 {
Mike Kelly1da02362019-08-01 08:43:57 +01002082 DataType::Float16,
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01002083 DataType::Float32,
Mike Kelly1da02362019-08-01 08:43:57 +01002084 DataType::Signed32,
Sadik Armagan2999a022019-04-09 14:20:12 +01002085 DataType::QuantisedAsymm8,
2086 DataType::QuantisedSymm16
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01002087 };
2088
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002089 ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2090 ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2091 ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01002092
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002093 ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2094 inputTensorInfo1,
2095 outputTensorInfo,
2096 descriptorName,
2097 "input_0",
2098 "input_1");
Nattapat Chaimanowong5a4304a2018-11-28 10:44:37 +00002099}
2100
narpra01a6bf9122018-09-10 09:50:09 +01002101void MeanQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2102{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002103 const std::string descriptorName{"MeanQueueDescriptor"};
James Conroy4d1ff582019-06-10 17:06:39 +01002104
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002105 ValidateNumInputs(workloadInfo, descriptorName, 1);
2106 ValidateNumOutputs(workloadInfo, descriptorName, 1);
2107
2108 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2109 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
James Conroy4d1ff582019-06-10 17:06:39 +01002110
2111 std::vector<DataType> supportedTypes =
2112 {
2113 DataType::Float32,
2114 DataType::Float16,
2115 DataType::QuantisedAsymm8,
2116 DataType::QuantisedSymm16
2117 };
narpra01eb061912018-09-10 17:35:27 +01002118
James Conroy4d1ff582019-06-10 17:06:39 +01002119 // First check if input tensor data type is supported, then
2120 // check if this data type matches the output tensor data type
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002121 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2122 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
James Conroy4d1ff582019-06-10 17:06:39 +01002123
narpra0132b90462018-09-13 11:07:48 +01002124 if (m_Parameters.m_KeepDims)
narpra01eb061912018-09-10 17:35:27 +01002125 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002126 ValidateTensorNumDimensions(outputTensorInfo, descriptorName, inputTensorInfo.GetNumDimensions(), "output");
narpra01eb061912018-09-10 17:35:27 +01002127 }
narpra0132b90462018-09-13 11:07:48 +01002128 else if (m_Parameters.m_Axis.empty())
narpra01eb061912018-09-10 17:35:27 +01002129 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002130 ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 1, "output");
narpra01eb061912018-09-10 17:35:27 +01002131 }
2132 else
2133 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002134 unsigned int outputDim =
2135 inputTensorInfo.GetNumDimensions() - boost::numeric_cast<unsigned int>(m_Parameters.m_Axis.size());
2136 ValidateTensorNumDimensions(outputTensorInfo,
2137 descriptorName,
narpra01eb061912018-09-10 17:35:27 +01002138 outputDim > 0 ? outputDim : 1,
2139 "output");
2140 }
narpra01a6bf9122018-09-10 09:50:09 +01002141}
2142
jimfly012c9322a2018-09-19 10:59:49 +01002143void PadQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2144{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002145 const std::string descriptorName{"PadQueueDescriptor"};
jimfly012c9322a2018-09-19 10:59:49 +01002146
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002147 ValidateNumInputs(workloadInfo, descriptorName, 1);
2148 ValidateNumOutputs(workloadInfo, descriptorName, 1);
2149
2150 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2151 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
Nina Drozd661dfa72018-10-02 11:14:17 +01002152
jimfly012c9322a2018-09-19 10:59:49 +01002153 // input and output should have the same number of dimensions
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002154 ValidateTensorNumDimensions(outputTensorInfo, descriptorName, inputTensorInfo.GetNumDimensions(), "output");
2155
jimfly012c9322a2018-09-19 10:59:49 +01002156 // there should be entry in the pad list for each dimension in the input tensor
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002157 if (m_Parameters.m_PadList.size() != inputTensorInfo.GetNumDimensions()) {
2158 throw InvalidArgumentException(descriptorName + ":Pad List should contain the same number of entries "
2159 "as there are dimensions in the input tensor that is " +
2160 std::to_string(inputTensorInfo.GetNumDimensions()) + " entries " +
2161 " not " + std::to_string(m_Parameters.m_PadList.size()) + " entries.");
jimfly012c9322a2018-09-19 10:59:49 +01002162 }
2163}
2164
Derek Lambertia9cca6a2019-03-25 15:41:58 +00002165void QuantizeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2166{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002167 const std::string descriptorName{"QuantizeQueueDescriptor"};
Derek Lambertia9cca6a2019-03-25 15:41:58 +00002168
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002169 ValidateNumInputs(workloadInfo, descriptorName, 1);
2170 ValidateNumOutputs(workloadInfo, descriptorName, 1);
Derek Lambertia9cca6a2019-03-25 15:41:58 +00002171
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002172 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2173 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2174
Sadik Armagan2208b602019-07-31 16:36:27 +01002175 std::vector<DataType> supportedTypes =
Derek Lambertia9cca6a2019-03-25 15:41:58 +00002176 {
James Conroyd47a0642019-09-17 14:22:06 +01002177 DataType::Float32,
2178 DataType::Float16
Sadik Armagan2208b602019-07-31 16:36:27 +01002179 };
2180
2181 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
Derek Lambertia9cca6a2019-03-25 15:41:58 +00002182
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002183 if (outputTensorInfo.GetDataType() != DataType::QuantisedAsymm8 &&
2184 outputTensorInfo.GetDataType() != DataType::QuantisedSymm16)
Derek Lambertia9cca6a2019-03-25 15:41:58 +00002185 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002186 throw InvalidArgumentException(descriptorName + ": Output of quantized layer must be quantized type.");
Derek Lambertia9cca6a2019-03-25 15:41:58 +00002187 }
2188}
2189
Éanna Ó Catháin4e1e1362018-11-12 11:36:34 +00002190void BatchToSpaceNdQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2191{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002192 const std::string descriptorName{"BatchToSpaceNdQueueDescriptor"};
Francis Murtaghd0dfe172019-06-25 10:57:10 +01002193
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002194 ValidateNumInputs(workloadInfo, descriptorName, 1);
2195 ValidateNumOutputs(workloadInfo, descriptorName, 1);
Francis Murtaghd0dfe172019-06-25 10:57:10 +01002196
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002197 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2198 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
Francis Murtaghd0dfe172019-06-25 10:57:10 +01002199
2200 std::vector<DataType> supportedTypes =
2201 {
James Conroyd47a0642019-09-17 14:22:06 +01002202 DataType::Float32,
2203 DataType::Float16,
2204 DataType::QuantisedAsymm8,
2205 DataType::QuantisedSymm16
Francis Murtaghd0dfe172019-06-25 10:57:10 +01002206 };
2207
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002208 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2209 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
Éanna Ó Catháin4e1e1362018-11-12 11:36:34 +00002210}
2211
Conor Kennedy430b5d82018-11-14 15:28:28 +00002212void StridedSliceQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2213{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002214 const std::string descriptorName{"StridedSliceQueueDescriptor"};
Conor Kennedy430b5d82018-11-14 15:28:28 +00002215
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002216 ValidateNumInputs(workloadInfo, descriptorName, 1);
2217 ValidateNumOutputs(workloadInfo, descriptorName, 1);
2218
2219 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2220 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
Matteo Martincighe851b3d2019-05-28 14:31:20 +01002221
2222 std::vector<DataType> supportedTypes =
2223 {
2224 DataType::Float16,
2225 DataType::Float32,
Matteo Martincigh42666a12019-05-29 08:53:41 +01002226 DataType::QuantisedAsymm8,
2227 DataType::QuantisedSymm16
Matteo Martincighe851b3d2019-05-28 14:31:20 +01002228 };
2229
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002230 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2231 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
Matteo Martincighe851b3d2019-05-28 14:31:20 +01002232
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002233 ValidateTensorQuantizationSpace(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
Matteo Martincighe851b3d2019-05-28 14:31:20 +01002234
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002235 const uint32_t rank = inputTensorInfo.GetNumDimensions();
Nattapat Chaimanowonga0d28442018-11-21 16:48:17 +00002236 if (rank > 4)
2237 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002238 throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
Nattapat Chaimanowonga0d28442018-11-21 16:48:17 +00002239 }
2240
Conor Kennedy430b5d82018-11-14 15:28:28 +00002241 // Begin, End & Stride length must be of rank(input0)
2242 if (m_Parameters.m_Begin.size() != rank)
2243 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002244 throw InvalidArgumentException(descriptorName + ": Begin length must be of rank " + std::to_string(rank));
Conor Kennedy430b5d82018-11-14 15:28:28 +00002245 }
2246
2247 if (m_Parameters.m_End.size() != rank)
2248 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002249 throw InvalidArgumentException(descriptorName + ": End length must be of rank " + std::to_string(rank));
Conor Kennedy430b5d82018-11-14 15:28:28 +00002250 }
2251
2252 if (m_Parameters.m_Stride.size() != rank)
2253 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002254 throw InvalidArgumentException(descriptorName + ": Stride length must be of rank " + std::to_string(rank));
Conor Kennedy430b5d82018-11-14 15:28:28 +00002255 }
2256
2257 // Stride entries must be non-zero
2258 for (auto& stride : m_Parameters.m_Stride)
2259 {
2260 if (stride == 0)
2261 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002262 throw InvalidArgumentException(descriptorName + ": Stride entries must be non-zero.");
Conor Kennedy430b5d82018-11-14 15:28:28 +00002263 }
2264 }
2265}
2266
kevmay0190539692018-11-29 08:40:19 +00002267void MinimumQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2268{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002269 const std::string descriptorName{"MinimumQueueDescriptor"};
kevmay0190539692018-11-29 08:40:19 +00002270
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002271 ValidateNumInputs(workloadInfo, descriptorName, 2);
2272 ValidateNumOutputs(workloadInfo, descriptorName, 1);
2273
2274 const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2275 const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2276 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2277
2278 std::vector<DataType> supportedTypes =
2279 {
Mike Kelly1da02362019-08-01 08:43:57 +01002280 DataType::Float16,
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01002281 DataType::Float32,
Mike Kelly1da02362019-08-01 08:43:57 +01002282 DataType::Signed32,
Sadik Armagan2999a022019-04-09 14:20:12 +01002283 DataType::QuantisedAsymm8,
2284 DataType::QuantisedSymm16
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01002285 };
2286
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002287 ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2288 ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2289 ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01002290
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002291 ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2292 inputTensorInfo1,
2293 outputTensorInfo,
2294 descriptorName,
2295 "input_0",
2296 "input_1");
kevmay0190539692018-11-29 08:40:19 +00002297}
2298
Nattapat Chaimanowonga9a1cf12018-12-03 16:06:49 +00002299void DebugQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2300{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002301 const std::string descriptorName{"DebugQueueDescriptor"};
2302
2303 ValidateNumInputs(workloadInfo, descriptorName, 1);
2304 ValidateNumOutputs(workloadInfo, descriptorName, 1);
Nattapat Chaimanowonga9a1cf12018-12-03 16:06:49 +00002305}
2306
FrancisMurtagh30cdfca2018-12-18 12:57:35 +00002307void EqualQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2308{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002309 const std::string descriptorName{"EqualQueueDescriptor"};
FrancisMurtagh30cdfca2018-12-18 12:57:35 +00002310
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002311 ValidateNumInputs(workloadInfo, descriptorName, 2);
2312 ValidateNumOutputs(workloadInfo, descriptorName, 1);
kevmay012b4d88e2019-01-24 14:05:09 +00002313
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002314 const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2315 const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2316 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2317
2318 ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2319 inputTensorInfo1,
2320 outputTensorInfo,
2321 descriptorName,
2322 "input_0",
2323 "input_1");
2324
2325 if (outputTensorInfo.GetDataType() != DataType::Boolean)
kevmay012b4d88e2019-01-24 14:05:09 +00002326 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002327 throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
kevmay012b4d88e2019-01-24 14:05:09 +00002328 }
FrancisMurtagh30cdfca2018-12-18 12:57:35 +00002329}
2330
FrancisMurtagh878f0232018-12-19 10:56:15 +00002331void GreaterQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2332{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002333 const std::string descriptorName{"GreaterQueueDescriptor"};
FrancisMurtagh878f0232018-12-19 10:56:15 +00002334
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002335 ValidateNumInputs(workloadInfo, descriptorName, 2);
2336 ValidateNumOutputs(workloadInfo, descriptorName, 1);
kevmay012b4d88e2019-01-24 14:05:09 +00002337
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002338 const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2339 const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2340 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2341
2342 ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2343 inputTensorInfo1,
2344 outputTensorInfo,
2345 descriptorName,
2346 "input_0",
2347 "input_1");
2348
2349 if (outputTensorInfo.GetDataType() != DataType::Boolean)
kevmay012b4d88e2019-01-24 14:05:09 +00002350 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002351 throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
kevmay012b4d88e2019-01-24 14:05:09 +00002352 }
FrancisMurtagh878f0232018-12-19 10:56:15 +00002353}
2354
Mohamed Nour Abouelseouda1d3c6a2018-12-27 12:39:16 +00002355void RsqrtQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2356{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002357 const std::string descriptorName{"RsqrtQueueDescriptor"};
2358
2359 ValidateNumInputs(workloadInfo, descriptorName, 1);
2360 ValidateNumOutputs(workloadInfo, descriptorName, 1);
2361
2362 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2363 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2364
2365 ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
nikraj010421e7f2019-06-14 09:40:34 +01002366
2367 std::vector<DataType> supportedTypes =
2368 {
James Conroyd47a0642019-09-17 14:22:06 +01002369 DataType::Float16,
2370 DataType::Float32,
2371 DataType::QuantisedAsymm8,
2372 DataType::QuantisedSymm16
nikraj010421e7f2019-06-14 09:40:34 +01002373 };
2374
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002375 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2376 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
Mohamed Nour Abouelseouda1d3c6a2018-12-27 12:39:16 +00002377}
2378
narpra01b89b05f2019-01-16 09:53:09 +00002379void GatherQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2380{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002381 const std::string descriptorName{"GatherQueueDescriptor"};
Ellen Norris-Thompsone0dbedf2019-06-24 09:23:38 +01002382
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002383 ValidateNumInputs(workloadInfo, descriptorName, 2);
2384 ValidateNumOutputs(workloadInfo, descriptorName, 1);
narpra014951d842019-01-18 16:53:53 +00002385
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002386 const TensorInfo& indicesTensorInfo = workloadInfo.m_InputTensorInfos[1];
2387 if (indicesTensorInfo.GetDataType() != DataType::Signed32)
narpra014951d842019-01-18 16:53:53 +00002388 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002389 throw InvalidArgumentException(descriptorName + ": Indices tensor type must be Int32.");
narpra014951d842019-01-18 16:53:53 +00002390 }
2391
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002392 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2393 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2394
Ellen Norris-Thompsone0dbedf2019-06-24 09:23:38 +01002395 std::vector<DataType> supportedTypes =
2396 {
James Conroyd47a0642019-09-17 14:22:06 +01002397 DataType::Float16,
2398 DataType::Float32,
2399 DataType::QuantisedAsymm8,
2400 DataType::QuantisedSymm16
Ellen Norris-Thompsone0dbedf2019-06-24 09:23:38 +01002401 };
2402
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002403 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
Ellen Norris-Thompsone0dbedf2019-06-24 09:23:38 +01002404
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002405 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
Ellen Norris-Thompsone0dbedf2019-06-24 09:23:38 +01002406
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002407 unsigned int outputDim = inputTensorInfo.GetNumDimensions() + indicesTensorInfo.GetNumDimensions() - 1;
2408 ValidateTensorNumDimensions(outputTensorInfo, descriptorName, outputDim, "output");
narpra01b89b05f2019-01-16 09:53:09 +00002409}
2410
Narumol Prangnawaratbc67cef2019-01-31 15:31:54 +00002411void DetectionPostProcessQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2412{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002413 const std::string& descriptorName{"DetectionPostProcessQueueDescriptor"};
2414
Aron Virginas-Tar6331f912019-06-03 17:10:02 +01002415 ValidateNumInputs(workloadInfo, descriptorName, 2);
Narumol Prangnawaratbc67cef2019-01-31 15:31:54 +00002416
2417 if (workloadInfo.m_OutputTensorInfos.size() != 4)
2418 {
Aron Virginas-Tar6331f912019-06-03 17:10:02 +01002419 throw InvalidArgumentException(descriptorName + ": Requires exactly four outputs. " +
Narumol Prangnawaratbc67cef2019-01-31 15:31:54 +00002420 to_string(workloadInfo.m_OutputTensorInfos.size()) + " has been provided.");
2421 }
2422
2423 if (m_Anchors == nullptr)
2424 {
Aron Virginas-Tar6331f912019-06-03 17:10:02 +01002425 throw InvalidArgumentException(descriptorName + ": Anchors tensor descriptor is missing.");
Narumol Prangnawaratbc67cef2019-01-31 15:31:54 +00002426 }
2427
2428 const TensorInfo& boxEncodingsInfo = workloadInfo.m_InputTensorInfos[0];
Aron Virginas-Tar6331f912019-06-03 17:10:02 +01002429 const TensorInfo& scoresInfo = workloadInfo.m_InputTensorInfos[1];
2430 const TensorInfo& anchorsInfo = m_Anchors->GetTensorInfo();
2431
2432 const TensorInfo& detectionBoxesInfo = workloadInfo.m_OutputTensorInfos[0];
Narumol Prangnawarat6d302bf2019-02-04 11:46:26 +00002433 const TensorInfo& detectionClassesInfo = workloadInfo.m_OutputTensorInfos[1];
Aron Virginas-Tar6331f912019-06-03 17:10:02 +01002434 const TensorInfo& detectionScoresInfo = workloadInfo.m_OutputTensorInfos[2];
2435 const TensorInfo& numDetectionsInfo = workloadInfo.m_OutputTensorInfos[3];
Narumol Prangnawaratbc67cef2019-01-31 15:31:54 +00002436
Aron Virginas-Tar6331f912019-06-03 17:10:02 +01002437 ValidateTensorNumDimensions(boxEncodingsInfo, descriptorName, 3, "box encodings");
2438 ValidateTensorNumDimensions(scoresInfo, descriptorName, 3, "scores");
2439 ValidateTensorNumDimensions(anchorsInfo, descriptorName, 2, "anchors");
Narumol Prangnawaratbc67cef2019-01-31 15:31:54 +00002440
Aron Virginas-Tar6331f912019-06-03 17:10:02 +01002441 const std::vector<DataType> supportedInputTypes =
2442 {
2443 DataType::Float32,
Matthew Jackson9bff1442019-09-12 09:08:23 +01002444 DataType::Float16,
Aron Virginas-Tar6331f912019-06-03 17:10:02 +01002445 DataType::QuantisedAsymm8,
2446 DataType::QuantisedSymm16
2447 };
Narumol Prangnawaratbc67cef2019-01-31 15:31:54 +00002448
Aron Virginas-Tar6331f912019-06-03 17:10:02 +01002449 ValidateDataTypes(boxEncodingsInfo, supportedInputTypes, descriptorName);
2450 ValidateDataTypes(scoresInfo, supportedInputTypes, descriptorName);
2451 ValidateDataTypes(anchorsInfo, supportedInputTypes, descriptorName);
2452
2453 ValidateTensorNumDimensions(detectionBoxesInfo, descriptorName, 3, "detection boxes");
2454 ValidateTensorNumDimensions(detectionScoresInfo, descriptorName, 2, "detection scores");
2455 ValidateTensorNumDimensions(detectionClassesInfo, descriptorName, 2, "detection classes");
2456 ValidateTensorNumDimensions(numDetectionsInfo, descriptorName, 1, "num detections");
2457
2458 // NOTE: Output is always Float32 regardless of input type
2459 ValidateTensorDataType(detectionBoxesInfo, DataType::Float32, descriptorName, "detection boxes");
2460 ValidateTensorDataType(detectionScoresInfo, DataType::Float32, descriptorName, "detection scores");
2461 ValidateTensorDataType(detectionClassesInfo, DataType::Float32, descriptorName, "detection classes");
2462 ValidateTensorDataType(numDetectionsInfo, DataType::Float32, descriptorName, "num detections");
Narumol Prangnawaratbc67cef2019-01-31 15:31:54 +00002463
2464 if (m_Parameters.m_NmsIouThreshold <= 0.0f || m_Parameters.m_NmsIouThreshold > 1.0f)
2465 {
Aron Virginas-Tar6331f912019-06-03 17:10:02 +01002466 throw InvalidArgumentException(descriptorName + ": Intersection over union threshold "
Narumol Prangnawaratbc67cef2019-01-31 15:31:54 +00002467 "must be positive and less than or equal to 1.");
2468 }
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002469
Narumol Prangnawaratbc67cef2019-01-31 15:31:54 +00002470 if (scoresInfo.GetShape()[2] != m_Parameters.m_NumClasses + 1)
2471 {
Aron Virginas-Tar6331f912019-06-03 17:10:02 +01002472 throw InvalidArgumentException(descriptorName + ": Number of classes with background "
Narumol Prangnawaratbc67cef2019-01-31 15:31:54 +00002473 "should be equal to number of classes + 1.");
2474 }
2475}
2476
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +00002477void DequantizeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2478{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002479 const std::string& descriptorName{"DequantizeQueueDescriptor"};
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +00002480
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002481 ValidateNumInputs(workloadInfo, descriptorName, 1);
2482 ValidateNumOutputs(workloadInfo, descriptorName, 1);
2483
2484 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2485 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2486
Aron Virginas-Tare9323ec2019-11-26 12:50:34 +00002487 if (!IsQuantizedType(inputTensorInfo.GetDataType()))
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +00002488 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002489 throw InvalidArgumentException(descriptorName + ": Input to dequantize layer must be quantized type.");
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +00002490 }
2491
Sadik Armagan2208b602019-07-31 16:36:27 +01002492 std::vector<DataType> supportedTypes =
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +00002493 {
James Conroyd47a0642019-09-17 14:22:06 +01002494 DataType::Float32,
2495 DataType::Float16
Sadik Armagan2208b602019-07-31 16:36:27 +01002496 };
2497
2498 ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +00002499}
2500
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +01002501void MergeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2502{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002503 const std::string& descriptorName{"MergeQueueDescriptor"};
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +01002504
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002505 ValidateNumInputs(workloadInfo, descriptorName, 2);
2506 ValidateNumOutputs(workloadInfo, descriptorName, 1);
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +01002507
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002508 const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2509 const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2510 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +01002511
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002512 ValidateTensorShapesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
2513 ValidateTensorShapesMatch(inputTensorInfo0, outputTensorInfo, descriptorName, "input_0", "output");
2514
2515 ValidateTensorDataTypesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
2516 ValidateTensorDataTypesMatch(inputTensorInfo0, outputTensorInfo, descriptorName, "input_0", "output");
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +01002517}
2518
Sadik Armaganeff363d2019-04-05 15:25:46 +01002519void SwitchQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2520{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002521 const std::string& descriptorName{"SwitchQueueDescriptor"};
Sadik Armaganeff363d2019-04-05 15:25:46 +01002522
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002523 ValidateNumInputs(workloadInfo, descriptorName, 2);
2524 ValidateNumOutputs(workloadInfo, descriptorName, 2);
2525
2526 const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2527 const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2528
2529 const TensorInfo& outputTensorInfo0 = workloadInfo.m_OutputTensorInfos[0];
2530 const TensorInfo& outputTensorInfo1 = workloadInfo.m_OutputTensorInfos[1];
2531
2532 std::vector<DataType> supportedTypes =
2533 {
Sadik Armaganeff363d2019-04-05 15:25:46 +01002534 DataType::Float32,
2535 DataType::QuantisedAsymm8,
2536 DataType::QuantisedSymm16
2537 };
2538
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002539 ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2540 ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
Sadik Armaganeff363d2019-04-05 15:25:46 +01002541
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002542 ValidateDataTypes(outputTensorInfo0, supportedTypes, descriptorName);
2543 ValidateDataTypes(outputTensorInfo1, supportedTypes, descriptorName);
Sadik Armaganeff363d2019-04-05 15:25:46 +01002544
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002545 ValidateTensorShapesMatch(inputTensorInfo0,
2546 outputTensorInfo0,
2547 descriptorName,
2548 "input_0",
2549 "output_0");
Sadik Armaganeff363d2019-04-05 15:25:46 +01002550
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002551 ValidateTensorShapesMatch(inputTensorInfo0,
2552 outputTensorInfo1,
2553 descriptorName,
2554 "input_0",
2555 "output_1");
Sadik Armaganeff363d2019-04-05 15:25:46 +01002556}
2557
Matteo Martincigh49124022019-01-11 13:25:59 +00002558void PreCompiledQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2559{
2560 // This is internally generated so it should not need validation.
2561}
2562
Matteo Martincigh0e406ee2019-06-12 15:42:18 +01002563void PreluQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2564{
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002565 const std::string& descriptorName{"PreluQueueDescriptor"};
2566
2567 ValidateNumInputs(workloadInfo, descriptorName, 2);
2568 ValidateNumOutputs(workloadInfo, descriptorName, 1);
2569
2570 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2571 const TensorInfo& alphaTensorInfo = workloadInfo.m_InputTensorInfos[1];
2572 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
Matteo Martincigh0e406ee2019-06-12 15:42:18 +01002573
2574 std::vector<DataType> supportedTypes
2575 {
2576 DataType::Float16,
2577 DataType::Float32,
Matteo Martincighab9e5252019-06-13 17:27:46 +01002578 DataType::QuantisedAsymm8,
2579 DataType::QuantisedSymm16
Matteo Martincigh0e406ee2019-06-12 15:42:18 +01002580 };
2581
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002582 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2583 ValidateDataTypes(alphaTensorInfo, supportedTypes, descriptorName);
Matteo Martincigh0e406ee2019-06-12 15:42:18 +01002584
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002585 ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
Matteo Martincigh0e406ee2019-06-12 15:42:18 +01002586
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002587 ValidateTensorDataTypesMatch(inputTensorInfo, alphaTensorInfo, descriptorName, "input", "alpha");
2588 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "ouptut");
Matteo Martincigh0e406ee2019-06-12 15:42:18 +01002589
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002590 ValidateBroadcastTensorShapesMatch(inputTensorInfo,
2591 alphaTensorInfo,
2592 outputTensorInfo,
2593 descriptorName,
Matteo Martincigh0e406ee2019-06-12 15:42:18 +01002594 "input",
2595 "alpha");
2596}
2597
Aron Virginas-Tar639fb042019-06-20 14:28:19 +01002598void TransposeConvolution2dQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2599{
2600 const std::string descriptorName{"TransposeConvolution2dQueueDescriptor"};
2601
2602 ValidateNumInputs(workloadInfo, descriptorName, 1);
2603 ValidateNumOutputs(workloadInfo, descriptorName, 1);
2604
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002605 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2606 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2607
2608 ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
2609 ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
Aron Virginas-Tar639fb042019-06-20 14:28:19 +01002610
2611 ValidatePointer(m_Weight, descriptorName, "weight");
Aron Virginas-Tar639fb042019-06-20 14:28:19 +01002612
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002613 const TensorInfo& weightTensorInfo = m_Weight->GetTensorInfo();
2614 ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 4, "weight");
Aron Virginas-Tar639fb042019-06-20 14:28:19 +01002615
Aron Virginas-Tar94d3b932019-11-11 12:54:47 +00002616 ValidateWeightDataType(inputTensorInfo, weightTensorInfo, descriptorName);
2617
2618 Optional<TensorInfo> optionalBiasTensorInfo;
Aron Virginas-Tar639fb042019-06-20 14:28:19 +01002619 if (m_Parameters.m_BiasEnabled)
2620 {
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002621 ValidatePointer(m_Bias, descriptorName, "bias");
Aron Virginas-Tar639fb042019-06-20 14:28:19 +01002622
Aron Virginas-Tar94d3b932019-11-11 12:54:47 +00002623 optionalBiasTensorInfo = MakeOptional<TensorInfo>(m_Bias->GetTensorInfo());
2624 const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value();
Aron Virginas-Tar639fb042019-06-20 14:28:19 +01002625
Aron Virginas-Tar94d3b932019-11-11 12:54:47 +00002626 ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002627 ValidateBiasTensorQuantization(biasTensorInfo, inputTensorInfo, weightTensorInfo, descriptorName);
Aron Virginas-Tar639fb042019-06-20 14:28:19 +01002628 }
Aron Virginas-Tar94d3b932019-11-11 12:54:47 +00002629
2630 ValidatePerAxisQuantization(inputTensorInfo,
2631 outputTensorInfo,
2632 weightTensorInfo,
2633 optionalBiasTensorInfo,
2634 descriptorName);
2635
2636 std::vector<DataType> supportedTypes =
2637 {
2638 DataType::Float32,
2639 DataType::Float16,
2640 DataType::QuantisedAsymm8,
2641 DataType::QuantisedSymm16
2642 };
2643
2644 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2645 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
Aron Virginas-Tar639fb042019-06-20 14:28:19 +01002646}
2647
James Conroy9c3cae82019-08-01 16:01:48 +01002648void QuantizedLstmQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2649{
2650 const std::string descriptorName{"QuantizedLstmQueueDescriptor"};
2651
2652 // Validate number of inputs/outputs
2653 ValidateNumInputs(workloadInfo, descriptorName, 3);
2654 ValidateNumOutputs(workloadInfo, descriptorName, 2);
2655
2656 // Input/output tensor infos
2657 auto inputInfo = workloadInfo.m_InputTensorInfos[0];
2658 auto cellStateInInfo = workloadInfo.m_InputTensorInfos[1];
2659 auto outputStateInInfo = workloadInfo.m_InputTensorInfos[2];
2660
2661 auto cellStateOutInfo = workloadInfo.m_OutputTensorInfos[0];
2662 auto outputStateOutInfo = workloadInfo.m_OutputTensorInfos[1];
2663
2664 std::vector<DataType> inputOutputSupportedTypes =
2665 {
2666 DataType::QuantisedAsymm8
2667 };
2668
2669 std::vector<DataType> cellStateSupportedTypes =
2670 {
2671 DataType::QuantisedSymm16
2672 };
2673
2674 std::vector<DataType> weightsSupportedTypes =
2675 {
2676 DataType::QuantisedAsymm8
2677 };
2678
2679 std::vector<DataType> biasSupportedTypes =
2680 {
2681 DataType::Signed32
2682 };
2683
2684 // Validate types of input/output tensors
2685 ValidateDataTypes(inputInfo, inputOutputSupportedTypes, descriptorName);
2686 ValidateDataTypes(cellStateInInfo, cellStateSupportedTypes, descriptorName);
2687 ValidateDataTypes(outputStateInInfo, inputOutputSupportedTypes, descriptorName);
2688
2689 ValidateDataTypes(cellStateOutInfo, cellStateSupportedTypes, descriptorName);
2690 ValidateDataTypes(outputStateOutInfo, inputOutputSupportedTypes, descriptorName);
2691
2692 // Validate matching types of input/output tensors
2693 ValidateTensorDataTypesMatch(inputInfo, outputStateInInfo, descriptorName, "input", "outputStateIn");
2694 ValidateTensorDataTypesMatch(outputStateInInfo, outputStateOutInfo, descriptorName,
2695 "outputStateIn", "outputStateOut");
2696 ValidateTensorDataTypesMatch(cellStateInInfo, cellStateOutInfo, descriptorName, "cellStateIn", "cellStateOut");
2697
2698 // Validate matching quantization info for input/output tensors
2699 ValidateTensorQuantizationSpace(inputInfo, outputStateInInfo, descriptorName, "input", "outputStateIn");
2700 ValidateTensorQuantizationSpace(inputInfo, outputStateOutInfo, descriptorName, "input", "outputStateOut");
2701 ValidateTensorQuantizationSpace(cellStateInInfo, cellStateOutInfo, descriptorName, "cellStateIn", "cellStateOut");
Aron Virginas-Tar636ab402019-09-16 14:27:45 +01002702
James Conroy9c3cae82019-08-01 16:01:48 +01002703 // Infer number of batches, input size and output size from tensor dimensions
2704 const uint32_t numBatches = inputInfo.GetShape()[0];
2705 const uint32_t inputSize = inputInfo.GetShape()[1];
2706 const uint32_t outputSize = cellStateInInfo.GetShape()[1];
2707
2708 // Validate number of dimensions and number of elements for input/output tensors
2709 ValidateTensorNumDimNumElem(inputInfo, 2, (numBatches * inputSize), descriptorName + " input");
2710 ValidateTensorNumDimNumElem(cellStateInInfo, 2, (numBatches * outputSize), descriptorName + " cellStateIn");
2711 ValidateTensorNumDimNumElem(outputStateInInfo, 2, (numBatches * outputSize), descriptorName + " outputStateIn");
2712 ValidateTensorNumDimNumElem(cellStateOutInfo, 2, (numBatches * outputSize), descriptorName + " cellStateOut");
2713 ValidateTensorNumDimNumElem(outputStateOutInfo, 2, (numBatches * outputSize), descriptorName + " outputStateOut");
2714
2715 // Validate number of dimensions and number of elements for weights tensors
2716 ValidatePointer(m_InputToInputWeights, descriptorName, "InputToInputWeights");
2717 auto inputToInputWeightsInfo = m_InputToInputWeights->GetTensorInfo();
2718 ValidateTensorNumDimNumElem(inputToInputWeightsInfo, 2, (outputSize * inputSize), " InputToInputWeights");
2719
2720 ValidatePointer(m_InputToForgetWeights, descriptorName, "InputToForgetWeights");
2721 auto inputToForgetWeightsInfo = m_InputToForgetWeights->GetTensorInfo();
2722 ValidateTensorNumDimNumElem(inputToForgetWeightsInfo, 2, (outputSize * inputSize), " InputToForgetWeights");
2723
2724 ValidatePointer(m_InputToCellWeights, descriptorName, "InputToCellWeights");
2725 auto inputToCellWeightsInfo = m_InputToCellWeights->GetTensorInfo();
2726 ValidateTensorNumDimNumElem(inputToCellWeightsInfo, 2, (outputSize * inputSize), " InputToCellWeights");
2727
2728 ValidatePointer(m_InputToOutputWeights, descriptorName, "InputToOutputWeights");
2729 auto inputToOutputWeightsInfo = m_InputToOutputWeights->GetTensorInfo();
2730 ValidateTensorNumDimNumElem(inputToOutputWeightsInfo, 2, (outputSize * inputSize), " InputToOutputWeights");
2731
2732 ValidatePointer(m_RecurrentToInputWeights, descriptorName, "RecurrentToInputWeights");
2733 auto recurrentToInputWeightsInfo = m_RecurrentToInputWeights->GetTensorInfo();
2734 ValidateTensorNumDimNumElem(recurrentToInputWeightsInfo, 2, (outputSize * outputSize), " RecurrentToInputWeights");
2735
2736 ValidatePointer(m_RecurrentToForgetWeights, descriptorName, "RecurrentToForgetWeights");
2737 auto recurrentToForgetWeightsInfo = m_RecurrentToForgetWeights->GetTensorInfo();
2738 ValidateTensorNumDimNumElem(recurrentToForgetWeightsInfo, 2, (outputSize * outputSize),
2739 " RecurrentToForgetWeights");
2740
2741 ValidatePointer(m_RecurrentToCellWeights, descriptorName, "RecurrentToCellWeights");
2742 auto recurrentToCellWeightsInfo = m_RecurrentToCellWeights->GetTensorInfo();
2743 ValidateTensorNumDimNumElem(recurrentToCellWeightsInfo, 2, (outputSize * outputSize), " RecurrentToCellWeights");
2744
2745 ValidatePointer(m_RecurrentToOutputWeights, descriptorName, "RecurrentToOutputWeights");
2746 auto recurrentToOutputWeightsInfo = m_RecurrentToOutputWeights->GetTensorInfo();
2747 ValidateTensorNumDimNumElem(recurrentToOutputWeightsInfo, 2, (outputSize * outputSize), " RecurrentToCellWeights");
2748
2749 // Validate data types for weights tensors (all should match each other)
2750 ValidateDataTypes(inputToInputWeightsInfo, weightsSupportedTypes, descriptorName);
2751
2752 ValidateTensorDataTypesMatch(inputToInputWeightsInfo, inputToForgetWeightsInfo, descriptorName,
2753 "inputToInputWeights", "inputToForgetWeights");
2754 ValidateTensorDataTypesMatch(inputToInputWeightsInfo, inputToCellWeightsInfo, descriptorName,
2755 "inputToInputWeights", "inputToCellWeights");
2756 ValidateTensorDataTypesMatch(inputToInputWeightsInfo, inputToOutputWeightsInfo, descriptorName,
2757 "inputToInputWeights", "inputToOutputWeights");
2758
2759 ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToInputWeightsInfo, descriptorName,
2760 "inputToInputWeights", "recurrentToInputWeights");
2761 ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToForgetWeightsInfo, descriptorName,
2762 "inputToInputWeights", "recurrentToForgeteights");
2763 ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToCellWeightsInfo, descriptorName,
2764 "inputToInputWeights", "recurrentToCellWeights");
2765 ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToOutputWeightsInfo, descriptorName,
2766 "inputToInputWeights", "recurrentToOutputWeights");
2767
2768 // Validate matching quantization info for weight tensors (all should match each other)
2769 ValidateTensorQuantizationSpace(inputToInputWeightsInfo, inputToForgetWeightsInfo,
2770 descriptorName, "inputToInputWeights", "inputToForgetWeights");
2771 ValidateTensorQuantizationSpace(inputToInputWeightsInfo, inputToCellWeightsInfo,
2772 descriptorName, "inputToInputWeights", "inputToCellWeights");
2773 ValidateTensorQuantizationSpace(inputToInputWeightsInfo, inputToOutputWeightsInfo,
2774 descriptorName, "inputToInputWeights", "inputToOutputWeights");
2775
2776 ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToInputWeightsInfo,
2777 descriptorName, "inputToInputWeights", "recurrentToInputWeights");
2778 ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToForgetWeightsInfo,
2779 descriptorName, "inputToInputWeights", "recurrentToForgetWeights");
2780 ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToCellWeightsInfo,
2781 descriptorName, "inputToInputWeights", "recurrentToCellWeights");
2782 ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToOutputWeightsInfo,
2783 descriptorName, "inputToInputWeights", "recurrentToOutputWeights");
2784
2785 // Validate number of dimensions and number of elements in bias tensors
2786 ValidatePointer(m_InputGateBias, descriptorName, "InputGateBias");
2787 auto inputGateBiasInfo = m_InputGateBias->GetTensorInfo();
2788 ValidateTensorNumDimNumElem(inputGateBiasInfo, 1, outputSize, " InputGateBias");
2789
2790 ValidatePointer(m_ForgetGateBias, descriptorName, "ForgetGateBias");
2791 auto forgetGateBiasInfo = m_ForgetGateBias->GetTensorInfo();
2792 ValidateTensorNumDimNumElem(forgetGateBiasInfo, 1, outputSize, " ForgetGateBias");
2793
2794 ValidatePointer(m_CellBias, descriptorName, "CellBias");
2795 auto cellBiasInfo = m_CellBias->GetTensorInfo();
2796 ValidateTensorNumDimNumElem(cellBiasInfo, 1, outputSize, " CellBias");
2797
2798 ValidatePointer(m_OutputGateBias, descriptorName, "OutputGateBias");
2799 auto outputGateBiasInfo = m_OutputGateBias->GetTensorInfo();
2800 ValidateTensorNumDimNumElem(outputGateBiasInfo, 1, outputSize, " OutputGateBias");
2801
2802 // Validate data types for bias tensors (all should match each other)
2803 ValidateDataTypes(inputGateBiasInfo, biasSupportedTypes, descriptorName);
2804
2805 ValidateTensorDataTypesMatch(inputGateBiasInfo, forgetGateBiasInfo, descriptorName,
2806 "inputGateBias", "forgetGateBias");
2807 ValidateTensorDataTypesMatch(inputGateBiasInfo, cellBiasInfo, descriptorName,
2808 "inputGateBias", "cellBias");
2809 ValidateTensorDataTypesMatch(inputGateBiasInfo, outputGateBiasInfo, descriptorName,
2810 "inputGateBias", "outputGateBias");
2811
2812 // Validate bias tensor quantization info
2813 ValidateBiasTensorQuantization(inputGateBiasInfo, inputInfo, inputToInputWeightsInfo, descriptorName);
2814 ValidateBiasTensorQuantization(forgetGateBiasInfo, inputInfo, inputToInputWeightsInfo, descriptorName);
2815 ValidateBiasTensorQuantization(cellBiasInfo, inputInfo, inputToInputWeightsInfo, descriptorName);
2816 ValidateBiasTensorQuantization(outputGateBiasInfo, inputInfo, inputToInputWeightsInfo, descriptorName);
2817}
2818
Kevin May868eb142019-09-04 17:29:31 +01002819void AbsQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2820{
2821 const std::string descriptorName{"AbsQueueDescriptor"};
2822
2823 ValidateNumInputs(workloadInfo, descriptorName, 1);
2824 ValidateNumOutputs(workloadInfo, descriptorName, 1);
2825
2826 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2827 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2828
2829 ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2830
2831 std::vector<DataType> supportedTypes =
James Conroyd47a0642019-09-17 14:22:06 +01002832 {
2833 DataType::Float16,
2834 DataType::Float32,
2835 DataType::QuantisedAsymm8,
2836 DataType::QuantisedSymm16
2837 };
Kevin May868eb142019-09-04 17:29:31 +01002838
2839 ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2840 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2841}
2842
Aron Virginas-Tar636ab402019-09-16 14:27:45 +01002843void SliceQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2844{
2845 const std::string descriptorName{"SliceQueueDescriptor"};
2846
2847 ValidateNumInputs(workloadInfo, descriptorName, 1);
2848 ValidateNumOutputs(workloadInfo, descriptorName, 1);
2849
2850 const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2851 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2852
2853 ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2854
2855 const unsigned int rank = inputTensorInfo.GetNumDimensions();
2856 if (rank > 4)
2857 {
2858 throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
2859 }
2860
2861 ValidateTensorNumDimensions(outputTensorInfo, descriptorName, rank, "output");
2862
2863 // Check if m_Begin and m_Size have the expected length
2864 if (m_Parameters.m_Begin.size() != rank)
2865 {
2866 throw InvalidArgumentException(descriptorName +
2867 ": Length of begin offset descriptor must equal rank " + std::to_string(rank));
2868 }
2869 if (m_Parameters.m_Size.size() != rank)
2870 {
2871 throw InvalidArgumentException(descriptorName +
2872 ": Length of size descriptor must equal rank " + std::to_string(rank));
2873 }
2874
2875 // Check if the shape of the output tensor matches m_Size
2876 const TensorShape& outputShape = outputTensorInfo.GetShape();
2877 for (unsigned int i = 0u; i < rank; ++i)
2878 {
2879 if (m_Parameters.m_Size[i] != outputShape[i])
2880 {
2881 throw InvalidArgumentException(descriptorName + ": Size descriptor does not match output tensor.");
2882 }
2883 }
2884
2885 // Check if the sum of begin offset and size in a given dimension
2886 // does not exceed the size of corresponding input
2887 const TensorShape& inputShape = inputTensorInfo.GetShape();
2888 for(unsigned int i = 0u; i < rank; ++i)
2889 {
Aron Virginas-Tar92b9f872019-09-17 17:27:04 +01002890 if (m_Parameters.m_Begin[i] + m_Parameters.m_Size[i] > inputShape[i])
Aron Virginas-Tar636ab402019-09-16 14:27:45 +01002891 {
2892 throw InvalidArgumentException(descriptorName + ": Sum of begin offset and size for dimension " +
2893 std::to_string(i) + " exceeds input size.");
2894 }
2895 }
2896}
2897
Aron Virginas-Tardd6247f2019-09-19 14:31:17 +01002898void DepthToSpaceQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2899{
2900 const std::string descriptorName{"DepthToSpaceQueueDescriptor"};
2901
2902 ValidateNumInputs(workloadInfo, descriptorName, 1);
2903 ValidateNumOutputs(workloadInfo, descriptorName, 1);
2904
2905 const TensorInfo& inputInfo = workloadInfo.m_InputTensorInfos[0];
2906 const TensorInfo& outputInfo = workloadInfo.m_OutputTensorInfos[0];
2907
2908 ValidateTensorNumDimensions(inputInfo, descriptorName, 4, "input");
2909 ValidateTensorNumDimensions(outputInfo, descriptorName, 4, "output");
2910
2911 std::vector<DataType> supportedTypes =
2912 {
2913 DataType::Float32,
2914 DataType::Float16,
2915 DataType::QuantisedAsymm8,
2916 DataType::QuantisedSymm16
2917 };
2918
2919 ValidateDataTypes(inputInfo, supportedTypes, descriptorName);
2920 ValidateDataTypes(outputInfo, supportedTypes, descriptorName);
2921
2922 ValidateTensorNumElementsMatch(inputInfo, outputInfo, descriptorName, "input", "output");
2923
2924 if (m_Parameters.m_BlockSize == 0)
2925 {
2926 throw InvalidArgumentException(descriptorName + ": Block size cannot be 0.");
2927 }
2928
2929 DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
2930 const unsigned int wIndex = dimensionIndices.GetWidthIndex();
2931 const unsigned int hIndex = dimensionIndices.GetHeightIndex();
2932 const unsigned int cIndex = dimensionIndices.GetChannelsIndex();
2933
2934 const TensorShape& outputShape = outputInfo.GetShape();
2935 if (outputShape[hIndex] % m_Parameters.m_BlockSize != 0 || outputShape[wIndex] % m_Parameters.m_BlockSize != 0)
2936 {
2937 throw InvalidArgumentException(descriptorName + ": Output width and height shape"
2938 "must be divisible by block size.");
2939 }
2940
2941 const TensorShape& inputShape = inputInfo.GetShape();
2942 if (inputShape[cIndex] % (m_Parameters.m_BlockSize * m_Parameters.m_BlockSize) != 0)
2943 {
2944 throw InvalidArgumentException(descriptorName + ": The depth of the input tensor"
2945 "must be divisible by the square of block size." );
2946 }
2947}
2948
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +01002949void ComparisonQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2950{
2951 const std::string descriptorName{"ComparisonQueueDescriptor"};
2952
2953 ValidateNumInputs(workloadInfo, descriptorName, 2);
2954 ValidateNumOutputs(workloadInfo, descriptorName, 1);
2955
2956 const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2957 const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2958 const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2959
2960 ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2961 inputTensorInfo1,
2962 outputTensorInfo,
2963 descriptorName,
2964 "input_0",
2965 "input_1");
2966
2967 if (outputTensorInfo.GetDataType() != DataType::Boolean)
2968 {
2969 throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
2970 }
2971}
2972
Aron Virginas-Tar84062b72019-07-19 11:37:10 +01002973} // namespace armnn