ArmNN
 24.05
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  {
1079  };
1080 
1081  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1082 
1083  // For FullyConnected, we allow to have BFloat16 input with Float32 output for optimization.
1084  if (inputTensorInfo.GetDataType() == DataType::BFloat16)
1085  {
1086  if (outputTensorInfo.GetDataType() != DataType::BFloat16 && outputTensorInfo.GetDataType() != DataType::Float32)
1087  {
1088  throw InvalidArgumentException(descriptorName + ": " + " Output tensor type must be BFloat16 or Float32 "
1089  "for BFloat16 input.");
1090  }
1091  }
1092  else
1093  {
1094  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1095  }
1096 }
1097 
1098 void FusedQueueDescriptor::Validate(const WorkloadInfo& /*workloadInfo*/) const
1099 {
1100  // This is internally generated, so it should not need validation.
1101 }
1102 
1104 {
1105  const std::string descriptorName{"NormalizationQueueDescriptor"};
1106 
1107  ValidateNumInputs(workloadInfo, descriptorName, 1);
1108  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1109 
1110  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1111  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1112 
1113  // Check the supported data types
1114  std::vector<DataType> supportedTypes =
1115  {
1122  };
1123 
1124  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1125 
1126  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1127 
1128  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1129 }
1130 
1131 void AdditionQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1132 {
1133  const std::string descriptorName{"AdditionQueueDescriptor"};
1134 
1135  ValidateNumInputs(workloadInfo, descriptorName, 2);
1136  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1137 
1138  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
1139  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
1140  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1141 
1142  std::vector<DataType> supportedTypes =
1143  {
1151  };
1152 
1153  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
1154  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
1155  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1156 
1157  ValidateTensorDataTypesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
1158  ValidateTensorDataTypesMatch(inputTensorInfo1, outputTensorInfo, descriptorName, "input_1", "output");
1159 
1160  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
1161  inputTensorInfo1,
1162  outputTensorInfo,
1163  descriptorName,
1164  "input_0",
1165  "input_1");
1166 }
1167 
1169 {
1170  const std::string descriptorName{"MultiplicationQueueDescriptor"};
1171 
1172  ValidateNumInputs(workloadInfo, descriptorName, 2);
1173  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1174 
1175  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
1176  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
1177  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1178 
1179  std::vector<DataType> supportedTypes =
1180  {
1188  };
1189 
1190  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
1191  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
1192  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1193 
1194  ValidateTensorDataTypesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
1195  ValidateTensorDataTypesMatch(inputTensorInfo1, outputTensorInfo, descriptorName, "input_1", "output");
1196 
1197  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
1198  inputTensorInfo1,
1199  outputTensorInfo,
1200  descriptorName,
1201  "input_0",
1202  "input_1");
1203 }
1204 
1206 {
1207  const std::string descriptorName{"BatchNormalizationQueueDescriptor"};
1208 
1209  ValidateNumInputs(workloadInfo, descriptorName, 1);
1210  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1211 
1212  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1213  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1214 
1215  std::vector<DataType> supportedTypes =
1216  {
1223  };
1224 
1225  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1226  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1227 
1228  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1229  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1230 
1231  ValidatePointer(m_Mean, descriptorName, "mean");
1232  ValidatePointer(m_Variance, descriptorName, "variance");
1233  ValidatePointer(m_Beta, descriptorName, "beta");
1234  ValidatePointer(m_Gamma, descriptorName, "gamma");
1235 
1236  const TensorInfo& mean = m_Mean->GetTensorInfo();
1237  const TensorInfo& variance = m_Variance->GetTensorInfo();
1238  const TensorInfo& beta = m_Beta->GetTensorInfo();
1239  const TensorInfo& gamma = m_Gamma->GetTensorInfo();
1240 
1241  ValidateTensorNumDimensions(mean, descriptorName, 1, "mean");
1242  ValidateTensorNumDimensions(variance, descriptorName, 1, "variance");
1243  ValidateTensorNumDimensions(beta, descriptorName, 1, "beta");
1244  ValidateTensorNumDimensions(gamma, descriptorName, 1, "gamma");
1245 
1246  ValidateTensorShapesMatch(mean, variance, descriptorName, "mean", "variance");
1247  ValidateTensorShapesMatch(mean, beta, descriptorName, "mean", "beta");
1248  ValidateTensorShapesMatch(mean, gamma, descriptorName, "mean", "gamma");
1249 }
1250 
1252 {
1253  const std::string descriptorName{"Convolution2dQueueDescriptor"};
1254 
1255  uint32_t numInputs = 2;
1257  {
1258  numInputs = 3;
1259  }
1260 
1261  ValidateNumInputs(workloadInfo, descriptorName, numInputs);
1262  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1263 
1264  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1265  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1266 
1267  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1268  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1269 
1270  const TensorInfo& weightTensorInfo = workloadInfo.m_InputTensorInfos[1];
1271 
1272  ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 4, "weight");
1273 
1274  ValidateWeightDataType(inputTensorInfo, weightTensorInfo, descriptorName);
1275 
1276  Optional<TensorInfo> optionalBiasTensorInfo;
1278  {
1279  optionalBiasTensorInfo = MakeOptional<TensorInfo>(workloadInfo.m_InputTensorInfos[2]);
1280  const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value();
1281 
1282  ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
1283  ValidateBiasTensorQuantization(biasTensorInfo, weightTensorInfo, descriptorName);
1284  }
1285 
1286  if (m_Parameters.m_StrideX <= 0 || m_Parameters.m_StrideY <= 0 )
1287  {
1289  fmt::format("{}: strideX (provided {}) and strideY (provided {}) "
1290  "cannot be either negative or 0.",
1291  descriptorName, m_Parameters.m_StrideX, m_Parameters.m_StrideY));
1292  }
1293 
1294  ValidatePerAxisQuantization(inputTensorInfo,
1295  outputTensorInfo,
1296  weightTensorInfo,
1297  optionalBiasTensorInfo,
1298  descriptorName);
1299 
1300  std::vector<DataType> supportedTypes =
1301  {
1309  };
1310 
1311  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1312 
1313  // For Convolution2d, we allow to have BFloat16 input with Float32 output for optimization.
1314  if (inputTensorInfo.GetDataType() == DataType::BFloat16)
1315  {
1316  if (outputTensorInfo.GetDataType() != DataType::BFloat16 && outputTensorInfo.GetDataType() != DataType::Float32)
1317  {
1318  throw InvalidArgumentException(descriptorName + ": " + " Output tensor type must be BFloat16 or Float32 "
1319  "for BFloat16 input.");
1320  }
1321  }
1322  else
1323  {
1324  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1325  }
1326 }
1327 
1329 {
1330  const std::string descriptorName{"Convolution3dQueueDescriptor"};
1331 
1332  uint32_t numInputs = 2;
1334  {
1335  numInputs = 3;
1336  }
1337  ValidateNumInputs(workloadInfo, descriptorName, numInputs);
1338  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1339 
1340  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1341  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1342 
1343  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 5, "input");
1344  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 5, "output");
1345 
1346  const TensorInfo& weightTensorInfo = workloadInfo.m_InputTensorInfos[1];
1347  ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 5, "weight");
1348 
1349  ValidateWeightDataType(inputTensorInfo, weightTensorInfo, descriptorName);
1350 
1351  Optional<TensorInfo> optionalBiasTensorInfo;
1353  {
1354  optionalBiasTensorInfo = MakeOptional<TensorInfo>(workloadInfo.m_InputTensorInfos[2]);
1355  const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value();
1356 
1357  ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
1358  ValidateBiasTensorQuantization(biasTensorInfo, weightTensorInfo, descriptorName);
1359  }
1360 
1362  {
1364  fmt::format("{}: strideX (provided {}), strideY (provided {}) or strideZ (provided {})"
1365  "cannot be either negative or 0.",
1367  }
1368 
1369  ValidatePerAxisQuantization(inputTensorInfo,
1370  outputTensorInfo,
1371  weightTensorInfo,
1372  optionalBiasTensorInfo,
1373  descriptorName);
1374 
1375  std::vector<DataType> supportedTypes =
1376  {
1384  };
1385 
1386  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1387  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1388 }
1389 
1391 {
1392  const std::string descriptorName{"DepthwiseConvolution2dQueueDescriptor"};
1393 
1394  uint32_t numInputs = 2;
1396  {
1397  numInputs = 3;
1398  }
1399 
1400  ValidateNumInputs(workloadInfo, descriptorName, numInputs);
1401  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1402 
1403  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1404  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1405 
1406  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1407  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1408 
1409  const TensorInfo& weightTensorInfo = workloadInfo.m_InputTensorInfos[1];
1410  ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 4, "weight");
1411 
1413  {
1415  fmt::format("{}: dilationX (provided {}) and dilationY (provided {}) "
1416  "cannot be smaller than 1.",
1417  descriptorName, m_Parameters.m_DilationX, m_Parameters.m_DilationX));
1418  }
1419 
1420  if (m_Parameters.m_StrideX <= 0 || m_Parameters.m_StrideY <= 0 )
1421  {
1423  fmt::format("{}: strideX (provided {}) and strideY (provided {}) "
1424  "cannot be either negative or 0.",
1425  descriptorName, m_Parameters.m_StrideX, m_Parameters.m_StrideY));
1426  }
1427 
1428  if (weightTensorInfo.GetShape()[0] != 1)
1429  {
1430  throw InvalidArgumentException(fmt::format(
1431  "{0}: The weight format in armnn is expected to be [1, H, W, Cout]."
1432  "But first dimension is not equal to 1. Provided weight shape: [{1}, {2}, {3}, {4}]",
1433  descriptorName,
1434  weightTensorInfo.GetShape()[0],
1435  weightTensorInfo.GetShape()[1],
1436  weightTensorInfo.GetShape()[2],
1437  weightTensorInfo.GetShape()[3]));
1438  }
1439 
1440  const unsigned int channelIndex = (m_Parameters.m_DataLayout == DataLayout::NCHW) ? 1 : 3;
1441  const unsigned int numWeightOutputChannelsRefFormat = weightTensorInfo.GetShape()[3];
1442  const unsigned int numWeightOutputChannelsAclFormat = weightTensorInfo.GetShape()[1];
1443  const unsigned int numOutputChannels = outputTensorInfo.GetShape()[channelIndex];
1444 
1445  // Weights format has two valid options: [1, H, W, Cout] (CpuRef) or [1, Cout, H, W] (CpuAcc/GpuAcc).
1446  bool validRefFormat = (numWeightOutputChannelsRefFormat == numOutputChannels);
1447  bool validAclFormat = (numWeightOutputChannelsAclFormat == numOutputChannels);
1448 
1449  if (!(validRefFormat || validAclFormat))
1450  {
1451  throw InvalidArgumentException(fmt::format(
1452  "{0}: The weight format in armnn is expected to be [1, H, W, Cout] (CpuRef) or [1, Cout, H, W] "
1453  "(CpuAcc/GpuAcc). But neither the 4th (CpuRef) or 2nd (CpuAcc/GpuAcc) dimension is equal to Cout."
1454  "Cout = {1} Provided weight shape: [{2}, {3}, {4}, {5}]",
1455  descriptorName,
1456  numOutputChannels,
1457  weightTensorInfo.GetShape()[0],
1458  weightTensorInfo.GetShape()[1],
1459  weightTensorInfo.GetShape()[2],
1460  weightTensorInfo.GetShape()[3]));
1461  }
1462 
1463  ValidateWeightDataType(inputTensorInfo, weightTensorInfo, descriptorName);
1464 
1465  Optional<TensorInfo> optionalBiasTensorInfo;
1467  {
1468  optionalBiasTensorInfo = MakeOptional<TensorInfo>(workloadInfo.m_InputTensorInfos[2]);
1469  const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value();
1470 
1471  ValidateBiasTensorQuantization(biasTensorInfo, weightTensorInfo, descriptorName);
1472  ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
1473  }
1474  ValidatePerAxisQuantization(inputTensorInfo,
1475  outputTensorInfo,
1476  weightTensorInfo,
1477  optionalBiasTensorInfo,
1478  descriptorName);
1479 
1480  std::vector<DataType> supportedTypes =
1481  {
1488  };
1489 
1490  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1491  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1492 }
1493 
1494 void PermuteQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1495 {
1496  const std::string descriptorName{"PermuteQueueDescriptor"};
1497 
1498  ValidateNumInputs(workloadInfo, descriptorName, 1);
1499  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1500 
1501  const PermutationVector& mapping = m_Parameters.m_DimMappings;
1502 
1503  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1504  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1505 
1506  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, mapping.GetSize(), "input");
1507  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, mapping.GetSize(), "output");
1508 
1509  for (unsigned int i = 0u; i < mapping.GetSize(); ++i)
1510  {
1511  if (inputTensorInfo.GetShape()[i] != outputTensorInfo.GetShape()[mapping[i]])
1512  {
1513  throw InvalidArgumentException(descriptorName + ": src dimension " + to_string(i) +
1514  " (=" + to_string(inputTensorInfo.GetShape()[i]) + ") " +
1515  "must match dst dimension " + to_string(mapping[i]) +
1516  " (=" + to_string(outputTensorInfo.GetShape()[mapping[i]]) + ")");
1517  }
1518  }
1519 
1520  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1521 }
1522 
1523 void Pooling2dQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1524 {
1525  const std::string descriptorName{"Pooling2dQueueDescriptor"};
1526 
1527  ValidateNumInputs(workloadInfo, descriptorName, 1);
1528  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1529 
1530  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1531  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1532 
1533  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1534  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1535 
1536  std::vector<DataType> supportedTypes =
1537  {
1544  };
1545 
1546  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1547  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1548 }
1549 
1550 void Pooling3dQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1551 {
1552  const std::string descriptorName{"Pooling3dQueueDescriptor"};
1553 
1554  ValidateNumInputs(workloadInfo, descriptorName, 1);
1555  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1556 
1557  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1558  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1559 
1560  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 5, "input");
1561  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 5, "output");
1562 
1563  std::vector<DataType> supportedTypes =
1564  {
1571  };
1572 
1573  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1574  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1575 }
1576 
1577 void ResizeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1578 {
1579  const std::string descriptorName{"ResizeQueueDescriptor"};
1580 
1581  ValidateNumInputs(workloadInfo, descriptorName, 1);
1582  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1583 
1584  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1585  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1586 
1587  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1588  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1589 
1590  std::vector<DataType> supportedTypes =
1591  {
1599  };
1600 
1601  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1602  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1603 
1604  // Resize only changes width and height: batch and channel count must match.
1605  const unsigned int inputBatchSize = inputTensorInfo.GetShape()[0];
1606  const unsigned int outputBatchSize = outputTensorInfo.GetShape()[0];
1607  if (inputBatchSize != outputBatchSize)
1608  {
1610  fmt::format("{}: Input batch size ({}) does not match output batch size ({})",
1611  descriptorName, inputBatchSize, outputBatchSize));
1612  }
1613 
1614  DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
1615  const unsigned int inputChannelCount = inputTensorInfo.GetShape()[dimensionIndices.GetChannelsIndex()];
1616  const unsigned int outputChannelCount = outputTensorInfo.GetShape()[dimensionIndices.GetChannelsIndex()];
1617  if (inputChannelCount != outputChannelCount)
1618  {
1620  fmt::format("{}: Input channel count ({}) does not match output channel count ({})",
1621  descriptorName, inputChannelCount, outputChannelCount));
1622  }
1623 }
1624 
1625 void ReverseV2QueueDescriptor::Validate(const WorkloadInfo &workloadInfo) const
1626 {
1627  const std::string descriptorName{"ReverseV2QueueDescriptor"};
1628 
1629  // Backend restriction
1630  const unsigned int maxDimensions = 4;
1631 
1632  ValidateNumInputs(workloadInfo, descriptorName, 2);
1633  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1634 
1635  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1636  const TensorInfo& axisTensorInfo = workloadInfo.m_InputTensorInfos[1];
1637  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1638 
1639  const auto inputTensorNumDimensions = inputTensorInfo.GetNumDimensions();
1640  if (inputTensorNumDimensions > maxDimensions)
1641  {
1642  throw InvalidArgumentException(descriptorName +
1643  ": Input tensors with rank greater than " +
1644  std::to_string(maxDimensions) + " are not supported.");
1645  }
1646 
1647  const auto axisTensorNumDimensions = axisTensorInfo.GetNumDimensions();
1648  if (axisTensorNumDimensions > maxDimensions)
1649  {
1650  throw InvalidArgumentException(descriptorName +
1651  ": More than " + std::to_string(maxDimensions) + " axes cannot be specified.");
1652  }
1653 
1654  if (axisTensorNumDimensions > inputTensorNumDimensions)
1655  {
1656  throw InvalidArgumentException(descriptorName +
1657  ": More axes specified than the number of axes on the input tensor.");
1658  }
1659 
1660  std::vector<DataType> supportedTypes =
1661  {
1670  };
1671 
1672  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1673 
1674  std::vector<DataType> axisSupportedTypes =
1675  {
1677  };
1678 
1679  ValidateDataTypes(axisTensorInfo, axisSupportedTypes, descriptorName);
1680 
1681  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1682  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1683 }
1684 
1686 {
1687  const std::string descriptorName{"FakeQuantizationQueueDescriptor"};
1688 
1689  ValidateNumInputs(workloadInfo, descriptorName, 1);
1690  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1691 
1692  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1693  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1694 
1695  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 2, "input");
1696  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 2, "output");
1697 
1698  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1699 
1701  {
1702  throw InvalidArgumentException(descriptorName + ": min cannot be greater than max");
1703  }
1704 }
1705 
1707 {
1708  const std::string descriptorName{"InstanceNormalizationQueueDescriptor"};
1709 
1710  ValidateNumInputs(workloadInfo, descriptorName, 1);
1711  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1712 
1713  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1714  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1715 
1716  if (inputTensorInfo.GetNumDimensions() > 4)
1717  {
1718  throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
1719  }
1720 
1721  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1722 
1723  // Check the supported data types
1724  std::vector<DataType> supportedTypes =
1725  {
1729  };
1730 
1731  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1732  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1733 }
1734 
1736 {
1737  const std::string descriptorName{"L2NormalizationQueueDescriptor"};
1738 
1739  ValidateNumInputs(workloadInfo, descriptorName, 1);
1740  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1741 
1742  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1743  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1744 
1745  if (inputTensorInfo.GetNumDimensions() > 4)
1746  {
1747  throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
1748  }
1749 
1750  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1751 
1752  // Check the supported data types
1753  std::vector<DataType> supportedTypes =
1754  {
1761  };
1762 
1763  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1764  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1765 }
1766 
1767 void LogSoftmaxQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1768 {
1769  const std::string descriptorName{"LogSoftmaxQueueDescriptor"};
1770 
1771  ValidateNumInputs(workloadInfo, descriptorName, 1);
1772  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1773 
1774  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1775  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1776 
1777  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1778 
1779  std::vector<DataType> supportedTypes =
1780  {
1784  };
1785 
1786  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1787  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1788 }
1789 
1790 void ConstantQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1791 {
1792  const std::string descriptorName{"ConstantQueueDescriptor"};
1793 
1794  ValidateNumInputs(workloadInfo, descriptorName, 0);
1795  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1796 
1797  if (!m_LayerOutput)
1798  {
1799  throw InvalidArgumentException(descriptorName + ": No const input specified.");
1800  }
1801 
1802  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1803  ValidateTensorShapesMatch(m_LayerOutput->GetTensorInfo(), outputTensorInfo, descriptorName, "constant", "output");
1804 
1805  // Check the supported data types
1806  std::vector<DataType> supportedTypes =
1807  {
1816  };
1817 
1818  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1819 }
1820 
1821 void ReshapeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1822 {
1823  const std::string descriptorName{"ReshapeQueueDescriptor"};
1824 
1825  ValidateNumInputs(workloadInfo, descriptorName, 1);
1826  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1827 
1828  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1829  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1830 
1831  ValidateTensorNumElementsMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1832 
1833  // Check the supported data types
1834  std::vector<DataType> supportedTypes =
1835  {
1844  };
1845 
1846  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1847  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1848 }
1849 
1851 {
1852  const std::string descriptorName{"SpaceToBatchNdQueueDescriptor"};
1853 
1854  ValidateNumInputs(workloadInfo, descriptorName, 1);
1855  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1856 
1857  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1858  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1859 
1860  if (m_Parameters.m_BlockShape.size() != m_Parameters.m_PadList.size())
1861  {
1862  throw InvalidArgumentException(descriptorName + ": Pad List must contain the same number of "
1863  "dimensions as Block Shape.");
1864  }
1865 
1866  if (m_Parameters.m_BlockShape.size() == 2)
1867  {
1868  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1869  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1870  }
1871  else if (m_Parameters.m_BlockShape.size() == 1)
1872  {
1873  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 3, "input");
1874  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 3, "output");
1875  }
1876  else
1877  {
1878  throw InvalidArgumentException(descriptorName + ": Invalid Block and Crops size.");
1879  }
1880 
1881  // Check input + padding and output have the same number of elements
1882  DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
1883  const unsigned int inputHeight = inputTensorInfo.GetShape()[dimensionIndices.GetHeightIndex()] +
1884  m_Parameters.m_PadList[0].first + m_Parameters.m_PadList[0].second;
1885  const unsigned int inputWidth = (inputTensorInfo.GetNumDimensions() == 3) ? 1 :
1886  inputTensorInfo.GetShape()[dimensionIndices.GetWidthIndex()] +
1887  m_Parameters.m_PadList[1].first + m_Parameters.m_PadList[1].second;
1888 
1889  const int channelsIndex_int = (m_Parameters.m_DataLayout == DataLayout::NCHW) ? 1 : -1;
1890  const unsigned int channelsIndex = channelsIndex_int < 0 ?
1891  static_cast<unsigned int>(channelsIndex_int) + inputTensorInfo.GetNumDimensions()
1892  : static_cast<unsigned int>(channelsIndex_int);
1893 
1894  const unsigned int numInputElements = inputTensorInfo.GetShape()[0] *
1895  inputHeight *
1896  inputWidth *
1897  inputTensorInfo.GetShape()[channelsIndex];
1898 
1899  if (outputTensorInfo.GetNumElements() != numInputElements)
1900  {
1901  throw InvalidArgumentException(descriptorName + ": Input tensor has " +
1902  to_string(numInputElements) + " after padding but output tensor has " +
1903  to_string(outputTensorInfo.GetNumElements()) + " elements.");
1904  }
1905 
1906  // In a 4D tensor, there will be 2 spatialDimensions (H and W), and the for loop will run twice.
1907  // In a 3D tensor, there will be 1 spatialDimensions, and the for loop will run once.
1908  unsigned int firstSpatialDimension = m_Parameters.m_DataLayout == DataLayout::NCHW ? 2 : 1;
1909  for (unsigned int i = 0; i < m_Parameters.m_BlockShape.size(); ++i)
1910  {
1911  unsigned int spatialDimension = firstSpatialDimension + i;
1912  auto inputSize = inputTensorInfo.GetShape()[spatialDimension] +
1913  m_Parameters.m_PadList[i].first +
1914  m_Parameters.m_PadList[i].second;
1915  if (inputSize % m_Parameters.m_BlockShape[i] != 0)
1916  {
1917  throw InvalidArgumentException(descriptorName + ": Input dimension size after padding must be "
1918  "divisible by Block Shape in dimension: " + to_string(spatialDimension) + ".");
1919  }
1920  }
1921 
1922  std::vector<DataType> supportedTypes =
1923  {
1930  };
1931 
1932  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1933  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1934 }
1935 
1937 {
1938  const std::string descriptorName{"SpaceToDepthQueueDescriptor"};
1939 
1940  ValidateNumInputs(workloadInfo, descriptorName, 1);
1941  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1942 
1943  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1944  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1945 
1946  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1947  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1948 
1949  std::vector<DataType> supportedTypes =
1950  {
1957  };
1958 
1959  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1960  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1961 
1962  ValidateTensorNumElementsMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1963 
1964  if (m_Parameters.m_BlockSize == 0)
1965  {
1966  throw InvalidArgumentException(descriptorName + ": Block size cannot be 0.");
1967  }
1968 
1969  DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
1970  const unsigned int wIndex = dimensionIndices.GetWidthIndex();
1971  const unsigned int hIndex = dimensionIndices.GetHeightIndex();
1972  const unsigned int cIndex = dimensionIndices.GetChannelsIndex();
1973 
1974  const TensorShape& inputShape = inputTensorInfo.GetShape();
1975  if (inputShape[hIndex] % m_Parameters.m_BlockSize != 0 || inputShape[wIndex] % m_Parameters.m_BlockSize != 0)
1976  {
1977  throw InvalidArgumentException(descriptorName + ": Input shape must be divisible "
1978  "by block size in all spatial dimensions");
1979  }
1980 
1981  const TensorShape& outputShape = outputTensorInfo.GetShape();
1982  if (outputShape[cIndex] % (m_Parameters.m_BlockSize * m_Parameters.m_BlockSize) != 0)
1983  {
1984  throw InvalidArgumentException(descriptorName + ": The depth of the output tensor"
1985  "must be divisible by the square of block size." );
1986  }
1987 }
1988 
1989 void FloorQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1990 {
1991  const std::string descriptorName{"FloorQueueDescriptor"};
1992 
1993  ValidateNumInputs(workloadInfo, descriptorName, 1);
1994  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1995 
1996  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1997  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1998 
1999  std::vector<DataType> supportedTypes =
2000  {
2005  };
2006 
2007  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2008  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2009  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2010  ValidateTensorQuantizationSpace(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2011 }
2012 
2013 void LstmQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2014 {
2015  // ported from android/ml/nn/common/operations/LSTM.cpp CheckInputTensorDimensions()
2016 
2017  const std::string descriptorName{"LstmQueueDescriptor"};
2018 
2019  // check dimensions of all inputs and outputs
2020  if (workloadInfo.m_InputTensorInfos.size() != 3)
2021  {
2022  throw InvalidArgumentException(descriptorName + ": Invalid number of inputs.");
2023  }
2024  if (workloadInfo.m_OutputTensorInfos.size() != 4)
2025  {
2026  throw InvalidArgumentException(descriptorName + ": Invalid number of outputs.");
2027  }
2028 
2029  std::vector<DataType> supportedTypes =
2030  {
2035  };
2036 
2037  // check for supported type of one input and match them with all the other input and output
2038  ValidateDataTypes(workloadInfo.m_InputTensorInfos[0], supportedTypes, descriptorName);
2039 
2040  // type matches all other inputs
2041  for (uint32_t i = 1u; i < workloadInfo.m_InputTensorInfos.size(); ++i)
2042  {
2043  ValidateTensorDataTypesMatch(workloadInfo.m_InputTensorInfos[0],
2044  workloadInfo.m_InputTensorInfos[i],
2045  descriptorName,
2046  "input_0",
2047  "input_" + std::to_string(i));
2048  }
2049  // type matches all other outputs
2050  for (uint32_t i = 0u; i < workloadInfo.m_OutputTensorInfos.size(); ++i)
2051  {
2052  ValidateTensorDataTypesMatch(workloadInfo.m_InputTensorInfos[0],
2053  workloadInfo.m_OutputTensorInfos[i],
2054  "LstmQueueDescriptor",
2055  "input_0",
2056  "output_" + std::to_string(i));
2057  }
2058 
2059  // Making sure clipping parameters have valid values.
2060  // == 0 means no clipping
2061  // > 0 means clipping
2062  if (m_Parameters.m_ClippingThresCell < 0.0f)
2063  {
2064  throw InvalidArgumentException(descriptorName + ": negative cell clipping threshold is invalid");
2065  }
2066  if (m_Parameters.m_ClippingThresProj < 0.0f)
2067  {
2068  throw InvalidArgumentException(descriptorName + ": negative projection clipping threshold is invalid");
2069  }
2070 
2071  // Inferring batch size, number of outputs and number of cells from the inputs.
2072  const uint32_t n_input = workloadInfo.m_InputTensorInfos[0].GetShape()[1];
2073  const uint32_t n_batch = workloadInfo.m_InputTensorInfos[0].GetShape()[0];
2074  ValidatePointer(m_InputToOutputWeights, "Null pointer check", "InputToOutputWeights");
2075  const uint32_t n_cell = m_InputToOutputWeights->GetShape()[0];
2076  ValidatePointer(m_RecurrentToOutputWeights, "Null pointer check", "RecurrentToOutputWeights");
2077  const uint32_t n_output = m_RecurrentToOutputWeights->GetShape()[1];
2078 
2079  // input tensor
2080  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[0], 2, (n_batch * n_input),
2081  descriptorName + " input_0");
2082  // outputStateInTensor
2083  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[1], 2, (n_batch * n_output),
2084  descriptorName + " input_1");
2085  // outputStateInTensor
2086  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[2], 2, (n_batch * n_cell),
2087  descriptorName + " input_2");
2088  // scratchBufferTensor
2089  unsigned int scratchBufferSize = m_Parameters.m_CifgEnabled ? n_cell * 3 : n_cell * 4;
2090  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[0], 2, (n_batch * scratchBufferSize),
2091  descriptorName + " output_0");
2092  // outputStateOutTensor
2093  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[1], 2, (n_batch * n_output),
2094  descriptorName + " output_1");
2095  // cellStateOutTensor
2096  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[2], 2, (n_batch * n_cell),
2097  descriptorName + " output_2");
2098  // outputTensor
2099  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[3], 2, (n_batch * n_output),
2100  descriptorName + " output_3");
2101 
2102  // check that dimensions of inputs/outputs and QueueDescriptor data match with each other
2103  if ( m_InputToInputWeights )
2104  {
2106  (n_cell * n_input), "InputLayerNormWeights");
2107  }
2108 
2109  ValidatePointer(m_InputToForgetWeights, "Null pointer check", "InputToForgetWeights");
2111  (n_cell * n_input), "InputToForgetWeights");
2112 
2113  ValidatePointer(m_InputToCellWeights, "Null pointer check", "InputToCellWeights");
2115  (n_cell * n_input), "InputToCellWeights");
2116 
2118  {
2120  (n_cell * n_output), "RecurrentToInputWeights");
2121  }
2122 
2123  ValidatePointer(m_RecurrentToForgetWeights, "Null pointer check", "RecurrentToForgetWeights");
2125  (n_cell * n_output), "RecurrentToForgetWeights");
2126 
2127  ValidatePointer(m_RecurrentToCellWeights, "Null pointer check", "RecurrentToCellWeights");
2129  (n_cell * n_output), "RecurrentToCellWeights");
2130 
2131  // Make sure the input-gate's parameters are either both present (regular
2132  // LSTM) or not at all (CIFG-LSTM). And CifgEnable is set accordingly.
2133  bool cifg_weights_all_or_none = ((m_InputToInputWeights && m_RecurrentToInputWeights &&
2137  if (!cifg_weights_all_or_none)
2138  {
2139  throw InvalidArgumentException(descriptorName + ": Input-Gate's parameters InputToInputWeights and "
2140  "RecurrentToInputWeights must either both be present (regular LSTM) "
2141  "or both not present (CIFG-LSTM). In addition CifgEnable must be set "
2142  "accordingly.");
2143  }
2144 
2145  if ( m_CellToInputWeights )
2146  {
2148  n_cell, "CellToInputWeights");
2149  }
2150  if ( m_CellToForgetWeights )
2151  {
2153  n_cell, "CellToForgetWeights");
2154  }
2155  if ( m_CellToOutputWeights )
2156  {
2158  n_cell, "CellToOutputWeights");
2159  }
2160 
2161  // Making sure the peephole weights are there all or none. And PeepholeEnable is set accordingly.
2162  bool peephole_weights_all_or_none =
2167  if (!peephole_weights_all_or_none)
2168  {
2169  throw InvalidArgumentException(descriptorName + ": Invalid combination of peephole parameters.");
2170  }
2171 
2172  // Make sure the input gate bias is present only when not a CIFG-LSTM.
2174  {
2175  if (m_InputGateBias)
2176  {
2177  throw InvalidArgumentException(descriptorName + ": InputGateBias is present and CIFG-LSTM is enabled.");
2178  }
2179  }
2180  else
2181  {
2182  if (!m_InputGateBias)
2183  {
2184  throw InvalidArgumentException(descriptorName + ": If CIFG-LSTM is disabled InputGateBias "
2185  "must be present.");
2186  }
2188  n_cell, "InputGateBias");
2189  }
2190 
2191  ValidatePointer(m_ForgetGateBias, "Null pointer check", "ForgetGateBias");
2192  ValidateTensorNumDimNumElem(m_ForgetGateBias->GetTensorInfo(), 1, n_cell, "ForgetGateBias");
2193 
2194  ValidatePointer(m_CellBias, "Null pointer check", "CellBias");
2195  ValidateTensorNumDimNumElem(m_CellBias->GetTensorInfo(), 1, n_cell, "CellBias");
2196 
2197  ValidatePointer(m_OutputGateBias, "Null pointer check", "OutputGateBias");
2198  ValidateTensorNumDimNumElem(m_OutputGateBias->GetTensorInfo(), 1, n_cell, "OutputGateBias");
2199 
2200  if (m_ProjectionWeights)
2201  {
2203  (n_cell * n_output), "ProjectionWeights");
2204  }
2205  if (m_ProjectionBias)
2206  {
2207  ValidateTensorNumDimNumElem(m_ProjectionBias->GetTensorInfo(), 1, n_output, "ProjectionBias");
2208  }
2209 
2210  // Making sure the projection tensors are consistent:
2211  // 1) If projection weight is not present, then projection bias should not be
2212  // present.
2213  // 2) If projection weight is present, then projection bias is optional.
2214  bool projecton_tensors_consistent = ((!m_ProjectionWeights && !m_ProjectionBias &&
2220  if (!projecton_tensors_consistent)
2221  {
2222  throw InvalidArgumentException(descriptorName + ": Projection tensors are inconsistent.");
2223  }
2224 
2225  // The four layer normalization weights either all have values or none of them have values. Additionally, if
2226  // CIFG is used, input layer normalization weights tensor is omitted and the other layer normalization weights
2227  // either all have values or none of them have values. Layer normalization is used when the values of all the
2228  // layer normalization weights are present
2230  {
2231  ValidateTensorNumDimNumElem(m_InputLayerNormWeights->GetTensorInfo(), 1, n_cell, "InputLayerNormWeights");
2232  }
2234  {
2235  ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
2236  }
2238  {
2239  ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
2240  }
2242  {
2243  ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
2244  }
2245 
2247  {
2249  {
2251  {
2252  throw InvalidArgumentException(descriptorName + ": Layer normalisation is enabled and CIFG-LSTM is "
2253  "disabled but InputLayerNormWeights are not present");
2254  }
2256  1, n_cell, "InputLayerNormWeights");
2257  }
2258  else if (m_InputLayerNormWeights)
2259  {
2260  throw InvalidArgumentException(descriptorName + ":InputLayerNormWeights are present while CIFG is "
2261  "enabled");
2262  }
2263 
2264  ValidatePointer(m_ForgetLayerNormWeights, "Null pointer check layer normalisation enabled",
2265  "ForgetLayerNormWeights");
2266  ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
2267 
2268  ValidatePointer(m_OutputLayerNormWeights, "Null pointer check layer normalisation enabled",
2269  "OutputLayerNormWeights");
2270  ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
2271 
2272  ValidatePointer(m_CellLayerNormWeights, "Null pointer check layer normalisation enabled",
2273  "CellLayerNormWeights");
2274  ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
2275  }
2277  {
2278  throw InvalidArgumentException(descriptorName + ": Layer normalisation is disabled but one or more layer "
2279  "normalisation weights are present.");
2280  }
2281 }
2282 
2284 {
2285  const std::string descriptorName{"ConvertFp32ToFp16QueueDescriptor"};
2286 
2287  ValidateNumInputs(workloadInfo, descriptorName, 1);
2288  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2289 
2290  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2291  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2292 
2293  if (inputTensorInfo.GetDataType() != DataType::Float32)
2294  {
2295  throw InvalidArgumentException(descriptorName + ": Input tensor type must be Float32.");
2296  }
2297 
2298  if (outputTensorInfo.GetDataType() != DataType::Float16)
2299  {
2300  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Float16.");
2301  }
2302 
2303  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2304 }
2305 
2307 {
2308  const std::string descriptorName{"ConvertFp16ToFp32QueueDescriptor"};
2309 
2310  ValidateNumInputs(workloadInfo, descriptorName, 1);
2311  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2312 
2313  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2314  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2315 
2316  if (inputTensorInfo.GetDataType() != DataType::Float16)
2317  {
2318  throw InvalidArgumentException(descriptorName + ": Input tensor type must be Float16.");
2319  }
2320 
2321  if (outputTensorInfo.GetDataType() != DataType::Float32)
2322  {
2323  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Float32.");
2324  }
2325 
2326  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2327 }
2328 
2329 void DivisionQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2330 {
2331  const std::string descriptorName{"DivisionQueueDescriptor"};
2332 
2333  ValidateNumInputs(workloadInfo, descriptorName, 2);
2334  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2335 
2336  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2337  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2338  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2339 
2340  std::vector<DataType> supportedTypes =
2341  {
2349  };
2350 
2351  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2352  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2353  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
2354 
2355  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2356  inputTensorInfo1,
2357  outputTensorInfo,
2358  descriptorName,
2359  "input_0",
2360  "input_1");
2361 }
2362 
2364 {
2365  const std::string descriptorName{"SubtractionQueueDescriptor"};
2366 
2367  ValidateNumInputs(workloadInfo, descriptorName, 2);
2368  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2369 
2370  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2371  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2372  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2373 
2374  std::vector<DataType> supportedTypes =
2375  {
2383  };
2384 
2385  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2386  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2387  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
2388 
2389  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2390  inputTensorInfo1,
2391  outputTensorInfo,
2392  descriptorName,
2393  "input_0",
2394  "input_1");
2395 }
2396 
2397 void MaximumQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2398 {
2399  const std::string descriptorName{"MaximumQueueDescriptor"};
2400 
2401  ValidateNumInputs(workloadInfo, descriptorName, 2);
2402  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2403 
2404  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2405  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2406  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2407 
2408  std::vector<DataType> supportedTypes =
2409  {
2417  };
2418 
2419  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2420  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2421  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
2422 
2423  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2424  inputTensorInfo1,
2425  outputTensorInfo,
2426  descriptorName,
2427  "input_0",
2428  "input_1");
2429 }
2430 
2431 void MeanQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2432 {
2433  const std::string descriptorName{"MeanQueueDescriptor"};
2434 
2435  ValidateNumInputs(workloadInfo, descriptorName, 1);
2436  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2437 
2438  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2439  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2440 
2441  std::vector<DataType> supportedTypes =
2442  {
2449  };
2450 
2451  // First check if input tensor data type is supported, then
2452  // check if this data type matches the output tensor data type
2453  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2454  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2455 
2457  {
2458  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, inputTensorInfo.GetNumDimensions(), "output");
2459  }
2460  else if (m_Parameters.m_Axis.empty())
2461  {
2462  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 1, "output");
2463  }
2464  else
2465  {
2466  unsigned int outputDim =
2467  inputTensorInfo.GetNumDimensions() - armnn::numeric_cast<unsigned int>(m_Parameters.m_Axis.size());
2468  ValidateTensorNumDimensions(outputTensorInfo,
2469  descriptorName,
2470  outputDim > 0 ? outputDim : 1,
2471  "output");
2472  }
2473 }
2474 
2475 void PadQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2476 {
2477  const std::string descriptorName{"PadQueueDescriptor"};
2478 
2479  ValidateNumInputs(workloadInfo, descriptorName, 1);
2480  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2481 
2482  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2483  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2484 
2485  // input and output should have the same number of dimensions
2486  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, inputTensorInfo.GetNumDimensions(), "output");
2487 
2488  // there should be entry in the pad list for each dimension in the input tensor
2489  if (m_Parameters.m_PadList.size() != inputTensorInfo.GetNumDimensions()) {
2490  throw InvalidArgumentException(descriptorName + ":Pad List should contain the same number of entries "
2491  "as there are dimensions in the input tensor that is " +
2492  std::to_string(inputTensorInfo.GetNumDimensions()) + " entries " +
2493  " not " + std::to_string(m_Parameters.m_PadList.size()) + " entries.");
2494  }
2495 }
2496 
2497 void QuantizeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2498 {
2499  const std::string descriptorName{"QuantizeQueueDescriptor"};
2500 
2501  ValidateNumInputs(workloadInfo, descriptorName, 1);
2502  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2503 
2504  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2505  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2506 
2507  std::vector<DataType> supportedTypes =
2508  {
2516  };
2517 
2518  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2519 
2520  if (!IsQuantizedType(outputTensorInfo.GetDataType()))
2521  {
2522  throw InvalidArgumentException(descriptorName + ": Output of quantized layer must be quantized type.");
2523  }
2524 }
2525 
2527 {
2528  const std::string descriptorName{"BatchToSpaceNdQueueDescriptor"};
2529 
2530  ValidateNumInputs(workloadInfo, descriptorName, 1);
2531  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2532 
2533  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2534  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2535 
2536  if (m_Parameters.m_BlockShape.size() != m_Parameters.m_Crops.size())
2537  {
2538  throw InvalidArgumentException(descriptorName + ": Crops must contain the same number of "
2539  "dimensions as Block Shape.");
2540  }
2541 
2542  if (m_Parameters.m_BlockShape.size() == 2)
2543  {
2544  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
2545  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
2546  }
2547  else if (m_Parameters.m_BlockShape.size() == 1)
2548  {
2549  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 3, "input");
2550  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 3, "output");
2551  }
2552  else
2553  {
2554  throw InvalidArgumentException(descriptorName + ": Invalid Block and Crops size.");
2555  }
2556 
2557  // In a 4D tensor, there will be 2 spatialDimensions (H and W), and the for loop will run twice.
2558  // In a 3D tensor, there will be 1 spatialDimensions, and the for loop will run once.
2559  unsigned int firstSpatialDimension = m_Parameters.m_DataLayout == DataLayout::NCHW ? 2 : 1;
2560  for (unsigned int i = 0; i < m_Parameters.m_BlockShape.size(); ++i)
2561  {
2562  unsigned int spatialDimension = firstSpatialDimension + i;
2563  unsigned int cropSize = m_Parameters.m_Crops[i].first + m_Parameters.m_Crops[i].second;
2564  unsigned int outputSize = inputTensorInfo.GetShape()[spatialDimension] * m_Parameters.m_BlockShape[i];
2565  if (cropSize > outputSize)
2566  {
2567  throw InvalidArgumentException(descriptorName + ": CropSize must be less than or equal to the uncropped"
2568  "outputSize in dimension: " + to_string(spatialDimension) + ".");
2569  }
2570  }
2571 
2572  std::vector<DataType> supportedTypes =
2573  {
2580  };
2581 
2582  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2583  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2584 }
2585 
2587 {
2588  const std::string descriptorName{"StridedSliceQueueDescriptor"};
2589 
2590  ValidateNumInputs(workloadInfo, descriptorName, 1);
2591  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2592 
2593  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2594  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2595 
2596  std::vector<DataType> supportedTypes =
2597  {
2604  };
2605 
2606  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2607  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2608 
2609  ValidateTensorQuantizationSpace(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2610 
2611  const uint32_t rank = inputTensorInfo.GetNumDimensions();
2612  if (rank > 4)
2613  {
2614  throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
2615  }
2616 
2617  // Begin, End & Stride length must be of rank(input0)
2618  if (m_Parameters.m_Begin.size() != rank)
2619  {
2620  throw InvalidArgumentException(descriptorName + ": Begin length must be of rank " + std::to_string(rank));
2621  }
2622 
2623  if (m_Parameters.m_End.size() != rank)
2624  {
2625  throw InvalidArgumentException(descriptorName + ": End length must be of rank " + std::to_string(rank));
2626  }
2627 
2628  if (m_Parameters.m_Stride.size() != rank)
2629  {
2630  throw InvalidArgumentException(descriptorName + ": Stride length must be of rank " + std::to_string(rank));
2631  }
2632 
2633  // Stride entries must be non-zero
2634  for (auto& stride : m_Parameters.m_Stride)
2635  {
2636  if (stride == 0)
2637  {
2638  throw InvalidArgumentException(descriptorName + ": Stride entries must be non-zero.");
2639  }
2640  }
2641 }
2642 
2643 void MinimumQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2644 {
2645  const std::string descriptorName{"MinimumQueueDescriptor"};
2646 
2647  ValidateNumInputs(workloadInfo, descriptorName, 2);
2648  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2649 
2650  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2651  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2652  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2653 
2654  std::vector<DataType> supportedTypes =
2655  {
2663  };
2664 
2665  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2666  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2667  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
2668 
2669  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2670  inputTensorInfo1,
2671  outputTensorInfo,
2672  descriptorName,
2673  "input_0",
2674  "input_1");
2675 }
2676 
2677 void DebugQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2678 {
2679  const std::string descriptorName{"DebugQueueDescriptor"};
2680 
2681  ValidateNumInputs(workloadInfo, descriptorName, 1);
2682  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2683 }
2684 
2685 void EqualQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2686 {
2687  const std::string descriptorName{"EqualQueueDescriptor"};
2688 
2689  ValidateNumInputs(workloadInfo, descriptorName, 2);
2690  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2691 
2692  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2693  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2694  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2695 
2696  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2697  inputTensorInfo1,
2698  outputTensorInfo,
2699  descriptorName,
2700  "input_0",
2701  "input_1");
2702 
2703  if (outputTensorInfo.GetDataType() != DataType::Boolean)
2704  {
2705  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
2706  }
2707 }
2708 
2709 void GreaterQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2710 {
2711  const std::string descriptorName{"GreaterQueueDescriptor"};
2712 
2713  ValidateNumInputs(workloadInfo, descriptorName, 2);
2714  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2715 
2716  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2717  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2718  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2719 
2720  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2721  inputTensorInfo1,
2722  outputTensorInfo,
2723  descriptorName,
2724  "input_0",
2725  "input_1");
2726 
2727  if (outputTensorInfo.GetDataType() != DataType::Boolean)
2728  {
2729  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
2730  }
2731 }
2732 
2733 void RsqrtQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2734 {
2735  const std::string descriptorName{"RsqrtQueueDescriptor"};
2736 
2737  ValidateNumInputs(workloadInfo, descriptorName, 1);
2738  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2739 
2740  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2741  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2742 
2743  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2744 
2745  std::vector<DataType> supportedTypes =
2746  {
2753  };
2754 
2755  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2756  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2757 }
2758 
2759 void GatherNdQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2760 {
2761  const std::string descriptorName{"GatherNdQueueDescriptor"};
2762 
2763  ValidateNumInputs(workloadInfo, descriptorName, 2);
2764  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2765 
2766  const TensorInfo& indicesTensorInfo = workloadInfo.m_InputTensorInfos[1];
2767  if (indicesTensorInfo.GetDataType() != DataType::Signed32)
2768  {
2769  throw InvalidArgumentException(descriptorName + ": Indices tensor type must be Int32.");
2770  }
2771 
2772  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2773  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2774 
2775  std::vector<DataType> supportedTypes =
2776  {
2784  };
2785 
2786  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2787 
2788  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2789 
2790  unsigned int outputDim = outputTensorInfo.GetNumDimensions();
2791  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, outputDim, "output");
2792 }
2793 
2794 void GatherQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2795 {
2796  const std::string descriptorName{"GatherQueueDescriptor"};
2797 
2798  ValidateNumInputs(workloadInfo, descriptorName, 2);
2799  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2800 
2801  const TensorInfo& indicesTensorInfo = workloadInfo.m_InputTensorInfos[1];
2802  if (indicesTensorInfo.GetDataType() != DataType::Signed32)
2803  {
2804  throw InvalidArgumentException(descriptorName + ": Indices tensor type must be Int32.");
2805  }
2806 
2807  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2808  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2809 
2810  std::vector<DataType> supportedTypes =
2811  {
2819  };
2820 
2821  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2822 
2823  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2824 
2825  unsigned int outputDim = inputTensorInfo.GetNumDimensions() + indicesTensorInfo.GetNumDimensions() - 1;
2826  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, outputDim, "output");
2827 }
2828 
2830 {
2831  const std::string& descriptorName{"DetectionPostProcessQueueDescriptor"};
2832 
2833  ValidateNumInputs(workloadInfo, descriptorName, 2);
2834 
2835  if (workloadInfo.m_OutputTensorInfos.size() != 4)
2836  {
2837  throw InvalidArgumentException(descriptorName + ": Requires exactly four outputs. " +
2838  to_string(workloadInfo.m_OutputTensorInfos.size()) + " has been provided.");
2839  }
2840 
2841  if (m_Anchors == nullptr)
2842  {
2843  throw InvalidArgumentException(descriptorName + ": Anchors tensor descriptor is missing.");
2844  }
2845 
2846  const TensorInfo& boxEncodingsInfo = workloadInfo.m_InputTensorInfos[0];
2847  const TensorInfo& scoresInfo = workloadInfo.m_InputTensorInfos[1];
2848  const TensorInfo& anchorsInfo = m_Anchors->GetTensorInfo();
2849 
2850  const TensorInfo& detectionBoxesInfo = workloadInfo.m_OutputTensorInfos[0];
2851  const TensorInfo& detectionClassesInfo = workloadInfo.m_OutputTensorInfos[1];
2852  const TensorInfo& detectionScoresInfo = workloadInfo.m_OutputTensorInfos[2];
2853  const TensorInfo& numDetectionsInfo = workloadInfo.m_OutputTensorInfos[3];
2854 
2855  ValidateTensorNumDimensions(boxEncodingsInfo, descriptorName, 3, "box encodings");
2856  ValidateTensorNumDimensions(scoresInfo, descriptorName, 3, "scores");
2857  ValidateTensorNumDimensions(anchorsInfo, descriptorName, 2, "anchors");
2858 
2859  const std::vector<DataType> supportedInputTypes =
2860  {
2867  };
2868 
2869  ValidateDataTypes(boxEncodingsInfo, supportedInputTypes, descriptorName);
2870  ValidateDataTypes(scoresInfo, supportedInputTypes, descriptorName);
2871  ValidateDataTypes(anchorsInfo, supportedInputTypes, descriptorName);
2872 
2873  ValidateTensorNumDimensions(detectionBoxesInfo, descriptorName, 3, "detection boxes");
2874  ValidateTensorNumDimensions(detectionScoresInfo, descriptorName, 2, "detection scores");
2875  ValidateTensorNumDimensions(detectionClassesInfo, descriptorName, 2, "detection classes");
2876  ValidateTensorNumDimensions(numDetectionsInfo, descriptorName, 1, "num detections");
2877 
2878  // NOTE: Output is always Float32 regardless of input type
2879  ValidateTensorDataType(detectionBoxesInfo, DataType::Float32, descriptorName, "detection boxes");
2880  ValidateTensorDataType(detectionScoresInfo, DataType::Float32, descriptorName, "detection scores");
2881  ValidateTensorDataType(detectionClassesInfo, DataType::Float32, descriptorName, "detection classes");
2882  ValidateTensorDataType(numDetectionsInfo, DataType::Float32, descriptorName, "num detections");
2883 
2885  {
2886  throw InvalidArgumentException(descriptorName + ": Intersection over union threshold "
2887  "must be positive and less than or equal to 1.");
2888  }
2889 
2890  if (scoresInfo.GetShape()[2] != m_Parameters.m_NumClasses + 1)
2891  {
2892  throw InvalidArgumentException(descriptorName + ": Number of classes with background "
2893  "should be equal to number of classes + 1.");
2894  }
2895 }
2896 
2897 void DequantizeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2898 {
2899  const std::string& descriptorName{"DequantizeQueueDescriptor"};
2900 
2901  ValidateNumInputs(workloadInfo, descriptorName, 1);
2902  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2903 
2904  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2905  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2906 
2907  std::vector<DataType> inputSupportedTypes =
2908  {
2914  };
2915  ValidateDataTypes(inputTensorInfo, inputSupportedTypes, descriptorName);
2916 
2917  std::vector<DataType> outputSupportedTypes =
2918  {
2922  };
2923 
2924  ValidateDataTypes(outputTensorInfo, outputSupportedTypes, descriptorName);
2925 }
2926 
2927 void MergeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2928 {
2929  const std::string& descriptorName{"MergeQueueDescriptor"};
2930 
2931  ValidateNumInputs(workloadInfo, descriptorName, 2);
2932  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2933 
2934  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2935  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2936  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2937 
2938  ValidateTensorShapesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
2939  ValidateTensorShapesMatch(inputTensorInfo0, outputTensorInfo, descriptorName, "input_0", "output");
2940 
2941  ValidateTensorDataTypesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
2942  ValidateTensorDataTypesMatch(inputTensorInfo0, outputTensorInfo, descriptorName, "input_0", "output");
2943 }
2944 
2945 void ShapeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2946 {
2947  const std::string& descriptorName{"ShapeQueueDescriptor"};
2948 
2949  ValidateNumInputs(workloadInfo, descriptorName, 1);
2950  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2951 
2952  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2953  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2954 
2955  std::vector<DataType> supportedTypes =
2956  {
2965  };
2966 
2967  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2968  ValidateDataTypes(outputTensorInfo, {DataType::Signed32}, descriptorName);
2969 }
2970 
2971 void SwitchQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2972 {
2973  const std::string& descriptorName{"SwitchQueueDescriptor"};
2974 
2975  ValidateNumInputs(workloadInfo, descriptorName, 2);
2976  ValidateNumOutputs(workloadInfo, descriptorName, 2);
2977 
2978  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2979  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2980 
2981  const TensorInfo& outputTensorInfo0 = workloadInfo.m_OutputTensorInfos[0];
2982  const TensorInfo& outputTensorInfo1 = workloadInfo.m_OutputTensorInfos[1];
2983 
2984  std::vector<DataType> supportedTypes =
2985  {
2991  };
2992 
2993  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2994  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2995 
2996  ValidateDataTypes(outputTensorInfo0, supportedTypes, descriptorName);
2997  ValidateDataTypes(outputTensorInfo1, supportedTypes, descriptorName);
2998 
2999  ValidateTensorShapesMatch(inputTensorInfo0,
3000  outputTensorInfo0,
3001  descriptorName,
3002  "input_0",
3003  "output_0");
3004 
3005  ValidateTensorShapesMatch(inputTensorInfo0,
3006  outputTensorInfo1,
3007  descriptorName,
3008  "input_0",
3009  "output_1");
3010 }
3011 
3012 void PreCompiledQueueDescriptor::Validate(const WorkloadInfo& /*workloadInfo*/) const
3013 {
3014  // This is internally generated, so it should not need validation.
3015 }
3016 
3017 void PreluQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3018 {
3019  const std::string& descriptorName{"PreluQueueDescriptor"};
3020 
3021  ValidateNumInputs(workloadInfo, descriptorName, 2);
3022  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3023 
3024  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3025  const TensorInfo& alphaTensorInfo = workloadInfo.m_InputTensorInfos[1];
3026  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3027 
3028  std::vector<DataType> supportedTypes
3029  {
3036  };
3037 
3038  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3039  ValidateDataTypes(alphaTensorInfo, supportedTypes, descriptorName);
3040 
3041  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
3042 
3043  ValidateTensorDataTypesMatch(inputTensorInfo, alphaTensorInfo, descriptorName, "input", "alpha");
3044  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "ouptut");
3045 
3046  ValidateBroadcastTensorShapesMatch(inputTensorInfo,
3047  alphaTensorInfo,
3048  outputTensorInfo,
3049  descriptorName,
3050  "input",
3051  "alpha");
3052 }
3053 
3055 {
3056  const std::string descriptorName{"TransposeConvolution2dQueueDescriptor"};
3057 
3058  ValidateNumInputs(workloadInfo, descriptorName, 1);
3059  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3060 
3061  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3062  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3063 
3064  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
3065  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
3066 
3067  ValidatePointer(m_Weight, descriptorName, "weight");
3068 
3069  const TensorInfo& weightTensorInfo = m_Weight->GetTensorInfo();
3070  ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 4, "weight");
3071 
3072  ValidateWeightDataType(inputTensorInfo, weightTensorInfo, descriptorName);
3073 
3074  Optional<TensorInfo> optionalBiasTensorInfo;
3076  {
3077  ValidatePointer(m_Bias, descriptorName, "bias");
3078 
3079  optionalBiasTensorInfo = MakeOptional<TensorInfo>(m_Bias->GetTensorInfo());
3080  const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value();
3081 
3082  ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
3083  ValidateBiasTensorQuantization(biasTensorInfo, weightTensorInfo, descriptorName);
3084  }
3085 
3086  ValidatePerAxisQuantization(inputTensorInfo,
3087  outputTensorInfo,
3088  weightTensorInfo,
3089  optionalBiasTensorInfo,
3090  descriptorName);
3091 
3092  std::vector<DataType> supportedTypes =
3093  {
3100  };
3101 
3102  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3103  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3104 }
3105 
3106 void TransposeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3107 {
3108  const std::string descriptorName{"TransposeQueueDescriptor"};
3109 
3110  ValidateNumInputs(workloadInfo, descriptorName, 1);
3111  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3112 
3113  const PermutationVector& mapping = m_Parameters.m_DimMappings;
3114 
3115  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3116  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3117 
3118  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, mapping.GetSize(), "input");
3119  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, mapping.GetSize(), "output");
3120 
3121  for (unsigned int i = 0u; i < mapping.GetSize(); ++i)
3122  {
3123  if (inputTensorInfo.GetShape()[mapping[i]] != outputTensorInfo.GetShape()[i])
3124  {
3125  throw InvalidArgumentException(descriptorName + ": src dimension " + to_string(mapping[i]) +
3126  " (=" + to_string(inputTensorInfo.GetShape()[mapping[i]]) + ") " +
3127  "must match dst dimension " + to_string(i) +
3128  " (=" + to_string(outputTensorInfo.GetShape()[i]) + ")");
3129  }
3130  }
3131 
3132  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3133 }
3134 
3136 {
3137  const std::string descriptorName{"TransposeQueueDescriptor"};
3138 
3139  ValidateNumInputs(workloadInfo, descriptorName, 1);
3140  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3141 
3142  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3143  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3144 
3145  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3146 }
3147 
3148 void QLstmQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3149 {
3150  const std::string descriptorName{"QLstmQueueDescriptor"};
3151 
3152  // Validate number of inputs/outputs
3153  ValidateNumInputs(workloadInfo, descriptorName, 3);
3154  ValidateNumOutputs(workloadInfo, descriptorName, 3);
3155 
3156  // Input/output tensor info
3157  auto inputInfo = workloadInfo.m_InputTensorInfos[0];
3158  auto outputStateInInfo = workloadInfo.m_InputTensorInfos[1];
3159  auto cellStateInInfo = workloadInfo.m_InputTensorInfos[2];
3160 
3161  auto outputStateOutInfo = workloadInfo.m_OutputTensorInfos[0];
3162  auto cellStateOutInfo = workloadInfo.m_OutputTensorInfos[1];
3163  auto outputInfo = workloadInfo.m_OutputTensorInfos[2];
3164 
3165  // Supported types for various tensors in QLSTM
3166  std::vector<DataType> inputOutputSupportedTypes =
3167  {
3169  };
3170 
3171  std::vector<DataType> cellStateSupportedTypes =
3172  {
3174  };
3175 
3176  std::vector<DataType> weightsSupportedTypes =
3177  {
3179  };
3180 
3181  std::vector<DataType> layerNormPeepholeWeightsSupportedTypes =
3182  {
3184  };
3185 
3186  std::vector<DataType> biasSupportedTypes =
3187  {
3189  };
3190 
3191  // Validate types of input/output tensors
3192  ValidateDataTypes(inputInfo, inputOutputSupportedTypes, descriptorName);
3193  ValidateDataTypes(outputStateInInfo, inputOutputSupportedTypes, descriptorName);
3194  ValidateDataTypes(cellStateInInfo, cellStateSupportedTypes, descriptorName);
3195 
3196  ValidateDataTypes(outputStateOutInfo, inputOutputSupportedTypes, descriptorName);
3197  ValidateDataTypes(cellStateOutInfo, cellStateSupportedTypes, descriptorName);
3198  ValidateDataTypes(outputInfo, inputOutputSupportedTypes, descriptorName);
3199 
3200  // Validate matching types of input/output tensors
3201  ValidateTensorDataTypesMatch(inputInfo, outputStateInInfo, descriptorName, "input", "outputStateIn");
3202  ValidateTensorDataTypesMatch(outputStateInInfo, outputStateOutInfo, descriptorName,
3203  "outputStateIn", "outputStateOut");
3204  ValidateTensorDataTypesMatch(cellStateInInfo, cellStateOutInfo, descriptorName, "cellStateIn", "cellStateOut");
3205 
3206  // Infer number of batches, number of units, input size and output size from tensor dimensions
3207  const uint32_t numBatches = inputInfo.GetShape()[0];
3208  const uint32_t inputSize = inputInfo.GetShape()[1];
3209  const uint32_t outputSize = outputStateInInfo.GetShape()[1];
3210  const uint32_t numUnits = cellStateInInfo.GetShape()[1];
3211 
3212  // Validate number of dimensions and number of elements for input/output tensors
3213  ValidateTensorNumDimNumElem(inputInfo, 2, (numBatches * inputSize), descriptorName + " input");
3214  ValidateTensorNumDimNumElem(outputStateInInfo, 2, (numBatches * outputSize), descriptorName + " outputStateIn");
3215  ValidateTensorNumDimNumElem(cellStateInInfo, 2, (numBatches * numUnits), descriptorName + " cellStateIn");
3216 
3217  ValidateTensorNumDimNumElem(outputStateOutInfo, 2, (numBatches * outputSize), descriptorName + " outputStateOut");
3218  ValidateTensorNumDimNumElem(cellStateOutInfo, 2, (numBatches * numUnits), descriptorName + " cellStateOut");
3219  ValidateTensorNumDimNumElem(outputInfo, 2, (numBatches * outputSize), descriptorName + " output");
3220 
3221  // Validate number of dimensions and number of elements for MANDATORY weight tensors
3222  ValidatePointer(m_InputToForgetWeights, descriptorName, "InputToForgetWeights");
3223  auto inputToForgetWeightsInfo = m_InputToForgetWeights->GetTensorInfo();
3224  ValidateTensorNumDimNumElem(inputToForgetWeightsInfo, 2, (numUnits * inputSize), " InputToForgetWeights");
3225 
3226  ValidatePointer(m_InputToCellWeights, descriptorName, "InputToCellWeights");
3227  auto inputToCellWeightsInfo = m_InputToCellWeights->GetTensorInfo();
3228  ValidateTensorNumDimNumElem(inputToCellWeightsInfo, 2, (numUnits * inputSize), " InputToCellWeights");
3229 
3230  ValidatePointer(m_InputToOutputWeights, descriptorName, "InputToOutputWeights");
3231  auto inputToOutputWeightsInfo = m_InputToOutputWeights->GetTensorInfo();
3232  ValidateTensorNumDimNumElem(inputToOutputWeightsInfo, 2, (numUnits * inputSize), " InputToOutputWeights");
3233 
3234  ValidatePointer(m_RecurrentToForgetWeights, descriptorName, "RecurrentToForgetWeights");
3235  auto recurrentToForgetWeightsInfo = m_RecurrentToForgetWeights->GetTensorInfo();
3236  ValidateTensorNumDimNumElem(recurrentToForgetWeightsInfo, 2, (numUnits * outputSize),
3237  " RecurrentToForgetWeights");
3238 
3239  ValidatePointer(m_RecurrentToCellWeights, descriptorName, "RecurrentToCellWeights");
3240  auto recurrentToCellWeightsInfo = m_RecurrentToCellWeights->GetTensorInfo();
3241  ValidateTensorNumDimNumElem(recurrentToCellWeightsInfo, 2, (numUnits * outputSize), " RecurrentToCellWeights");
3242 
3243  ValidatePointer(m_RecurrentToOutputWeights, descriptorName, "RecurrentToOutputWeights");
3244  auto recurrentToOutputWeightsInfo = m_RecurrentToOutputWeights->GetTensorInfo();
3245  ValidateTensorNumDimNumElem(recurrentToOutputWeightsInfo, 2, (numUnits * outputSize), " RecurrentToCellWeights");
3246 
3247  // Validate data types for MANDATORY weights tensors (all should match each other)
3248  ValidateDataTypes(inputToForgetWeightsInfo, weightsSupportedTypes, descriptorName);
3249 
3250  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, inputToCellWeightsInfo, descriptorName,
3251  "inputToForgetWeights", "inputToCellWeights");
3252  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, inputToOutputWeightsInfo, descriptorName,
3253  "inputToForgetWeights", "inputToOutputWeights");
3254 
3255  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, recurrentToForgetWeightsInfo, descriptorName,
3256  "inputToForgetWeights", "recurrentToForgeteights");
3257  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, recurrentToCellWeightsInfo, descriptorName,
3258  "inputToForgetWeights", "recurrentToCellWeights");
3259  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, recurrentToOutputWeightsInfo, descriptorName,
3260  "inputToForgetWeights", "recurrentToOutputWeights");
3261 
3262  // Validate number of dimensions and number of elements for MANDATORY bias tensors
3263  ValidatePointer(m_ForgetGateBias, descriptorName, "ForgetGateBias");
3264  auto forgetGateBiasInfo = m_ForgetGateBias->GetTensorInfo();
3265  ValidateTensorNumDimNumElem(forgetGateBiasInfo, 1, numUnits, " ForgetGateBias");
3266 
3267  ValidatePointer(m_CellBias, descriptorName, "CellBias");
3268  auto cellBiasInfo = m_CellBias->GetTensorInfo();
3269  ValidateTensorNumDimNumElem(cellBiasInfo, 1, numUnits, " CellBias");
3270 
3271  ValidatePointer(m_OutputGateBias, descriptorName, "OutputGateBias");
3272  auto outputGateBiasInfo = m_OutputGateBias->GetTensorInfo();
3273  ValidateTensorNumDimNumElem(outputGateBiasInfo, 1, numUnits, " OutputGateBias");
3274 
3275  // Validate data types for MANDATORY bias tensors
3276  ValidateDataTypes(forgetGateBiasInfo, biasSupportedTypes, descriptorName);
3277 
3278  ValidateTensorDataTypesMatch(forgetGateBiasInfo, cellBiasInfo, descriptorName,
3279  "forgetGateBias", "cellBias");
3280  ValidateTensorDataTypesMatch(forgetGateBiasInfo, outputGateBiasInfo, descriptorName,
3281  "forgetGateBias", "outputGateBias");
3282 
3283  // Validate OPTIONAL params: CIFG (inputToInputWeights, recurrentToInputWeights, inputGateBias)
3284  const bool allCifgParamsPresentOrNot = ((m_InputToInputWeights && m_RecurrentToInputWeights && m_InputGateBias &&
3288 
3289  if (!allCifgParamsPresentOrNot)
3290  {
3291  throw InvalidArgumentException(descriptorName +
3292  ": InputToInputWeights, RecurrentToInputWeights and InputGateBias must either all be present "
3293  "(CIFG disabled) or not be present at all (CIFG enabled). m_Parameters.m_CifgEnabled should be "
3294  "set appropriately.");
3295  }
3296 
3298  {
3299  // Validate number of dimensions and number of elements
3300  auto inputToInputWeightsInfo = m_InputToInputWeights->GetTensorInfo();
3301  ValidateTensorNumDimNumElem(inputToInputWeightsInfo, 2, (numUnits * inputSize), " InputToInputWeights");
3302 
3303  auto recurrentToInputWeightsInfo = m_RecurrentToInputWeights->GetTensorInfo();
3304  ValidateTensorNumDimNumElem(recurrentToInputWeightsInfo, 2, (numUnits * outputSize),
3305  " RecurrentToInputWeights");
3306 
3307  auto inputGateBiasInfo = m_InputGateBias->GetTensorInfo();
3308  ValidateTensorNumDimNumElem(inputGateBiasInfo, 1, numUnits, " InputGateBias");
3309 
3310  // Validate data types
3311  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, inputToInputWeightsInfo, descriptorName,
3312  "inputToForgetWeights", "inputToInputWeights");
3313  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, recurrentToInputWeightsInfo, descriptorName,
3314  "inputToForgetWeights", "recurrentToInputWeights");
3315  ValidateTensorDataTypesMatch(forgetGateBiasInfo, inputGateBiasInfo, descriptorName,
3316  "forgetGateBias", "inputGateBias");
3317  }
3318 
3319  // Validate OPTIONAL params: Peephole (cellToInputWeights, cellToForgetWeights, cellToOutputWeights)
3320  bool allPeepholeWeightsPresentOrNot =
3325 
3326  if (!allPeepholeWeightsPresentOrNot)
3327  {
3328  throw InvalidArgumentException(descriptorName +
3329  ": CellToInputWeights, CellToForgetWeights and CellToOutputWeights should all be present (Peephole "
3330  "enabled) or not be present at all (Peephole disabled). CellToInputWeights should only be present "
3331  "when Peephole is enabled and CIFG is disabled. m_Parameters.m_PeepholeEnabled should be set "
3332  "appropriately.");
3333  }
3334 
3336  {
3337  auto cellToForgetWeightsInfo = m_CellToForgetWeights->GetTensorInfo();
3338  ValidateTensorNumDimNumElem(cellToForgetWeightsInfo, 1, numUnits, " cellToForgetWeights");
3339  ValidateDataTypes(cellToForgetWeightsInfo, layerNormPeepholeWeightsSupportedTypes, descriptorName);
3340 
3341  auto cellToOutputWeightsInfo = m_CellToOutputWeights->GetTensorInfo();
3342  ValidateTensorNumDimNumElem(cellToOutputWeightsInfo, 1, numUnits, " cellToOutputWeights");
3343  ValidateTensorDataTypesMatch(cellToForgetWeightsInfo, cellToOutputWeightsInfo, descriptorName,
3344  "cellToForgetWeight", "cellToOutputWeights");
3345 
3347  {
3348  auto cellToInputWeightsInfo = m_CellToInputWeights->GetTensorInfo();
3349  ValidateTensorNumDimNumElem(cellToInputWeightsInfo, 1, numUnits, " cellToInputWeights");
3350  ValidateTensorDataTypesMatch(cellToForgetWeightsInfo, cellToInputWeightsInfo, descriptorName,
3351  "cellToForgetWeights", "cellToInputWeights");
3352  }
3353  }
3354 
3355  // Validate OPTIONAL params: Layer Norm Weights
3356  bool allLayerNormWeightsPresentOrNot =
3361 
3362  if (!allLayerNormWeightsPresentOrNot)
3363  {
3364  throw InvalidArgumentException(descriptorName +
3365  ": InputLayerNormWeights, ForgetLayerNormWeights, m_OutputLayerNormWeights "
3366  "and CellLayerNormWeights should all be present (Layer Norm enabled) or not "
3367  "be present at all (Layer Norm disabled). InputLayerNormWeights should "
3368  "only be present when Layer Norm is enabled and CIFG is disabled. "
3369  "m_Parameters.m_LayerNormEnabled should be set appropriately.");
3370  }
3371 
3373  {
3374  auto forgetLayerNormWeightsInfo = m_ForgetLayerNormWeights->GetTensorInfo();
3375  ValidateTensorNumDimNumElem(forgetLayerNormWeightsInfo, 1, numUnits, " forgetLayerNormWeights");
3376  ValidateDataTypes(forgetLayerNormWeightsInfo, layerNormPeepholeWeightsSupportedTypes, descriptorName);
3377 
3378  auto cellLayerNormWeightsInfo = m_CellLayerNormWeights->GetTensorInfo();
3379  ValidateTensorNumDimNumElem(cellLayerNormWeightsInfo, 1, numUnits, " cellLayerNormWeights");
3380  ValidateTensorDataTypesMatch(forgetLayerNormWeightsInfo, cellLayerNormWeightsInfo, descriptorName,
3381  "forgetLayerNormWeights", "cellLayerNormWeights");
3382 
3383  auto outputLayerNormWeightsInfo = m_OutputLayerNormWeights->GetTensorInfo();
3384  ValidateTensorNumDimNumElem(outputLayerNormWeightsInfo, 1, numUnits, " outputLayerNormWeights");
3385  ValidateTensorDataTypesMatch(forgetLayerNormWeightsInfo, outputLayerNormWeightsInfo, descriptorName,
3386  "forgetLayerNormWeights", "outputLayerNormWeights");
3387 
3389  {
3390  auto inputLayerNormWeightsInfo = m_InputLayerNormWeights->GetTensorInfo();
3391  ValidateTensorNumDimNumElem(inputLayerNormWeightsInfo, 1, numUnits, " inputLayerNormWeights");
3392  ValidateTensorDataTypesMatch(forgetLayerNormWeightsInfo, inputLayerNormWeightsInfo, descriptorName,
3393  "forgetLayerNormWeights", "inputLayerNormWeights");
3394  }
3395  }
3396 
3397  // Validate OPTIONAL params: Projection (projectionWeights, projectionBias)
3398  bool correctProjectionTensorsPresent =
3402 
3403  if (!correctProjectionTensorsPresent)
3404  {
3405  throw InvalidArgumentException(descriptorName +
3406  ": If projection is enabled, ProjectionWeights should be present and "
3407  "ProjectionBias is optional. If projection is disabled, neither "
3408  "ProjectionWeights nor ProjectionBias should be present.");
3409  }
3410 
3412  {
3413  auto projectionWeightsInfo = m_ProjectionWeights->GetTensorInfo();
3414  ValidateTensorNumDimNumElem(projectionWeightsInfo, 2, (numUnits * outputSize), "ProjectionWeights");
3415  ValidateDataTypes(projectionWeightsInfo, weightsSupportedTypes, descriptorName);
3416 
3417  if (m_ProjectionBias)
3418  {
3419  auto projectionBiasInfo = m_ProjectionBias->GetTensorInfo();
3420  ValidateTensorNumDimNumElem(projectionBiasInfo, 1, outputSize, "ProjectionBias");
3421  ValidateDataTypes(projectionBiasInfo, biasSupportedTypes, descriptorName);
3422  }
3423 
3424  }
3425  else if ((outputInfo.GetQuantizationScale() != m_Parameters.m_HiddenStateScale) &&
3427  throw InvalidArgumentException(descriptorName +
3428  ": If projection is disabled, output quantization info (scale, offset) "
3429  "should match HiddenStateScale and HiddenStateZeroPoint.");
3430  }
3431 
3432 }
3433 
3435 {
3436  const std::string descriptorName{"QuantizedLstmQueueDescriptor"};
3437 
3438  // Validate number of inputs/outputs
3439  ValidateNumInputs(workloadInfo, descriptorName, 3);
3440  ValidateNumOutputs(workloadInfo, descriptorName, 2);
3441 
3442  // Input/output tensor infos
3443  auto inputInfo = workloadInfo.m_InputTensorInfos[0];
3444  auto cellStateInInfo = workloadInfo.m_InputTensorInfos[1];
3445  auto outputStateInInfo = workloadInfo.m_InputTensorInfos[2];
3446 
3447  auto cellStateOutInfo = workloadInfo.m_OutputTensorInfos[0];
3448  auto outputStateOutInfo = workloadInfo.m_OutputTensorInfos[1];
3449 
3450  std::vector<DataType> inputOutputSupportedTypes =
3451  {
3453  };
3454 
3455  std::vector<DataType> cellStateSupportedTypes =
3456  {
3458  };
3459 
3460  std::vector<DataType> weightsSupportedTypes =
3461  {
3463  };
3464 
3465  std::vector<DataType> biasSupportedTypes =
3466  {
3468  };
3469 
3470  // Validate types of input/output tensors
3471  ValidateDataTypes(inputInfo, inputOutputSupportedTypes, descriptorName);
3472  ValidateDataTypes(cellStateInInfo, cellStateSupportedTypes, descriptorName);
3473  ValidateDataTypes(outputStateInInfo, inputOutputSupportedTypes, descriptorName);
3474 
3475  ValidateDataTypes(cellStateOutInfo, cellStateSupportedTypes, descriptorName);
3476  ValidateDataTypes(outputStateOutInfo, inputOutputSupportedTypes, descriptorName);
3477 
3478  // Validate matching types of input/output tensors
3479  ValidateTensorDataTypesMatch(inputInfo, outputStateInInfo, descriptorName, "input", "outputStateIn");
3480  ValidateTensorDataTypesMatch(outputStateInInfo, outputStateOutInfo, descriptorName,
3481  "outputStateIn", "outputStateOut");
3482  ValidateTensorDataTypesMatch(cellStateInInfo, cellStateOutInfo, descriptorName, "cellStateIn", "cellStateOut");
3483 
3484  // Validate matching quantization info for input/output tensors
3485  ValidateTensorQuantizationSpace(inputInfo, outputStateInInfo, descriptorName, "input", "outputStateIn");
3486  ValidateTensorQuantizationSpace(inputInfo, outputStateOutInfo, descriptorName, "input", "outputStateOut");
3487  ValidateTensorQuantizationSpace(cellStateInInfo, cellStateOutInfo, descriptorName, "cellStateIn", "cellStateOut");
3488 
3489  // Infer number of batches, input size and output size from tensor dimensions
3490  const uint32_t numBatches = inputInfo.GetShape()[0];
3491  const uint32_t inputSize = inputInfo.GetShape()[1];
3492  const uint32_t outputSize = cellStateInInfo.GetShape()[1];
3493 
3494  // Validate number of dimensions and number of elements for input/output tensors
3495  ValidateTensorNumDimNumElem(inputInfo, 2, (numBatches * inputSize), descriptorName + " input");
3496  ValidateTensorNumDimNumElem(cellStateInInfo, 2, (numBatches * outputSize), descriptorName + " cellStateIn");
3497  ValidateTensorNumDimNumElem(outputStateInInfo, 2, (numBatches * outputSize), descriptorName + " outputStateIn");
3498  ValidateTensorNumDimNumElem(cellStateOutInfo, 2, (numBatches * outputSize), descriptorName + " cellStateOut");
3499  ValidateTensorNumDimNumElem(outputStateOutInfo, 2, (numBatches * outputSize), descriptorName + " outputStateOut");
3500 
3501  // Validate number of dimensions and number of elements for weights tensors
3502  ValidatePointer(m_InputToInputWeights, descriptorName, "InputToInputWeights");
3503  auto inputToInputWeightsInfo = m_InputToInputWeights->GetTensorInfo();
3504  ValidateTensorNumDimNumElem(inputToInputWeightsInfo, 2, (outputSize * inputSize), " InputToInputWeights");
3505 
3506  ValidatePointer(m_InputToForgetWeights, descriptorName, "InputToForgetWeights");
3507  auto inputToForgetWeightsInfo = m_InputToForgetWeights->GetTensorInfo();
3508  ValidateTensorNumDimNumElem(inputToForgetWeightsInfo, 2, (outputSize * inputSize), " InputToForgetWeights");
3509 
3510  ValidatePointer(m_InputToCellWeights, descriptorName, "InputToCellWeights");
3511  auto inputToCellWeightsInfo = m_InputToCellWeights->GetTensorInfo();
3512  ValidateTensorNumDimNumElem(inputToCellWeightsInfo, 2, (outputSize * inputSize), " InputToCellWeights");
3513 
3514  ValidatePointer(m_InputToOutputWeights, descriptorName, "InputToOutputWeights");
3515  auto inputToOutputWeightsInfo = m_InputToOutputWeights->GetTensorInfo();
3516  ValidateTensorNumDimNumElem(inputToOutputWeightsInfo, 2, (outputSize * inputSize), " InputToOutputWeights");
3517 
3518  ValidatePointer(m_RecurrentToInputWeights, descriptorName, "RecurrentToInputWeights");
3519  auto recurrentToInputWeightsInfo = m_RecurrentToInputWeights->GetTensorInfo();
3520  ValidateTensorNumDimNumElem(recurrentToInputWeightsInfo, 2, (outputSize * outputSize), " RecurrentToInputWeights");
3521 
3522  ValidatePointer(m_RecurrentToForgetWeights, descriptorName, "RecurrentToForgetWeights");
3523  auto recurrentToForgetWeightsInfo = m_RecurrentToForgetWeights->GetTensorInfo();
3524  ValidateTensorNumDimNumElem(recurrentToForgetWeightsInfo, 2, (outputSize * outputSize),
3525  " RecurrentToForgetWeights");
3526 
3527  ValidatePointer(m_RecurrentToCellWeights, descriptorName, "RecurrentToCellWeights");
3528  auto recurrentToCellWeightsInfo = m_RecurrentToCellWeights->GetTensorInfo();
3529  ValidateTensorNumDimNumElem(recurrentToCellWeightsInfo, 2, (outputSize * outputSize), " RecurrentToCellWeights");
3530 
3531  ValidatePointer(m_RecurrentToOutputWeights, descriptorName, "RecurrentToOutputWeights");
3532  auto recurrentToOutputWeightsInfo = m_RecurrentToOutputWeights->GetTensorInfo();
3533  ValidateTensorNumDimNumElem(recurrentToOutputWeightsInfo, 2, (outputSize * outputSize), " RecurrentToCellWeights");
3534 
3535  // Validate data types for weights tensors (all should match each other)
3536  ValidateDataTypes(inputToInputWeightsInfo, weightsSupportedTypes, descriptorName);
3537 
3538  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, inputToForgetWeightsInfo, descriptorName,
3539  "inputToInputWeights", "inputToForgetWeights");
3540  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, inputToCellWeightsInfo, descriptorName,
3541  "inputToInputWeights", "inputToCellWeights");
3542  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, inputToOutputWeightsInfo, descriptorName,
3543  "inputToInputWeights", "inputToOutputWeights");
3544 
3545  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToInputWeightsInfo, descriptorName,
3546  "inputToInputWeights", "recurrentToInputWeights");
3547  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToForgetWeightsInfo, descriptorName,
3548  "inputToInputWeights", "recurrentToForgeteights");
3549  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToCellWeightsInfo, descriptorName,
3550  "inputToInputWeights", "recurrentToCellWeights");
3551  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToOutputWeightsInfo, descriptorName,
3552  "inputToInputWeights", "recurrentToOutputWeights");
3553 
3554  // Validate matching quantization info for weight tensors (all should match each other)
3555  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, inputToForgetWeightsInfo,
3556  descriptorName, "inputToInputWeights", "inputToForgetWeights");
3557  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, inputToCellWeightsInfo,
3558  descriptorName, "inputToInputWeights", "inputToCellWeights");
3559  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, inputToOutputWeightsInfo,
3560  descriptorName, "inputToInputWeights", "inputToOutputWeights");
3561 
3562  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToInputWeightsInfo,
3563  descriptorName, "inputToInputWeights", "recurrentToInputWeights");
3564  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToForgetWeightsInfo,
3565  descriptorName, "inputToInputWeights", "recurrentToForgetWeights");
3566  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToCellWeightsInfo,
3567  descriptorName, "inputToInputWeights", "recurrentToCellWeights");
3568  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToOutputWeightsInfo,
3569  descriptorName, "inputToInputWeights", "recurrentToOutputWeights");
3570 
3571  // Validate number of dimensions and number of elements in bias tensors
3572  ValidatePointer(m_InputGateBias, descriptorName, "InputGateBias");
3573  auto inputGateBiasInfo = m_InputGateBias->GetTensorInfo();
3574  ValidateTensorNumDimNumElem(inputGateBiasInfo, 1, outputSize, " InputGateBias");
3575 
3576  ValidatePointer(m_ForgetGateBias, descriptorName, "ForgetGateBias");
3577  auto forgetGateBiasInfo = m_ForgetGateBias->GetTensorInfo();
3578  ValidateTensorNumDimNumElem(forgetGateBiasInfo, 1, outputSize, " ForgetGateBias");
3579 
3580  ValidatePointer(m_CellBias, descriptorName, "CellBias");
3581  auto cellBiasInfo = m_CellBias->GetTensorInfo();
3582  ValidateTensorNumDimNumElem(cellBiasInfo, 1, outputSize, " CellBias");
3583 
3584  ValidatePointer(m_OutputGateBias, descriptorName, "OutputGateBias");
3585  auto outputGateBiasInfo = m_OutputGateBias->GetTensorInfo();
3586  ValidateTensorNumDimNumElem(outputGateBiasInfo, 1, outputSize, " OutputGateBias");
3587 
3588  // Validate data types for bias tensors (all should match each other)
3589  ValidateDataTypes(inputGateBiasInfo, biasSupportedTypes, descriptorName);
3590 
3591  ValidateTensorDataTypesMatch(inputGateBiasInfo, forgetGateBiasInfo, descriptorName,
3592  "inputGateBias", "forgetGateBias");
3593  ValidateTensorDataTypesMatch(inputGateBiasInfo, cellBiasInfo, descriptorName,
3594  "inputGateBias", "cellBias");
3595  ValidateTensorDataTypesMatch(inputGateBiasInfo, outputGateBiasInfo, descriptorName,
3596  "inputGateBias", "outputGateBias");
3597 
3598  // Validate bias tensor quantization info
3599  ValidateBiasTensorQuantization(inputGateBiasInfo, inputToInputWeightsInfo, descriptorName);
3600  ValidateBiasTensorQuantization(forgetGateBiasInfo, inputToInputWeightsInfo, descriptorName);
3601  ValidateBiasTensorQuantization(cellBiasInfo, inputToInputWeightsInfo, descriptorName);
3602  ValidateBiasTensorQuantization(outputGateBiasInfo, inputToInputWeightsInfo, descriptorName);
3603 }
3604 
3605 void AbsQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3606 {
3607  const std::string descriptorName{"AbsQueueDescriptor"};
3608 
3609  ValidateNumInputs(workloadInfo, descriptorName, 1);
3610  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3611 
3612  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3613  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3614 
3615  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3616 
3617  std::vector<DataType> supportedTypes =
3618  {
3626  };
3627 
3628  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3629  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3630 }
3631 
3632 void SliceQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3633 {
3634  const std::string descriptorName{"SliceQueueDescriptor"};
3635 
3636  ValidateNumInputs(workloadInfo, descriptorName, 1);
3637  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3638 
3639  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3640  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3641 
3642  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3643 
3644  const unsigned int rank = inputTensorInfo.GetNumDimensions();
3645  if (rank > 4)
3646  {
3647  throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
3648  }
3649 
3650  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, rank, "output");
3651 
3652  // Check if m_Begin and m_Size have the expected length
3653  if (m_Parameters.m_Begin.size() != rank)
3654  {
3655  throw InvalidArgumentException(descriptorName +
3656  ": Length of begin offset descriptor must equal rank " + std::to_string(rank));
3657  }
3658  if (m_Parameters.m_Size.size() != rank)
3659  {
3660  throw InvalidArgumentException(descriptorName +
3661  ": Length of size descriptor must equal rank " + std::to_string(rank));
3662  }
3663 
3664  // Check if the shape of the output tensor matches m_Size
3665  const TensorShape& outputShape = outputTensorInfo.GetShape();
3666  for (unsigned int i = 0u; i < rank; ++i)
3667  {
3668  if (m_Parameters.m_Size[i] != outputShape[i])
3669  {
3670  throw InvalidArgumentException(descriptorName + ": Size descriptor does not match output tensor.");
3671  }
3672  }
3673 
3674  // Check if the sum of begin offset and size in a given dimension
3675  // does not exceed the size of corresponding input
3676  const TensorShape& inputShape = inputTensorInfo.GetShape();
3677  for(unsigned int i = 0u; i < rank; ++i)
3678  {
3679  if (m_Parameters.m_Begin[i] + m_Parameters.m_Size[i] > inputShape[i])
3680  {
3681  throw InvalidArgumentException(descriptorName + ": Sum of begin offset and size for dimension " +
3682  std::to_string(i) + " exceeds input size.");
3683  }
3684  }
3685 }
3686 
3688 {
3689  const std::string descriptorName{"DepthToSpaceQueueDescriptor"};
3690 
3691  ValidateNumInputs(workloadInfo, descriptorName, 1);
3692  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3693 
3694  const TensorInfo& inputInfo = workloadInfo.m_InputTensorInfos[0];
3695  const TensorInfo& outputInfo = workloadInfo.m_OutputTensorInfos[0];
3696 
3697  ValidateTensorNumDimensions(inputInfo, descriptorName, 4, "input");
3698  ValidateTensorNumDimensions(outputInfo, descriptorName, 4, "output");
3699 
3700  std::vector<DataType> supportedTypes =
3701  {
3708  };
3709 
3710  ValidateDataTypes(inputInfo, supportedTypes, descriptorName);
3711  ValidateDataTypes(outputInfo, supportedTypes, descriptorName);
3712 
3713  ValidateTensorNumElementsMatch(inputInfo, outputInfo, descriptorName, "input", "output");
3714 
3715  if (m_Parameters.m_BlockSize == 0)
3716  {
3717  throw InvalidArgumentException(descriptorName + ": Block size cannot be 0.");
3718  }
3719 
3720  DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
3721  const unsigned int wIndex = dimensionIndices.GetWidthIndex();
3722  const unsigned int hIndex = dimensionIndices.GetHeightIndex();
3723  const unsigned int cIndex = dimensionIndices.GetChannelsIndex();
3724 
3725  const TensorShape& outputShape = outputInfo.GetShape();
3726  if (outputShape[hIndex] % m_Parameters.m_BlockSize != 0 || outputShape[wIndex] % m_Parameters.m_BlockSize != 0)
3727  {
3728  throw InvalidArgumentException(descriptorName + ": Output width and height shape"
3729  "must be divisible by block size.");
3730  }
3731 
3732  const TensorShape& inputShape = inputInfo.GetShape();
3733  if (inputShape[cIndex] % (m_Parameters.m_BlockSize * m_Parameters.m_BlockSize) != 0)
3734  {
3735  throw InvalidArgumentException(descriptorName + ": The depth of the input tensor"
3736  "must be divisible by the square of block size." );
3737  }
3738 }
3739 
3740 void ComparisonQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3741 {
3742  const std::string descriptorName{"ComparisonQueueDescriptor"};
3743 
3744  ValidateNumInputs(workloadInfo, descriptorName, 2);
3745  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3746 
3747  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
3748  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
3749  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3750 
3751  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
3752  inputTensorInfo1,
3753  outputTensorInfo,
3754  descriptorName,
3755  "input_0",
3756  "input_1");
3757 
3758  if (outputTensorInfo.GetDataType() != DataType::Boolean)
3759  {
3760  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
3761  }
3762 }
3763 
3765 {
3766  const std::string descriptorName{"ElementwiseBinaryQueueDescriptor"};
3767 
3768  ValidateNumInputs(workloadInfo, descriptorName, 2);
3769  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3770 
3771  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
3772  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
3773  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3774 
3775  std::vector<DataType> supportedTypes =
3776  {
3784  };
3785 
3786  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
3787  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
3788 
3789  ValidateTensorDataTypesMatch(inputTensorInfo0, outputTensorInfo, descriptorName, "input", "output");
3790  ValidateTensorDataTypesMatch(inputTensorInfo1, outputTensorInfo, descriptorName, "input", "output");
3791 }
3792 
3794 {
3795  const std::string descriptorName{"ElementwiseUnaryQueueDescriptor"};
3796 
3797  ValidateNumInputs(workloadInfo, descriptorName, 1);
3798  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3799 
3800  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3801  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3802 
3803  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3804 
3805  std::vector<DataType> supportedTypes =
3806  {
3814  };
3815 
3816  std::vector<DataType> logicalSupportedTypes =
3817  {
3819  };
3820 
3822  {
3823  ValidateDataTypes(inputTensorInfo, logicalSupportedTypes, descriptorName);
3824  }
3825  else
3826  {
3827  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3828  }
3829 
3830 
3831  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3832 }
3833 
3834 void RankQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3835 {
3836  const std::string descriptorName{"RankQueueDescriptor"};
3837 
3838  ValidateNumInputs(workloadInfo, descriptorName, 1);
3839  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3840 
3841  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3842  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3843 
3844  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 1, "output");
3845  ValidateTensorNumElements(outputTensorInfo, descriptorName, 1, "output");
3846 
3847  std::vector<DataType> supportedTypes =
3848  {
3857  };
3858 
3859  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3860  ValidateDataTypes(outputTensorInfo, { DataType::Signed32 }, descriptorName);
3861 }
3862 
3864 {
3865  const std::string descriptorName{"LogicalBinaryQueueDescriptor"};
3866 
3867  ValidateNumInputs(workloadInfo, descriptorName, 2);
3868  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3869 
3870  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
3871  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
3872  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3873 
3874  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
3875  inputTensorInfo1,
3876  outputTensorInfo,
3877  descriptorName,
3878  "input_0",
3879  "input_1");
3880 
3881  if (inputTensorInfo0.GetDataType() != DataType::Boolean)
3882  {
3883  throw InvalidArgumentException(descriptorName + ": Input tensor 0 type must be Boolean.");
3884  }
3885 
3886  if (inputTensorInfo1.GetDataType() != DataType::Boolean)
3887  {
3888  throw InvalidArgumentException(descriptorName + ": Input tensor 1 type must be Boolean.");
3889  }
3890 
3891  if (outputTensorInfo.GetDataType() != DataType::Boolean)
3892  {
3893  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
3894  }
3895 }
3896 
3897 void ReduceQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3898 {
3899  const std::string descriptorName{"ReduceQueueDescriptor"};
3900 
3901  ValidateNumInputs(workloadInfo, descriptorName, 1);
3902  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3903 
3904  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3905  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3906 
3907  std::vector<DataType> supportedTypes =
3908  {
3916  };
3917 
3918  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3919  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3920 }
3921 
3923 {
3924  // Modified from LstmQueueDescriptor::Validate to support UnidirectionalSequenceLstm
3925 
3926  const std::string descriptorName{"UnidirectionalSequenceLstmQueueDescriptor"};
3927 
3928  // check dimensions of all inputs and outputs
3929  if (workloadInfo.m_InputTensorInfos.size() != 3)
3930  {
3931  throw InvalidArgumentException(descriptorName + ": Invalid number of inputs.");
3932  }
3933  if (workloadInfo.m_OutputTensorInfos.size() != 3)
3934  {
3935  throw InvalidArgumentException(descriptorName + ": Invalid number of outputs.");
3936  }
3937 
3938  std::vector<DataType> supportedTypes =
3939  {
3942  };
3943 
3944  // check for supported type of one input and match them with all the other input and output
3945  ValidateDataTypes(workloadInfo.m_InputTensorInfos[0], supportedTypes, descriptorName);
3946 
3947  // Making sure clipping parameters have valid values.
3948  // == 0 means no clipping
3949  // > 0 means clipping
3950  if (m_Parameters.m_ClippingThresCell < 0.0f)
3951  {
3952  throw InvalidArgumentException(descriptorName + ": negative cell clipping threshold is invalid");
3953  }
3954  if (m_Parameters.m_ClippingThresProj < 0.0f)
3955  {
3956  throw InvalidArgumentException(descriptorName + ": negative projection clipping threshold is invalid");
3957  }
3958 
3959  unsigned int batchIndx = 0;
3960  unsigned int inputIndx = 1;
3961  uint32_t timeStep = 1;
3962  unsigned int timeIndx = 1;
3963  inputIndx = 2;
3965  {
3966  batchIndx = 1;
3967  timeIndx = 0;
3968 
3969  }
3970  timeStep = workloadInfo.m_InputTensorInfos[0].GetShape()[timeIndx];
3971 
3972  // Inferring batch size, number of outputs and number of cells from the inputs.
3973  const uint32_t n_input = workloadInfo.m_InputTensorInfos[0].GetShape()[inputIndx];
3974  const uint32_t n_batch = workloadInfo.m_InputTensorInfos[0].GetShape()[batchIndx];
3975  ValidatePointer(m_InputToOutputWeights, "Null pointer check", "InputToOutputWeights");
3976  const uint32_t n_cell = m_InputToOutputWeights->GetShape()[0];
3977  ValidatePointer(m_RecurrentToOutputWeights, "Null pointer check", "RecurrentToOutputWeights");
3978  const uint32_t n_output = m_RecurrentToOutputWeights->GetShape()[1];
3979 
3980  // input tensor
3981  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[0], 3, (timeStep * n_batch * n_input),
3982  descriptorName + " input_0");
3983  // outputStateInTensor
3984  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[1], 2, (n_batch * n_output),
3985  descriptorName + " input_1");
3986  // outputStateInTensor
3987  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[2], 2, (n_batch * n_cell),
3988  descriptorName + " input_2");
3989 
3990  // outputTensor
3991  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[2], 3, (timeStep * n_batch * n_output),
3992  descriptorName + " output_0");
3993 
3994  // check that dimensions of inputs/outputs and QueueDescriptor data match with each other
3995  if ( m_InputToInputWeights )
3996  {
3998  (n_cell * n_input), "InputLayerNormWeights");
3999  }
4000 
4001  ValidatePointer(m_InputToForgetWeights, "Null pointer check", "InputToForgetWeights");
4003  (n_cell * n_input), "InputToForgetWeights");
4004 
4005  ValidatePointer(m_InputToCellWeights, "Null pointer check", "InputToCellWeights");
4007  (n_cell * n_input), "InputToCellWeights");
4008 
4010  {
4012  (n_cell * n_output), "RecurrentToInputWeights");
4013  }
4014 
4015  ValidatePointer(m_RecurrentToForgetWeights, "Null pointer check", "RecurrentToForgetWeights");
4017  (n_cell * n_output), "RecurrentToForgetWeights");
4018 
4019  ValidatePointer(m_RecurrentToCellWeights, "Null pointer check", "RecurrentToCellWeights");
4021  (n_cell * n_output), "RecurrentToCellWeights");
4022 
4023  // Make sure the input-gate's parameters are either both present (regular
4024  // LSTM) or not at all (CIFG-LSTM). And CifgEnable is set accordingly.
4025  bool cifg_weights_all_or_none = ((m_InputToInputWeights && m_RecurrentToInputWeights &&
4029  if (!cifg_weights_all_or_none)
4030  {
4031  throw InvalidArgumentException(descriptorName + ": Input-Gate's parameters InputToInputWeights and "
4032  "RecurrentToInputWeights must either both be present (regular LSTM) "
4033  "or both not present (CIFG-LSTM). In addition CifgEnable must be set "
4034  "accordingly.");
4035  }
4036 
4037  if ( m_CellToInputWeights )
4038  {
4040  n_cell, "CellToInputWeights");
4041  }
4042  if ( m_CellToForgetWeights )
4043  {
4045  n_cell, "CellToForgetWeights");
4046  }
4047  if ( m_CellToOutputWeights )
4048  {
4050  n_cell, "CellToOutputWeights");
4051  }
4052 
4053  // Making sure the peephole weights are there all or none. And PeepholeEnable is set accordingly.
4054  bool peephole_weights_all_or_none =
4059  if (!peephole_weights_all_or_none)
4060  {
4061  throw InvalidArgumentException(descriptorName + ": Invalid combination of peephole parameters.");
4062  }
4063 
4064  // Make sure the input gate bias is present only when not a CIFG-LSTM.
4066  {
4067  if (m_InputGateBias)
4068  {
4069  throw InvalidArgumentException(descriptorName + ": InputGateBias is present and CIFG-LSTM is enabled.");
4070  }
4071  }
4072  else
4073  {
4074  if (!m_InputGateBias)
4075  {
4076  throw InvalidArgumentException(descriptorName + ": If CIFG-LSTM is disabled InputGateBias "
4077  "must be present.");
4078  }
4080  n_cell, "InputGateBias");
4081  }
4082 
4083  ValidatePointer(m_ForgetGateBias, "Null pointer check", "ForgetGateBias");
4084  ValidateTensorNumDimNumElem(m_ForgetGateBias->GetTensorInfo(), 1, n_cell, "ForgetGateBias");
4085 
4086  ValidatePointer(m_CellBias, "Null pointer check", "CellBias");
4087  ValidateTensorNumDimNumElem(m_CellBias->GetTensorInfo(), 1, n_cell, "CellBias");
4088 
4089  ValidatePointer(m_OutputGateBias, "Null pointer check", "OutputGateBias");
4090  ValidateTensorNumDimNumElem(m_OutputGateBias->GetTensorInfo(), 1, n_cell, "OutputGateBias");
4091 
4092  if (m_ProjectionWeights)
4093  {
4095  (n_cell * n_output), "ProjectionWeights");
4096  }
4097  if (m_ProjectionBias)
4098  {
4099  ValidateTensorNumDimNumElem(m_ProjectionBias->GetTensorInfo(), 1, n_output, "ProjectionBias");
4100  }
4101 
4102  // Making sure the projection tensors are consistent:
4103  // 1) If projection weight is not present, then projection bias should not be
4104  // present.
4105  // 2) If projection weight is present, then projection bias is optional.
4106  bool projecton_tensors_consistent = ((!m_ProjectionWeights && !m_ProjectionBias &&
4112  if (!projecton_tensors_consistent)
4113  {
4114  throw InvalidArgumentException(descriptorName + ": Projection tensors are inconsistent.");
4115  }
4116 
4117  // The four layer normalization weights either all have values or none of them have values. Additionally, if
4118  // CIFG is used, input layer normalization weights tensor is omitted and the other layer normalization weights
4119  // either all have values or none of them have values. Layer normalization is used when the values of all the
4120  // layer normalization weights are present
4122  {
4123  ValidateTensorNumDimNumElem(m_InputLayerNormWeights->GetTensorInfo(), 1, n_cell, "InputLayerNormWeights");
4124  }
4126  {
4127  ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
4128  }
4130  {
4131  ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
4132  }
4134  {
4135  ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
4136  }
4137 
4139  {
4141  {
4143  {
4144  throw InvalidArgumentException(descriptorName + ": Layer normalisation is enabled and CIFG-LSTM is "
4145  "disabled but InputLayerNormWeights are not present");
4146  }
4148  1, n_cell, "InputLayerNormWeights");
4149  }
4150  else if (m_InputLayerNormWeights)
4151  {
4152  throw InvalidArgumentException(descriptorName + ":InputLayerNormWeights are present while CIFG is "
4153  "enabled");
4154  }
4155 
4156  ValidatePointer(m_ForgetLayerNormWeights, "Null pointer check layer normalisation enabled",
4157  "ForgetLayerNormWeights");
4158  ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
4159 
4160  ValidatePointer(m_OutputLayerNormWeights, "Null pointer check layer normalisation enabled",
4161  "OutputLayerNormWeights");
4162  ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
4163 
4164  ValidatePointer(m_CellLayerNormWeights, "Null pointer check layer normalisation enabled",
4165  "CellLayerNormWeights");
4166  ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
4167  }
4169  {
4170  throw InvalidArgumentException(descriptorName + ": Layer normalisation is disabled but one or more layer "
4171  "normalisation weights are present.");
4172  }
4173 }
4174 
4176 {
4177  const std::string descriptorName{"BatchMatMulDescriptor"};
4178 
4179  ValidateNumInputs(workloadInfo, descriptorName, 2);
4180  ValidateNumOutputs(workloadInfo, descriptorName, 1);
4181 
4182  // Inputs must be: both 2D+
4183  // For inputs X and Y whose dimensions to be multiplied are (M,N) and (I,J) respectively,
4184  // axes N and I must be the same size
4185 
4186  const auto& inputXInfoBeforeParams = workloadInfo.m_InputTensorInfos[0];
4187  const auto& inputYInfoBeforeParams = workloadInfo.m_InputTensorInfos[1];
4188  const auto& outputInfo = workloadInfo.m_OutputTensorInfos[0];
4189  // Output info has already been inferred
4190 
4191  std::vector<DataType> supportedTypes =
4192  {
4199  };
4200 
4201  ValidateDataTypes(inputXInfoBeforeParams, supportedTypes, descriptorName);
4202  ValidateDataTypes(inputYInfoBeforeParams, supportedTypes, descriptorName);
4203  ValidateDataTypes(outputInfo, supportedTypes, descriptorName);
4204 
4205  if ((inputXInfoBeforeParams.GetNumDimensions() < 2) ||
4206  (inputYInfoBeforeParams.GetNumDimensions() < 2))
4207  {
4208  throw InvalidArgumentException(descriptorName + ": Input tensors are not 2D or greater.");
4209  }
4210 
4211  TensorInfo inputXInfoAfterParams;
4212  TensorInfo inputYInfoAfterParams;
4213 
4216  {
4217  throw InvalidArgumentException(descriptorName +
4218  ": Invalid descriptor parameters - Transpose and Adjoint "
4219  "cannot both be true for a given input tensor.");
4220  }
4222  {
4223  inputXInfoAfterParams = armnnUtils::Permuted(inputXInfoBeforeParams,
4226  inputXInfoBeforeParams.GetShape()));
4227  }
4228  else if(m_Parameters.m_AdjointX)
4229  {
4231  inputXInfoBeforeParams.GetShape());
4232  if(inputXInfoBeforeParams.GetShape()[axesToMul.first] !=
4233  inputXInfoBeforeParams.GetShape()[axesToMul.second])
4234  {
4235  throw InvalidArgumentException(descriptorName +
4236  ": Adjoint is set to true for input tensor X, but the axes to be adjointed are not square." );
4237  }
4238  // Shape remains the same as it's square
4239  inputXInfoAfterParams = inputXInfoBeforeParams;
4240  }
4241  else
4242  {
4243  inputXInfoAfterParams = inputXInfoBeforeParams;
4244  }
4245 
4247  {
4248  inputYInfoAfterParams = armnnUtils::Permuted(inputYInfoBeforeParams,
4251  inputYInfoBeforeParams.GetShape()));
4252  }
4253  else if(m_Parameters.m_AdjointY)
4254  {
4256  inputYInfoBeforeParams.GetShape());
4257  if(inputYInfoBeforeParams.GetShape()[axesToMul.first] !=
4258  inputYInfoBeforeParams.GetShape()[axesToMul.second])
4259  {
4260  throw InvalidArgumentException(descriptorName +
4261  ": Adjoint is set to true for input tensor Y, but the axes to be adjointed are not square." );
4262  }
4263  // Shape remains the same as it's square
4264  inputYInfoAfterParams = inputYInfoBeforeParams;
4265  }
4266  else
4267  {
4268  inputYInfoAfterParams = inputYInfoBeforeParams;
4269  }
4270 
4271  switch(m_Parameters.m_DataLayoutX)
4272  {
4273  case DataLayout::NCDHW:
4274  case DataLayout::NDHWC:
4275  if(inputXInfoAfterParams.GetNumDimensions() < 3)
4276  {
4277  throw InvalidArgumentException(descriptorName +
4278  ": Input tensor X does not have the correct "
4279  "number of dimensions for the Data Layout that it has been assigned.");
4280  }
4281  break;
4282  case DataLayout::NCHW:
4283  case DataLayout::NHWC:
4284  default:
4285  break;
4286  }
4287 
4288  switch(m_Parameters.m_DataLayoutY)
4289  {
4290  case DataLayout::NCDHW:
4291  case DataLayout::NDHWC:
4292  if(inputYInfoAfterParams.GetNumDimensions() < 3)
4293  {
4294  throw InvalidArgumentException(descriptorName +
4295  ": Input tensor Y does not have the correct "
4296  "number of dimensions for the Data Layout that it has been assigned.");
4297  }
4298  break;
4299  case DataLayout::NCHW:
4300  case DataLayout::NHWC:
4301  default:
4302  break;
4303  }
4304 
4306  inputXInfoAfterParams.GetShape());
4308  inputXInfoBeforeParams.GetShape());
4309 
4310  if(inputXInfoAfterParams.GetShape()[axesXToMul.second]
4311  != inputYInfoAfterParams.GetShape()[axesYToMul.first])
4312  {
4313  throw InvalidArgumentException(descriptorName +
4314  ": The final axis of input tensor X must be the same size as "
4315  "the second last axis of input tensor Y.");
4316  }
4317 
4318  { // Separate scope so we don't pollute the rest of the scope with our temp variables
4319  // e.g. NHWC isnt compatible with NCHW as of now
4322 
4323  if(xLayout == DataLayout::NCHW || xLayout == DataLayout::NCDHW)
4324  {
4325  if(yLayout == DataLayout::NHWC || yLayout == DataLayout::NDHWC)
4326  {
4327  throw InvalidArgumentException(descriptorName +
4328  ": Invalid input tensor data layout combination.");
4329  }
4330  }
4331  if(yLayout == DataLayout::NCHW || yLayout == DataLayout::NCDHW)
4332  {
4333  if(xLayout == DataLayout::NHWC || xLayout == DataLayout::NDHWC)
4334  {
4335  throw InvalidArgumentException(descriptorName +
4336  ": Invalid input tensor data layout combination.");
4337  }
4338  }
4339  }
4340 
4341  // Simulate aligning the ends of the matrix dims and prepending 1's to the beginning of the shorter one
4342  unsigned int outputTensorDimSize = std::max(inputXInfoAfterParams.GetNumDimensions(),
4343  inputYInfoAfterParams.GetNumDimensions());
4344  if(outputTensorDimSize-2 > 0)
4345  {
4346  TensorInfo tiXNotMul = TensorInfo(TensorShape(outputTensorDimSize-2),
4348  TensorInfo tiYNotMul = TensorInfo(TensorShape(outputTensorDimSize-2),
4350  TensorInfo tiOutNotMul = TensorInfo(TensorShape(outputTensorDimSize-2),
4352 
4353  auto doAxisExtension = [&](std::vector<unsigned int> axisIndices, TensorInfo& ti)
4354  {
4355  auto sizeDiff = (outputTensorDimSize-2) - axisIndices.size();
4356 
4357  for(unsigned int i = 0; i < sizeDiff; i++)
4358  {
4359  axisIndices.insert(axisIndices.begin(), 1);
4360  }
4361 
4362  for(unsigned int i = 0; i < ti.GetNumDimensions(); i++)
4363  {
4364  ti.GetShape()[i] = inputXInfoAfterParams.GetShape()[i];
4365  }
4366  };
4367 
4369  inputXInfoAfterParams.GetShape());
4371  inputYInfoAfterParams.GetShape());
4372 
4373  doAxisExtension(axesXNotMul, tiXNotMul);
4374  doAxisExtension(axesYNotMul, tiYNotMul);
4375 
4376  for(unsigned int i = 0; i < tiOutNotMul.GetNumDimensions(); i++)
4377  {
4378  tiOutNotMul.GetShape()[i] = std::max(tiXNotMul.GetShape()[i],
4379  tiYNotMul.GetShape()[i]);
4380  }
4381 
4382  ValidateBroadcastTensorShapesMatch(tiXNotMul,
4383  tiYNotMul,
4384  tiOutNotMul,
4385  descriptorName,
4386  "input_X",
4387  "input_Y");
4388  }
4389 }
4390 
4391 void TileQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
4392 {
4393  const std::string& descriptorName{"TileQueueDescriptor"};
4394 
4395  ValidateNumInputs(workloadInfo, descriptorName, 1);
4396  ValidateNumOutputs(workloadInfo, descriptorName, 1);
4397 
4398  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
4399  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
4400 
4401  std::vector<DataType> supportedTypes =
4402  {
4410  };
4411 
4412  // Multiples length must be the same as the number of dimensions in input.
4413  if (m_Parameters.m_Multiples.size() != inputTensorInfo.GetNumDimensions())
4414  {
4415  throw InvalidArgumentException(descriptorName +
4416  ": Multiples length is not same as the number of dimensions in Input.");
4417  }
4418 
4419  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
4420  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
4421 }
4422 
4424 {
4425  const std::string& descriptorName{"BroadcastToQueueDescriptor"};
4426 
4427  ValidateNumInputs(workloadInfo, descriptorName, 1);
4428  ValidateNumOutputs(workloadInfo, descriptorName, 1);
4429 
4430  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
4431  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
4432 
4433  std::vector<DataType> supportedTypes =
4434  {
4443  };
4444 
4445  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
4446  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
4447 }
4448 
4449 void ScatterNdQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
4450 {
4451  const std::string& descriptorName{"ScatterQueueDescriptor"};
4452 
4453  ValidateNumInputs(workloadInfo, descriptorName, 3);
4454  ValidateNumOutputs(workloadInfo, descriptorName, 1);
4455 
4456  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
4457  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
4458  const TensorInfo& inputTensorInfo2 = workloadInfo.m_InputTensorInfos[2];
4459  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
4460 
4461  std::vector<DataType> supportedTypes =
4462  {
4470  };
4471 
4472  std::vector<DataType> indicesSupportedTypes =
4473  {
4475  };
4476 
4478  {
4479  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
4480  }
4481  else
4482  {
4483  ValidateDataTypes(inputTensorInfo0, indicesSupportedTypes, descriptorName);
4484  }
4485 
4486  ValidateDataTypes(inputTensorInfo1, indicesSupportedTypes, descriptorName);
4487  ValidateDataTypes(inputTensorInfo2, supportedTypes, descriptorName);
4488  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
4489 }
4490 
4491 } // 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:2945
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:2643
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:4423
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:2586
WorkloadData.hpp
armnn::PreCompiledQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3012
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:2685
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:1098
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:2897
armnn::QLstmQueueDescriptor::m_InputLayerNormWeights
const ConstTensorHandle * m_InputLayerNormWeights
Definition: WorkloadData.hpp:606
armnn::LogSoftmaxQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1767
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:1550
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:3148
armnn::TensorInfo::GetNumDimensions
unsigned int GetNumDimensions() const
Definition: Tensor.hpp:197
armnn::QuantizedLstmQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3434
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:3106
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:3922
armnn::DataType::QSymmS8
@ QSymmS8
armnn::DepthwiseConvolution2dQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1390
armnn::LstmQueueDescriptor::m_InputToCellWeights
const ConstTensorHandle * m_InputToCellWeights
Definition: WorkloadData.hpp:429
armnn::ElementwiseUnaryQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3793
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:2794
armnn::ReverseV2QueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1625
armnn::QLstmQueueDescriptor::m_InputToInputWeights
const ConstTensorHandle * m_InputToInputWeights
Definition: WorkloadData.hpp:589
armnn::BatchMatMulQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:4175
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:1989
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:3605
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:1706
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:2829
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:1685
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:1205
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:1494
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:2397
Logging.hpp
armnn::DebugQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2677
armnn::ElementwiseBinaryQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3764
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:3834
armnn::TileQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:4391
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:3863
armnn::SubtractionQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2363
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:3135
armnn::BatchMatMulDescriptor::m_DataLayoutY
DataLayout m_DataLayoutY
Definition: Descriptors.hpp:1622
armnn::MeanQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2431
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:1577
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:2329
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:1790
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:3017
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:1523
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:2709
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:2733
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:1251
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:3687
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:2526
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:3054
armnn::SpaceToDepthQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1936
armnn::PermutationVector::GetSize
SizeType GetSize() const
Definition: Types.hpp:357
armnn::MergeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2927
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:4449
armnn::QLstmQueueDescriptor::m_InputToOutputWeights
const ConstTensorHandle * m_InputToOutputWeights
Definition: WorkloadData.hpp:592
armnn::GatherNdQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2759
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:1103
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:2971
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:3740
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:3632
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:1850
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:2283
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:3897
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:2475
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:2013
armnn::LstmQueueDescriptor::m_OutputGateBias
const ConstTensorHandle * m_OutputGateBias
Definition: WorkloadData.hpp:441
armnn::L2NormalizationQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1735
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:2306
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:2497
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:1821
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:1168
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:1328
armnn::AdditionQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1131
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