ArmNN
 24.08
WorkloadData.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017-2024 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
11 #include <armnnUtils/Permute.hpp>
13 #include <armnn/Logging.hpp>
14 
15 #include <algorithm>
16 #include <iomanip>
17 #include <string>
18 #include <sstream>
19 
20 #include <fmt/format.h>
21 
22 using namespace armnnUtils;
23 
24 namespace armnn
25 {
26 
27 //---------------------------------------------------------------
29 {
30  switch (inputDataType)
31  {
32  case DataType::Float16:
33  return DataType::Float16;
34  case DataType::BFloat16:
35  case DataType::Float32:
36  return DataType::Float32;
37  case DataType::QAsymmS8:
38  case DataType::QAsymmU8:
39  case DataType::QSymmS8:
40  case DataType::QSymmS16:
41  return DataType::Signed32;
42  default:
43  throw InvalidArgumentException("GetBiasDataType(): Unsupported data type.");
44  }
45 }
46 
47 namespace
48 {
49 
50 //---------------------------------------------------------------
51 //android ndk does not support std::to_string function.
52 template <typename T>
53 std::string to_string(T value)
54 {
55  std::ostringstream os;
56  os << value;
57  return os.str();
58 }
59 
60 //---------------------------------------------------------------
61 void ValidatePointer(const void* ptr, std::string const& descName, std::string const& paramName)
62 {
63  if (!ptr)
64  {
65  throw InvalidArgumentException(descName + ": Invalid null pointer. The " +
66  paramName + " parameter must be set.");
67  }
68 }
69 
70 //---------------------------------------------------------------
71 void ValidateTensorShapesMatch(const TensorInfo& first,
72  const TensorInfo& second,
73  std::string const& descName,
74  std::string const& firstName,
75  std::string const& secondName)
76 {
77  if (first.GetShape() != second.GetShape())
78  {
79  throw InvalidArgumentException(descName + ": "
80  + firstName + " & " + secondName + " must have identical shapes");
81  }
82 }
83 
84 //---------------------------------------------------------------
85 void ValidateNumInputs(const WorkloadInfo& workloadInfo, std::string const& descName, const unsigned int expectedSize)
86 {
87  if (workloadInfo.m_InputTensorInfos.size() != expectedSize)
88  {
89  throw InvalidArgumentException(descName +
90  ": Requires exactly " + to_string(expectedSize) + "input(s). " +
91  to_string(workloadInfo.m_InputTensorInfos.size()) + " have been provided.");
92  }
93 }
94 
95 //---------------------------------------------------------------
96 void ValidateNumOutputs(const WorkloadInfo& workloadInfo, std::string const& descName, const unsigned int expectedSize)
97 {
98  if (workloadInfo.m_OutputTensorInfos.size() != expectedSize)
99  {
100  throw InvalidArgumentException(descName +
101  ": Requires exactly " + to_string(expectedSize) + " output(s). " +
102  to_string(workloadInfo.m_OutputTensorInfos.size()) + " has been provided.");
103  }
104 }
105 
106 //---------------------------------------------------------------
107 
108 //---------------------------------------------------------------
109 void ValidateTensorNumElements(const TensorInfo& tensor,
110  std::string const& descName,
111  unsigned int numElements,
112  std::string const& tensorName)
113 {
114  if (tensor.GetNumElements() != numElements)
115  {
116  throw InvalidArgumentException(descName + ": Expected " + to_string(numElements) + " but got " +
117  to_string(tensor.GetNumElements()) + " elements for " +
118  tensorName + " tensor.");
119  }
120 }
121 
122 //---------------------------------------------------------------
123 void ValidateTensorDataType(const TensorInfo& tensor, DataType dataType,
124  const std::string& descName, std::string const& tensorName)
125 {
126  if (tensor.GetDataType() != dataType)
127  {
128  throw InvalidArgumentException(descName + ": Expected data type " + GetDataTypeName(dataType) + " but got " +
129  GetDataTypeName(tensor.GetDataType()) + " for " + tensorName + " tensor.");
130  }
131 }
132 
133 void ValidPerAxisQuantizedDataType(const TensorInfo& tensor, const std::string& descName, const std::string& tensorName)
134 {
135  if (tensor.GetDataType() != DataType::QSymmS8)
136  {
137  throw InvalidArgumentException(descName +
138  ": Expected data type which supports per-axis quantization scheme but got " +
139  GetDataTypeName(tensor.GetDataType()) + " for " + tensorName + " tensor.");
140  }
141 }
142 
143 //---------------------------------------------------------------
144 void ValidateTensorQuantizationSpace(const TensorInfo& first,
145  const TensorInfo& second,
146  const std::string& descName,
147  std::string const& firstName,
148  std::string const& secondName)
149 {
150  if (!first.IsQuantized() ||
151  !second.IsQuantized())
152  {
153  // Not a quantized type, ignore the validation
154  return;
155  }
156 
157  DataType firstDataType = first.GetDataType();
158  DataType secondDataType = second.GetDataType();
159 
160  if (firstDataType != secondDataType)
161  {
162  throw InvalidArgumentException(descName + ": " + firstName + " and " + secondName +
163  " must be of the same quantized type, " +
164  firstName + " is " + GetDataTypeName(firstDataType) + ", " +
165  secondName + " is " + GetDataTypeName(secondDataType));
166  }
167 
168  if (!first.IsTypeSpaceMatch(second))
169  {
170  throw InvalidArgumentException(descName + ": " + firstName + " and " + secondName +
171  " must have the same quantization space, " +
172  firstName + " has offset " + to_string(first.GetQuantizationOffset()) +
173  " and scale " + to_string(first.GetQuantizationScale()) + ", " +
174  secondName + " has offset " + to_string(second.GetQuantizationOffset()) +
175  " and scale " + to_string(second.GetQuantizationScale()));
176  }
177 }
178 
179 //---------------------------------------------------------------
180 void ValidateBiasTensorQuantization(const TensorInfo& biasTensor,
181  const TensorInfo& weightsTensorInfo,
182  const std::string& descName)
183 {
184  if (biasTensor.GetQuantizationOffset() != 0)
185  {
186  throw InvalidArgumentException(descName + ": Expected zero quantization offset for bias tensor but got " +
187  to_string(biasTensor.GetQuantizationOffset()));
188  }
189 
190  if (biasTensor.HasMultipleQuantizationScales() || weightsTensorInfo.HasMultipleQuantizationScales())
191  {
192  // Validate per-axis quantization scales
193  const std::vector<float>& weightScales = weightsTensorInfo.GetQuantizationScales();
194  const std::vector<float>& biasScales = biasTensor.GetQuantizationScales();
195 
196  if (weightScales.size() != biasScales.size())
197  {
198  std::stringstream msg;
199  msg << descName << ": Expected matching number of per-axis quantization scales for weights and bias, "
200  << "but got different values. This is currently unsupported: weights=" << weightScales.size()
201  << ", biases=" << biasScales.size();
202  throw InvalidArgumentException(msg.str(), CHECK_LOCATION());
203  }
204  }
205 }
206 
207 //---------------------------------------------------------------
208 void ValidateTensors(const std::vector<ITensorHandle*>& vec,
209  unsigned int numExpected,
210  const std::string& descName,
211  const std::string& varName)
212 {
213  if (vec.empty() && numExpected > 0)
214  {
215  throw InvalidArgumentException(descName + ": Invalid empty " + varName + " array.");
216  }
217 
218  for (unsigned int i = 0; i < numExpected; ++i)
219  {
220  if (!vec[i])
221  {
222  throw InvalidArgumentException(descName + ": Invalid NULL for " + varName + to_string(i));
223  }
224  }
225 }
226 
227 //---------------------------------------------------------------
228 void ValidateBroadcastTensorShapesMatch(const TensorInfo& first,
229  const TensorInfo& second,
230  const TensorInfo& output,
231  std::string const& descName,
232  std::string const& firstName,
233  std::string const& secondName)
234 {
235  // Tensors must have the same number of dimensions in order to be explicit about which dimensions will get
236  // broadcasted.
237  // NOTE: This check is dependent on the AddBroadcastReshapeLayerImpl optimization having been applied to the layer.
238  if (first.GetNumDimensions() != second.GetNumDimensions())
239  {
240  throw InvalidArgumentException(descName + ": Tensors "
241  + firstName + " & " + secondName
242  + " must have the same number of dimensions in order to be broadcasted");
243  }
244  uint32_t numDims = first.GetNumDimensions();
245  std::vector<uint32_t> outputDims(numDims, 0u);
246  for (uint32_t i = 0; i < numDims; i++)
247  {
248  const bool dimsNotEqual = first.GetShape()[i] != second.GetShape()[i];
249  const bool dimsNotOne = (first.GetShape()[i] != 1) && (second.GetShape()[i] != 1);
250  if (dimsNotEqual && dimsNotOne)
251  {
252  throw InvalidArgumentException("Broadcasting is not possible for incompatible shapes");
253  }
254  outputDims[i] = std::max(first.GetShape()[i], second.GetShape()[i]);
255  }
256  TensorShape broadcastShape = TensorShape(armnn::numeric_cast<unsigned int>(outputDims.size()), outputDims.data());
257  if (broadcastShape != output.GetShape())
258  {
259  throw InvalidArgumentException(descName + ": The tensor shape resulting from adding "
260  + firstName + " & " + secondName
261  + " does not match the output shape");
262  }
263 }
264 
265 //---------------------------------------------------------------
266 void ValidateDataTypes(const TensorInfo& info,
267  const std::vector<armnn::DataType>& supportedTypes,
268  std::string const& descName)
269 {
270  auto iterator = std::find(supportedTypes.begin(), supportedTypes.end(), info.GetDataType());
271  if (iterator == supportedTypes.end())
272  {
273  throw InvalidArgumentException(descName + ": " + " Tensor type " + GetDataTypeName(info.GetDataType()) +
274  " is not supported.");
275  }
276 }
277 
278 //---------------------------------------------------------------
279 void ValidateTensorDataTypesMatch(const TensorInfo& first,
280  const TensorInfo& second,
281  std::string const& descName,
282  std::string const& firstName,
283  std::string const& secondName)
284 {
285  if (first.GetDataType() != second.GetDataType())
286  {
287  throw InvalidArgumentException(descName + ": " + firstName + " & " + secondName +
288  " must have identical data types.");
289  }
290 }
291 
292 //---------------------------------------------------------------
293 void ValidateTensorNumElementsMatch(const TensorInfo& first,
294  const TensorInfo& second,
295  std::string const& descName,
296  std::string const& firstName,
297  std::string const& secondName)
298 {
299  if (first.GetNumElements() != second.GetNumElements())
300  {
301  throw InvalidArgumentException(descName + ": " + firstName + " & " + secondName +
302  " must have the same number of elements.");
303  }
304 }
305 
306 void ValidateWeightDataType(const TensorInfo& inputInfo,
307  const TensorInfo& weightInfo,
308  const std::string& descName)
309 {
310  const DataType inputType = inputInfo.GetDataType();
311  if (IsQuantized8BitType(inputType))
312  {
313  const std::vector<DataType> validTypes =
314  {
315  DataType::QAsymmS8,
316  DataType::QAsymmU8,
317  DataType::QSymmS8
318  };
319 
320  ValidateDataTypes(weightInfo, validTypes, descName);
321  }
322  else
323  {
324  ValidateTensorDataTypesMatch(inputInfo, weightInfo, descName, "input", "weight");
325  }
326 }
327 
328 void ValidatePerAxisQuantizationDimension(const TensorInfo& tensorInfo,
329  const std::string& descName,
330  const std::string& tensorName)
331 {
332  const Optional<unsigned int>& quantizationDim = tensorInfo.GetQuantizationDim();
333  if (!quantizationDim.has_value())
334  {
335  throw InvalidArgumentException(fmt::format("{0}: Quantization dimension for per-axis quantization "
336  "not set on tensor {1}.", descName, tensorName));
337  }
338 }
339 
340 void ValidatePerAxisQuantizationOffset(const TensorInfo& tensorInfo,
341  const std::string& descName,
342  const std::string& tensorName)
343 {
344  int32_t quantizationOffset = tensorInfo.GetQuantizationOffset();
345  if (quantizationOffset != 0)
346  {
347  throw InvalidArgumentException(fmt::format(
348  "{0}: Quantization offset for per-axis quantization expected to be 0 on tensor {1}, but got: {2}",
349  descName, tensorName, quantizationOffset));
350  }
351 }
352 
353 void ValidatePerAxisQuantization(const TensorInfo& inputInfo,
354  const TensorInfo& outputInfo,
355  const TensorInfo& weightInfo,
356  const Optional<TensorInfo>& optionalBiasInfo,
357  const std::string& descName)
358 {
359  if (weightInfo.HasPerAxisQuantization())
360  {
361  const DataType inputDataType = inputInfo.GetDataType();
362  const DataType outputDataType = outputInfo.GetDataType();
363 
364  const bool canHavePerAxisQuantization = (IsQuantized8BitType(inputDataType)) && inputDataType == outputDataType;
365 
366  if (!canHavePerAxisQuantization)
367  {
368  throw InvalidArgumentException(fmt::format(
369  "{0}: Per-axis quantization parameters set on tensor {1}, but data type does not support "
370  "per-axis quantization.", descName, "weight"));
371  }
372 
373 
374  ValidPerAxisQuantizedDataType(weightInfo, descName, "weight");
375  ValidatePerAxisQuantizationDimension(weightInfo, descName, "weight");
376  ValidatePerAxisQuantizationOffset(weightInfo, descName, "weight");
377 
378  if (optionalBiasInfo.has_value())
379  {
380  const TensorInfo& biasInfo = optionalBiasInfo.value();
381  if (!biasInfo.HasPerAxisQuantization())
382  {
383  throw InvalidArgumentException(fmt::format(
384  "{}: Per-axis quantization parameters not set on bias tensor, "
385  "despite being set on weight tensor.", descName));
386  }
387 
388  ValidateTensorDataType(biasInfo, DataType::Signed32, descName, "bias");
389  ValidatePerAxisQuantizationDimension(biasInfo, descName, "bias");
390  ValidatePerAxisQuantizationOffset(biasInfo, descName, "bias");
391  }
392  }
393 }
394 
395 } // anonymous namespace
396 
397 //---------------------------------------------------------------
399  std::string const& descName,
400  unsigned int numDimensions,
401  std::string const& tensorName) const
402 {
403  // If we're allowing expanded dimensions then numDimensions becomes the minimum number of Dimensions we can allow.
404  // Throw an Exception if the tensors has fewer than numDimensions or if the squeezed dimensions are greater than
405  // numDimensions.
407  {
408  unsigned int squeezedDims = 0;
409 
410  for (unsigned int i = 0; i < tensor.GetNumDimensions(); ++i)
411  {
412  if (tensor.GetShape()[i] != 1)
413  {
414  ++squeezedDims;
415  }
416  }
417  if (tensor.GetNumDimensions() < numDimensions || squeezedDims > numDimensions)
418  {
419  throw InvalidArgumentException(descName + ": Expected " + to_string(numDimensions) + " or less but got " +
420  to_string(tensor.GetNumDimensions()) + " dimensions for " +
421  tensorName + " tensor.");
422  }
423  }
424  else
425  {
426  if (tensor.GetNumDimensions() != numDimensions)
427  {
428  throw InvalidArgumentException(descName + ": Expected " + to_string(numDimensions) + " but got " +
429  to_string(tensor.GetNumDimensions()) + " dimensions for " +
430  tensorName + " tensor.");
431  }
432  }
433 }
434 
435 //---------------------------------------------------------------
437  unsigned int numDimension,
438  unsigned int numElements,
439  std::string const& tensorName) const
440 {
441  const std::string functionName{"ValidateTensorNumDimNumElem"};
442  ValidateTensorNumDimensions(tensorInfo, functionName, numDimension, tensorName);
443  ValidateTensorNumElements(tensorInfo, functionName, numElements, tensorName);
444 }
445 
446 //---------------------------------------------------------------
447 void QueueDescriptor::ValidateInputsOutputs(const std::string& descName,
448  unsigned int numExpectedIn, unsigned int numExpectedOut) const
449 {
450  ValidateTensors(m_Inputs, numExpectedIn, descName, "input");
451  ValidateTensors(m_Outputs, numExpectedOut, descName, "output");
452 }
453 
454 //---------------------------------------------------------------
455 void MapQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
456 {
457  const std::string descriptorName{"MapQueueDescriptor"};
458 
459  ValidateNumInputs(workloadInfo, descriptorName, 1);
460  ValidateNumOutputs(workloadInfo, descriptorName, 0);
461 
462  for (unsigned int i = 0; i < m_Inputs.size(); ++i)
463  {
464  if (!m_Inputs[i])
465  {
467  fmt::format("{}: Invalid NULL input {}.", descriptorName, static_cast<int>(i)));
468  }
469  }
470 }
471 
472 //---------------------------------------------------------------
473 void UnmapQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
474 {
475  const std::string descriptorName{"UnmapQueueDescriptor"};
476 
477  ValidateNumInputs(workloadInfo, descriptorName, 1);
478  ValidateNumOutputs(workloadInfo, descriptorName, 0);
479 
480  for (unsigned int i = 0; i < m_Inputs.size(); ++i)
481  {
482  if (!m_Inputs[i])
483  {
485  fmt::format("{}: Invalid NULL input {}.", descriptorName, static_cast<int>(i)));
486  }
487  }
488 }
489 
490 //---------------------------------------------------------------
491 void MemCopyQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
492 {
493  const std::string descriptorName{"MemCopyQueueDescriptor"};
494 
495  ValidateNumInputs(workloadInfo, descriptorName, 1);
496  ValidateNumOutputs(workloadInfo, descriptorName , 1);
497 
498  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
499  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
500 
501  ValidateTensorNumElementsMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
502  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
503 
504  if (m_Inputs.size() != m_Outputs.size())
505  {
506  throw InvalidArgumentException(fmt::format(
507  "{0}: Number of inputs ({1}) does not match the number of outputs ({2}).",
508  descriptorName, m_Inputs.size(), m_Outputs.size()));
509  }
510 
511  for (unsigned int i = 0; i < m_Inputs.size(); ++i)
512  {
513  if (!m_Inputs[i])
514  {
515  throw InvalidArgumentException(fmt::format(
516  "{0}: Invalid NULL input {1}.", descriptorName, i));
517  }
518 
519  if (!m_Outputs[i])
520  {
521  throw InvalidArgumentException(fmt::format("{0}: Invalid NULL output {1}", descriptorName, i));
522  }
523  }
524 }
525 
526 //---------------------------------------------------------------
527 void MemImportQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
528 {
529  ValidateNumInputs(workloadInfo, "MemImportQueueDescriptor", 1);
530  ValidateNumOutputs(workloadInfo, "MemImportQueueDescriptor" , 1);
531 
532  if (workloadInfo.m_InputTensorInfos.size() != 1)
533  {
534  throw InvalidArgumentException(fmt::format("Number of input infos ({}) is not 1.",
535  workloadInfo.m_InputTensorInfos.size()));
536 
537  }
538 
539  if (workloadInfo.m_InputTensorInfos.size() != workloadInfo.m_OutputTensorInfos.size())
540  {
541  throw InvalidArgumentException(fmt::format(
542  "Number of input infos ({0}) does not match the number of output infos ({1})",
543  workloadInfo.m_InputTensorInfos.size(), workloadInfo.m_OutputTensorInfos.size()));
544  }
545 
546  for (std::size_t i = 0; i < workloadInfo.m_InputTensorInfos.size(); ++i)
547  {
548  if (workloadInfo.m_InputTensorInfos[i].GetNumElements() !=
549  workloadInfo.m_OutputTensorInfos[i].GetNumElements())
550  {
551  throw InvalidArgumentException(fmt::format(
552  "Number of elements for tensor input and output {} does not match", i ));
553  }
554  }
555 
556  if (m_Inputs.size() != 1)
557  {
558  throw InvalidArgumentException(fmt::format("Number of inputs ({}) is not 1.", m_Inputs.size()));
559  }
560 
561  if (m_Inputs.size() != m_Outputs.size())
562  {
563  throw InvalidArgumentException(fmt::format(
564  "Number of inputs ({0}) does not match the number of outputs ({1})",
565  m_Inputs.size(), m_Outputs.size()));
566  }
567 
568  for (unsigned int i = 0; i < m_Inputs.size(); ++i)
569  {
570  if (!m_Inputs[i])
571  {
572  throw InvalidArgumentException(fmt::format("Invalid null input {}", i));
573  }
574 
575  if (!m_Outputs[i])
576  {
577  throw InvalidArgumentException(fmt::format("Invalid null output {}", i));
578  }
579  }
580 }
581 
582 //---------------------------------------------------------------
583 void MemSyncQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
584 {
585  ValidateNumInputs(workloadInfo, "MemSyncQueueDescriptor", 1);
586 
587  if (m_Inputs.size() != 1)
588  {
589  throw InvalidArgumentException(fmt::format("Number of inputs ({}) is not 1.", m_Inputs.size()));
590  }
591 
592  if (m_Outputs.size() != 0)
593  {
594  throw InvalidArgumentException(fmt::format("Number of outputs ({}) is not 0.", m_Outputs.size()));
595  }
596 
597  if (!m_Inputs[0])
598  {
599  throw InvalidArgumentException(fmt::format("Invalid null input 0"));
600  }
601 }
602 
603 //---------------------------------------------------------------
604 void ActivationQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
605 {
606  const std::string descriptorName{"ActivationQueueDescriptor"};
607 
608  ValidateNumInputs(workloadInfo, descriptorName, 1);
609  ValidateNumOutputs(workloadInfo, descriptorName, 1);
610 
611  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
612  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
613 
614  std::vector<DataType> supportedTypes =
615  {
622  };
623 
624  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
625  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
626  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
627 }
628 
629 void ArgMinMaxQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
630 {
631  const std::string descriptorName{"ArgMinMaxQueueDescriptor"};
632 
633  ValidateNumInputs(workloadInfo, descriptorName, 1);
634  ValidateNumOutputs(workloadInfo, descriptorName, 1);
635 
636  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
637  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
638 
639  if (outputTensorInfo.GetDataType() != DataType::Signed32 &&
640  outputTensorInfo.GetDataType() != DataType::Signed64)
641  {
642  throw InvalidArgumentException(descriptorName + ": Output of ArgMinMax layer must be Int32 or Int64.");
643  }
644 
645  std::vector<DataType> supportedInputTypes =
646  {
655  };
656 
657  ValidateDataTypes(inputTensorInfo, supportedInputTypes, descriptorName);
658 
659  auto inputShape = inputTensorInfo.GetShape();
660  auto outputShape = outputTensorInfo.GetShape();
661 
662  auto inputNumDimensions = inputShape.GetNumDimensions();
663  auto unsignedAxis = armnnUtils::GetUnsignedAxis(inputNumDimensions, m_Parameters.m_Axis);
664 
665  const std::string outputShapeError{": Output tensor shape does not match shape inferred from input tensor."};
666 
667  // 1D input shape results in scalar output shape
668  if (inputShape.GetNumDimensions() == 1)
669  {
670  if (outputShape.GetNumDimensions() != 1 && outputShape[0] != 1)
671  {
672  throw InvalidArgumentException(descriptorName + outputShapeError);
673  }
674  }
675  else
676  {
677  for (unsigned int i = 0; i < unsignedAxis; ++i)
678  {
679  if (outputShape[i] != inputShape[i])
680  {
681  throw InvalidArgumentException(descriptorName + outputShapeError);
682  }
683  }
684 
685  for (auto i = unsignedAxis + 1; i < inputNumDimensions; ++i)
686  {
687  if (outputShape[i - 1] != inputShape[i])
688  {
689  throw InvalidArgumentException(descriptorName + outputShapeError);
690  }
691  }
692  }
693 }
694 
695 void CastQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
696 {
697  const std::string descriptorName{"CastQueueDescriptor"};
698 
699  ValidateNumInputs(workloadInfo, descriptorName, 1);
700  ValidateNumOutputs(workloadInfo, descriptorName, 1);
701 
702  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
703  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
704 
705  std::vector<DataType> supportedTypes =
706  {
717  };
718 
719  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
720  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
721 }
722 
723 void SoftmaxQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
724 {
725  const std::string descriptorName{"SoftmaxQueueDescriptor"};
726 
727  ValidateNumInputs(workloadInfo, descriptorName, 1);
728  ValidateNumOutputs(workloadInfo, descriptorName, 1);
729 
730  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
731  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
732 
733  std::vector<DataType> supportedTypes =
734  {
741  };
742 
743  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
744  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
745  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
746 }
747 
748 void SplitterQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
749 {
750  const std::string descriptorName{"SplitterQueueDescriptor"};
751 
752  ValidateNumInputs(workloadInfo, descriptorName, 1);
753 
754  // Check the supported data types
755  std::vector<DataType> supportedTypes =
756  {
765  };
766 
767  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
768  for (unsigned long i = 0ul; i < workloadInfo.m_OutputTensorInfos.size(); ++i)
769  {
770  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[i];
771  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
772 
773  const std::string outputName = "output_" + std::to_string(i);
774  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", outputName);
775  }
776 
777  if (workloadInfo.m_OutputTensorInfos.size() <= 0)
778  {
779  throw InvalidArgumentException(descriptorName + ": At least one output needs to be provided.");
780  }
781 
782  if (workloadInfo.m_OutputTensorInfos.size() != m_ViewOrigins.size())
783  {
785  descriptorName + ": Number of split windows "
786  "has to match number of workloadInfo.m_OutputTensorInfos. "
787  "Number of windows: " +
788  to_string(m_ViewOrigins.size()) +
789  ". Number of workloadInfo.m_OutputTensorInfos: " + to_string(workloadInfo.m_OutputTensorInfos.size()));
790  }
791 
792  //The dimensionality of all the windows has to match the dimensionality (not shape) of the input.
793  std::size_t inputDims = workloadInfo.m_InputTensorInfos[0].GetNumDimensions();
794  for(unsigned int w = 0; w < m_ViewOrigins.size(); ++w )
795  {
796  //Checks that the dimensionality of input is same as the split windows.
797  ViewOrigin const& e = m_ViewOrigins[w];
798  if (e.m_Origin.size() != inputDims)
799  {
800  throw InvalidArgumentException(descriptorName + ": Window origin have to "
801  "have the same dimensionality as the input tensor. "
802  "Window origin (index: " +
803  to_string(w) + ") has " + to_string(e.m_Origin.size()) +
804  " dimensions, the input "
805  "tensor has " +
806  to_string(inputDims) + " dimensions.");
807  }
808  for (unsigned int i = 0; i < e.m_Origin.size(); ++i)
809  {
810  if (e.m_Origin[i] + workloadInfo.m_OutputTensorInfos[w].GetShape()[i] >
811  workloadInfo.m_InputTensorInfos[0].GetShape()[i])
812  {
813  throw InvalidArgumentException(descriptorName + ": Window extent coordinates have to "
814  "be smaller or equal than the size of the input in that coord.");
815  }
816  }
817  }
818 }
819 
820 void ConcatQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
821 {
822  const std::string descriptorName{"ConcatQueueDescriptor"};
823 
824  ValidateNumOutputs(workloadInfo, descriptorName, 1);
825 
826  if (m_Inputs.size() <= 0)
827  {
828  throw InvalidArgumentException(descriptorName + ": At least one input needs to be provided.");
829  }
830  if (m_Outputs.size() <= 0)
831  {
832  throw InvalidArgumentException(descriptorName + ": At least one output needs to be provided.");
833  }
834 
835  if (workloadInfo.m_InputTensorInfos.size() <= 0)
836  {
837  throw InvalidArgumentException(descriptorName + ": At least one TensorInfo input needs to be provided.");
838  }
839  if (workloadInfo.m_OutputTensorInfos.size() <= 0)
840  {
841  throw InvalidArgumentException(descriptorName + ": At least one TensorInfo output needs to be provided.");
842  }
843 
844  if(m_Parameters.GetConcatAxis() > workloadInfo.m_InputTensorInfos[0].GetShape().GetNumDimensions())
845  {
846  throw InvalidArgumentException(descriptorName + ": Invalid concatenation axis provided.");
847  }
848 
849  if (workloadInfo.m_InputTensorInfos[0].GetShape().GetNumDimensions() - m_Parameters.GetConcatAxis() == 1)
850  {
851  return;
852  }
853 
854  if (workloadInfo.m_InputTensorInfos.size() != m_ViewOrigins.size())
855  {
857  descriptorName + ": Number of split windows "
858  "has to match number of workloadInfo.m_InputTensorInfos. "
859  "Number of windows: " +
860  to_string(m_ViewOrigins.size()) +
861  ". Number of workloadInfo.m_InputTensorInfos: " + to_string(workloadInfo.m_InputTensorInfos.size()));
862  }
863 
864  //The dimensionality of all the windows has to match the dimensionality (not shape) of the output.
865  std::size_t outputDims = workloadInfo.m_OutputTensorInfos[0].GetNumDimensions();
866  for(unsigned int w = 0; w < m_ViewOrigins.size(); ++w )
867  {
868  //Checks that the dimensionality of output is same as the split windows.
869  ViewOrigin const& e = m_ViewOrigins[w];
870  if (e.m_Origin.size() != outputDims)
871  {
872  throw InvalidArgumentException(descriptorName + ": Window origin have to "
873  "have the same dimensionality as the output tensor. "
874  "Window origin (index: " +
875  to_string(w) + ") has " + to_string(e.m_Origin.size()) +
876  " dimensions, the output "
877  "tensor has " +
878  to_string(outputDims) + " dimensions.");
879  }
880  //Checks that the merge windows are within the output tensor.
881  for (unsigned int i = 0; i < e.m_Origin.size(); ++i)
882  {
883  if (e.m_Origin[i] + workloadInfo.m_InputTensorInfos[w].GetShape()[i]
884  > workloadInfo.m_OutputTensorInfos[0].GetShape()[i])
885  {
886  throw InvalidArgumentException(descriptorName + ": Window extent coordinates have to "
887  "be smaller or equal than the size of the output in that coord.");
888  }
889  }
890  }
891 
892  // Check the supported data types
893  std::vector<DataType> supportedTypes =
894  {
903  };
904 
905  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
906  for (unsigned long i = 0ul; i < workloadInfo.m_InputTensorInfos.size(); ++i)
907  {
908  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[i];
909  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
910 
911  const std::string inputName = "input_" + std::to_string(i);
912  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, inputName, "output");
913  }
914 }
915 
916 void StackQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
917 {
918  const std::string descriptorName{"StackQueueDescriptor"};
919 
920  ValidateNumOutputs(workloadInfo, descriptorName, 1);
921 
922  if (m_Parameters.m_NumInputs != workloadInfo.m_InputTensorInfos.size())
923  {
924  throw InvalidArgumentException(descriptorName + ": Must have the defined number of input tensors.");
925  }
926 
927  // All inputs must have the same shape, which is defined in parameters
928  const TensorShape& inputShape = m_Parameters.m_InputShape;
929  for (unsigned int i = 0; i < workloadInfo.m_InputTensorInfos.size(); ++i)
930  {
931  if (workloadInfo.m_InputTensorInfos[i].GetShape() != inputShape)
932  {
933  throw InvalidArgumentException(descriptorName + ": All input tensor shapes must match the defined shape.");
934  }
935  }
936 
937  if (inputShape.GetNumDimensions() > 4)
938  {
939  throw InvalidArgumentException(descriptorName + ": Input tensor may have up to 4 dimensions.");
940  }
941 
942  // m_Axis is 0-based and may take values from 0 to the number of input dimensions (inclusive),
943  // since the output tensor has an additional dimension.
944  if (m_Parameters.m_Axis > inputShape.GetNumDimensions())
945  {
946  throw InvalidArgumentException(descriptorName + ": Axis may not be greater "
947  "than the number of input dimensions.");
948  }
949 
950  // Output shape must be as inferred from the input shape
951  const TensorShape& outputShape = workloadInfo.m_OutputTensorInfos[0].GetShape();
952  for (unsigned int i = 0; i < m_Parameters.m_Axis; ++i)
953  {
954  if (outputShape[i] != inputShape[i])
955  {
956  throw InvalidArgumentException(descriptorName + ": Output tensor must "
957  "match shape inferred from input tensor.");
958  }
959  }
960 
961  if (outputShape[m_Parameters.m_Axis] != m_Parameters.m_NumInputs)
962  {
963  throw InvalidArgumentException(descriptorName + ": Output tensor must "
964  "match shape inferred from input tensor.");
965  }
966 
967  for (unsigned int i = m_Parameters.m_Axis + 1; i < inputShape.GetNumDimensions() + 1; ++i)
968  {
969  if (outputShape[i] != inputShape[i-1])
970  {
971  throw InvalidArgumentException(descriptorName + ": Output tensor must "
972  "match shape inferred from input tensor.");
973  }
974  }
975 
976  if (outputShape.GetNumDimensions() > 5)
977  {
978  throw InvalidArgumentException(descriptorName + ": Output tensor may have up to 5 dimensions.");
979  }
980 
981  // Check the supported data types
982  std::vector<DataType> supportedTypes =
983  {
992  };
993 
994  ValidateDataTypes(workloadInfo.m_InputTensorInfos[0], supportedTypes, descriptorName);
995 
996  for (unsigned int i = 1ul; i < workloadInfo.m_InputTensorInfos.size(); ++i)
997  {
998  ValidateTensorDataTypesMatch(workloadInfo.m_InputTensorInfos[0],
999  workloadInfo.m_InputTensorInfos[i],
1000  descriptorName,
1001  "input_0",
1002  "input_" + std::to_string(i));
1003  }
1004 
1005  ValidateTensorDataTypesMatch(workloadInfo.m_InputTensorInfos[0],
1006  workloadInfo.m_OutputTensorInfos[0],
1007  descriptorName,
1008  "input_0",
1009  "output");
1010 }
1011 
1012 void FillQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1013 {
1014  const std::string descriptorName{"FillQueueDescriptor"};
1015 
1016  ValidateNumInputs(workloadInfo, descriptorName, 1);
1017  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1018 
1019  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1020  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1021 
1022  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 1, "input");
1023 
1024  std::vector<DataType> supportedTypes =
1025  {
1030  };
1031 
1032  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1033 }
1034 
1036 {
1037  const std::string descriptorName{"FullyConnectedQueueDescriptor"};
1038 
1039  uint32_t numInputs = 2;
1041  {
1042  numInputs = 3;
1043  }
1044 
1045  ValidateNumInputs(workloadInfo, descriptorName, numInputs);
1046  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1047 
1048  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1049  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1050 
1051  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 2, "output");
1052 
1053  if (!(inputTensorInfo.GetNumDimensions() == 2 || inputTensorInfo.GetNumDimensions() == 4))
1054  {
1055  throw InvalidArgumentException(descriptorName + ": Input tensor must have 2 or 4 dimensions.");
1056  }
1057 
1058  TensorInfo weightTensorInfo = workloadInfo.m_InputTensorInfos[1];
1059  ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 2, "weight");
1060 
1062  {
1063  TensorInfo biasTensorInfo = workloadInfo.m_InputTensorInfos[2];
1064  // Validates type and quantization values.
1065  ValidateBiasTensorQuantization(biasTensorInfo, weightTensorInfo, descriptorName);
1066  ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
1067  ValidateTensorNumDimensions(biasTensorInfo, descriptorName, 1, "bias");
1068  }
1069 
1070  // Check the supported data types
1071  std::vector<DataType> supportedTypes =
1072  {
1080  };
1081 
1082  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1083 
1084  // For FullyConnected, we allow to have BFloat16 input with Float32 output for optimization.
1085  if (inputTensorInfo.GetDataType() == DataType::BFloat16)
1086  {
1087  if (outputTensorInfo.GetDataType() != DataType::BFloat16 && outputTensorInfo.GetDataType() != DataType::Float32)
1088  {
1089  throw InvalidArgumentException(descriptorName + ": " + " Output tensor type must be BFloat16 or Float32 "
1090  "for BFloat16 input.");
1091  }
1092  }
1093  else
1094  {
1095  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1096  }
1097 }
1098 
1099 void FusedQueueDescriptor::Validate(const WorkloadInfo& /*workloadInfo*/) const
1100 {
1101  // This is internally generated, so it should not need validation.
1102 }
1103 
1105 {
1106  const std::string descriptorName{"NormalizationQueueDescriptor"};
1107 
1108  ValidateNumInputs(workloadInfo, descriptorName, 1);
1109  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1110 
1111  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1112  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1113 
1114  // Check the supported data types
1115  std::vector<DataType> supportedTypes =
1116  {
1123  };
1124 
1125  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1126 
1127  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1128 
1129  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1130 }
1131 
1132 void AdditionQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1133 {
1134  const std::string descriptorName{"AdditionQueueDescriptor"};
1135 
1136  ValidateNumInputs(workloadInfo, descriptorName, 2);
1137  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1138 
1139  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
1140  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
1141  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1142 
1143  std::vector<DataType> supportedTypes =
1144  {
1152  };
1153 
1154  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
1155  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
1156  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1157 
1158  ValidateTensorDataTypesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
1159  ValidateTensorDataTypesMatch(inputTensorInfo1, outputTensorInfo, descriptorName, "input_1", "output");
1160 
1161  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
1162  inputTensorInfo1,
1163  outputTensorInfo,
1164  descriptorName,
1165  "input_0",
1166  "input_1");
1167 }
1168 
1170 {
1171  const std::string descriptorName{"MultiplicationQueueDescriptor"};
1172 
1173  ValidateNumInputs(workloadInfo, descriptorName, 2);
1174  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1175 
1176  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
1177  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
1178  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1179 
1180  std::vector<DataType> supportedTypes =
1181  {
1189  };
1190 
1191  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
1192  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
1193  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1194 
1195  ValidateTensorDataTypesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
1196  ValidateTensorDataTypesMatch(inputTensorInfo1, outputTensorInfo, descriptorName, "input_1", "output");
1197 
1198  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
1199  inputTensorInfo1,
1200  outputTensorInfo,
1201  descriptorName,
1202  "input_0",
1203  "input_1");
1204 }
1205 
1207 {
1208  const std::string descriptorName{"BatchNormalizationQueueDescriptor"};
1209 
1210  ValidateNumInputs(workloadInfo, descriptorName, 1);
1211  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1212 
1213  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1214  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1215 
1216  std::vector<DataType> supportedTypes =
1217  {
1224  };
1225 
1226  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1227  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1228 
1229  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1230  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1231 
1232  ValidatePointer(m_Mean, descriptorName, "mean");
1233  ValidatePointer(m_Variance, descriptorName, "variance");
1234  ValidatePointer(m_Beta, descriptorName, "beta");
1235  ValidatePointer(m_Gamma, descriptorName, "gamma");
1236 
1237  const TensorInfo& mean = m_Mean->GetTensorInfo();
1238  const TensorInfo& variance = m_Variance->GetTensorInfo();
1239  const TensorInfo& beta = m_Beta->GetTensorInfo();
1240  const TensorInfo& gamma = m_Gamma->GetTensorInfo();
1241 
1242  ValidateTensorNumDimensions(mean, descriptorName, 1, "mean");
1243  ValidateTensorNumDimensions(variance, descriptorName, 1, "variance");
1244  ValidateTensorNumDimensions(beta, descriptorName, 1, "beta");
1245  ValidateTensorNumDimensions(gamma, descriptorName, 1, "gamma");
1246 
1247  ValidateTensorShapesMatch(mean, variance, descriptorName, "mean", "variance");
1248  ValidateTensorShapesMatch(mean, beta, descriptorName, "mean", "beta");
1249  ValidateTensorShapesMatch(mean, gamma, descriptorName, "mean", "gamma");
1250 }
1251 
1253 {
1254  const std::string descriptorName{"Convolution2dQueueDescriptor"};
1255 
1256  uint32_t numInputs = 2;
1258  {
1259  numInputs = 3;
1260  }
1261 
1262  ValidateNumInputs(workloadInfo, descriptorName, numInputs);
1263  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1264 
1265  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1266  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1267 
1268  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1269  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1270 
1271  const TensorInfo& weightTensorInfo = workloadInfo.m_InputTensorInfos[1];
1272 
1273  ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 4, "weight");
1274 
1275  ValidateWeightDataType(inputTensorInfo, weightTensorInfo, descriptorName);
1276 
1277  Optional<TensorInfo> optionalBiasTensorInfo;
1279  {
1280  optionalBiasTensorInfo = MakeOptional<TensorInfo>(workloadInfo.m_InputTensorInfos[2]);
1281  const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value();
1282 
1283  ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
1284  ValidateBiasTensorQuantization(biasTensorInfo, weightTensorInfo, descriptorName);
1285  }
1286 
1287  if (m_Parameters.m_StrideX <= 0 || m_Parameters.m_StrideY <= 0 )
1288  {
1290  fmt::format("{}: strideX (provided {}) and strideY (provided {}) "
1291  "cannot be either negative or 0.",
1292  descriptorName, m_Parameters.m_StrideX, m_Parameters.m_StrideY));
1293  }
1294 
1295  ValidatePerAxisQuantization(inputTensorInfo,
1296  outputTensorInfo,
1297  weightTensorInfo,
1298  optionalBiasTensorInfo,
1299  descriptorName);
1300 
1301  std::vector<DataType> supportedTypes =
1302  {
1310  };
1311 
1312  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1313 
1314  // For Convolution2d, we allow to have BFloat16 input with Float32 output for optimization.
1315  if (inputTensorInfo.GetDataType() == DataType::BFloat16)
1316  {
1317  if (outputTensorInfo.GetDataType() != DataType::BFloat16 && outputTensorInfo.GetDataType() != DataType::Float32)
1318  {
1319  throw InvalidArgumentException(descriptorName + ": " + " Output tensor type must be BFloat16 or Float32 "
1320  "for BFloat16 input.");
1321  }
1322  }
1323  else
1324  {
1325  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1326  }
1327 }
1328 
1330 {
1331  const std::string descriptorName{"Convolution3dQueueDescriptor"};
1332 
1333  uint32_t numInputs = 2;
1335  {
1336  numInputs = 3;
1337  }
1338  ValidateNumInputs(workloadInfo, descriptorName, numInputs);
1339  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1340 
1341  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1342  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1343 
1344  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 5, "input");
1345  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 5, "output");
1346 
1347  const TensorInfo& weightTensorInfo = workloadInfo.m_InputTensorInfos[1];
1348  ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 5, "weight");
1349 
1350  ValidateWeightDataType(inputTensorInfo, weightTensorInfo, descriptorName);
1351 
1352  Optional<TensorInfo> optionalBiasTensorInfo;
1354  {
1355  optionalBiasTensorInfo = MakeOptional<TensorInfo>(workloadInfo.m_InputTensorInfos[2]);
1356  const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value();
1357 
1358  ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
1359  ValidateBiasTensorQuantization(biasTensorInfo, weightTensorInfo, descriptorName);
1360  }
1361 
1363  {
1365  fmt::format("{}: strideX (provided {}), strideY (provided {}) or strideZ (provided {})"
1366  "cannot be either negative or 0.",
1368  }
1369 
1370  ValidatePerAxisQuantization(inputTensorInfo,
1371  outputTensorInfo,
1372  weightTensorInfo,
1373  optionalBiasTensorInfo,
1374  descriptorName);
1375 
1376  std::vector<DataType> supportedTypes =
1377  {
1385  };
1386 
1387  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1388  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1389 }
1390 
1392 {
1393  const std::string descriptorName{"DepthwiseConvolution2dQueueDescriptor"};
1394 
1395  uint32_t numInputs = 2;
1397  {
1398  numInputs = 3;
1399  }
1400 
1401  ValidateNumInputs(workloadInfo, descriptorName, numInputs);
1402  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1403 
1404  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1405  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1406 
1407  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1408  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1409 
1410  const TensorInfo& weightTensorInfo = workloadInfo.m_InputTensorInfos[1];
1411  ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 4, "weight");
1412 
1414  {
1416  fmt::format("{}: dilationX (provided {}) and dilationY (provided {}) "
1417  "cannot be smaller than 1.",
1418  descriptorName, m_Parameters.m_DilationX, m_Parameters.m_DilationX));
1419  }
1420 
1421  if (m_Parameters.m_StrideX <= 0 || m_Parameters.m_StrideY <= 0 )
1422  {
1424  fmt::format("{}: strideX (provided {}) and strideY (provided {}) "
1425  "cannot be either negative or 0.",
1426  descriptorName, m_Parameters.m_StrideX, m_Parameters.m_StrideY));
1427  }
1428 
1429  if (weightTensorInfo.GetShape()[0] != 1)
1430  {
1431  throw InvalidArgumentException(fmt::format(
1432  "{0}: The weight format in armnn is expected to be [1, H, W, Cout]."
1433  "But first dimension is not equal to 1. Provided weight shape: [{1}, {2}, {3}, {4}]",
1434  descriptorName,
1435  weightTensorInfo.GetShape()[0],
1436  weightTensorInfo.GetShape()[1],
1437  weightTensorInfo.GetShape()[2],
1438  weightTensorInfo.GetShape()[3]));
1439  }
1440 
1441  const unsigned int channelIndex = (m_Parameters.m_DataLayout == DataLayout::NCHW) ? 1 : 3;
1442  const unsigned int numWeightOutputChannelsRefFormat = weightTensorInfo.GetShape()[3];
1443  const unsigned int numWeightOutputChannelsAclFormat = weightTensorInfo.GetShape()[1];
1444  const unsigned int numOutputChannels = outputTensorInfo.GetShape()[channelIndex];
1445 
1446  // Weights format has two valid options: [1, H, W, Cout] (CpuRef) or [1, Cout, H, W] (CpuAcc/GpuAcc).
1447  bool validRefFormat = (numWeightOutputChannelsRefFormat == numOutputChannels);
1448  bool validAclFormat = (numWeightOutputChannelsAclFormat == numOutputChannels);
1449 
1450  if (!(validRefFormat || validAclFormat))
1451  {
1452  throw InvalidArgumentException(fmt::format(
1453  "{0}: The weight format in armnn is expected to be [1, H, W, Cout] (CpuRef) or [1, Cout, H, W] "
1454  "(CpuAcc/GpuAcc). But neither the 4th (CpuRef) or 2nd (CpuAcc/GpuAcc) dimension is equal to Cout."
1455  "Cout = {1} Provided weight shape: [{2}, {3}, {4}, {5}]",
1456  descriptorName,
1457  numOutputChannels,
1458  weightTensorInfo.GetShape()[0],
1459  weightTensorInfo.GetShape()[1],
1460  weightTensorInfo.GetShape()[2],
1461  weightTensorInfo.GetShape()[3]));
1462  }
1463 
1464  ValidateWeightDataType(inputTensorInfo, weightTensorInfo, descriptorName);
1465 
1466  Optional<TensorInfo> optionalBiasTensorInfo;
1468  {
1469  optionalBiasTensorInfo = MakeOptional<TensorInfo>(workloadInfo.m_InputTensorInfos[2]);
1470  const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value();
1471 
1472  ValidateBiasTensorQuantization(biasTensorInfo, weightTensorInfo, descriptorName);
1473  ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
1474  }
1475  ValidatePerAxisQuantization(inputTensorInfo,
1476  outputTensorInfo,
1477  weightTensorInfo,
1478  optionalBiasTensorInfo,
1479  descriptorName);
1480 
1481  std::vector<DataType> supportedTypes =
1482  {
1489  };
1490 
1491  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1492  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1493 }
1494 
1495 void PermuteQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1496 {
1497  const std::string descriptorName{"PermuteQueueDescriptor"};
1498 
1499  ValidateNumInputs(workloadInfo, descriptorName, 1);
1500  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1501 
1502  const PermutationVector& mapping = m_Parameters.m_DimMappings;
1503 
1504  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1505  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1506 
1507  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, mapping.GetSize(), "input");
1508  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, mapping.GetSize(), "output");
1509 
1510  for (unsigned int i = 0u; i < mapping.GetSize(); ++i)
1511  {
1512  if (inputTensorInfo.GetShape()[i] != outputTensorInfo.GetShape()[mapping[i]])
1513  {
1514  throw InvalidArgumentException(descriptorName + ": src dimension " + to_string(i) +
1515  " (=" + to_string(inputTensorInfo.GetShape()[i]) + ") " +
1516  "must match dst dimension " + to_string(mapping[i]) +
1517  " (=" + to_string(outputTensorInfo.GetShape()[mapping[i]]) + ")");
1518  }
1519  }
1520 
1521  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1522 }
1523 
1524 void Pooling2dQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1525 {
1526  const std::string descriptorName{"Pooling2dQueueDescriptor"};
1527 
1528  ValidateNumInputs(workloadInfo, descriptorName, 1);
1529  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1530 
1531  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1532  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1533 
1534  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1535  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1536 
1537  std::vector<DataType> supportedTypes =
1538  {
1545  };
1546 
1547  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1548  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1549 }
1550 
1551 void Pooling3dQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1552 {
1553  const std::string descriptorName{"Pooling3dQueueDescriptor"};
1554 
1555  ValidateNumInputs(workloadInfo, descriptorName, 1);
1556  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1557 
1558  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1559  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1560 
1561  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 5, "input");
1562  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 5, "output");
1563 
1564  std::vector<DataType> supportedTypes =
1565  {
1572  };
1573 
1574  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1575  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1576 }
1577 
1578 void ResizeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1579 {
1580  const std::string descriptorName{"ResizeQueueDescriptor"};
1581 
1582  ValidateNumInputs(workloadInfo, descriptorName, 1);
1583  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1584 
1585  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1586  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1587 
1588  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1589  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1590 
1591  std::vector<DataType> supportedTypes =
1592  {
1600  };
1601 
1602  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1603  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1604 
1605  // Resize only changes width and height: batch and channel count must match.
1606  const unsigned int inputBatchSize = inputTensorInfo.GetShape()[0];
1607  const unsigned int outputBatchSize = outputTensorInfo.GetShape()[0];
1608  if (inputBatchSize != outputBatchSize)
1609  {
1611  fmt::format("{}: Input batch size ({}) does not match output batch size ({})",
1612  descriptorName, inputBatchSize, outputBatchSize));
1613  }
1614 
1615  DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
1616  const unsigned int inputChannelCount = inputTensorInfo.GetShape()[dimensionIndices.GetChannelsIndex()];
1617  const unsigned int outputChannelCount = outputTensorInfo.GetShape()[dimensionIndices.GetChannelsIndex()];
1618  if (inputChannelCount != outputChannelCount)
1619  {
1621  fmt::format("{}: Input channel count ({}) does not match output channel count ({})",
1622  descriptorName, inputChannelCount, outputChannelCount));
1623  }
1624 }
1625 
1626 void ReverseV2QueueDescriptor::Validate(const WorkloadInfo &workloadInfo) const
1627 {
1628  const std::string descriptorName{"ReverseV2QueueDescriptor"};
1629 
1630  // Backend restriction
1631  const unsigned int maxDimensions = 4;
1632 
1633  ValidateNumInputs(workloadInfo, descriptorName, 2);
1634  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1635 
1636  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1637  const TensorInfo& axisTensorInfo = workloadInfo.m_InputTensorInfos[1];
1638  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1639 
1640  const auto inputTensorNumDimensions = inputTensorInfo.GetNumDimensions();
1641  if (inputTensorNumDimensions > maxDimensions)
1642  {
1643  throw InvalidArgumentException(descriptorName +
1644  ": Input tensors with rank greater than " +
1645  std::to_string(maxDimensions) + " are not supported.");
1646  }
1647 
1648  const auto axisTensorNumDimensions = axisTensorInfo.GetNumDimensions();
1649  if (axisTensorNumDimensions > maxDimensions)
1650  {
1651  throw InvalidArgumentException(descriptorName +
1652  ": More than " + std::to_string(maxDimensions) + " axes cannot be specified.");
1653  }
1654 
1655  if (axisTensorNumDimensions > inputTensorNumDimensions)
1656  {
1657  throw InvalidArgumentException(descriptorName +
1658  ": More axes specified than the number of axes on the input tensor.");
1659  }
1660 
1661  std::vector<DataType> supportedTypes =
1662  {
1671  };
1672 
1673  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1674 
1675  std::vector<DataType> axisSupportedTypes =
1676  {
1678  };
1679 
1680  ValidateDataTypes(axisTensorInfo, axisSupportedTypes, descriptorName);
1681 
1682  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1683  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1684 }
1685 
1687 {
1688  const std::string descriptorName{"FakeQuantizationQueueDescriptor"};
1689 
1690  ValidateNumInputs(workloadInfo, descriptorName, 1);
1691  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1692 
1693  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1694  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1695 
1696  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 2, "input");
1697  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 2, "output");
1698 
1699  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1700 
1702  {
1703  throw InvalidArgumentException(descriptorName + ": min cannot be greater than max");
1704  }
1705 }
1706 
1708 {
1709  const std::string descriptorName{"InstanceNormalizationQueueDescriptor"};
1710 
1711  ValidateNumInputs(workloadInfo, descriptorName, 1);
1712  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1713 
1714  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1715  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1716 
1717  if (inputTensorInfo.GetNumDimensions() > 4)
1718  {
1719  throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
1720  }
1721 
1722  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1723 
1724  // Check the supported data types
1725  std::vector<DataType> supportedTypes =
1726  {
1730  };
1731 
1732  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1733  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1734 }
1735 
1737 {
1738  const std::string descriptorName{"L2NormalizationQueueDescriptor"};
1739 
1740  ValidateNumInputs(workloadInfo, descriptorName, 1);
1741  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1742 
1743  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1744  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1745 
1746  if (inputTensorInfo.GetNumDimensions() > 4)
1747  {
1748  throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
1749  }
1750 
1751  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1752 
1753  // Check the supported data types
1754  std::vector<DataType> supportedTypes =
1755  {
1762  };
1763 
1764  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1765  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1766 }
1767 
1768 void LogSoftmaxQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1769 {
1770  const std::string descriptorName{"LogSoftmaxQueueDescriptor"};
1771 
1772  ValidateNumInputs(workloadInfo, descriptorName, 1);
1773  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1774 
1775  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1776  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1777 
1778  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1779 
1780  std::vector<DataType> supportedTypes =
1781  {
1785  };
1786 
1787  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1788  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1789 }
1790 
1791 void ConstantQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1792 {
1793  const std::string descriptorName{"ConstantQueueDescriptor"};
1794 
1795  ValidateNumInputs(workloadInfo, descriptorName, 0);
1796  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1797 
1798  if (!m_LayerOutput)
1799  {
1800  throw InvalidArgumentException(descriptorName + ": No const input specified.");
1801  }
1802 
1803  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1804  ValidateTensorShapesMatch(m_LayerOutput->GetTensorInfo(), outputTensorInfo, descriptorName, "constant", "output");
1805 
1806  // Check the supported data types
1807  std::vector<DataType> supportedTypes =
1808  {
1817  };
1818 
1819  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1820 }
1821 
1822 void ReshapeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1823 {
1824  const std::string descriptorName{"ReshapeQueueDescriptor"};
1825 
1826  ValidateNumInputs(workloadInfo, descriptorName, 1);
1827  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1828 
1829  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1830  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1831 
1832  ValidateTensorNumElementsMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1833 
1834  // Check the supported data types
1835  std::vector<DataType> supportedTypes =
1836  {
1845  };
1846 
1847  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1848  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1849 }
1850 
1852 {
1853  const std::string descriptorName{"SpaceToBatchNdQueueDescriptor"};
1854 
1855  ValidateNumInputs(workloadInfo, descriptorName, 1);
1856  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1857 
1858  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1859  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1860 
1861  if (m_Parameters.m_BlockShape.size() != m_Parameters.m_PadList.size())
1862  {
1863  throw InvalidArgumentException(descriptorName + ": Pad List must contain the same number of "
1864  "dimensions as Block Shape.");
1865  }
1866 
1867  if (m_Parameters.m_BlockShape.size() == 2)
1868  {
1869  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1870  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1871  }
1872  else if (m_Parameters.m_BlockShape.size() == 1)
1873  {
1874  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 3, "input");
1875  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 3, "output");
1876  }
1877  else
1878  {
1879  throw InvalidArgumentException(descriptorName + ": Invalid Block and Crops size.");
1880  }
1881 
1882  // Check input + padding and output have the same number of elements
1883  DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
1884  const unsigned int inputHeight = inputTensorInfo.GetShape()[dimensionIndices.GetHeightIndex()] +
1885  m_Parameters.m_PadList[0].first + m_Parameters.m_PadList[0].second;
1886  const unsigned int inputWidth = (inputTensorInfo.GetNumDimensions() == 3) ? 1 :
1887  inputTensorInfo.GetShape()[dimensionIndices.GetWidthIndex()] +
1888  m_Parameters.m_PadList[1].first + m_Parameters.m_PadList[1].second;
1889 
1890  const int channelsIndex_int = (m_Parameters.m_DataLayout == DataLayout::NCHW) ? 1 : -1;
1891  const unsigned int channelsIndex = channelsIndex_int < 0 ?
1892  static_cast<unsigned int>(channelsIndex_int) + inputTensorInfo.GetNumDimensions()
1893  : static_cast<unsigned int>(channelsIndex_int);
1894 
1895  const unsigned int numInputElements = inputTensorInfo.GetShape()[0] *
1896  inputHeight *
1897  inputWidth *
1898  inputTensorInfo.GetShape()[channelsIndex];
1899 
1900  if (outputTensorInfo.GetNumElements() != numInputElements)
1901  {
1902  throw InvalidArgumentException(descriptorName + ": Input tensor has " +
1903  to_string(numInputElements) + " after padding but output tensor has " +
1904  to_string(outputTensorInfo.GetNumElements()) + " elements.");
1905  }
1906 
1907  // In a 4D tensor, there will be 2 spatialDimensions (H and W), and the for loop will run twice.
1908  // In a 3D tensor, there will be 1 spatialDimensions, and the for loop will run once.
1909  unsigned int firstSpatialDimension = m_Parameters.m_DataLayout == DataLayout::NCHW ? 2 : 1;
1910  for (unsigned int i = 0; i < m_Parameters.m_BlockShape.size(); ++i)
1911  {
1912  unsigned int spatialDimension = firstSpatialDimension + i;
1913  auto inputSize = inputTensorInfo.GetShape()[spatialDimension] +
1914  m_Parameters.m_PadList[i].first +
1915  m_Parameters.m_PadList[i].second;
1916  if (inputSize % m_Parameters.m_BlockShape[i] != 0)
1917  {
1918  throw InvalidArgumentException(descriptorName + ": Input dimension size after padding must be "
1919  "divisible by Block Shape in dimension: " + to_string(spatialDimension) + ".");
1920  }
1921  }
1922 
1923  std::vector<DataType> supportedTypes =
1924  {
1931  };
1932 
1933  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1934  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1935 }
1936 
1938 {
1939  const std::string descriptorName{"SpaceToDepthQueueDescriptor"};
1940 
1941  ValidateNumInputs(workloadInfo, descriptorName, 1);
1942  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1943 
1944  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1945  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1946 
1947  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1948  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1949 
1950  std::vector<DataType> supportedTypes =
1951  {
1958  };
1959 
1960  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1961  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1962 
1963  ValidateTensorNumElementsMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1964 
1965  if (m_Parameters.m_BlockSize == 0)
1966  {
1967  throw InvalidArgumentException(descriptorName + ": Block size cannot be 0.");
1968  }
1969 
1970  DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
1971  const unsigned int wIndex = dimensionIndices.GetWidthIndex();
1972  const unsigned int hIndex = dimensionIndices.GetHeightIndex();
1973  const unsigned int cIndex = dimensionIndices.GetChannelsIndex();
1974 
1975  const TensorShape& inputShape = inputTensorInfo.GetShape();
1976  if (inputShape[hIndex] % m_Parameters.m_BlockSize != 0 || inputShape[wIndex] % m_Parameters.m_BlockSize != 0)
1977  {
1978  throw InvalidArgumentException(descriptorName + ": Input shape must be divisible "
1979  "by block size in all spatial dimensions");
1980  }
1981 
1982  const TensorShape& outputShape = outputTensorInfo.GetShape();
1983  if (outputShape[cIndex] % (m_Parameters.m_BlockSize * m_Parameters.m_BlockSize) != 0)
1984  {
1985  throw InvalidArgumentException(descriptorName + ": The depth of the output tensor"
1986  "must be divisible by the square of block size." );
1987  }
1988 }
1989 
1990 void FloorQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1991 {
1992  const std::string descriptorName{"FloorQueueDescriptor"};
1993 
1994  ValidateNumInputs(workloadInfo, descriptorName, 1);
1995  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1996 
1997  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1998  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1999 
2000  std::vector<DataType> supportedTypes =
2001  {
2006  };
2007 
2008  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2009  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2010  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2011  ValidateTensorQuantizationSpace(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2012 }
2013 
2014 void LstmQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2015 {
2016  // ported from android/ml/nn/common/operations/LSTM.cpp CheckInputTensorDimensions()
2017 
2018  const std::string descriptorName{"LstmQueueDescriptor"};
2019 
2020  // check dimensions of all inputs and outputs
2021  if (workloadInfo.m_InputTensorInfos.size() != 3)
2022  {
2023  throw InvalidArgumentException(descriptorName + ": Invalid number of inputs.");
2024  }
2025  if (workloadInfo.m_OutputTensorInfos.size() != 4)
2026  {
2027  throw InvalidArgumentException(descriptorName + ": Invalid number of outputs.");
2028  }
2029 
2030  std::vector<DataType> supportedTypes =
2031  {
2036  };
2037 
2038  // check for supported type of one input and match them with all the other input and output
2039  ValidateDataTypes(workloadInfo.m_InputTensorInfos[0], supportedTypes, descriptorName);
2040 
2041  // type matches all other inputs
2042  for (uint32_t i = 1u; i < workloadInfo.m_InputTensorInfos.size(); ++i)
2043  {
2044  ValidateTensorDataTypesMatch(workloadInfo.m_InputTensorInfos[0],
2045  workloadInfo.m_InputTensorInfos[i],
2046  descriptorName,
2047  "input_0",
2048  "input_" + std::to_string(i));
2049  }
2050  // type matches all other outputs
2051  for (uint32_t i = 0u; i < workloadInfo.m_OutputTensorInfos.size(); ++i)
2052  {
2053  ValidateTensorDataTypesMatch(workloadInfo.m_InputTensorInfos[0],
2054  workloadInfo.m_OutputTensorInfos[i],
2055  "LstmQueueDescriptor",
2056  "input_0",
2057  "output_" + std::to_string(i));
2058  }
2059 
2060  // Making sure clipping parameters have valid values.
2061  // == 0 means no clipping
2062  // > 0 means clipping
2063  if (m_Parameters.m_ClippingThresCell < 0.0f)
2064  {
2065  throw InvalidArgumentException(descriptorName + ": negative cell clipping threshold is invalid");
2066  }
2067  if (m_Parameters.m_ClippingThresProj < 0.0f)
2068  {
2069  throw InvalidArgumentException(descriptorName + ": negative projection clipping threshold is invalid");
2070  }
2071 
2072  // Inferring batch size, number of outputs and number of cells from the inputs.
2073  const uint32_t n_input = workloadInfo.m_InputTensorInfos[0].GetShape()[1];
2074  const uint32_t n_batch = workloadInfo.m_InputTensorInfos[0].GetShape()[0];
2075  ValidatePointer(m_InputToOutputWeights, "Null pointer check", "InputToOutputWeights");
2076  const uint32_t n_cell = m_InputToOutputWeights->GetShape()[0];
2077  ValidatePointer(m_RecurrentToOutputWeights, "Null pointer check", "RecurrentToOutputWeights");
2078  const uint32_t n_output = m_RecurrentToOutputWeights->GetShape()[1];
2079 
2080  // input tensor
2081  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[0], 2, (n_batch * n_input),
2082  descriptorName + " input_0");
2083  // outputStateInTensor
2084  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[1], 2, (n_batch * n_output),
2085  descriptorName + " input_1");
2086  // outputStateInTensor
2087  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[2], 2, (n_batch * n_cell),
2088  descriptorName + " input_2");
2089  // scratchBufferTensor
2090  unsigned int scratchBufferSize = m_Parameters.m_CifgEnabled ? n_cell * 3 : n_cell * 4;
2091  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[0], 2, (n_batch * scratchBufferSize),
2092  descriptorName + " output_0");
2093  // outputStateOutTensor
2094  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[1], 2, (n_batch * n_output),
2095  descriptorName + " output_1");
2096  // cellStateOutTensor
2097  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[2], 2, (n_batch * n_cell),
2098  descriptorName + " output_2");
2099  // outputTensor
2100  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[3], 2, (n_batch * n_output),
2101  descriptorName + " output_3");
2102 
2103  // check that dimensions of inputs/outputs and QueueDescriptor data match with each other
2104  if ( m_InputToInputWeights )
2105  {
2107  (n_cell * n_input), "InputLayerNormWeights");
2108  }
2109 
2110  ValidatePointer(m_InputToForgetWeights, "Null pointer check", "InputToForgetWeights");
2112  (n_cell * n_input), "InputToForgetWeights");
2113 
2114  ValidatePointer(m_InputToCellWeights, "Null pointer check", "InputToCellWeights");
2116  (n_cell * n_input), "InputToCellWeights");
2117 
2119  {
2121  (n_cell * n_output), "RecurrentToInputWeights");
2122  }
2123 
2124  ValidatePointer(m_RecurrentToForgetWeights, "Null pointer check", "RecurrentToForgetWeights");
2126  (n_cell * n_output), "RecurrentToForgetWeights");
2127 
2128  ValidatePointer(m_RecurrentToCellWeights, "Null pointer check", "RecurrentToCellWeights");
2130  (n_cell * n_output), "RecurrentToCellWeights");
2131 
2132  // Make sure the input-gate's parameters are either both present (regular
2133  // LSTM) or not at all (CIFG-LSTM). And CifgEnable is set accordingly.
2134  bool cifg_weights_all_or_none = ((m_InputToInputWeights && m_RecurrentToInputWeights &&
2138  if (!cifg_weights_all_or_none)
2139  {
2140  throw InvalidArgumentException(descriptorName + ": Input-Gate's parameters InputToInputWeights and "
2141  "RecurrentToInputWeights must either both be present (regular LSTM) "
2142  "or both not present (CIFG-LSTM). In addition CifgEnable must be set "
2143  "accordingly.");
2144  }
2145 
2146  if ( m_CellToInputWeights )
2147  {
2149  n_cell, "CellToInputWeights");
2150  }
2151  if ( m_CellToForgetWeights )
2152  {
2154  n_cell, "CellToForgetWeights");
2155  }
2156  if ( m_CellToOutputWeights )
2157  {
2159  n_cell, "CellToOutputWeights");
2160  }
2161 
2162  // Making sure the peephole weights are there all or none. And PeepholeEnable is set accordingly.
2163  bool peephole_weights_all_or_none =
2168  if (!peephole_weights_all_or_none)
2169  {
2170  throw InvalidArgumentException(descriptorName + ": Invalid combination of peephole parameters.");
2171  }
2172 
2173  // Make sure the input gate bias is present only when not a CIFG-LSTM.
2175  {
2176  if (m_InputGateBias)
2177  {
2178  throw InvalidArgumentException(descriptorName + ": InputGateBias is present and CIFG-LSTM is enabled.");
2179  }
2180  }
2181  else
2182  {
2183  if (!m_InputGateBias)
2184  {
2185  throw InvalidArgumentException(descriptorName + ": If CIFG-LSTM is disabled InputGateBias "
2186  "must be present.");
2187  }
2189  n_cell, "InputGateBias");
2190  }
2191 
2192  ValidatePointer(m_ForgetGateBias, "Null pointer check", "ForgetGateBias");
2193  ValidateTensorNumDimNumElem(m_ForgetGateBias->GetTensorInfo(), 1, n_cell, "ForgetGateBias");
2194 
2195  ValidatePointer(m_CellBias, "Null pointer check", "CellBias");
2196  ValidateTensorNumDimNumElem(m_CellBias->GetTensorInfo(), 1, n_cell, "CellBias");
2197 
2198  ValidatePointer(m_OutputGateBias, "Null pointer check", "OutputGateBias");
2199  ValidateTensorNumDimNumElem(m_OutputGateBias->GetTensorInfo(), 1, n_cell, "OutputGateBias");
2200 
2201  if (m_ProjectionWeights)
2202  {
2204  (n_cell * n_output), "ProjectionWeights");
2205  }
2206  if (m_ProjectionBias)
2207  {
2208  ValidateTensorNumDimNumElem(m_ProjectionBias->GetTensorInfo(), 1, n_output, "ProjectionBias");
2209  }
2210 
2211  // Making sure the projection tensors are consistent:
2212  // 1) If projection weight is not present, then projection bias should not be
2213  // present.
2214  // 2) If projection weight is present, then projection bias is optional.
2215  bool projecton_tensors_consistent = ((!m_ProjectionWeights && !m_ProjectionBias &&
2221  if (!projecton_tensors_consistent)
2222  {
2223  throw InvalidArgumentException(descriptorName + ": Projection tensors are inconsistent.");
2224  }
2225 
2226  // The four layer normalization weights either all have values or none of them have values. Additionally, if
2227  // CIFG is used, input layer normalization weights tensor is omitted and the other layer normalization weights
2228  // either all have values or none of them have values. Layer normalization is used when the values of all the
2229  // layer normalization weights are present
2231  {
2232  ValidateTensorNumDimNumElem(m_InputLayerNormWeights->GetTensorInfo(), 1, n_cell, "InputLayerNormWeights");
2233  }
2235  {
2236  ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
2237  }
2239  {
2240  ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
2241  }
2243  {
2244  ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
2245  }
2246 
2248  {
2250  {
2252  {
2253  throw InvalidArgumentException(descriptorName + ": Layer normalisation is enabled and CIFG-LSTM is "
2254  "disabled but InputLayerNormWeights are not present");
2255  }
2257  1, n_cell, "InputLayerNormWeights");
2258  }
2259  else if (m_InputLayerNormWeights)
2260  {
2261  throw InvalidArgumentException(descriptorName + ":InputLayerNormWeights are present while CIFG is "
2262  "enabled");
2263  }
2264 
2265  ValidatePointer(m_ForgetLayerNormWeights, "Null pointer check layer normalisation enabled",
2266  "ForgetLayerNormWeights");
2267  ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
2268 
2269  ValidatePointer(m_OutputLayerNormWeights, "Null pointer check layer normalisation enabled",
2270  "OutputLayerNormWeights");
2271  ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
2272 
2273  ValidatePointer(m_CellLayerNormWeights, "Null pointer check layer normalisation enabled",
2274  "CellLayerNormWeights");
2275  ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
2276  }
2278  {
2279  throw InvalidArgumentException(descriptorName + ": Layer normalisation is disabled but one or more layer "
2280  "normalisation weights are present.");
2281  }
2282 }
2283 
2285 {
2286  const std::string descriptorName{"ConvertFp32ToFp16QueueDescriptor"};
2287 
2288  ValidateNumInputs(workloadInfo, descriptorName, 1);
2289  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2290 
2291  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2292  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2293 
2294  if (inputTensorInfo.GetDataType() != DataType::Float32)
2295  {
2296  throw InvalidArgumentException(descriptorName + ": Input tensor type must be Float32.");
2297  }
2298 
2299  if (outputTensorInfo.GetDataType() != DataType::Float16)
2300  {
2301  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Float16.");
2302  }
2303 
2304  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2305 }
2306 
2308 {
2309  const std::string descriptorName{"ConvertFp16ToFp32QueueDescriptor"};
2310 
2311  ValidateNumInputs(workloadInfo, descriptorName, 1);
2312  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2313 
2314  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2315  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2316 
2317  if (inputTensorInfo.GetDataType() != DataType::Float16)
2318  {
2319  throw InvalidArgumentException(descriptorName + ": Input tensor type must be Float16.");
2320  }
2321 
2322  if (outputTensorInfo.GetDataType() != DataType::Float32)
2323  {
2324  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Float32.");
2325  }
2326 
2327  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2328 }
2329 
2330 void DivisionQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2331 {
2332  const std::string descriptorName{"DivisionQueueDescriptor"};
2333 
2334  ValidateNumInputs(workloadInfo, descriptorName, 2);
2335  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2336 
2337  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2338  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2339  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2340 
2341  std::vector<DataType> supportedTypes =
2342  {
2350  };
2351 
2352  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2353  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2354  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
2355 
2356  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2357  inputTensorInfo1,
2358  outputTensorInfo,
2359  descriptorName,
2360  "input_0",
2361  "input_1");
2362 }
2363 
2365 {
2366  const std::string descriptorName{"SubtractionQueueDescriptor"};
2367 
2368  ValidateNumInputs(workloadInfo, descriptorName, 2);
2369  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2370 
2371  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2372  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2373  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2374 
2375  std::vector<DataType> supportedTypes =
2376  {
2384  };
2385 
2386  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2387  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2388  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
2389 
2390  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2391  inputTensorInfo1,
2392  outputTensorInfo,
2393  descriptorName,
2394  "input_0",
2395  "input_1");
2396 }
2397 
2398 void MaximumQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2399 {
2400  const std::string descriptorName{"MaximumQueueDescriptor"};
2401 
2402  ValidateNumInputs(workloadInfo, descriptorName, 2);
2403  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2404 
2405  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2406  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2407  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2408 
2409  std::vector<DataType> supportedTypes =
2410  {
2418  };
2419 
2420  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2421  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2422  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
2423 
2424  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2425  inputTensorInfo1,
2426  outputTensorInfo,
2427  descriptorName,
2428  "input_0",
2429  "input_1");
2430 }
2431 
2432 void MeanQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2433 {
2434  const std::string descriptorName{"MeanQueueDescriptor"};
2435 
2436  ValidateNumInputs(workloadInfo, descriptorName, 1);
2437  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2438 
2439  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2440  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2441 
2442  std::vector<DataType> supportedTypes =
2443  {
2451  };
2452 
2453  // First check if input tensor data type is supported, then
2454  // check if this data type matches the output tensor data type
2455  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2456  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2457 
2459  {
2460  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, inputTensorInfo.GetNumDimensions(), "output");
2461  }
2462  else if (m_Parameters.m_Axis.empty())
2463  {
2464  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 1, "output");
2465  }
2466  else
2467  {
2468  unsigned int outputDim =
2469  inputTensorInfo.GetNumDimensions() - armnn::numeric_cast<unsigned int>(m_Parameters.m_Axis.size());
2470  ValidateTensorNumDimensions(outputTensorInfo,
2471  descriptorName,
2472  outputDim > 0 ? outputDim : 1,
2473  "output");
2474  }
2475 }
2476 
2477 void PadQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2478 {
2479  const std::string descriptorName{"PadQueueDescriptor"};
2480 
2481  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 
2487  // input and output should have the same number of dimensions
2488  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, inputTensorInfo.GetNumDimensions(), "output");
2489 
2490  // there should be entry in the pad list for each dimension in the input tensor
2491  if (m_Parameters.m_PadList.size() != inputTensorInfo.GetNumDimensions()) {
2492  throw InvalidArgumentException(descriptorName + ":Pad List should contain the same number of entries "
2493  "as there are dimensions in the input tensor that is " +
2494  std::to_string(inputTensorInfo.GetNumDimensions()) + " entries " +
2495  " not " + std::to_string(m_Parameters.m_PadList.size()) + " entries.");
2496  }
2497 }
2498 
2499 void QuantizeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2500 {
2501  const std::string descriptorName{"QuantizeQueueDescriptor"};
2502 
2503  ValidateNumInputs(workloadInfo, descriptorName, 1);
2504  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2505 
2506  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2507  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2508 
2509  std::vector<DataType> supportedTypes =
2510  {
2518  };
2519 
2520  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2521 
2522  if (!IsQuantizedType(outputTensorInfo.GetDataType()))
2523  {
2524  throw InvalidArgumentException(descriptorName + ": Output of quantized layer must be quantized type.");
2525  }
2526 }
2527 
2529 {
2530  const std::string descriptorName{"BatchToSpaceNdQueueDescriptor"};
2531 
2532  ValidateNumInputs(workloadInfo, descriptorName, 1);
2533  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2534 
2535  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2536  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2537 
2538  if (m_Parameters.m_BlockShape.size() != m_Parameters.m_Crops.size())
2539  {
2540  throw InvalidArgumentException(descriptorName + ": Crops must contain the same number of "
2541  "dimensions as Block Shape.");
2542  }
2543 
2544  if (m_Parameters.m_BlockShape.size() == 2)
2545  {
2546  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
2547  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
2548  }
2549  else if (m_Parameters.m_BlockShape.size() == 1)
2550  {
2551  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 3, "input");
2552  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 3, "output");
2553  }
2554  else
2555  {
2556  throw InvalidArgumentException(descriptorName + ": Invalid Block and Crops size.");
2557  }
2558 
2559  // In a 4D tensor, there will be 2 spatialDimensions (H and W), and the for loop will run twice.
2560  // In a 3D tensor, there will be 1 spatialDimensions, and the for loop will run once.
2561  unsigned int firstSpatialDimension = m_Parameters.m_DataLayout == DataLayout::NCHW ? 2 : 1;
2562  for (unsigned int i = 0; i < m_Parameters.m_BlockShape.size(); ++i)
2563  {
2564  unsigned int spatialDimension = firstSpatialDimension + i;
2565  unsigned int cropSize = m_Parameters.m_Crops[i].first + m_Parameters.m_Crops[i].second;
2566  unsigned int outputSize = inputTensorInfo.GetShape()[spatialDimension] * m_Parameters.m_BlockShape[i];
2567  if (cropSize > outputSize)
2568  {
2569  throw InvalidArgumentException(descriptorName + ": CropSize must be less than or equal to the uncropped"
2570  "outputSize in dimension: " + to_string(spatialDimension) + ".");
2571  }
2572  }
2573 
2574  std::vector<DataType> supportedTypes =
2575  {
2582  };
2583 
2584  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2585  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2586 }
2587 
2589 {
2590  const std::string descriptorName{"StridedSliceQueueDescriptor"};
2591 
2592  ValidateNumInputs(workloadInfo, descriptorName, 1);
2593  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2594 
2595  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2596  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2597 
2598  std::vector<DataType> supportedTypes =
2599  {
2606  };
2607 
2608  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2609  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2610 
2611  ValidateTensorQuantizationSpace(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2612 
2613  const uint32_t rank = inputTensorInfo.GetNumDimensions();
2614  if (rank > 4)
2615  {
2616  throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
2617  }
2618 
2619  // Begin, End & Stride length must be of rank(input0)
2620  if (m_Parameters.m_Begin.size() != rank)
2621  {
2622  throw InvalidArgumentException(descriptorName + ": Begin length must be of rank " + std::to_string(rank));
2623  }
2624 
2625  if (m_Parameters.m_End.size() != rank)
2626  {
2627  throw InvalidArgumentException(descriptorName + ": End length must be of rank " + std::to_string(rank));
2628  }
2629 
2630  if (m_Parameters.m_Stride.size() != rank)
2631  {
2632  throw InvalidArgumentException(descriptorName + ": Stride length must be of rank " + std::to_string(rank));
2633  }
2634 
2635  // Stride entries must be non-zero
2636  for (auto& stride : m_Parameters.m_Stride)
2637  {
2638  if (stride == 0)
2639  {
2640  throw InvalidArgumentException(descriptorName + ": Stride entries must be non-zero.");
2641  }
2642  }
2643 }
2644 
2645 void MinimumQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2646 {
2647  const std::string descriptorName{"MinimumQueueDescriptor"};
2648 
2649  ValidateNumInputs(workloadInfo, descriptorName, 2);
2650  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2651 
2652  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2653  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2654  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2655 
2656  std::vector<DataType> supportedTypes =
2657  {
2665  };
2666 
2667  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2668  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2669  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
2670 
2671  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2672  inputTensorInfo1,
2673  outputTensorInfo,
2674  descriptorName,
2675  "input_0",
2676  "input_1");
2677 }
2678 
2679 void DebugQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2680 {
2681  const std::string descriptorName{"DebugQueueDescriptor"};
2682 
2683  ValidateNumInputs(workloadInfo, descriptorName, 1);
2684  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2685 }
2686 
2687 void EqualQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2688 {
2689  const std::string descriptorName{"EqualQueueDescriptor"};
2690 
2691  ValidateNumInputs(workloadInfo, descriptorName, 2);
2692  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2693 
2694  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2695  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2696  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2697 
2698  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2699  inputTensorInfo1,
2700  outputTensorInfo,
2701  descriptorName,
2702  "input_0",
2703  "input_1");
2704 
2705  if (outputTensorInfo.GetDataType() != DataType::Boolean)
2706  {
2707  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
2708  }
2709 }
2710 
2711 void GreaterQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2712 {
2713  const std::string descriptorName{"GreaterQueueDescriptor"};
2714 
2715  ValidateNumInputs(workloadInfo, descriptorName, 2);
2716  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2717 
2718  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2719  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2720  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2721 
2722  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2723  inputTensorInfo1,
2724  outputTensorInfo,
2725  descriptorName,
2726  "input_0",
2727  "input_1");
2728 
2729  if (outputTensorInfo.GetDataType() != DataType::Boolean)
2730  {
2731  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
2732  }
2733 }
2734 
2735 void RsqrtQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2736 {
2737  const std::string descriptorName{"RsqrtQueueDescriptor"};
2738 
2739  ValidateNumInputs(workloadInfo, descriptorName, 1);
2740  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2741 
2742  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2743  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2744 
2745  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2746 
2747  std::vector<DataType> supportedTypes =
2748  {
2755  };
2756 
2757  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2758  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2759 }
2760 
2761 void GatherNdQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2762 {
2763  const std::string descriptorName{"GatherNdQueueDescriptor"};
2764 
2765  ValidateNumInputs(workloadInfo, descriptorName, 2);
2766  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2767 
2768  const TensorInfo& indicesTensorInfo = workloadInfo.m_InputTensorInfos[1];
2769  if (indicesTensorInfo.GetDataType() != DataType::Signed32)
2770  {
2771  throw InvalidArgumentException(descriptorName + ": Indices tensor type must be Int32.");
2772  }
2773 
2774  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2775  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2776 
2777  std::vector<DataType> supportedTypes =
2778  {
2786  };
2787 
2788  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2789 
2790  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2791 
2792  unsigned int outputDim = outputTensorInfo.GetNumDimensions();
2793  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, outputDim, "output");
2794 }
2795 
2796 void GatherQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2797 {
2798  const std::string descriptorName{"GatherQueueDescriptor"};
2799 
2800  ValidateNumInputs(workloadInfo, descriptorName, 2);
2801  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2802 
2803  const TensorInfo& indicesTensorInfo = workloadInfo.m_InputTensorInfos[1];
2804  if (indicesTensorInfo.GetDataType() != DataType::Signed32)
2805  {
2806  throw InvalidArgumentException(descriptorName + ": Indices tensor type must be Int32.");
2807  }
2808 
2809  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2810  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2811 
2812  std::vector<DataType> supportedTypes =
2813  {
2821  };
2822 
2823  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2824 
2825  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2826 
2827  unsigned int outputDim = inputTensorInfo.GetNumDimensions() + indicesTensorInfo.GetNumDimensions() - 1;
2828  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, outputDim, "output");
2829 }
2830 
2832 {
2833  const std::string& descriptorName{"DetectionPostProcessQueueDescriptor"};
2834 
2835  ValidateNumInputs(workloadInfo, descriptorName, 2);
2836 
2837  if (workloadInfo.m_OutputTensorInfos.size() != 4)
2838  {
2839  throw InvalidArgumentException(descriptorName + ": Requires exactly four outputs. " +
2840  to_string(workloadInfo.m_OutputTensorInfos.size()) + " has been provided.");
2841  }
2842 
2843  if (m_Anchors == nullptr)
2844  {
2845  throw InvalidArgumentException(descriptorName + ": Anchors tensor descriptor is missing.");
2846  }
2847 
2848  const TensorInfo& boxEncodingsInfo = workloadInfo.m_InputTensorInfos[0];
2849  const TensorInfo& scoresInfo = workloadInfo.m_InputTensorInfos[1];
2850  const TensorInfo& anchorsInfo = m_Anchors->GetTensorInfo();
2851 
2852  const TensorInfo& detectionBoxesInfo = workloadInfo.m_OutputTensorInfos[0];
2853  const TensorInfo& detectionClassesInfo = workloadInfo.m_OutputTensorInfos[1];
2854  const TensorInfo& detectionScoresInfo = workloadInfo.m_OutputTensorInfos[2];
2855  const TensorInfo& numDetectionsInfo = workloadInfo.m_OutputTensorInfos[3];
2856 
2857  ValidateTensorNumDimensions(boxEncodingsInfo, descriptorName, 3, "box encodings");
2858  ValidateTensorNumDimensions(scoresInfo, descriptorName, 3, "scores");
2859  ValidateTensorNumDimensions(anchorsInfo, descriptorName, 2, "anchors");
2860 
2861  const std::vector<DataType> supportedInputTypes =
2862  {
2869  };
2870 
2871  ValidateDataTypes(boxEncodingsInfo, supportedInputTypes, descriptorName);
2872  ValidateDataTypes(scoresInfo, supportedInputTypes, descriptorName);
2873  ValidateDataTypes(anchorsInfo, supportedInputTypes, descriptorName);
2874 
2875  ValidateTensorNumDimensions(detectionBoxesInfo, descriptorName, 3, "detection boxes");
2876  ValidateTensorNumDimensions(detectionScoresInfo, descriptorName, 2, "detection scores");
2877  ValidateTensorNumDimensions(detectionClassesInfo, descriptorName, 2, "detection classes");
2878  ValidateTensorNumDimensions(numDetectionsInfo, descriptorName, 1, "num detections");
2879 
2880  // NOTE: Output is always Float32 regardless of input type
2881  ValidateTensorDataType(detectionBoxesInfo, DataType::Float32, descriptorName, "detection boxes");
2882  ValidateTensorDataType(detectionScoresInfo, DataType::Float32, descriptorName, "detection scores");
2883  ValidateTensorDataType(detectionClassesInfo, DataType::Float32, descriptorName, "detection classes");
2884  ValidateTensorDataType(numDetectionsInfo, DataType::Float32, descriptorName, "num detections");
2885 
2887  {
2888  throw InvalidArgumentException(descriptorName + ": Intersection over union threshold "
2889  "must be positive and less than or equal to 1.");
2890  }
2891 
2892  if (scoresInfo.GetShape()[2] != m_Parameters.m_NumClasses + 1)
2893  {
2894  throw InvalidArgumentException(descriptorName + ": Number of classes with background "
2895  "should be equal to number of classes + 1.");
2896  }
2897 }
2898 
2899 void DequantizeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2900 {
2901  const std::string& descriptorName{"DequantizeQueueDescriptor"};
2902 
2903  ValidateNumInputs(workloadInfo, descriptorName, 1);
2904  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2905 
2906  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2907  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2908 
2909  std::vector<DataType> inputSupportedTypes =
2910  {
2916  };
2917  ValidateDataTypes(inputTensorInfo, inputSupportedTypes, descriptorName);
2918 
2919  std::vector<DataType> outputSupportedTypes =
2920  {
2924  };
2925 
2926  ValidateDataTypes(outputTensorInfo, outputSupportedTypes, descriptorName);
2927 }
2928 
2929 void MergeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2930 {
2931  const std::string& descriptorName{"MergeQueueDescriptor"};
2932 
2933  ValidateNumInputs(workloadInfo, descriptorName, 2);
2934  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2935 
2936  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2937  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2938  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2939 
2940  ValidateTensorShapesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
2941  ValidateTensorShapesMatch(inputTensorInfo0, outputTensorInfo, descriptorName, "input_0", "output");
2942 
2943  ValidateTensorDataTypesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
2944  ValidateTensorDataTypesMatch(inputTensorInfo0, outputTensorInfo, descriptorName, "input_0", "output");
2945 }
2946 
2947 void ShapeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2948 {
2949  const std::string& descriptorName{"ShapeQueueDescriptor"};
2950 
2951  ValidateNumInputs(workloadInfo, descriptorName, 1);
2952  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2953 
2954  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2955  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2956 
2957  std::vector<DataType> supportedTypes =
2958  {
2967  };
2968 
2969  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2970  ValidateDataTypes(outputTensorInfo, {DataType::Signed32}, descriptorName);
2971 }
2972 
2973 void SwitchQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2974 {
2975  const std::string& descriptorName{"SwitchQueueDescriptor"};
2976 
2977  ValidateNumInputs(workloadInfo, descriptorName, 2);
2978  ValidateNumOutputs(workloadInfo, descriptorName, 2);
2979 
2980  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2981  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2982 
2983  const TensorInfo& outputTensorInfo0 = workloadInfo.m_OutputTensorInfos[0];
2984  const TensorInfo& outputTensorInfo1 = workloadInfo.m_OutputTensorInfos[1];
2985 
2986  std::vector<DataType> supportedTypes =
2987  {
2993  };
2994 
2995  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2996  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2997 
2998  ValidateDataTypes(outputTensorInfo0, supportedTypes, descriptorName);
2999  ValidateDataTypes(outputTensorInfo1, supportedTypes, descriptorName);
3000 
3001  ValidateTensorShapesMatch(inputTensorInfo0,
3002  outputTensorInfo0,
3003  descriptorName,
3004  "input_0",
3005  "output_0");
3006 
3007  ValidateTensorShapesMatch(inputTensorInfo0,
3008  outputTensorInfo1,
3009  descriptorName,
3010  "input_0",
3011  "output_1");
3012 }
3013 
3014 void PreCompiledQueueDescriptor::Validate(const WorkloadInfo& /*workloadInfo*/) const
3015 {
3016  // This is internally generated, so it should not need validation.
3017 }
3018 
3019 void PreluQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3020 {
3021  const std::string& descriptorName{"PreluQueueDescriptor"};
3022 
3023  ValidateNumInputs(workloadInfo, descriptorName, 2);
3024  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3025 
3026  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3027  const TensorInfo& alphaTensorInfo = workloadInfo.m_InputTensorInfos[1];
3028  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3029 
3030  std::vector<DataType> supportedTypes
3031  {
3038  };
3039 
3040  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3041  ValidateDataTypes(alphaTensorInfo, supportedTypes, descriptorName);
3042 
3043  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
3044 
3045  ValidateTensorDataTypesMatch(inputTensorInfo, alphaTensorInfo, descriptorName, "input", "alpha");
3046  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "ouptut");
3047 
3048  ValidateBroadcastTensorShapesMatch(inputTensorInfo,
3049  alphaTensorInfo,
3050  outputTensorInfo,
3051  descriptorName,
3052  "input",
3053  "alpha");
3054 }
3055 
3057 {
3058  const std::string descriptorName{"TransposeConvolution2dQueueDescriptor"};
3059 
3060  ValidateNumInputs(workloadInfo, descriptorName, 1);
3061  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3062 
3063  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3064  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3065 
3066  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
3067  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
3068 
3069  ValidatePointer(m_Weight, descriptorName, "weight");
3070 
3071  const TensorInfo& weightTensorInfo = m_Weight->GetTensorInfo();
3072  ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 4, "weight");
3073 
3074  ValidateWeightDataType(inputTensorInfo, weightTensorInfo, descriptorName);
3075 
3076  Optional<TensorInfo> optionalBiasTensorInfo;
3078  {
3079  ValidatePointer(m_Bias, descriptorName, "bias");
3080 
3081  optionalBiasTensorInfo = MakeOptional<TensorInfo>(m_Bias->GetTensorInfo());
3082  const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value();
3083 
3084  ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
3085  ValidateBiasTensorQuantization(biasTensorInfo, weightTensorInfo, descriptorName);
3086  }
3087 
3088  ValidatePerAxisQuantization(inputTensorInfo,
3089  outputTensorInfo,
3090  weightTensorInfo,
3091  optionalBiasTensorInfo,
3092  descriptorName);
3093 
3094  std::vector<DataType> supportedTypes =
3095  {
3102  };
3103 
3104  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3105  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3106 }
3107 
3108 void TransposeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3109 {
3110  const std::string descriptorName{"TransposeQueueDescriptor"};
3111 
3112  ValidateNumInputs(workloadInfo, descriptorName, 1);
3113  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3114 
3115  const PermutationVector& mapping = m_Parameters.m_DimMappings;
3116 
3117  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3118  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3119 
3120  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, mapping.GetSize(), "input");
3121  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, mapping.GetSize(), "output");
3122 
3123  for (unsigned int i = 0u; i < mapping.GetSize(); ++i)
3124  {
3125  if (inputTensorInfo.GetShape()[mapping[i]] != outputTensorInfo.GetShape()[i])
3126  {
3127  throw InvalidArgumentException(descriptorName + ": src dimension " + to_string(mapping[i]) +
3128  " (=" + to_string(inputTensorInfo.GetShape()[mapping[i]]) + ") " +
3129  "must match dst dimension " + to_string(i) +
3130  " (=" + to_string(outputTensorInfo.GetShape()[i]) + ")");
3131  }
3132  }
3133 
3134  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3135 }
3136 
3138 {
3139  const std::string descriptorName{"TransposeQueueDescriptor"};
3140 
3141  ValidateNumInputs(workloadInfo, descriptorName, 1);
3142  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3143 
3144  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3145  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3146 
3147  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3148 }
3149 
3150 void QLstmQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3151 {
3152  const std::string descriptorName{"QLstmQueueDescriptor"};
3153 
3154  // Validate number of inputs/outputs
3155  ValidateNumInputs(workloadInfo, descriptorName, 3);
3156  ValidateNumOutputs(workloadInfo, descriptorName, 3);
3157 
3158  // Input/output tensor info
3159  auto inputInfo = workloadInfo.m_InputTensorInfos[0];
3160  auto outputStateInInfo = workloadInfo.m_InputTensorInfos[1];
3161  auto cellStateInInfo = workloadInfo.m_InputTensorInfos[2];
3162 
3163  auto outputStateOutInfo = workloadInfo.m_OutputTensorInfos[0];
3164  auto cellStateOutInfo = workloadInfo.m_OutputTensorInfos[1];
3165  auto outputInfo = workloadInfo.m_OutputTensorInfos[2];
3166 
3167  // Supported types for various tensors in QLSTM
3168  std::vector<DataType> inputOutputSupportedTypes =
3169  {
3171  };
3172 
3173  std::vector<DataType> cellStateSupportedTypes =
3174  {
3176  };
3177 
3178  std::vector<DataType> weightsSupportedTypes =
3179  {
3181  };
3182 
3183  std::vector<DataType> layerNormPeepholeWeightsSupportedTypes =
3184  {
3186  };
3187 
3188  std::vector<DataType> biasSupportedTypes =
3189  {
3191  };
3192 
3193  // Validate types of input/output tensors
3194  ValidateDataTypes(inputInfo, inputOutputSupportedTypes, descriptorName);
3195  ValidateDataTypes(outputStateInInfo, inputOutputSupportedTypes, descriptorName);
3196  ValidateDataTypes(cellStateInInfo, cellStateSupportedTypes, descriptorName);
3197 
3198  ValidateDataTypes(outputStateOutInfo, inputOutputSupportedTypes, descriptorName);
3199  ValidateDataTypes(cellStateOutInfo, cellStateSupportedTypes, descriptorName);
3200  ValidateDataTypes(outputInfo, inputOutputSupportedTypes, descriptorName);
3201 
3202  // Validate matching types of input/output tensors
3203  ValidateTensorDataTypesMatch(inputInfo, outputStateInInfo, descriptorName, "input", "outputStateIn");
3204  ValidateTensorDataTypesMatch(outputStateInInfo, outputStateOutInfo, descriptorName,
3205  "outputStateIn", "outputStateOut");
3206  ValidateTensorDataTypesMatch(cellStateInInfo, cellStateOutInfo, descriptorName, "cellStateIn", "cellStateOut");
3207 
3208  // Infer number of batches, number of units, input size and output size from tensor dimensions
3209  const uint32_t numBatches = inputInfo.GetShape()[0];
3210  const uint32_t inputSize = inputInfo.GetShape()[1];
3211  const uint32_t outputSize = outputStateInInfo.GetShape()[1];
3212  const uint32_t numUnits = cellStateInInfo.GetShape()[1];
3213 
3214  // Validate number of dimensions and number of elements for input/output tensors
3215  ValidateTensorNumDimNumElem(inputInfo, 2, (numBatches * inputSize), descriptorName + " input");
3216  ValidateTensorNumDimNumElem(outputStateInInfo, 2, (numBatches * outputSize), descriptorName + " outputStateIn");
3217  ValidateTensorNumDimNumElem(cellStateInInfo, 2, (numBatches * numUnits), descriptorName + " cellStateIn");
3218 
3219  ValidateTensorNumDimNumElem(outputStateOutInfo, 2, (numBatches * outputSize), descriptorName + " outputStateOut");
3220  ValidateTensorNumDimNumElem(cellStateOutInfo, 2, (numBatches * numUnits), descriptorName + " cellStateOut");
3221  ValidateTensorNumDimNumElem(outputInfo, 2, (numBatches * outputSize), descriptorName + " output");
3222 
3223  // Validate number of dimensions and number of elements for MANDATORY weight tensors
3224  ValidatePointer(m_InputToForgetWeights, descriptorName, "InputToForgetWeights");
3225  auto inputToForgetWeightsInfo = m_InputToForgetWeights->GetTensorInfo();
3226  ValidateTensorNumDimNumElem(inputToForgetWeightsInfo, 2, (numUnits * inputSize), " InputToForgetWeights");
3227 
3228  ValidatePointer(m_InputToCellWeights, descriptorName, "InputToCellWeights");
3229  auto inputToCellWeightsInfo = m_InputToCellWeights->GetTensorInfo();
3230  ValidateTensorNumDimNumElem(inputToCellWeightsInfo, 2, (numUnits * inputSize), " InputToCellWeights");
3231 
3232  ValidatePointer(m_InputToOutputWeights, descriptorName, "InputToOutputWeights");
3233  auto inputToOutputWeightsInfo = m_InputToOutputWeights->GetTensorInfo();
3234  ValidateTensorNumDimNumElem(inputToOutputWeightsInfo, 2, (numUnits * inputSize), " InputToOutputWeights");
3235 
3236  ValidatePointer(m_RecurrentToForgetWeights, descriptorName, "RecurrentToForgetWeights");
3237  auto recurrentToForgetWeightsInfo = m_RecurrentToForgetWeights->GetTensorInfo();
3238  ValidateTensorNumDimNumElem(recurrentToForgetWeightsInfo, 2, (numUnits * outputSize),
3239  " RecurrentToForgetWeights");
3240 
3241  ValidatePointer(m_RecurrentToCellWeights, descriptorName, "RecurrentToCellWeights");
3242  auto recurrentToCellWeightsInfo = m_RecurrentToCellWeights->GetTensorInfo();
3243  ValidateTensorNumDimNumElem(recurrentToCellWeightsInfo, 2, (numUnits * outputSize), " RecurrentToCellWeights");
3244 
3245  ValidatePointer(m_RecurrentToOutputWeights, descriptorName, "RecurrentToOutputWeights");
3246  auto recurrentToOutputWeightsInfo = m_RecurrentToOutputWeights->GetTensorInfo();
3247  ValidateTensorNumDimNumElem(recurrentToOutputWeightsInfo, 2, (numUnits * outputSize), " RecurrentToCellWeights");
3248 
3249  // Validate data types for MANDATORY weights tensors (all should match each other)
3250  ValidateDataTypes(inputToForgetWeightsInfo, weightsSupportedTypes, descriptorName);
3251 
3252  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, inputToCellWeightsInfo, descriptorName,
3253  "inputToForgetWeights", "inputToCellWeights");
3254  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, inputToOutputWeightsInfo, descriptorName,
3255  "inputToForgetWeights", "inputToOutputWeights");
3256 
3257  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, recurrentToForgetWeightsInfo, descriptorName,
3258  "inputToForgetWeights", "recurrentToForgeteights");
3259  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, recurrentToCellWeightsInfo, descriptorName,
3260  "inputToForgetWeights", "recurrentToCellWeights");
3261  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, recurrentToOutputWeightsInfo, descriptorName,
3262  "inputToForgetWeights", "recurrentToOutputWeights");
3263 
3264  // Validate number of dimensions and number of elements for MANDATORY bias tensors
3265  ValidatePointer(m_ForgetGateBias, descriptorName, "ForgetGateBias");
3266  auto forgetGateBiasInfo = m_ForgetGateBias->GetTensorInfo();
3267  ValidateTensorNumDimNumElem(forgetGateBiasInfo, 1, numUnits, " ForgetGateBias");
3268 
3269  ValidatePointer(m_CellBias, descriptorName, "CellBias");
3270  auto cellBiasInfo = m_CellBias->GetTensorInfo();
3271  ValidateTensorNumDimNumElem(cellBiasInfo, 1, numUnits, " CellBias");
3272 
3273  ValidatePointer(m_OutputGateBias, descriptorName, "OutputGateBias");
3274  auto outputGateBiasInfo = m_OutputGateBias->GetTensorInfo();
3275  ValidateTensorNumDimNumElem(outputGateBiasInfo, 1, numUnits, " OutputGateBias");
3276 
3277  // Validate data types for MANDATORY bias tensors
3278  ValidateDataTypes(forgetGateBiasInfo, biasSupportedTypes, descriptorName);
3279 
3280  ValidateTensorDataTypesMatch(forgetGateBiasInfo, cellBiasInfo, descriptorName,
3281  "forgetGateBias", "cellBias");
3282  ValidateTensorDataTypesMatch(forgetGateBiasInfo, outputGateBiasInfo, descriptorName,
3283  "forgetGateBias", "outputGateBias");
3284 
3285  // Validate OPTIONAL params: CIFG (inputToInputWeights, recurrentToInputWeights, inputGateBias)
3286  const bool allCifgParamsPresentOrNot = ((m_InputToInputWeights && m_RecurrentToInputWeights && m_InputGateBias &&
3290 
3291  if (!allCifgParamsPresentOrNot)
3292  {
3293  throw InvalidArgumentException(descriptorName +
3294  ": InputToInputWeights, RecurrentToInputWeights and InputGateBias must either all be present "
3295  "(CIFG disabled) or not be present at all (CIFG enabled). m_Parameters.m_CifgEnabled should be "
3296  "set appropriately.");
3297  }
3298 
3300  {
3301  // Validate number of dimensions and number of elements
3302  auto inputToInputWeightsInfo = m_InputToInputWeights->GetTensorInfo();
3303  ValidateTensorNumDimNumElem(inputToInputWeightsInfo, 2, (numUnits * inputSize), " InputToInputWeights");
3304 
3305  auto recurrentToInputWeightsInfo = m_RecurrentToInputWeights->GetTensorInfo();
3306  ValidateTensorNumDimNumElem(recurrentToInputWeightsInfo, 2, (numUnits * outputSize),
3307  " RecurrentToInputWeights");
3308 
3309  auto inputGateBiasInfo = m_InputGateBias->GetTensorInfo();
3310  ValidateTensorNumDimNumElem(inputGateBiasInfo, 1, numUnits, " InputGateBias");
3311 
3312  // Validate data types
3313  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, inputToInputWeightsInfo, descriptorName,
3314  "inputToForgetWeights", "inputToInputWeights");
3315  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, recurrentToInputWeightsInfo, descriptorName,
3316  "inputToForgetWeights", "recurrentToInputWeights");
3317  ValidateTensorDataTypesMatch(forgetGateBiasInfo, inputGateBiasInfo, descriptorName,
3318  "forgetGateBias", "inputGateBias");
3319  }
3320 
3321  // Validate OPTIONAL params: Peephole (cellToInputWeights, cellToForgetWeights, cellToOutputWeights)
3322  bool allPeepholeWeightsPresentOrNot =
3327 
3328  if (!allPeepholeWeightsPresentOrNot)
3329  {
3330  throw InvalidArgumentException(descriptorName +
3331  ": CellToInputWeights, CellToForgetWeights and CellToOutputWeights should all be present (Peephole "
3332  "enabled) or not be present at all (Peephole disabled). CellToInputWeights should only be present "
3333  "when Peephole is enabled and CIFG is disabled. m_Parameters.m_PeepholeEnabled should be set "
3334  "appropriately.");
3335  }
3336 
3338  {
3339  auto cellToForgetWeightsInfo = m_CellToForgetWeights->GetTensorInfo();
3340  ValidateTensorNumDimNumElem(cellToForgetWeightsInfo, 1, numUnits, " cellToForgetWeights");
3341  ValidateDataTypes(cellToForgetWeightsInfo, layerNormPeepholeWeightsSupportedTypes, descriptorName);
3342 
3343  auto cellToOutputWeightsInfo = m_CellToOutputWeights->GetTensorInfo();
3344  ValidateTensorNumDimNumElem(cellToOutputWeightsInfo, 1, numUnits, " cellToOutputWeights");
3345  ValidateTensorDataTypesMatch(cellToForgetWeightsInfo, cellToOutputWeightsInfo, descriptorName,
3346  "cellToForgetWeight", "cellToOutputWeights");
3347 
3349  {
3350  auto cellToInputWeightsInfo = m_CellToInputWeights->GetTensorInfo();
3351  ValidateTensorNumDimNumElem(cellToInputWeightsInfo, 1, numUnits, " cellToInputWeights");
3352  ValidateTensorDataTypesMatch(cellToForgetWeightsInfo, cellToInputWeightsInfo, descriptorName,
3353  "cellToForgetWeights", "cellToInputWeights");
3354  }
3355  }
3356 
3357  // Validate OPTIONAL params: Layer Norm Weights
3358  bool allLayerNormWeightsPresentOrNot =
3363 
3364  if (!allLayerNormWeightsPresentOrNot)
3365  {
3366  throw InvalidArgumentException(descriptorName +
3367  ": InputLayerNormWeights, ForgetLayerNormWeights, m_OutputLayerNormWeights "
3368  "and CellLayerNormWeights should all be present (Layer Norm enabled) or not "
3369  "be present at all (Layer Norm disabled). InputLayerNormWeights should "
3370  "only be present when Layer Norm is enabled and CIFG is disabled. "
3371  "m_Parameters.m_LayerNormEnabled should be set appropriately.");
3372  }
3373 
3375  {
3376  auto forgetLayerNormWeightsInfo = m_ForgetLayerNormWeights->GetTensorInfo();
3377  ValidateTensorNumDimNumElem(forgetLayerNormWeightsInfo, 1, numUnits, " forgetLayerNormWeights");
3378  ValidateDataTypes(forgetLayerNormWeightsInfo, layerNormPeepholeWeightsSupportedTypes, descriptorName);
3379 
3380  auto cellLayerNormWeightsInfo = m_CellLayerNormWeights->GetTensorInfo();
3381  ValidateTensorNumDimNumElem(cellLayerNormWeightsInfo, 1, numUnits, " cellLayerNormWeights");
3382  ValidateTensorDataTypesMatch(forgetLayerNormWeightsInfo, cellLayerNormWeightsInfo, descriptorName,
3383  "forgetLayerNormWeights", "cellLayerNormWeights");
3384 
3385  auto outputLayerNormWeightsInfo = m_OutputLayerNormWeights->GetTensorInfo();
3386  ValidateTensorNumDimNumElem(outputLayerNormWeightsInfo, 1, numUnits, " outputLayerNormWeights");
3387  ValidateTensorDataTypesMatch(forgetLayerNormWeightsInfo, outputLayerNormWeightsInfo, descriptorName,
3388  "forgetLayerNormWeights", "outputLayerNormWeights");
3389 
3391  {
3392  auto inputLayerNormWeightsInfo = m_InputLayerNormWeights->GetTensorInfo();
3393  ValidateTensorNumDimNumElem(inputLayerNormWeightsInfo, 1, numUnits, " inputLayerNormWeights");
3394  ValidateTensorDataTypesMatch(forgetLayerNormWeightsInfo, inputLayerNormWeightsInfo, descriptorName,
3395  "forgetLayerNormWeights", "inputLayerNormWeights");
3396  }
3397  }
3398 
3399  // Validate OPTIONAL params: Projection (projectionWeights, projectionBias)
3400  bool correctProjectionTensorsPresent =
3404 
3405  if (!correctProjectionTensorsPresent)
3406  {
3407  throw InvalidArgumentException(descriptorName +
3408  ": If projection is enabled, ProjectionWeights should be present and "
3409  "ProjectionBias is optional. If projection is disabled, neither "
3410  "ProjectionWeights nor ProjectionBias should be present.");
3411  }
3412 
3414  {
3415  auto projectionWeightsInfo = m_ProjectionWeights->GetTensorInfo();
3416  ValidateTensorNumDimNumElem(projectionWeightsInfo, 2, (numUnits * outputSize), "ProjectionWeights");
3417  ValidateDataTypes(projectionWeightsInfo, weightsSupportedTypes, descriptorName);
3418 
3419  if (m_ProjectionBias)
3420  {
3421  auto projectionBiasInfo = m_ProjectionBias->GetTensorInfo();
3422  ValidateTensorNumDimNumElem(projectionBiasInfo, 1, outputSize, "ProjectionBias");
3423  ValidateDataTypes(projectionBiasInfo, biasSupportedTypes, descriptorName);
3424  }
3425 
3426  }
3427  else if ((outputInfo.GetQuantizationScale() != m_Parameters.m_HiddenStateScale) &&
3429  throw InvalidArgumentException(descriptorName +
3430  ": If projection is disabled, output quantization info (scale, offset) "
3431  "should match HiddenStateScale and HiddenStateZeroPoint.");
3432  }
3433 
3434 }
3435 
3437 {
3438  const std::string descriptorName{"QuantizedLstmQueueDescriptor"};
3439 
3440  // Validate number of inputs/outputs
3441  ValidateNumInputs(workloadInfo, descriptorName, 3);
3442  ValidateNumOutputs(workloadInfo, descriptorName, 2);
3443 
3444  // Input/output tensor infos
3445  auto inputInfo = workloadInfo.m_InputTensorInfos[0];
3446  auto cellStateInInfo = workloadInfo.m_InputTensorInfos[1];
3447  auto outputStateInInfo = workloadInfo.m_InputTensorInfos[2];
3448 
3449  auto cellStateOutInfo = workloadInfo.m_OutputTensorInfos[0];
3450  auto outputStateOutInfo = workloadInfo.m_OutputTensorInfos[1];
3451 
3452  std::vector<DataType> inputOutputSupportedTypes =
3453  {
3455  };
3456 
3457  std::vector<DataType> cellStateSupportedTypes =
3458  {
3460  };
3461 
3462  std::vector<DataType> weightsSupportedTypes =
3463  {
3465  };
3466 
3467  std::vector<DataType> biasSupportedTypes =
3468  {
3470  };
3471 
3472  // Validate types of input/output tensors
3473  ValidateDataTypes(inputInfo, inputOutputSupportedTypes, descriptorName);
3474  ValidateDataTypes(cellStateInInfo, cellStateSupportedTypes, descriptorName);
3475  ValidateDataTypes(outputStateInInfo, inputOutputSupportedTypes, descriptorName);
3476 
3477  ValidateDataTypes(cellStateOutInfo, cellStateSupportedTypes, descriptorName);
3478  ValidateDataTypes(outputStateOutInfo, inputOutputSupportedTypes, descriptorName);
3479 
3480  // Validate matching types of input/output tensors
3481  ValidateTensorDataTypesMatch(inputInfo, outputStateInInfo, descriptorName, "input", "outputStateIn");
3482  ValidateTensorDataTypesMatch(outputStateInInfo, outputStateOutInfo, descriptorName,
3483  "outputStateIn", "outputStateOut");
3484  ValidateTensorDataTypesMatch(cellStateInInfo, cellStateOutInfo, descriptorName, "cellStateIn", "cellStateOut");
3485 
3486  // Validate matching quantization info for input/output tensors
3487  ValidateTensorQuantizationSpace(inputInfo, outputStateInInfo, descriptorName, "input", "outputStateIn");
3488  ValidateTensorQuantizationSpace(inputInfo, outputStateOutInfo, descriptorName, "input", "outputStateOut");
3489  ValidateTensorQuantizationSpace(cellStateInInfo, cellStateOutInfo, descriptorName, "cellStateIn", "cellStateOut");
3490 
3491  // Infer number of batches, input size and output size from tensor dimensions
3492  const uint32_t numBatches = inputInfo.GetShape()[0];
3493  const uint32_t inputSize = inputInfo.GetShape()[1];
3494  const uint32_t outputSize = cellStateInInfo.GetShape()[1];
3495 
3496  // Validate number of dimensions and number of elements for input/output tensors
3497  ValidateTensorNumDimNumElem(inputInfo, 2, (numBatches * inputSize), descriptorName + " input");
3498  ValidateTensorNumDimNumElem(cellStateInInfo, 2, (numBatches * outputSize), descriptorName + " cellStateIn");
3499  ValidateTensorNumDimNumElem(outputStateInInfo, 2, (numBatches * outputSize), descriptorName + " outputStateIn");
3500  ValidateTensorNumDimNumElem(cellStateOutInfo, 2, (numBatches * outputSize), descriptorName + " cellStateOut");
3501  ValidateTensorNumDimNumElem(outputStateOutInfo, 2, (numBatches * outputSize), descriptorName + " outputStateOut");
3502 
3503  // Validate number of dimensions and number of elements for weights tensors
3504  ValidatePointer(m_InputToInputWeights, descriptorName, "InputToInputWeights");
3505  auto inputToInputWeightsInfo = m_InputToInputWeights->GetTensorInfo();
3506  ValidateTensorNumDimNumElem(inputToInputWeightsInfo, 2, (outputSize * inputSize), " InputToInputWeights");
3507 
3508  ValidatePointer(m_InputToForgetWeights, descriptorName, "InputToForgetWeights");
3509  auto inputToForgetWeightsInfo = m_InputToForgetWeights->GetTensorInfo();
3510  ValidateTensorNumDimNumElem(inputToForgetWeightsInfo, 2, (outputSize * inputSize), " InputToForgetWeights");
3511 
3512  ValidatePointer(m_InputToCellWeights, descriptorName, "InputToCellWeights");
3513  auto inputToCellWeightsInfo = m_InputToCellWeights->GetTensorInfo();
3514  ValidateTensorNumDimNumElem(inputToCellWeightsInfo, 2, (outputSize * inputSize), " InputToCellWeights");
3515 
3516  ValidatePointer(m_InputToOutputWeights, descriptorName, "InputToOutputWeights");
3517  auto inputToOutputWeightsInfo = m_InputToOutputWeights->GetTensorInfo();
3518  ValidateTensorNumDimNumElem(inputToOutputWeightsInfo, 2, (outputSize * inputSize), " InputToOutputWeights");
3519 
3520  ValidatePointer(m_RecurrentToInputWeights, descriptorName, "RecurrentToInputWeights");
3521  auto recurrentToInputWeightsInfo = m_RecurrentToInputWeights->GetTensorInfo();
3522  ValidateTensorNumDimNumElem(recurrentToInputWeightsInfo, 2, (outputSize * outputSize), " RecurrentToInputWeights");
3523 
3524  ValidatePointer(m_RecurrentToForgetWeights, descriptorName, "RecurrentToForgetWeights");
3525  auto recurrentToForgetWeightsInfo = m_RecurrentToForgetWeights->GetTensorInfo();
3526  ValidateTensorNumDimNumElem(recurrentToForgetWeightsInfo, 2, (outputSize * outputSize),
3527  " RecurrentToForgetWeights");
3528 
3529  ValidatePointer(m_RecurrentToCellWeights, descriptorName, "RecurrentToCellWeights");
3530  auto recurrentToCellWeightsInfo = m_RecurrentToCellWeights->GetTensorInfo();
3531  ValidateTensorNumDimNumElem(recurrentToCellWeightsInfo, 2, (outputSize * outputSize), " RecurrentToCellWeights");
3532 
3533  ValidatePointer(m_RecurrentToOutputWeights, descriptorName, "RecurrentToOutputWeights");
3534  auto recurrentToOutputWeightsInfo = m_RecurrentToOutputWeights->GetTensorInfo();
3535  ValidateTensorNumDimNumElem(recurrentToOutputWeightsInfo, 2, (outputSize * outputSize), " RecurrentToCellWeights");
3536 
3537  // Validate data types for weights tensors (all should match each other)
3538  ValidateDataTypes(inputToInputWeightsInfo, weightsSupportedTypes, descriptorName);
3539 
3540  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, inputToForgetWeightsInfo, descriptorName,
3541  "inputToInputWeights", "inputToForgetWeights");
3542  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, inputToCellWeightsInfo, descriptorName,
3543  "inputToInputWeights", "inputToCellWeights");
3544  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, inputToOutputWeightsInfo, descriptorName,
3545  "inputToInputWeights", "inputToOutputWeights");
3546 
3547  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToInputWeightsInfo, descriptorName,
3548  "inputToInputWeights", "recurrentToInputWeights");
3549  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToForgetWeightsInfo, descriptorName,
3550  "inputToInputWeights", "recurrentToForgeteights");
3551  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToCellWeightsInfo, descriptorName,
3552  "inputToInputWeights", "recurrentToCellWeights");
3553  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToOutputWeightsInfo, descriptorName,
3554  "inputToInputWeights", "recurrentToOutputWeights");
3555 
3556  // Validate matching quantization info for weight tensors (all should match each other)
3557  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, inputToForgetWeightsInfo,
3558  descriptorName, "inputToInputWeights", "inputToForgetWeights");
3559  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, inputToCellWeightsInfo,
3560  descriptorName, "inputToInputWeights", "inputToCellWeights");
3561  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, inputToOutputWeightsInfo,
3562  descriptorName, "inputToInputWeights", "inputToOutputWeights");
3563 
3564  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToInputWeightsInfo,
3565  descriptorName, "inputToInputWeights", "recurrentToInputWeights");
3566  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToForgetWeightsInfo,
3567  descriptorName, "inputToInputWeights", "recurrentToForgetWeights");
3568  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToCellWeightsInfo,
3569  descriptorName, "inputToInputWeights", "recurrentToCellWeights");
3570  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToOutputWeightsInfo,
3571  descriptorName, "inputToInputWeights", "recurrentToOutputWeights");
3572 
3573  // Validate number of dimensions and number of elements in bias tensors
3574  ValidatePointer(m_InputGateBias, descriptorName, "InputGateBias");
3575  auto inputGateBiasInfo = m_InputGateBias->GetTensorInfo();
3576  ValidateTensorNumDimNumElem(inputGateBiasInfo, 1, outputSize, " InputGateBias");
3577 
3578  ValidatePointer(m_ForgetGateBias, descriptorName, "ForgetGateBias");
3579  auto forgetGateBiasInfo = m_ForgetGateBias->GetTensorInfo();
3580  ValidateTensorNumDimNumElem(forgetGateBiasInfo, 1, outputSize, " ForgetGateBias");
3581 
3582  ValidatePointer(m_CellBias, descriptorName, "CellBias");
3583  auto cellBiasInfo = m_CellBias->GetTensorInfo();
3584  ValidateTensorNumDimNumElem(cellBiasInfo, 1, outputSize, " CellBias");
3585 
3586  ValidatePointer(m_OutputGateBias, descriptorName, "OutputGateBias");
3587  auto outputGateBiasInfo = m_OutputGateBias->GetTensorInfo();
3588  ValidateTensorNumDimNumElem(outputGateBiasInfo, 1, outputSize, " OutputGateBias");
3589 
3590  // Validate data types for bias tensors (all should match each other)
3591  ValidateDataTypes(inputGateBiasInfo, biasSupportedTypes, descriptorName);
3592 
3593  ValidateTensorDataTypesMatch(inputGateBiasInfo, forgetGateBiasInfo, descriptorName,
3594  "inputGateBias", "forgetGateBias");
3595  ValidateTensorDataTypesMatch(inputGateBiasInfo, cellBiasInfo, descriptorName,
3596  "inputGateBias", "cellBias");
3597  ValidateTensorDataTypesMatch(inputGateBiasInfo, outputGateBiasInfo, descriptorName,
3598  "inputGateBias", "outputGateBias");
3599 
3600  // Validate bias tensor quantization info
3601  ValidateBiasTensorQuantization(inputGateBiasInfo, inputToInputWeightsInfo, descriptorName);
3602  ValidateBiasTensorQuantization(forgetGateBiasInfo, inputToInputWeightsInfo, descriptorName);
3603  ValidateBiasTensorQuantization(cellBiasInfo, inputToInputWeightsInfo, descriptorName);
3604  ValidateBiasTensorQuantization(outputGateBiasInfo, inputToInputWeightsInfo, descriptorName);
3605 }
3606 
3607 void AbsQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3608 {
3609  const std::string descriptorName{"AbsQueueDescriptor"};
3610 
3611  ValidateNumInputs(workloadInfo, descriptorName, 1);
3612  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3613 
3614  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3615  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3616 
3617  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3618 
3619  std::vector<DataType> supportedTypes =
3620  {
3628  };
3629 
3630  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3631  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3632 }
3633 
3634 void SliceQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3635 {
3636  const std::string descriptorName{"SliceQueueDescriptor"};
3637 
3638  ValidateNumInputs(workloadInfo, descriptorName, 1);
3639  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3640 
3641  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3642  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3643 
3644  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3645 
3646  const unsigned int rank = inputTensorInfo.GetNumDimensions();
3647  if (rank > 5)
3648  {
3649  throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 5 are not supported.");
3650  }
3651 
3652  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, rank, "output");
3653 
3654  // Check if m_Begin and m_Size have the expected length
3655  if (m_Parameters.m_Begin.size() != rank)
3656  {
3657  throw InvalidArgumentException(descriptorName +
3658  ": Length of begin offset descriptor must equal rank " + std::to_string(rank));
3659  }
3660  if (m_Parameters.m_Size.size() != rank)
3661  {
3662  throw InvalidArgumentException(descriptorName +
3663  ": Length of size descriptor must equal rank " + std::to_string(rank));
3664  }
3665 
3666  // Check if the shape of the output tensor matches m_Size
3667  const TensorShape& outputShape = outputTensorInfo.GetShape();
3668  for (unsigned int i = 0u; i < rank; ++i)
3669  {
3670  if (m_Parameters.m_Size[i] != outputShape[i])
3671  {
3672  throw InvalidArgumentException(descriptorName + ": Size descriptor does not match output tensor.");
3673  }
3674  }
3675 
3676  // Check if the sum of begin offset and size in a given dimension
3677  // does not exceed the size of corresponding input
3678  const TensorShape& inputShape = inputTensorInfo.GetShape();
3679  for(unsigned int i = 0u; i < rank; ++i)
3680  {
3681  if (m_Parameters.m_Begin[i] + m_Parameters.m_Size[i] > inputShape[i])
3682  {
3683  throw InvalidArgumentException(descriptorName + ": Sum of begin offset and size for dimension " +
3684  std::to_string(i) + " exceeds input size.");
3685  }
3686  }
3687 }
3688 
3690 {
3691  const std::string descriptorName{"DepthToSpaceQueueDescriptor"};
3692 
3693  ValidateNumInputs(workloadInfo, descriptorName, 1);
3694  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3695 
3696  const TensorInfo& inputInfo = workloadInfo.m_InputTensorInfos[0];
3697  const TensorInfo& outputInfo = workloadInfo.m_OutputTensorInfos[0];
3698 
3699  ValidateTensorNumDimensions(inputInfo, descriptorName, 4, "input");
3700  ValidateTensorNumDimensions(outputInfo, descriptorName, 4, "output");
3701 
3702  std::vector<DataType> supportedTypes =
3703  {
3710  };
3711 
3712  ValidateDataTypes(inputInfo, supportedTypes, descriptorName);
3713  ValidateDataTypes(outputInfo, supportedTypes, descriptorName);
3714 
3715  ValidateTensorNumElementsMatch(inputInfo, outputInfo, descriptorName, "input", "output");
3716 
3717  if (m_Parameters.m_BlockSize == 0)
3718  {
3719  throw InvalidArgumentException(descriptorName + ": Block size cannot be 0.");
3720  }
3721 
3722  DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
3723  const unsigned int wIndex = dimensionIndices.GetWidthIndex();
3724  const unsigned int hIndex = dimensionIndices.GetHeightIndex();
3725  const unsigned int cIndex = dimensionIndices.GetChannelsIndex();
3726 
3727  const TensorShape& outputShape = outputInfo.GetShape();
3728  if (outputShape[hIndex] % m_Parameters.m_BlockSize != 0 || outputShape[wIndex] % m_Parameters.m_BlockSize != 0)
3729  {
3730  throw InvalidArgumentException(descriptorName + ": Output width and height shape"
3731  "must be divisible by block size.");
3732  }
3733 
3734  const TensorShape& inputShape = inputInfo.GetShape();
3735  if (inputShape[cIndex] % (m_Parameters.m_BlockSize * m_Parameters.m_BlockSize) != 0)
3736  {
3737  throw InvalidArgumentException(descriptorName + ": The depth of the input tensor"
3738  "must be divisible by the square of block size." );
3739  }
3740 }
3741 
3742 void ComparisonQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3743 {
3744  const std::string descriptorName{"ComparisonQueueDescriptor"};
3745 
3746  ValidateNumInputs(workloadInfo, descriptorName, 2);
3747  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3748 
3749  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
3750  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
3751  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3752 
3753  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
3754  inputTensorInfo1,
3755  outputTensorInfo,
3756  descriptorName,
3757  "input_0",
3758  "input_1");
3759 
3760  if (outputTensorInfo.GetDataType() != DataType::Boolean)
3761  {
3762  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
3763  }
3764 }
3765 
3767 {
3768  const std::string descriptorName{"ElementwiseBinaryQueueDescriptor"};
3769 
3770  ValidateNumInputs(workloadInfo, descriptorName, 2);
3771  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3772 
3773  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
3774  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
3775  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3776 
3777  std::vector<DataType> supportedTypes =
3778  {
3786  };
3787 
3788  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
3789  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
3790 
3791  ValidateTensorDataTypesMatch(inputTensorInfo0, outputTensorInfo, descriptorName, "input", "output");
3792  ValidateTensorDataTypesMatch(inputTensorInfo1, outputTensorInfo, descriptorName, "input", "output");
3793 }
3794 
3796 {
3797  const std::string descriptorName{"ElementwiseUnaryQueueDescriptor"};
3798 
3799  ValidateNumInputs(workloadInfo, descriptorName, 1);
3800  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3801 
3802  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3803  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3804 
3805  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3806 
3807  std::vector<DataType> supportedTypes =
3808  {
3816  };
3817 
3818  std::vector<DataType> logicalSupportedTypes =
3819  {
3821  };
3822 
3824  {
3825  ValidateDataTypes(inputTensorInfo, logicalSupportedTypes, descriptorName);
3826  }
3827  else
3828  {
3829  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3830  }
3831 
3832 
3833  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3834 }
3835 
3836 void RankQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3837 {
3838  const std::string descriptorName{"RankQueueDescriptor"};
3839 
3840  ValidateNumInputs(workloadInfo, descriptorName, 1);
3841  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3842 
3843  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3844  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3845 
3846  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 1, "output");
3847  ValidateTensorNumElements(outputTensorInfo, descriptorName, 1, "output");
3848 
3849  std::vector<DataType> supportedTypes =
3850  {
3859  };
3860 
3861  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3862  ValidateDataTypes(outputTensorInfo, { DataType::Signed32 }, descriptorName);
3863 }
3864 
3866 {
3867  const std::string descriptorName{"LogicalBinaryQueueDescriptor"};
3868 
3869  ValidateNumInputs(workloadInfo, descriptorName, 2);
3870  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3871 
3872  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
3873  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
3874  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3875 
3876  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
3877  inputTensorInfo1,
3878  outputTensorInfo,
3879  descriptorName,
3880  "input_0",
3881  "input_1");
3882 
3883  if (inputTensorInfo0.GetDataType() != DataType::Boolean)
3884  {
3885  throw InvalidArgumentException(descriptorName + ": Input tensor 0 type must be Boolean.");
3886  }
3887 
3888  if (inputTensorInfo1.GetDataType() != DataType::Boolean)
3889  {
3890  throw InvalidArgumentException(descriptorName + ": Input tensor 1 type must be Boolean.");
3891  }
3892 
3893  if (outputTensorInfo.GetDataType() != DataType::Boolean)
3894  {
3895  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
3896  }
3897 }
3898 
3899 void ReduceQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3900 {
3901  const std::string descriptorName{"ReduceQueueDescriptor"};
3902 
3903  ValidateNumInputs(workloadInfo, descriptorName, 1);
3904  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3905 
3906  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3907  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3908 
3909  std::vector<DataType> supportedTypes =
3910  {
3918  };
3919 
3920  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3921  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3922 }
3923 
3925 {
3926  // Modified from LstmQueueDescriptor::Validate to support UnidirectionalSequenceLstm
3927 
3928  const std::string descriptorName{"UnidirectionalSequenceLstmQueueDescriptor"};
3929 
3930  // check dimensions of all inputs and outputs
3931  if (workloadInfo.m_InputTensorInfos.size() != 3)
3932  {
3933  throw InvalidArgumentException(descriptorName + ": Invalid number of inputs.");
3934  }
3935  if (workloadInfo.m_OutputTensorInfos.size() != 3)
3936  {
3937  throw InvalidArgumentException(descriptorName + ": Invalid number of outputs.");
3938  }
3939 
3940  std::vector<DataType> supportedTypes =
3941  {
3944  };
3945 
3946  // check for supported type of one input and match them with all the other input and output
3947  ValidateDataTypes(workloadInfo.m_InputTensorInfos[0], supportedTypes, descriptorName);
3948 
3949  // Making sure clipping parameters have valid values.
3950  // == 0 means no clipping
3951  // > 0 means clipping
3952  if (m_Parameters.m_ClippingThresCell < 0.0f)
3953  {
3954  throw InvalidArgumentException(descriptorName + ": negative cell clipping threshold is invalid");
3955  }
3956  if (m_Parameters.m_ClippingThresProj < 0.0f)
3957  {
3958  throw InvalidArgumentException(descriptorName + ": negative projection clipping threshold is invalid");
3959  }
3960 
3961  unsigned int batchIndx = 0;
3962  unsigned int inputIndx = 1;
3963  uint32_t timeStep = 1;
3964  unsigned int timeIndx = 1;
3965  inputIndx = 2;
3967  {
3968  batchIndx = 1;
3969  timeIndx = 0;
3970 
3971  }
3972  timeStep = workloadInfo.m_InputTensorInfos[0].GetShape()[timeIndx];
3973 
3974  // Inferring batch size, number of outputs and number of cells from the inputs.
3975  const uint32_t n_input = workloadInfo.m_InputTensorInfos[0].GetShape()[inputIndx];
3976  const uint32_t n_batch = workloadInfo.m_InputTensorInfos[0].GetShape()[batchIndx];
3977  ValidatePointer(m_InputToOutputWeights, "Null pointer check", "InputToOutputWeights");
3978  const uint32_t n_cell = m_InputToOutputWeights->GetShape()[0];
3979  ValidatePointer(m_RecurrentToOutputWeights, "Null pointer check", "RecurrentToOutputWeights");
3980  const uint32_t n_output = m_RecurrentToOutputWeights->GetShape()[1];
3981 
3982  // input tensor
3983  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[0], 3, (timeStep * n_batch * n_input),
3984  descriptorName + " input_0");
3985  // outputStateInTensor
3986  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[1], 2, (n_batch * n_output),
3987  descriptorName + " input_1");
3988  // outputStateInTensor
3989  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[2], 2, (n_batch * n_cell),
3990  descriptorName + " input_2");
3991 
3992  // outputTensor
3993  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[2], 3, (timeStep * n_batch * n_output),
3994  descriptorName + " output_0");
3995 
3996  // check that dimensions of inputs/outputs and QueueDescriptor data match with each other
3997  if ( m_InputToInputWeights )
3998  {
4000  (n_cell * n_input), "InputLayerNormWeights");
4001  }
4002 
4003  ValidatePointer(m_InputToForgetWeights, "Null pointer check", "InputToForgetWeights");
4005  (n_cell * n_input), "InputToForgetWeights");
4006 
4007  ValidatePointer(m_InputToCellWeights, "Null pointer check", "InputToCellWeights");
4009  (n_cell * n_input), "InputToCellWeights");
4010 
4012  {
4014  (n_cell * n_output), "RecurrentToInputWeights");
4015  }
4016 
4017  ValidatePointer(m_RecurrentToForgetWeights, "Null pointer check", "RecurrentToForgetWeights");
4019  (n_cell * n_output), "RecurrentToForgetWeights");
4020 
4021  ValidatePointer(m_RecurrentToCellWeights, "Null pointer check", "RecurrentToCellWeights");
4023  (n_cell * n_output), "RecurrentToCellWeights");
4024 
4025  // Make sure the input-gate's parameters are either both present (regular
4026  // LSTM) or not at all (CIFG-LSTM). And CifgEnable is set accordingly.
4027  bool cifg_weights_all_or_none = ((m_InputToInputWeights && m_RecurrentToInputWeights &&
4031  if (!cifg_weights_all_or_none)
4032  {
4033  throw InvalidArgumentException(descriptorName + ": Input-Gate's parameters InputToInputWeights and "
4034  "RecurrentToInputWeights must either both be present (regular LSTM) "
4035  "or both not present (CIFG-LSTM). In addition CifgEnable must be set "
4036  "accordingly.");
4037  }
4038 
4039  if ( m_CellToInputWeights )
4040  {
4042  n_cell, "CellToInputWeights");
4043  }
4044  if ( m_CellToForgetWeights )
4045  {
4047  n_cell, "CellToForgetWeights");
4048  }
4049  if ( m_CellToOutputWeights )
4050  {
4052  n_cell, "CellToOutputWeights");
4053  }
4054 
4055  // Making sure the peephole weights are there all or none. And PeepholeEnable is set accordingly.
4056  bool peephole_weights_all_or_none =
4061  if (!peephole_weights_all_or_none)
4062  {
4063  throw InvalidArgumentException(descriptorName + ": Invalid combination of peephole parameters.");
4064  }
4065 
4066  // Make sure the input gate bias is present only when not a CIFG-LSTM.
4068  {
4069  if (m_InputGateBias)
4070  {
4071  throw InvalidArgumentException(descriptorName + ": InputGateBias is present and CIFG-LSTM is enabled.");
4072  }
4073  }
4074  else
4075  {
4076  if (!m_InputGateBias)
4077  {
4078  throw InvalidArgumentException(descriptorName + ": If CIFG-LSTM is disabled InputGateBias "
4079  "must be present.");
4080  }
4082  n_cell, "InputGateBias");
4083  }
4084 
4085  ValidatePointer(m_ForgetGateBias, "Null pointer check", "ForgetGateBias");
4086  ValidateTensorNumDimNumElem(m_ForgetGateBias->GetTensorInfo(), 1, n_cell, "ForgetGateBias");
4087 
4088  ValidatePointer(m_CellBias, "Null pointer check", "CellBias");
4089  ValidateTensorNumDimNumElem(m_CellBias->GetTensorInfo(), 1, n_cell, "CellBias");
4090 
4091  ValidatePointer(m_OutputGateBias, "Null pointer check", "OutputGateBias");
4092  ValidateTensorNumDimNumElem(m_OutputGateBias->GetTensorInfo(), 1, n_cell, "OutputGateBias");
4093 
4094  if (m_ProjectionWeights)
4095  {
4097  (n_cell * n_output), "ProjectionWeights");
4098  }
4099  if (m_ProjectionBias)
4100  {
4101  ValidateTensorNumDimNumElem(m_ProjectionBias->GetTensorInfo(), 1, n_output, "ProjectionBias");
4102  }
4103 
4104  // Making sure the projection tensors are consistent:
4105  // 1) If projection weight is not present, then projection bias should not be
4106  // present.
4107  // 2) If projection weight is present, then projection bias is optional.
4108  bool projecton_tensors_consistent = ((!m_ProjectionWeights && !m_ProjectionBias &&
4114  if (!projecton_tensors_consistent)
4115  {
4116  throw InvalidArgumentException(descriptorName + ": Projection tensors are inconsistent.");
4117  }
4118 
4119  // The four layer normalization weights either all have values or none of them have values. Additionally, if
4120  // CIFG is used, input layer normalization weights tensor is omitted and the other layer normalization weights
4121  // either all have values or none of them have values. Layer normalization is used when the values of all the
4122  // layer normalization weights are present
4124  {
4125  ValidateTensorNumDimNumElem(m_InputLayerNormWeights->GetTensorInfo(), 1, n_cell, "InputLayerNormWeights");
4126  }
4128  {
4129  ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
4130  }
4132  {
4133  ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
4134  }
4136  {
4137  ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
4138  }
4139 
4141  {
4143  {
4145  {
4146  throw InvalidArgumentException(descriptorName + ": Layer normalisation is enabled and CIFG-LSTM is "
4147  "disabled but InputLayerNormWeights are not present");
4148  }
4150  1, n_cell, "InputLayerNormWeights");
4151  }
4152  else if (m_InputLayerNormWeights)
4153  {
4154  throw InvalidArgumentException(descriptorName + ":InputLayerNormWeights are present while CIFG is "
4155  "enabled");
4156  }
4157 
4158  ValidatePointer(m_ForgetLayerNormWeights, "Null pointer check layer normalisation enabled",
4159  "ForgetLayerNormWeights");
4160  ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
4161 
4162  ValidatePointer(m_OutputLayerNormWeights, "Null pointer check layer normalisation enabled",
4163  "OutputLayerNormWeights");
4164  ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
4165 
4166  ValidatePointer(m_CellLayerNormWeights, "Null pointer check layer normalisation enabled",
4167  "CellLayerNormWeights");
4168  ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
4169  }
4171  {
4172  throw InvalidArgumentException(descriptorName + ": Layer normalisation is disabled but one or more layer "
4173  "normalisation weights are present.");
4174  }
4175 }
4176 
4178 {
4179  const std::string descriptorName{"BatchMatMulDescriptor"};
4180 
4181  ValidateNumInputs(workloadInfo, descriptorName, 2);
4182  ValidateNumOutputs(workloadInfo, descriptorName, 1);
4183 
4184  // Inputs must be: both 2D+
4185  // For inputs X and Y whose dimensions to be multiplied are (M,N) and (I,J) respectively,
4186  // axes N and I must be the same size
4187 
4188  const auto& inputXInfoBeforeParams = workloadInfo.m_InputTensorInfos[0];
4189  const auto& inputYInfoBeforeParams = workloadInfo.m_InputTensorInfos[1];
4190  const auto& outputInfo = workloadInfo.m_OutputTensorInfos[0];
4191  // Output info has already been inferred
4192 
4193  std::vector<DataType> supportedTypes =
4194  {
4201  };
4202 
4203  ValidateDataTypes(inputXInfoBeforeParams, supportedTypes, descriptorName);
4204  ValidateDataTypes(inputYInfoBeforeParams, supportedTypes, descriptorName);
4205  ValidateDataTypes(outputInfo, supportedTypes, descriptorName);
4206 
4207  if ((inputXInfoBeforeParams.GetNumDimensions() < 2) ||
4208  (inputYInfoBeforeParams.GetNumDimensions() < 2))
4209  {
4210  throw InvalidArgumentException(descriptorName + ": Input tensors are not 2D or greater.");
4211  }
4212 
4213  TensorInfo inputXInfoAfterParams;
4214  TensorInfo inputYInfoAfterParams;
4215 
4218  {
4219  throw InvalidArgumentException(descriptorName +
4220  ": Invalid descriptor parameters - Transpose and Adjoint "
4221  "cannot both be true for a given input tensor.");
4222  }
4224  {
4225  inputXInfoAfterParams = armnnUtils::Permuted(inputXInfoBeforeParams,
4228  inputXInfoBeforeParams.GetShape()));
4229  }
4230  else if(m_Parameters.m_AdjointX)
4231  {
4233  inputXInfoBeforeParams.GetShape());
4234  if(inputXInfoBeforeParams.GetShape()[axesToMul.first] !=
4235  inputXInfoBeforeParams.GetShape()[axesToMul.second])
4236  {
4237  throw InvalidArgumentException(descriptorName +
4238  ": Adjoint is set to true for input tensor X, but the axes to be adjointed are not square." );
4239  }
4240  // Shape remains the same as it's square
4241  inputXInfoAfterParams = inputXInfoBeforeParams;
4242  }
4243  else
4244  {
4245  inputXInfoAfterParams = inputXInfoBeforeParams;
4246  }
4247 
4249  {
4250  inputYInfoAfterParams = armnnUtils::Permuted(inputYInfoBeforeParams,
4253  inputYInfoBeforeParams.GetShape()));
4254  }
4255  else if(m_Parameters.m_AdjointY)
4256  {
4258  inputYInfoBeforeParams.GetShape());
4259  if(inputYInfoBeforeParams.GetShape()[axesToMul.first] !=
4260  inputYInfoBeforeParams.GetShape()[axesToMul.second])
4261  {
4262  throw InvalidArgumentException(descriptorName +
4263  ": Adjoint is set to true for input tensor Y, but the axes to be adjointed are not square." );
4264  }
4265  // Shape remains the same as it's square
4266  inputYInfoAfterParams = inputYInfoBeforeParams;
4267  }
4268  else
4269  {
4270  inputYInfoAfterParams = inputYInfoBeforeParams;
4271  }
4272 
4273  switch(m_Parameters.m_DataLayoutX)
4274  {
4275  case DataLayout::NCDHW:
4276  case DataLayout::NDHWC:
4277  if(inputXInfoAfterParams.GetNumDimensions() < 3)
4278  {
4279  throw InvalidArgumentException(descriptorName +
4280  ": Input tensor X does not have the correct "
4281  "number of dimensions for the Data Layout that it has been assigned.");
4282  }
4283  break;
4284  case DataLayout::NCHW:
4285  case DataLayout::NHWC:
4286  default:
4287  break;
4288  }
4289 
4290  switch(m_Parameters.m_DataLayoutY)
4291  {
4292  case DataLayout::NCDHW:
4293  case DataLayout::NDHWC:
4294  if(inputYInfoAfterParams.GetNumDimensions() < 3)
4295  {
4296  throw InvalidArgumentException(descriptorName +
4297  ": Input tensor Y does not have the correct "
4298  "number of dimensions for the Data Layout that it has been assigned.");
4299  }
4300  break;
4301  case DataLayout::NCHW:
4302  case DataLayout::NHWC:
4303  default:
4304  break;
4305  }
4306 
4308  inputXInfoAfterParams.GetShape());
4310  inputYInfoBeforeParams.GetShape());
4311 
4312  if(inputXInfoAfterParams.GetShape()[axesXToMul.second]
4313  != inputYInfoAfterParams.GetShape()[axesYToMul.first])
4314  {
4315  throw InvalidArgumentException(descriptorName +
4316  ": The final axis of input tensor X must be the same size as "
4317  "the second last axis of input tensor Y.");
4318  }
4319 
4320  { // Separate scope so we don't pollute the rest of the scope with our temp variables
4321  // e.g. NHWC isnt compatible with NCHW as of now
4324 
4325  if(xLayout == DataLayout::NCHW || xLayout == DataLayout::NCDHW)
4326  {
4327  if(yLayout == DataLayout::NHWC || yLayout == DataLayout::NDHWC)
4328  {
4329  throw InvalidArgumentException(descriptorName +
4330  ": Invalid input tensor data layout combination.");
4331  }
4332  }
4333  if(yLayout == DataLayout::NCHW || yLayout == DataLayout::NCDHW)
4334  {
4335  if(xLayout == DataLayout::NHWC || xLayout == DataLayout::NDHWC)
4336  {
4337  throw InvalidArgumentException(descriptorName +
4338  ": Invalid input tensor data layout combination.");
4339  }
4340  }
4341  }
4342 
4343  // Simulate aligning the ends of the matrix dims and prepending 1's to the beginning of the shorter one
4344  unsigned int outputTensorDimSize = std::max(inputXInfoAfterParams.GetNumDimensions(),
4345  inputYInfoAfterParams.GetNumDimensions());
4346  if(outputTensorDimSize-2 > 0)
4347  {
4348  TensorInfo tiXNotMul = TensorInfo(TensorShape(outputTensorDimSize-2),
4350  TensorInfo tiYNotMul = TensorInfo(TensorShape(outputTensorDimSize-2),
4352  TensorInfo tiOutNotMul = TensorInfo(TensorShape(outputTensorDimSize-2),
4354 
4355  auto doAxisExtension = [&](std::vector<unsigned int> axisIndices, TensorInfo& ti)
4356  {
4357  auto sizeDiff = (outputTensorDimSize-2) - axisIndices.size();
4358 
4359  for(unsigned int i = 0; i < sizeDiff; i++)
4360  {
4361  axisIndices.insert(axisIndices.begin(), 1);
4362  }
4363 
4364  for(unsigned int i = 0; i < ti.GetNumDimensions(); i++)
4365  {
4366  ti.GetShape()[i] = inputXInfoAfterParams.GetShape()[i];
4367  }
4368  };
4369 
4371  inputXInfoAfterParams.GetShape());
4373  inputYInfoAfterParams.GetShape());
4374 
4375  doAxisExtension(axesXNotMul, tiXNotMul);
4376  doAxisExtension(axesYNotMul, tiYNotMul);
4377 
4378  for(unsigned int i = 0; i < tiOutNotMul.GetNumDimensions(); i++)
4379  {
4380  tiOutNotMul.GetShape()[i] = std::max(tiXNotMul.GetShape()[i],
4381  tiYNotMul.GetShape()[i]);
4382  }
4383 
4384  ValidateBroadcastTensorShapesMatch(tiXNotMul,
4385  tiYNotMul,
4386  tiOutNotMul,
4387  descriptorName,
4388  "input_X",
4389  "input_Y");
4390  }
4391 }
4392 
4393 void TileQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
4394 {
4395  const std::string& descriptorName{"TileQueueDescriptor"};
4396 
4397  ValidateNumInputs(workloadInfo, descriptorName, 1);
4398  ValidateNumOutputs(workloadInfo, descriptorName, 1);
4399 
4400  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
4401  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
4402 
4403  std::vector<DataType> supportedTypes =
4404  {
4412  };
4413 
4414  // Multiples length must be the same as the number of dimensions in input.
4415  if (m_Parameters.m_Multiples.size() != inputTensorInfo.GetNumDimensions())
4416  {
4417  throw InvalidArgumentException(descriptorName +
4418  ": Multiples length is not same as the number of dimensions in Input.");
4419  }
4420 
4421  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
4422  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
4423 }
4424 
4426 {
4427  const std::string& descriptorName{"BroadcastToQueueDescriptor"};
4428 
4429  ValidateNumInputs(workloadInfo, descriptorName, 1);
4430  ValidateNumOutputs(workloadInfo, descriptorName, 1);
4431 
4432  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
4433  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
4434 
4435  std::vector<DataType> supportedTypes =
4436  {
4445  };
4446 
4447  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
4448  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
4449 }
4450 
4451 void ScatterNdQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
4452 {
4453  const std::string& descriptorName{"ScatterQueueDescriptor"};
4454 
4455  ValidateNumInputs(workloadInfo, descriptorName, 3);
4456  ValidateNumOutputs(workloadInfo, descriptorName, 1);
4457 
4458  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
4459  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
4460  const TensorInfo& inputTensorInfo2 = workloadInfo.m_InputTensorInfos[2];
4461  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
4462 
4463  std::vector<DataType> supportedTypes =
4464  {
4472  };
4473 
4474  std::vector<DataType> indicesSupportedTypes =
4475  {
4477  };
4478 
4480  {
4481  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
4482  }
4483  else
4484  {
4485  ValidateDataTypes(inputTensorInfo0, indicesSupportedTypes, descriptorName);
4486  }
4487 
4488  ValidateDataTypes(inputTensorInfo1, indicesSupportedTypes, descriptorName);
4489  ValidateDataTypes(inputTensorInfo2, supportedTypes, descriptorName);
4490  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
4491 }
4492 
4493 } // namespace armnn
armnn::LstmQueueDescriptor::m_ForgetLayerNormWeights
const ConstTensorHandle * m_ForgetLayerNormWeights
Definition: WorkloadData.hpp:445
armnn::LstmQueueDescriptor::m_CellBias
const ConstTensorHandle * m_CellBias
Definition: WorkloadData.hpp:440
armnn::SliceDescriptor::m_Begin
std::vector< unsigned int > m_Begin
Beginning indices of the slice in each dimension.
Definition: Descriptors.hpp:1244
armnn::QuantizedLstmQueueDescriptor::m_CellBias
const ConstTensorHandle * m_CellBias
Definition: WorkloadData.hpp:645
armnn::ShapeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2947
armnn::OriginsDescriptor::GetConcatAxis
unsigned int GetConcatAxis() const
Get the concatenation axis value.
Definition: Descriptors.cpp:162
armnn::DataType::Boolean
@ Boolean
armnn::TensorInfo::GetNumElements
unsigned int GetNumElements() const
Definition: Tensor.hpp:198
armnn::BatchMatMulDescriptor::m_TransposeX
bool m_TransposeX
Transpose the slices of each input tensor Transpose and Adjoint can not both be set to true for the s...
Definition: Descriptors.hpp:1612
armnn::QuantizedLstmQueueDescriptor::m_RecurrentToInputWeights
const ConstTensorHandle * m_RecurrentToInputWeights
Definition: WorkloadData.hpp:638
armnn::ConstTensorHandle::GetShape
TensorShape GetShape() const override
Get the number of elements for each dimension ordered from slowest iterating dimension to fastest ite...
Definition: TensorHandle.hpp:56
armnn::FillQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1012
armnn::MinimumQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2645
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_CellBias
const ConstTensorHandle * m_CellBias
Definition: WorkloadData.hpp:736
armnn::QuantizedLstmQueueDescriptor::m_InputToForgetWeights
const ConstTensorHandle * m_InputToForgetWeights
Definition: WorkloadData.hpp:634
armnn::Optional< unsigned int >
armnn::DataLayout::NCDHW
@ NCDHW
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_RecurrentToCellWeights
const ConstTensorHandle * m_RecurrentToCellWeights
Definition: WorkloadData.hpp:729
armnn::BroadcastToQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:4425
armnn::IsQuantized8BitType
constexpr bool IsQuantized8BitType(DataType dataType)
Definition: TypesUtils.hpp:316
armnn::QLstmDescriptor::m_ProjectionEnabled
bool m_ProjectionEnabled
Enable/disable the projection layer.
Definition: Descriptors.hpp:1422
armnn::LstmDescriptor::m_TimeMajor
bool m_TimeMajor
Enable/disable time major.
Definition: Descriptors.hpp:1154
armnn::BatchNormalizationQueueDescriptor::m_Gamma
const ConstTensorHandle * m_Gamma
Definition: WorkloadData.hpp:324
armnn::DataLayout
DataLayout
Definition: Types.hpp:62
armnn::SpaceToBatchNdDescriptor::m_DataLayout
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Definition: Descriptors.hpp:1071
armnn::StridedSliceQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2588
WorkloadData.hpp
armnn::PreCompiledQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3014
armnn::DepthwiseConvolution2dDescriptor::m_BiasEnabled
bool m_BiasEnabled
Enable/disable bias.
Definition: Descriptors.hpp:708
armnn::MemCopyQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:491
armnn::TensorInfo::GetQuantizationScales
std::vector< float > GetQuantizationScales() const
Definition: Tensor.cpp:451
armnn::StridedSliceDescriptor::m_Begin
std::vector< int > m_Begin
Begin values for the input that will be sliced.
Definition: Descriptors.hpp:1342
armnn::BatchMatMulDescriptor::m_AdjointX
bool m_AdjointX
Adjoint the slices of each input tensor Transpose and Adjoint can not both be set to true for the sam...
Definition: Descriptors.hpp:1617
armnn::DataLayout::NHWC
@ NHWC
armnn::BatchMatMulDescriptor::GetAxesToMul
static std::pair< unsigned int, unsigned int > GetAxesToMul(DataLayout dataLayout, const TensorShape &tensorShape)
Static helper to get the two axes (for each input) for multiplication.
Definition: Descriptors.cpp:485
armnn::EqualQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2687
armnn::LstmQueueDescriptor::m_InputToInputWeights
const ConstTensorHandle * m_InputToInputWeights
Definition: WorkloadData.hpp:427
armnn::QueueDescriptor::ValidateInputsOutputs
void ValidateInputsOutputs(const std::string &descName, unsigned int numExpectedIn, unsigned int numExpectedOut) const
Definition: WorkloadData.cpp:447
armnn::FusedQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1099
armnn::QLstmQueueDescriptor::m_InputToForgetWeights
const ConstTensorHandle * m_InputToForgetWeights
Definition: WorkloadData.hpp:590
armnnUtils::GetUnsignedAxis
unsigned int GetUnsignedAxis(const unsigned int inputDimension, const int axis)
Definition: TensorUtils.cpp:236
armnn::DequantizeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2899
armnn::QLstmQueueDescriptor::m_InputLayerNormWeights
const ConstTensorHandle * m_InputLayerNormWeights
Definition: WorkloadData.hpp:606
armnn::LogSoftmaxQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1768
armnn::TensorInfo::GetQuantizationScale
float GetQuantizationScale() const
Definition: Tensor.cpp:461
armnn::DepthwiseConvolution2dDescriptor::m_DataLayout
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Definition: Descriptors.hpp:710
armnn::BatchNormalizationQueueDescriptor::m_Variance
const ConstTensorHandle * m_Variance
Definition: WorkloadData.hpp:322
armnn::LstmQueueDescriptor::m_ForgetGateBias
const ConstTensorHandle * m_ForgetGateBias
Definition: WorkloadData.hpp:439
armnn::ScatterNdDescriptor::m_InputEnabled
bool m_InputEnabled
Flag to show if input tensor is accepted.
Definition: Descriptors.hpp:1722
armnn::BatchMatMulDescriptor::m_DataLayoutX
DataLayout m_DataLayoutX
Data layout of each input tensor, such as NHWC/NDHWC (leave as default for arbitrary layout)
Definition: Descriptors.hpp:1621
armnn::TensorInfo
Definition: Tensor.hpp:152
armnn::Pooling3dQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1551
armnn::LstmQueueDescriptor::m_InputToForgetWeights
const ConstTensorHandle * m_InputToForgetWeights
Definition: WorkloadData.hpp:428
armnn::GetDataTypeName
constexpr const char * GetDataTypeName(DataType dataType)
Definition: TypesUtils.hpp:233
armnn::FakeQuantizationDescriptor::m_Max
float m_Max
Maximum value.
Definition: Descriptors.hpp:921
armnn::QLstmQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3150
armnn::TensorInfo::GetNumDimensions
unsigned int GetNumDimensions() const
Definition: Tensor.hpp:197
armnn::QuantizedLstmQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3436
armnn::TransposeConvolution2dQueueDescriptor::m_Weight
const ConstTensorHandle * m_Weight
Definition: WorkloadData.hpp:551
armnn::BatchToSpaceNdDescriptor::m_BlockShape
std::vector< unsigned int > m_BlockShape
Block shape values.
Definition: Descriptors.hpp:898
CHECK_LOCATION
#define CHECK_LOCATION()
Definition: Exceptions.hpp:203
armnn::TransposeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3108
armnnUtils::DataLayoutIndexed
Provides access to the appropriate indexes for Channels, Height and Width based on DataLayout.
Definition: DataLayoutIndexed.hpp:17
armnn::QueueDescriptor::m_AllowExpandedDims
bool m_AllowExpandedDims
Definition: WorkloadData.hpp:52
armnn::DataType::Float32
@ Float32
armnn::BatchMatMulDescriptor::GetPermuteVec
static PermutationVector GetPermuteVec(DataLayout dataLayout, const TensorShape &tensorShape)
Static helper to get the axes which will be transposed.
Definition: Descriptors.cpp:523
armnn::ResizeDescriptor::m_DataLayout
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Definition: Descriptors.hpp:1014
armnn::Convolution2dDescriptor::m_StrideY
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
Definition: Descriptors.hpp:576
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_InputLayerNormWeights
const ConstTensorHandle * m_InputLayerNormWeights
Definition: WorkloadData.hpp:740
armnn::SpaceToBatchNdDescriptor::m_BlockShape
std::vector< unsigned int > m_BlockShape
Block shape value.
Definition: Descriptors.hpp:1066
armnn::BatchNormalizationQueueDescriptor::m_Mean
const ConstTensorHandle * m_Mean
Definition: WorkloadData.hpp:321
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_InputToOutputWeights
const ConstTensorHandle * m_InputToOutputWeights
Definition: WorkloadData.hpp:726
armnn::BatchMatMulDescriptor::m_AdjointY
bool m_AdjointY
Definition: Descriptors.hpp:1618
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_OutputLayerNormWeights
const ConstTensorHandle * m_OutputLayerNormWeights
Definition: WorkloadData.hpp:743
armnn::QuantizedLstmQueueDescriptor::m_RecurrentToOutputWeights
const ConstTensorHandle * m_RecurrentToOutputWeights
Definition: WorkloadData.hpp:641
armnn::QuantizedLstmQueueDescriptor::m_InputGateBias
const ConstTensorHandle * m_InputGateBias
Definition: WorkloadData.hpp:643
armnn::DataType::QAsymmU8
@ QAsymmU8
armnn::ConstTensorHandle::GetTensorInfo
const TensorInfo & GetTensorInfo() const
Definition: TensorHandle.hpp:40
armnn::UnidirectionalSequenceLstmQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3924
armnn::DataType::QSymmS8
@ QSymmS8
armnn::DepthwiseConvolution2dQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1391
armnn::LstmQueueDescriptor::m_InputToCellWeights
const ConstTensorHandle * m_InputToCellWeights
Definition: WorkloadData.hpp:429
armnn::ElementwiseUnaryQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3795
armnnUtils::Permuted
armnn::TensorShape Permuted(const armnn::TensorShape &srcShape, const armnn::PermutationVector &mappings)
Definition: Permute.cpp:125
armnn::GatherQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2796
armnn::ReverseV2QueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1626
armnn::QLstmQueueDescriptor::m_InputToInputWeights
const ConstTensorHandle * m_InputToInputWeights
Definition: WorkloadData.hpp:589
armnn::BatchMatMulQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:4177
armnn::SplitterQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:748
armnn::BatchToSpaceNdDescriptor::m_Crops
std::vector< std::pair< unsigned int, unsigned int > > m_Crops
The values to crop from the input dimension.
Definition: Descriptors.hpp:900
armnn::TensorInfo::HasPerAxisQuantization
bool HasPerAxisQuantization() const
Definition: Tensor.cpp:446
armnn::DepthwiseConvolution2dDescriptor::m_StrideY
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
Definition: Descriptors.hpp:702
armnn::SplitterQueueDescriptor::m_ViewOrigins
std::vector< ViewOrigin > m_ViewOrigins
Definition: WorkloadData.hpp:124
armnn::FloorQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1990
armnn::DetectionPostProcessQueueDescriptor::m_Anchors
const ConstTensorHandle * m_Anchors
Definition: WorkloadData.hpp:246
armnn::DataType::QSymmS16
@ QSymmS16
armnn::AbsQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3607
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_OutputGateBias
const ConstTensorHandle * m_OutputGateBias
Definition: WorkloadData.hpp:737
NumericCast.hpp
armnn::DataType::BFloat16
@ BFloat16
armnn::QLstmQueueDescriptor::m_ProjectionWeights
const ConstTensorHandle * m_ProjectionWeights
Definition: WorkloadData.hpp:604
armnn::QLstmQueueDescriptor::m_ForgetLayerNormWeights
const ConstTensorHandle * m_ForgetLayerNormWeights
Definition: WorkloadData.hpp:607
armnn::LstmQueueDescriptor::m_CellToOutputWeights
const ConstTensorHandle * m_CellToOutputWeights
Definition: WorkloadData.hpp:437
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_ForgetLayerNormWeights
const ConstTensorHandle * m_ForgetLayerNormWeights
Definition: WorkloadData.hpp:741
armnn::InstanceNormalizationQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1707
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_InputToForgetWeights
const ConstTensorHandle * m_InputToForgetWeights
Definition: WorkloadData.hpp:724
TensorUtils.hpp
armnn::QLstmQueueDescriptor::m_RecurrentToOutputWeights
const ConstTensorHandle * m_RecurrentToOutputWeights
Definition: WorkloadData.hpp:596
armnnUtils::DataLayoutIndexed::GetHeightIndex
unsigned int GetHeightIndex() const
Definition: DataLayoutIndexed.hpp:24
armnn::MeanDescriptor::m_KeepDims
bool m_KeepDims
Enable/disable keep dimensions. If true, then the reduced dimensions that are of length 1 are kept.
Definition: Descriptors.hpp:1192
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_RecurrentToOutputWeights
const ConstTensorHandle * m_RecurrentToOutputWeights
Definition: WorkloadData.hpp:730
armnn::DetectionPostProcessQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2831
armnn::DataLayout::NDHWC
@ NDHWC
armnn::ActivationQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:604
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_ProjectionWeights
const ConstTensorHandle * m_ProjectionWeights
Definition: WorkloadData.hpp:738
armnn::SplitterQueueDescriptor::ViewOrigin
Definition: WorkloadData.hpp:113
armnn::SpaceToBatchNdDescriptor::m_PadList
std::vector< std::pair< unsigned int, unsigned int > > m_PadList
Specifies the padding values for the input dimension: heightPad{top, bottom} widthPad{left,...
Definition: Descriptors.hpp:1069
armnn::LstmDescriptor::m_PeepholeEnabled
bool m_PeepholeEnabled
Enable/disable peephole.
Definition: Descriptors.hpp:1148
armnn::TensorShape
Definition: Tensor.hpp:20
armnn::FakeQuantizationQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1686
armnn::StackDescriptor::m_NumInputs
uint32_t m_NumInputs
Number of input tensors.
Definition: Descriptors.hpp:1275
armnn::QuantizedLstmQueueDescriptor::m_RecurrentToCellWeights
const ConstTensorHandle * m_RecurrentToCellWeights
Definition: WorkloadData.hpp:640
armnn::DataType::Float16
@ Float16
armnn::WorkloadInfo::m_OutputTensorInfos
std::vector< TensorInfo > m_OutputTensorInfos
Definition: WorkloadInfo.hpp:19
armnn::BatchNormalizationQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1206
armnn::QLstmQueueDescriptor::m_CellToOutputWeights
const ConstTensorHandle * m_CellToOutputWeights
Definition: WorkloadData.hpp:599
armnn::ConcatQueueDescriptor::ViewOrigin
Definition: WorkloadData.hpp:132
armnn::LstmDescriptor::m_ClippingThresProj
float m_ClippingThresProj
Clipping threshold value for the projection.
Definition: Descriptors.hpp:1144
armnn::QueueDescriptorWithParameters< ArgMinMaxDescriptor >::m_Parameters
ArgMinMaxDescriptor m_Parameters
Definition: WorkloadData.hpp:66
armnn::TensorShape::GetNumDimensions
unsigned int GetNumDimensions() const
Function that returns the tensor rank.
Definition: Tensor.cpp:174
armnn::DepthwiseConvolution2dDescriptor::m_DilationY
uint32_t m_DilationY
Dilation factor value for height dimension.
Definition: Descriptors.hpp:706
armnn::UnaryOperation::LogicalNot
@ LogicalNot
armnn::QLstmQueueDescriptor::m_CellToForgetWeights
const ConstTensorHandle * m_CellToForgetWeights
Definition: WorkloadData.hpp:598
armnn::PermuteQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1495
armnn::FullyConnectedDescriptor::m_BiasEnabled
bool m_BiasEnabled
Enable/disable bias.
Definition: Descriptors.hpp:526
armnn::MapQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:455
armnn::MaximumQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2398
Logging.hpp
armnn::DebugQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2679
armnn::ElementwiseBinaryQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3766
armnn::QuantizedLstmQueueDescriptor::m_InputToInputWeights
const ConstTensorHandle * m_InputToInputWeights
Definition: WorkloadData.hpp:633
armnn::MemImportQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:527
armnn::BatchMatMulDescriptor::m_TransposeY
bool m_TransposeY
Definition: Descriptors.hpp:1613
armnn::DetectionPostProcessDescriptor::m_NumClasses
uint32_t m_NumClasses
Number of classes.
Definition: Descriptors.hpp:755
armnn::TensorInfo::GetQuantizationDim
Optional< unsigned int > GetQuantizationDim() const
Definition: Tensor.cpp:498
armnn::WorkloadInfo
Contains information about TensorInfos of a layer.
Definition: WorkloadInfo.hpp:16
armnn::ConcatQueueDescriptor::ViewOrigin::m_Origin
std::vector< unsigned int > m_Origin
Definition: WorkloadData.hpp:138
armnn::StackDescriptor::m_Axis
uint32_t m_Axis
0-based axis along which to stack the input tensors.
Definition: Descriptors.hpp:1273
armnn::TensorInfo::HasMultipleQuantizationScales
bool HasMultipleQuantizationScales() const
Definition: Tensor.hpp:203
armnn::DataType
DataType
Definition: Types.hpp:48
armnn::TensorInfo::IsQuantized
bool IsQuantized() const
Definition: Tensor.cpp:508
armnn::DetectionPostProcessDescriptor::m_NmsIouThreshold
float m_NmsIouThreshold
Intersection over union threshold.
Definition: Descriptors.hpp:753
armnn::RankQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3836
armnn::TileQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:4393
armnn::TensorInfo::IsTypeSpaceMatch
bool IsTypeSpaceMatch(const TensorInfo &other) const
Check that the types are the same and, if quantize, that the quantization parameters are the same.
Definition: Tensor.cpp:432
armnn::LogicalBinaryQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3865
armnn::SubtractionQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2364
armnn::Convolution2dDescriptor::m_BiasEnabled
bool m_BiasEnabled
Enable/disable bias.
Definition: Descriptors.hpp:582
armnn::ChannelShuffleQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3137
armnn::BatchMatMulDescriptor::m_DataLayoutY
DataLayout m_DataLayoutY
Definition: Descriptors.hpp:1622
armnn::MeanQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2432
armnn::QLstmQueueDescriptor::m_OutputLayerNormWeights
const ConstTensorHandle * m_OutputLayerNormWeights
Definition: WorkloadData.hpp:609
armnnUtils
Definition: CompatibleTypes.hpp:10
armnn::InvalidArgumentException
Definition: Exceptions.hpp:80
armnn::ConcatQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:820
armnn::QLstmQueueDescriptor::m_InputGateBias
const ConstTensorHandle * m_InputGateBias
Definition: WorkloadData.hpp:600
armnn::BatchNormalizationQueueDescriptor::m_Beta
const ConstTensorHandle * m_Beta
Definition: WorkloadData.hpp:323
armnn::QuantizedLstmQueueDescriptor::m_RecurrentToForgetWeights
const ConstTensorHandle * m_RecurrentToForgetWeights
Definition: WorkloadData.hpp:639
armnn::QLstmQueueDescriptor::m_OutputGateBias
const ConstTensorHandle * m_OutputGateBias
Definition: WorkloadData.hpp:603
armnn::ResizeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1578
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_ForgetGateBias
const ConstTensorHandle * m_ForgetGateBias
Definition: WorkloadData.hpp:735
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_InputGateBias
const ConstTensorHandle * m_InputGateBias
Definition: WorkloadData.hpp:734
armnn::DivisionQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2330
armnn::QLstmQueueDescriptor::m_ForgetGateBias
const ConstTensorHandle * m_ForgetGateBias
Definition: WorkloadData.hpp:601
armnn::Convolution3dDescriptor::m_StrideY
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
Definition: Descriptors.hpp:643
armnn::ConstantQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1791
armnn::QuantizedLstmQueueDescriptor::m_InputToCellWeights
const ConstTensorHandle * m_InputToCellWeights
Definition: WorkloadData.hpp:635
armnn::Convolution3dDescriptor::m_StrideX
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
Definition: Descriptors.hpp:641
armnn::PreluQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3019
armnn::LstmQueueDescriptor::m_InputGateBias
const ConstTensorHandle * m_InputGateBias
Definition: WorkloadData.hpp:438
armnn::PermutationVector
Definition: Types.hpp:314
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_CellToInputWeights
const ConstTensorHandle * m_CellToInputWeights
Definition: WorkloadData.hpp:731
armnn::Pooling2dQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1524
armnnUtils::DataLayoutIndexed::GetWidthIndex
unsigned int GetWidthIndex() const
Definition: DataLayoutIndexed.hpp:25
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_CellToOutputWeights
const ConstTensorHandle * m_CellToOutputWeights
Definition: WorkloadData.hpp:733
armnn::GreaterQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2711
armnn::TransposeConvolution2dQueueDescriptor::m_Bias
const ConstTensorHandle * m_Bias
Definition: WorkloadData.hpp:552
armnn::LstmQueueDescriptor::m_RecurrentToCellWeights
const ConstTensorHandle * m_RecurrentToCellWeights
Definition: WorkloadData.hpp:433
armnn::QLstmQueueDescriptor::m_RecurrentToInputWeights
const ConstTensorHandle * m_RecurrentToInputWeights
Definition: WorkloadData.hpp:593
Permute.hpp
armnn::PermuteDescriptor::m_DimMappings
PermutationVector m_DimMappings
Indicates how to translate tensor elements from a given source into the target destination,...
Definition: Descriptors.hpp:173
armnn::BoostLogSeverityMapping::info
@ info
armnn::StackDescriptor::m_InputShape
TensorShape m_InputShape
Required shape of all input tensors.
Definition: Descriptors.hpp:1277
armnn::Convolution2dDescriptor::m_StrideX
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
Definition: Descriptors.hpp:574
armnn::TensorInfo::GetDataType
DataType GetDataType() const
Definition: Tensor.hpp:200
armnn::LstmQueueDescriptor::m_CellLayerNormWeights
const ConstTensorHandle * m_CellLayerNormWeights
Definition: WorkloadData.hpp:446
armnn::QueueDescriptor::m_Outputs
std::vector< ITensorHandle * > m_Outputs
Definition: WorkloadData.hpp:27
armnn::CastQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:695
armnn::RsqrtQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2735
armnn::QuantizedLstmQueueDescriptor::m_InputToOutputWeights
const ConstTensorHandle * m_InputToOutputWeights
Definition: WorkloadData.hpp:636
armnn::DataType::Signed32
@ Signed32
armnn::QLstmQueueDescriptor::m_RecurrentToForgetWeights
const ConstTensorHandle * m_RecurrentToForgetWeights
Definition: WorkloadData.hpp:594
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_RecurrentToForgetWeights
const ConstTensorHandle * m_RecurrentToForgetWeights
Definition: WorkloadData.hpp:728
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_CellToForgetWeights
const ConstTensorHandle * m_CellToForgetWeights
Definition: WorkloadData.hpp:732
armnn::DataType::QAsymmS8
@ QAsymmS8
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_RecurrentToInputWeights
const ConstTensorHandle * m_RecurrentToInputWeights
Definition: WorkloadData.hpp:727
armnn::ElementwiseUnaryDescriptor::m_Operation
UnaryOperation m_Operation
Specifies the elementwiseUnary operation to execute.
Definition: Descriptors.hpp:145
armnn::Convolution2dQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1252
armnn::FullyConnectedQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1035
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_InputToInputWeights
const ConstTensorHandle * m_InputToInputWeights
Definition: WorkloadData.hpp:723
armnn::ConstantQueueDescriptor::m_LayerOutput
const ConstTensorHandle * m_LayerOutput
Definition: WorkloadData.hpp:375
armnn::DepthToSpaceQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3689
armnn::SpaceToDepthDescriptor::m_BlockSize
unsigned int m_BlockSize
Scalar specifying the input block size. It must be >= 1.
Definition: Descriptors.hpp:1092
armnn::SoftmaxQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:723
armnn::BatchToSpaceNdQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2528
armnn::StridedSliceDescriptor::m_Stride
std::vector< int > m_Stride
Stride values for the input that will be sliced.
Definition: Descriptors.hpp:1346
armnn::TransposeConvolution2dQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3056
armnn::SpaceToDepthQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1937
armnn::PermutationVector::GetSize
SizeType GetSize() const
Definition: Types.hpp:357
armnn::MergeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2929
armnn::TransposeDescriptor::m_DimMappings
PermutationVector m_DimMappings
Indicates how to translate tensor elements from a given source into the target destination,...
Definition: Descriptors.hpp:1514
TensorHandle.hpp
armnn::SplitterQueueDescriptor::ViewOrigin::m_Origin
std::vector< unsigned int > m_Origin
Definition: WorkloadData.hpp:119
armnn::TileDescriptor::m_Multiples
std::vector< uint32_t > m_Multiples
The vector to multiply the input shape by.
Definition: Descriptors.hpp:1656
armnn::MeanDescriptor::m_Axis
std::vector< unsigned int > m_Axis
Values for the dimensions to reduce.
Definition: Descriptors.hpp:1190
armnn::LstmDescriptor::m_CifgEnabled
bool m_CifgEnabled
Enable/disable cifg (coupled input & forget gate).
Definition: Descriptors.hpp:1146
armnn::LstmQueueDescriptor::m_RecurrentToOutputWeights
const ConstTensorHandle * m_RecurrentToOutputWeights
Definition: WorkloadData.hpp:434
armnn::ScatterNdQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:4451
armnn::QLstmQueueDescriptor::m_InputToOutputWeights
const ConstTensorHandle * m_InputToOutputWeights
Definition: WorkloadData.hpp:592
armnn::GatherNdQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2761
armnn::TensorInfo::GetShape
const TensorShape & GetShape() const
Definition: Tensor.hpp:193
armnn::QLstmDescriptor::m_HiddenStateZeroPoint
int32_t m_HiddenStateZeroPoint
Hidden State zero point.
Definition: Descriptors.hpp:1434
armnn::NormalizationQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1104
armnn::LstmQueueDescriptor::m_InputLayerNormWeights
const ConstTensorHandle * m_InputLayerNormWeights
Definition: WorkloadData.hpp:444
armnn::GetBiasDataType
DataType GetBiasDataType(DataType inputDataType)
Definition: WorkloadData.cpp:28
armnn::PadDescriptor::m_PadList
std::vector< std::pair< unsigned int, unsigned int > > m_PadList
Specifies the padding for input dimension.
Definition: Descriptors.hpp:1218
armnn::LstmDescriptor::m_LayerNormEnabled
bool m_LayerNormEnabled
Enable/disable layer normalization.
Definition: Descriptors.hpp:1152
armnn::MemSyncQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:583
armnn::LstmQueueDescriptor::m_RecurrentToForgetWeights
const ConstTensorHandle * m_RecurrentToForgetWeights
Definition: WorkloadData.hpp:432
armnn::SwitchQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2973
armnn::WorkloadInfo::m_InputTensorInfos
std::vector< TensorInfo > m_InputTensorInfos
Definition: WorkloadInfo.hpp:18
armnn::QLstmDescriptor::m_CifgEnabled
bool m_CifgEnabled
Enable/disable CIFG (coupled input & forget gate).
Definition: Descriptors.hpp:1418
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_ProjectionBias
const ConstTensorHandle * m_ProjectionBias
Definition: WorkloadData.hpp:739
armnn::ConcatQueueDescriptor::m_ViewOrigins
std::vector< ViewOrigin > m_ViewOrigins
Definition: WorkloadData.hpp:143
armnn::ComparisonQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3742
armnn::LstmQueueDescriptor::m_ProjectionWeights
const ConstTensorHandle * m_ProjectionWeights
Definition: WorkloadData.hpp:442
armnn::LstmQueueDescriptor::m_CellToInputWeights
const ConstTensorHandle * m_CellToInputWeights
Definition: WorkloadData.hpp:435
armnn::IsQuantizedType
constexpr bool IsQuantizedType()
Definition: TypesUtils.hpp:311
armnn::SliceQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3634
armnn::QueueDescriptor::ValidateTensorNumDimensions
void ValidateTensorNumDimensions(const TensorInfo &tensor, std::string const &descName, unsigned int numDimensions, std::string const &tensorName) const
Definition: WorkloadData.cpp:398
armnn::SpaceToBatchNdQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1851
armnn
Copyright (c) 2021 ARM Limited and Contributors.
Definition: 01_00_quick_start.dox:6
armnn::Convolution3dDescriptor::m_BiasEnabled
bool m_BiasEnabled
Enable/disable bias.
Definition: Descriptors.hpp:653
armnn::ArgMinMaxDescriptor::m_Axis
int m_Axis
Axis to reduce across the input tensor.
Definition: Descriptors.hpp:83
armnnUtils::DataLayoutIndexed::GetChannelsIndex
unsigned int GetChannelsIndex() const
Definition: DataLayoutIndexed.hpp:23
armnn::Convolution3dDescriptor::m_StrideZ
uint32_t m_StrideZ
Stride value when proceeding through input for the depth dimension.
Definition: Descriptors.hpp:645
armnn::ConvertFp32ToFp16QueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2284
armnn::ArgMinMaxQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:629
armnn::ReduceQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3899
armnn::QLstmDescriptor::m_HiddenStateScale
float m_HiddenStateScale
Hidden State quantization scale.
Definition: Descriptors.hpp:1436
armnn::FakeQuantizationDescriptor::m_Min
float m_Min
Minimum value.
Definition: Descriptors.hpp:919
armnn::LstmQueueDescriptor::m_RecurrentToInputWeights
const ConstTensorHandle * m_RecurrentToInputWeights
Definition: WorkloadData.hpp:431
armnn::LstmDescriptor::m_ProjectionEnabled
bool m_ProjectionEnabled
Enable/disable the projection layer.
Definition: Descriptors.hpp:1150
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_InputToCellWeights
const ConstTensorHandle * m_InputToCellWeights
Definition: WorkloadData.hpp:725
armnn::StridedSliceDescriptor::m_End
std::vector< int > m_End
End values for the input that will be sliced.
Definition: Descriptors.hpp:1344
armnn::LstmQueueDescriptor::m_ProjectionBias
const ConstTensorHandle * m_ProjectionBias
Definition: WorkloadData.hpp:443
armnn::PadQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2477
armnn::UnmapQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:473
armnn::LstmQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2014
armnn::LstmQueueDescriptor::m_OutputGateBias
const ConstTensorHandle * m_OutputGateBias
Definition: WorkloadData.hpp:441
armnn::L2NormalizationQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1736
armnn::QLstmQueueDescriptor::m_ProjectionBias
const ConstTensorHandle * m_ProjectionBias
Definition: WorkloadData.hpp:605
armnn::QLstmQueueDescriptor::m_CellToInputWeights
const ConstTensorHandle * m_CellToInputWeights
Definition: WorkloadData.hpp:597
armnn::ConvertFp16ToFp32QueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2307
armnn::TransposeConvolution2dDescriptor::m_BiasEnabled
bool m_BiasEnabled
Enable/disable bias.
Definition: Descriptors.hpp:1481
armnn::QLstmDescriptor::m_LayerNormEnabled
bool m_LayerNormEnabled
Enable/disable layer normalization.
Definition: Descriptors.hpp:1424
armnn::DataType::Signed64
@ Signed64
armnn::SliceDescriptor::m_Size
std::vector< unsigned int > m_Size
Size of the slice in each dimension.
Definition: Descriptors.hpp:1247
armnn::QLstmQueueDescriptor::m_CellBias
const ConstTensorHandle * m_CellBias
Definition: WorkloadData.hpp:602
armnn::BatchToSpaceNdDescriptor::m_DataLayout
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Definition: Descriptors.hpp:902
armnn::TensorInfo::GetQuantizationOffset
int32_t GetQuantizationOffset() const
Definition: Tensor.cpp:482
armnn::QueueDescriptor::ValidateTensorNumDimNumElem
void ValidateTensorNumDimNumElem(const TensorInfo &tensorInfo, unsigned int numDimension, unsigned int numElements, std::string const &tensorName) const
Definition: WorkloadData.cpp:436
armnn::LstmQueueDescriptor::m_CellToForgetWeights
const ConstTensorHandle * m_CellToForgetWeights
Definition: WorkloadData.hpp:436
armnn::LstmQueueDescriptor::m_InputToOutputWeights
const ConstTensorHandle * m_InputToOutputWeights
Definition: WorkloadData.hpp:430
armnn::DepthwiseConvolution2dDescriptor::m_DilationX
uint32_t m_DilationX
Dilation factor value for width dimension.
Definition: Descriptors.hpp:704
armnn::QLstmQueueDescriptor::m_InputToCellWeights
const ConstTensorHandle * m_InputToCellWeights
Definition: WorkloadData.hpp:591
armnn::StackQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:916
armnn::LstmDescriptor::m_ClippingThresCell
float m_ClippingThresCell
Clipping threshold value for the cell state.
Definition: Descriptors.hpp:1142
armnn::QuantizeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2499
armnn::LstmQueueDescriptor::m_OutputLayerNormWeights
const ConstTensorHandle * m_OutputLayerNormWeights
Definition: WorkloadData.hpp:447
armnn::BatchMatMulDescriptor::GetAxesNotMul
static std::vector< unsigned int > GetAxesNotMul(DataLayout dataLayout, const TensorShape &tensorShape)
Static helper to get the axes (for each input) that will not be multiplied together.
Definition: Descriptors.cpp:506
DataLayoutIndexed.hpp
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_CellLayerNormWeights
const ConstTensorHandle * m_CellLayerNormWeights
Definition: WorkloadData.hpp:742
armnn::QLstmDescriptor::m_PeepholeEnabled
bool m_PeepholeEnabled
Enable/disable peephole.
Definition: Descriptors.hpp:1420
armnn::ReshapeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1822
armnn::QuantizedLstmQueueDescriptor::m_OutputGateBias
const ConstTensorHandle * m_OutputGateBias
Definition: WorkloadData.hpp:646
WorkloadInfo.hpp
armnn::OptionalReferenceSwitch< std::is_reference< T >::value, T >::value
const T & value() const
Definition: Optional.hpp:146
armnn::MultiplicationQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1169
armnn::QLstmQueueDescriptor::m_CellLayerNormWeights
const ConstTensorHandle * m_CellLayerNormWeights
Definition: WorkloadData.hpp:608
armnn::QueueDescriptor::m_Inputs
std::vector< ITensorHandle * > m_Inputs
Definition: WorkloadData.hpp:26
armnn::OptionalBase::has_value
bool has_value() const noexcept
Definition: Optional.hpp:53
armnn::QLstmQueueDescriptor::m_RecurrentToCellWeights
const ConstTensorHandle * m_RecurrentToCellWeights
Definition: WorkloadData.hpp:595
armnn::DataLayout::NCHW
@ NCHW
armnn::QuantizedLstmQueueDescriptor::m_ForgetGateBias
const ConstTensorHandle * m_ForgetGateBias
Definition: WorkloadData.hpp:644
armnn::Convolution3dQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1329
armnn::AdditionQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1132
armnn::SpaceToDepthDescriptor::m_DataLayout
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Definition: Descriptors.hpp:1095
armnn::DepthwiseConvolution2dDescriptor::m_StrideX
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
Definition: Descriptors.hpp:700