ArmNN
 23.02
WorkloadData.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2022 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  return DataType::Signed32;
39  case DataType::QAsymmU8:
40  return DataType::Signed32;
41  case DataType::QSymmS8:
42  return DataType::Signed32;
43  case DataType::QSymmS16:
44  return DataType::Signed32;
45  default:
46  ARMNN_ASSERT_MSG(false, "Invalid input data type");
47  return DataType::Float32;
48  }
49 }
50 
51 namespace
52 {
53 
54 //---------------------------------------------------------------
55 //android ndk does not support std::to_string function.
56 template <typename T>
57 std::string to_string(T value)
58 {
59  std::ostringstream os;
60  os << value;
61  return os.str();
62 }
63 
64 //---------------------------------------------------------------
65 void ValidatePointer(const void* ptr, std::string const& descName, std::string const& paramName)
66 {
67  if (!ptr)
68  {
69  throw InvalidArgumentException(descName + ": Invalid null pointer. The " +
70  paramName + " parameter must be set.");
71  }
72 }
73 
74 //---------------------------------------------------------------
75 void ValidateTensorShapesMatch(const TensorInfo& first,
76  const TensorInfo& second,
77  std::string const& descName,
78  std::string const& firstName,
79  std::string const& secondName)
80 {
81  if (first.GetShape() != second.GetShape())
82  {
83  throw InvalidArgumentException(descName + ": "
84  + firstName + " & " + secondName + " must have identical shapes");
85  }
86 }
87 
88 //---------------------------------------------------------------
89 void ValidateNumInputs(const WorkloadInfo& workloadInfo, std::string const& descName, const unsigned int expectedSize)
90 {
91  if (workloadInfo.m_InputTensorInfos.size() != expectedSize)
92  {
93  throw InvalidArgumentException(descName +
94  ": Requires exactly " + to_string(expectedSize) + "input(s). " +
95  to_string(workloadInfo.m_InputTensorInfos.size()) + " have been provided.");
96  }
97 }
98 
99 //---------------------------------------------------------------
100 void ValidateNumOutputs(const WorkloadInfo& workloadInfo, std::string const& descName, const unsigned int expectedSize)
101 {
102  if (workloadInfo.m_OutputTensorInfos.size() != expectedSize)
103  {
104  throw InvalidArgumentException(descName +
105  ": Requires exactly " + to_string(expectedSize) + " output(s). " +
106  to_string(workloadInfo.m_OutputTensorInfos.size()) + " has been provided.");
107  }
108 }
109 
110 //---------------------------------------------------------------
111 
112 //---------------------------------------------------------------
113 void ValidateTensorNumElements(const TensorInfo& tensor,
114  std::string const& descName,
115  unsigned int numElements,
116  std::string const& tensorName)
117 {
118  if (tensor.GetNumElements() != numElements)
119  {
120  throw InvalidArgumentException(descName + ": Expected " + to_string(numElements) + " but got " +
121  to_string(tensor.GetNumElements()) + " elements for " +
122  tensorName + " tensor.");
123  }
124 }
125 
126 //---------------------------------------------------------------
127 void ValidateTensorDataType(const TensorInfo& tensor, DataType dataType,
128  const std::string& descName, std::string const& tensorName)
129 {
130  if (tensor.GetDataType() != dataType)
131  {
132  throw InvalidArgumentException(descName + ": Expected data type " + GetDataTypeName(dataType) + " but got " +
133  GetDataTypeName(tensor.GetDataType()) + " for " + tensorName + " tensor.");
134  }
135 }
136 
137 void ValidPerAxisQuantizedDataType(const TensorInfo& tensor, const std::string& descName, const std::string& tensorName)
138 {
139  if (tensor.GetDataType() != DataType::QSymmS8)
140  {
141  throw InvalidArgumentException(descName +
142  ": Expected data type which supports per-axis quantization scheme but got " +
143  GetDataTypeName(tensor.GetDataType()) + " for " + tensorName + " tensor.");
144  }
145 }
146 
147 //---------------------------------------------------------------
148 void ValidateTensorQuantizationSpace(const TensorInfo& first,
149  const TensorInfo& second,
150  const std::string& descName,
151  std::string const& firstName,
152  std::string const& secondName)
153 {
154  if (!first.IsQuantized() ||
155  !second.IsQuantized())
156  {
157  // Not a quantized type, ignore the validation
158  return;
159  }
160 
161  DataType firstDataType = first.GetDataType();
162  DataType secondDataType = second.GetDataType();
163 
164  if (firstDataType != secondDataType)
165  {
166  throw InvalidArgumentException(descName + ": " + firstName + " and " + secondName +
167  " must be of the same quantized type, " +
168  firstName + " is " + GetDataTypeName(firstDataType) + ", " +
169  secondName + " is " + GetDataTypeName(secondDataType));
170  }
171 
172  if (!first.IsTypeSpaceMatch(second))
173  {
174  throw InvalidArgumentException(descName + ": " + firstName + " and " + secondName +
175  " must have the same quantization space, " +
176  firstName + " has offset " + to_string(first.GetQuantizationOffset()) +
177  " and scale " + to_string(first.GetQuantizationScale()) + ", " +
178  secondName + " has offset " + to_string(second.GetQuantizationOffset()) +
179  " and scale " + to_string(second.GetQuantizationScale()));
180  }
181 }
182 
183 //---------------------------------------------------------------
184 void ValidateBiasTensorQuantization(const TensorInfo& biasTensor,
185  const TensorInfo& inputTensorInfo,
186  const TensorInfo& weightsTensorInfo,
187  const std::string& descName)
188 {
189  // Helper lambda function to validate a single bias quantization scale value
190  auto VerifyBiasQuantizationScale = [&descName](float biasScale, float expectedScale) -> void
191  {
192  constexpr float tolerance = 0.0001f;
193  if (std::abs(biasScale - expectedScale) > tolerance)
194  {
195  // Print the float values with extra precision to see very small differences
196  ARMNN_LOG(warning) << std::setprecision(6) << descName << ": Expected " << expectedScale <<
197  " for bias quantization scale (product of input and weight scales), but got " <<
198  biasScale << ". Using scale provided.";
199  }
200  };
201 
202  if (biasTensor.GetQuantizationOffset() != 0)
203  {
204  throw InvalidArgumentException(descName + ": Expected zero quantization offset for bias tensor but got " +
205  to_string(biasTensor.GetQuantizationOffset()));
206  }
207 
208  if (biasTensor.HasMultipleQuantizationScales() || weightsTensorInfo.HasMultipleQuantizationScales())
209  {
210  // Validate per-axis quantization scales
211  const std::vector<float>& weightScales = weightsTensorInfo.GetQuantizationScales();
212  const std::vector<float>& biasScales = biasTensor.GetQuantizationScales();
213 
214  if (weightScales.size() != biasScales.size())
215  {
216  std::stringstream msg;
217  msg << descName << ": Expected matching number of per-axis quantization scales for weights and bias, "
218  << "but got different values. This is currently unsupported: weights=" << weightScales.size()
219  << ", biases=" << biasScales.size();
220  throw InvalidArgumentException(msg.str(), CHECK_LOCATION());
221  }
222 
223  for (size_t i = 0ul; i < biasScales.size(); ++i)
224  {
225  const float expectedScale = inputTensorInfo.GetQuantizationScale() * weightScales[i];
226  VerifyBiasQuantizationScale(biasScales[i], expectedScale);
227  }
228  }
229  else
230  {
231  // Validate per-tensor quantization scale
232  const float expectedScale = inputTensorInfo.GetQuantizationScale() * weightsTensorInfo.GetQuantizationScale();
233  VerifyBiasQuantizationScale(biasTensor.GetQuantizationScale(), expectedScale);
234  }
235 }
236 
237 //---------------------------------------------------------------
238 void ValidateTensors(const std::vector<ITensorHandle*>& vec,
239  unsigned int numExpected,
240  const std::string& descName,
241  const std::string& varName)
242 {
243  if (vec.empty() && numExpected > 0)
244  {
245  throw InvalidArgumentException(descName + ": Invalid empty " + varName + " array.");
246  }
247 
248  for (unsigned int i = 0; i < numExpected; ++i)
249  {
250  if (!vec[i])
251  {
252  throw InvalidArgumentException(descName + ": Invalid NULL for " + varName + to_string(i));
253  }
254  }
255 }
256 
257 //---------------------------------------------------------------
258 void ValidateBroadcastTensorShapesMatch(const TensorInfo& first,
259  const TensorInfo& second,
260  const TensorInfo& output,
261  std::string const& descName,
262  std::string const& firstName,
263  std::string const& secondName)
264 {
265  // Tensors must have the same number of dimensions in order to be explicit about which dimensions will get
266  // broadcasted.
267  if (first.GetNumDimensions() != second.GetNumDimensions())
268  {
269  throw InvalidArgumentException(descName + ": Tensors "
270  + firstName + " & " + secondName
271  + " must have the same number of dimensions in order to be broadcasted");
272  }
273  uint32_t numDims = first.GetNumDimensions();
274  std::vector<uint32_t> outputDims(numDims, 0u);
275  for (uint32_t i = 0; i < numDims; i++)
276  {
277  const bool dimsNotEqual = first.GetShape()[i] != second.GetShape()[i];
278  const bool dimsNotOne = (first.GetShape()[i] != 1) && (second.GetShape()[i] != 1);
279  if (dimsNotEqual && dimsNotOne)
280  {
281  throw InvalidArgumentException("Broadcasting is not possible for incompatible shapes");
282  }
283  outputDims[i] = std::max(first.GetShape()[i], second.GetShape()[i]);
284  }
285  TensorShape broadcastShape = TensorShape(armnn::numeric_cast<unsigned int>(outputDims.size()), outputDims.data());
286  if (broadcastShape != output.GetShape())
287  {
288  throw InvalidArgumentException(descName + ": The tensor shape resulting from adding "
289  + firstName + " & " + secondName
290  + " does not match the output shape");
291  }
292 }
293 
294 //---------------------------------------------------------------
295 void ValidateDataTypes(const TensorInfo& info,
296  const std::vector<armnn::DataType>& supportedTypes,
297  std::string const& descName)
298 {
299  auto iterator = std::find(supportedTypes.begin(), supportedTypes.end(), info.GetDataType());
300  if (iterator == supportedTypes.end())
301  {
302  throw InvalidArgumentException(descName + ": " + " Tensor type is not supported.");
303  }
304 }
305 
306 //---------------------------------------------------------------
307 void ValidateTensorDataTypesMatch(const TensorInfo& first,
308  const TensorInfo& second,
309  std::string const& descName,
310  std::string const& firstName,
311  std::string const& secondName)
312 {
313  if (first.GetDataType() != second.GetDataType())
314  {
315  throw InvalidArgumentException(descName + ": " + firstName + " & " + secondName +
316  " must have identical data types.");
317  }
318 }
319 
320 //---------------------------------------------------------------
321 void ValidateTensorNumElementsMatch(const TensorInfo& first,
322  const TensorInfo& second,
323  std::string const& descName,
324  std::string const& firstName,
325  std::string const& secondName)
326 {
327  if (first.GetNumElements() != second.GetNumElements())
328  {
329  throw InvalidArgumentException(descName + ": " + firstName + " & " + secondName +
330  " must have the same number of elements.");
331  }
332 }
333 
334 void ValidateWeightDataType(const TensorInfo& inputInfo,
335  const TensorInfo& weightInfo,
336  const std::string& descName)
337 {
338  const DataType inputType = inputInfo.GetDataType();
339  if (IsQuantized8BitType(inputType))
340  {
341  const std::vector<DataType> validTypes =
342  {
343  DataType::QAsymmS8,
344  DataType::QAsymmU8,
345  DataType::QSymmS8
346  };
347 
348  ValidateDataTypes(weightInfo, validTypes, descName);
349  }
350  else
351  {
352  ValidateTensorDataTypesMatch(inputInfo, weightInfo, descName, "input", "weight");
353  }
354 }
355 
356 void ValidatePerAxisQuantizationDimension(const TensorInfo& tensorInfo,
357  const std::string& descName,
358  const std::string& tensorName)
359 {
360  const Optional<unsigned int>& quantizationDim = tensorInfo.GetQuantizationDim();
361  if (!quantizationDim.has_value())
362  {
363  throw InvalidArgumentException(fmt::format("{0}: Quantization dimension for per-axis quantization "
364  "not set on tensor {1}.", descName, tensorName));
365  }
366 }
367 
368 void ValidatePerAxisQuantizationOffset(const TensorInfo& tensorInfo,
369  const std::string& descName,
370  const std::string& tensorName)
371 {
372  int32_t quantizationOffset = tensorInfo.GetQuantizationOffset();
373  if (quantizationOffset != 0)
374  {
375  throw InvalidArgumentException(fmt::format(
376  "{0}: Quantization offset for per-axis quantization expected to be 0 on tensor {1}, but got: {2}",
377  descName, tensorName, quantizationOffset));
378  }
379 }
380 
381 void ValidatePerAxisQuantization(const TensorInfo& inputInfo,
382  const TensorInfo& outputInfo,
383  const TensorInfo& weightInfo,
384  const Optional<TensorInfo>& optionalBiasInfo,
385  const std::string& descName)
386 {
387  if (weightInfo.HasPerAxisQuantization())
388  {
389  const DataType inputDataType = inputInfo.GetDataType();
390  const DataType outputDataType = outputInfo.GetDataType();
391 
392  const bool canHavePerAxisQuantization = (IsQuantized8BitType(inputDataType)) && inputDataType == outputDataType;
393 
394  if (!canHavePerAxisQuantization)
395  {
396  throw InvalidArgumentException(fmt::format(
397  "{0}: Per-axis quantization parameters set on tensor {1}, but data type does not support "
398  "per-axis quantization.", descName, "weight"));
399  }
400 
401 
402  ValidPerAxisQuantizedDataType(weightInfo, descName, "weight");
403  ValidatePerAxisQuantizationDimension(weightInfo, descName, "weight");
404  ValidatePerAxisQuantizationOffset(weightInfo, descName, "weight");
405 
406  if (optionalBiasInfo.has_value())
407  {
408  const TensorInfo& biasInfo = optionalBiasInfo.value();
409  if (!biasInfo.HasPerAxisQuantization())
410  {
411  throw InvalidArgumentException(fmt::format(
412  "{}: Per-axis quantization parameters not set on bias tensor, "
413  "despite being set on weight tensor.", descName));
414  }
415 
416  ValidateTensorDataType(biasInfo, DataType::Signed32, descName, "bias");
417  ValidatePerAxisQuantizationDimension(biasInfo, descName, "bias");
418  ValidatePerAxisQuantizationOffset(biasInfo, descName, "bias");
419  }
420  }
421 }
422 
423 } // anonymous namespace
424 
425 //---------------------------------------------------------------
427  std::string const& descName,
428  unsigned int numDimensions,
429  std::string const& tensorName) const
430 {
431  // If we're allowing expanded dimensions then numDimensions becomes the minimum number of Dimensions we can allow.
432  // Throw an Exception if the tensors has fewer than numDimensions or if the squeezed dimensions are greater than
433  // numDimensions.
435  {
436  unsigned int squeezedDims = 0;
437 
438  for (unsigned int i = 0; i < tensor.GetNumDimensions(); ++i)
439  {
440  if (tensor.GetShape()[i] != 1)
441  {
442  ++squeezedDims;
443  }
444  }
445  if (tensor.GetNumDimensions() < numDimensions || squeezedDims > numDimensions)
446  {
447  throw InvalidArgumentException(descName + ": Expected " + to_string(numDimensions) + " or less but got " +
448  to_string(tensor.GetNumDimensions()) + " dimensions for " +
449  tensorName + " tensor.");
450  }
451  }
452  else
453  {
454  if (tensor.GetNumDimensions() != numDimensions)
455  {
456  throw InvalidArgumentException(descName + ": Expected " + to_string(numDimensions) + " but got " +
457  to_string(tensor.GetNumDimensions()) + " dimensions for " +
458  tensorName + " tensor.");
459  }
460  }
461 }
462 
463 //---------------------------------------------------------------
465  unsigned int numDimension,
466  unsigned int numElements,
467  std::string const& tensorName) const
468 {
469  const std::string functionName{"ValidateTensorNumDimNumElem"};
470  ValidateTensorNumDimensions(tensorInfo, functionName, numDimension, tensorName);
471  ValidateTensorNumElements(tensorInfo, functionName, numElements, tensorName);
472 }
473 
474 //---------------------------------------------------------------
475 void QueueDescriptor::ValidateInputsOutputs(const std::string& descName,
476  unsigned int numExpectedIn, unsigned int numExpectedOut) const
477 {
478  ValidateTensors(m_Inputs, numExpectedIn, descName, "input");
479  ValidateTensors(m_Outputs, numExpectedOut, descName, "output");
480 }
481 
482 //---------------------------------------------------------------
483 void MapQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
484 {
485  const std::string descriptorName{"MapQueueDescriptor"};
486 
487  ValidateNumInputs(workloadInfo, descriptorName, 1);
488  ValidateNumOutputs(workloadInfo, descriptorName, 0);
489 
490  for (unsigned int i = 0; i < m_Inputs.size(); ++i)
491  {
492  if (!m_Inputs[i])
493  {
495  fmt::format("{}: Invalid NULL input {}.", descriptorName, static_cast<int>(i)));
496  }
497  }
498 }
499 
500 //---------------------------------------------------------------
501 void UnmapQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
502 {
503  const std::string descriptorName{"UnmapQueueDescriptor"};
504 
505  ValidateNumInputs(workloadInfo, descriptorName, 1);
506  ValidateNumOutputs(workloadInfo, descriptorName, 0);
507 
508  for (unsigned int i = 0; i < m_Inputs.size(); ++i)
509  {
510  if (!m_Inputs[i])
511  {
513  fmt::format("{}: Invalid NULL input {}.", descriptorName, static_cast<int>(i)));
514  }
515  }
516 }
517 
518 //---------------------------------------------------------------
519 void MemCopyQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
520 {
521  const std::string descriptorName{"MemCopyQueueDescriptor"};
522 
523  ValidateNumInputs(workloadInfo, descriptorName, 1);
524  ValidateNumOutputs(workloadInfo, descriptorName , 1);
525 
526  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
527  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
528 
529  ValidateTensorNumElementsMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
530  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
531 
532  if (m_Inputs.size() != m_Outputs.size())
533  {
534  throw InvalidArgumentException(fmt::format(
535  "{0}: Number of inputs ({1}) does not match the number of outputs ({2}).",
536  descriptorName, m_Inputs.size(), m_Outputs.size()));
537  }
538 
539  for (unsigned int i = 0; i < m_Inputs.size(); ++i)
540  {
541  if (!m_Inputs[i])
542  {
543  throw InvalidArgumentException(fmt::format(
544  "{0}: Invalid NULL input {1}.", descriptorName, i));
545  }
546 
547  if (!m_Outputs[i])
548  {
549  throw InvalidArgumentException(fmt::format("{0}: Invalid NULL output {1}", descriptorName, i));
550  }
551  }
552 }
553 
554 //---------------------------------------------------------------
555 void MemImportQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
556 {
557  ValidateNumInputs(workloadInfo, "MemImportQueueDescriptor", 1);
558  ValidateNumOutputs(workloadInfo, "MemImportQueueDescriptor" , 1);
559 
560  if (workloadInfo.m_InputTensorInfos.size() != 1)
561  {
562  throw InvalidArgumentException(fmt::format("Number of input infos ({}) is not 1.",
563  workloadInfo.m_InputTensorInfos.size()));
564 
565  }
566 
567  if (workloadInfo.m_InputTensorInfos.size() != workloadInfo.m_OutputTensorInfos.size())
568  {
569  throw InvalidArgumentException(fmt::format(
570  "Number of input infos ({0}) does not match the number of output infos ({1})",
571  workloadInfo.m_InputTensorInfos.size(), workloadInfo.m_OutputTensorInfos.size()));
572  }
573 
574  for (std::size_t i = 0; i < workloadInfo.m_InputTensorInfos.size(); ++i)
575  {
576  if (workloadInfo.m_InputTensorInfos[i].GetNumElements() !=
577  workloadInfo.m_OutputTensorInfos[i].GetNumElements())
578  {
579  throw InvalidArgumentException(fmt::format(
580  "Number of elements for tensor input and output {} does not match", i ));
581  }
582  }
583 
584  if (m_Inputs.size() != 1)
585  {
586  throw InvalidArgumentException(fmt::format("Number of inputs ({}) is not 1.", m_Inputs.size()));
587  }
588 
589  if (m_Inputs.size() != m_Outputs.size())
590  {
591  throw InvalidArgumentException(fmt::format(
592  "Number of inputs ({0}) does not match the number of outputs ({1})",
593  m_Inputs.size(), m_Outputs.size()));
594  }
595 
596  for (unsigned int i = 0; i < m_Inputs.size(); ++i)
597  {
598  if (!m_Inputs[i])
599  {
600  throw InvalidArgumentException(fmt::format("Invalid null input {}", i));
601  }
602 
603  if (!m_Outputs[i])
604  {
605  throw InvalidArgumentException(fmt::format("Invalid null output {}", i));
606  }
607  }
608 }
609 
610 //---------------------------------------------------------------
611 void MemSyncQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
612 {
613  ValidateNumInputs(workloadInfo, "MemSyncQueueDescriptor", 1);
614 
615  if (m_Inputs.size() != 1)
616  {
617  throw InvalidArgumentException(fmt::format("Number of inputs ({}) is not 1.", m_Inputs.size()));
618  }
619 
620  if (m_Outputs.size() != 0)
621  {
622  throw InvalidArgumentException(fmt::format("Number of outputs ({}) is not 0.", m_Outputs.size()));
623  }
624 
625  if (!m_Inputs[0])
626  {
627  throw InvalidArgumentException(fmt::format("Invalid null input 0"));
628  }
629 }
630 
631 //---------------------------------------------------------------
632 void ActivationQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
633 {
634  const std::string descriptorName{"ActivationQueueDescriptor"};
635 
636  ValidateNumInputs(workloadInfo, descriptorName, 1);
637  ValidateNumOutputs(workloadInfo, descriptorName, 1);
638 
639  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
640  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
641 
642  std::vector<DataType> supportedTypes =
643  {
650  };
651 
652  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
653  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
654  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
655 }
656 
657 void ArgMinMaxQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
658 {
659  const std::string descriptorName{"ArgMinMaxQueueDescriptor"};
660 
661  ValidateNumInputs(workloadInfo, descriptorName, 1);
662  ValidateNumOutputs(workloadInfo, descriptorName, 1);
663 
664  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
665  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
666 
667  if (outputTensorInfo.GetDataType() != DataType::Signed32 &&
668  outputTensorInfo.GetDataType() != DataType::Signed64)
669  {
670  throw InvalidArgumentException(descriptorName + ": Output of ArgMinMax layer must be Int32 or Int64.");
671  }
672 
673  std::vector<DataType> supportedInputTypes =
674  {
683  };
684 
685  ValidateDataTypes(inputTensorInfo, supportedInputTypes, descriptorName);
686 
687  auto inputShape = inputTensorInfo.GetShape();
688  auto outputShape = outputTensorInfo.GetShape();
689 
690  auto inputNumDimensions = inputShape.GetNumDimensions();
691  auto unsignedAxis = armnnUtils::GetUnsignedAxis(inputNumDimensions, m_Parameters.m_Axis);
692 
693  const std::string outputShapeError{": Output tensor shape does not match shape inferred from input tensor."};
694 
695  // 1D input shape results in scalar output shape
696  if (inputShape.GetNumDimensions() == 1)
697  {
698  if (outputShape.GetNumDimensions() != 1 && outputShape[0] != 1)
699  {
700  throw InvalidArgumentException(descriptorName + outputShapeError);
701  }
702  }
703  else
704  {
705  for (unsigned int i = 0; i < unsignedAxis; ++i)
706  {
707  if (outputShape[i] != inputShape[i])
708  {
709  throw InvalidArgumentException(descriptorName + outputShapeError);
710  }
711  }
712 
713  for (auto i = unsignedAxis + 1; i < inputNumDimensions; ++i)
714  {
715  if (outputShape[i - 1] != inputShape[i])
716  {
717  throw InvalidArgumentException(descriptorName + outputShapeError);
718  }
719  }
720  }
721 }
722 
723 void CastQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
724 {
725  const std::string descriptorName{"CastQueueDescriptor"};
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  {
744  };
745 
746  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
747  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
748 }
749 
750 void SoftmaxQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
751 {
752  const std::string descriptorName{"SoftmaxQueueDescriptor"};
753 
754  ValidateNumInputs(workloadInfo, descriptorName, 1);
755  ValidateNumOutputs(workloadInfo, descriptorName, 1);
756 
757  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
758  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
759 
760  std::vector<DataType> supportedTypes =
761  {
768  };
769 
770  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
771  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
772  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
773 }
774 
775 void SplitterQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
776 {
777  const std::string descriptorName{"SplitterQueueDescriptor"};
778 
779  ValidateNumInputs(workloadInfo, descriptorName, 1);
780 
781  // Check the supported data types
782  std::vector<DataType> supportedTypes =
783  {
792  };
793 
794  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
795  for (unsigned long i = 0ul; i < workloadInfo.m_OutputTensorInfos.size(); ++i)
796  {
797  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[i];
798  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
799 
800  const std::string outputName = "output_" + std::to_string(i);
801  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", outputName);
802  }
803 
804  if (workloadInfo.m_OutputTensorInfos.size() <= 0)
805  {
806  throw InvalidArgumentException(descriptorName + ": At least one output needs to be provided.");
807  }
808 
809  if (workloadInfo.m_OutputTensorInfos.size() != m_ViewOrigins.size())
810  {
812  descriptorName + ": Number of split windows "
813  "has to match number of workloadInfo.m_OutputTensorInfos. "
814  "Number of windows: " +
815  to_string(m_ViewOrigins.size()) +
816  ". Number of workloadInfo.m_OutputTensorInfos: " + to_string(workloadInfo.m_OutputTensorInfos.size()));
817  }
818 
819  //The dimensionality of all the windows has to match the dimensionality (not shape) of the input.
820  std::size_t inputDims = workloadInfo.m_InputTensorInfos[0].GetNumDimensions();
821  for(unsigned int w = 0; w < m_ViewOrigins.size(); ++w )
822  {
823  //Checks that the dimensionality of input is same as the split windows.
824  ViewOrigin const& e = m_ViewOrigins[w];
825  if (e.m_Origin.size() != inputDims)
826  {
827  throw InvalidArgumentException(descriptorName + ": Window origin have to "
828  "have the same dimensionality as the input tensor. "
829  "Window origin (index: " +
830  to_string(w) + ") has " + to_string(e.m_Origin.size()) +
831  " dimensions, the input "
832  "tensor has " +
833  to_string(inputDims) + " dimensions.");
834  }
835  for (unsigned int i = 0; i < e.m_Origin.size(); ++i)
836  {
837  if (e.m_Origin[i] + workloadInfo.m_OutputTensorInfos[w].GetShape()[i] >
838  workloadInfo.m_InputTensorInfos[0].GetShape()[i])
839  {
840  throw InvalidArgumentException(descriptorName + ": Window extent coordinates have to "
841  "be smaller or equal than the size of the input in that coord.");
842  }
843  }
844  }
845 }
846 
847 void ConcatQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
848 {
849  const std::string descriptorName{"ConcatQueueDescriptor"};
850 
851  ValidateNumOutputs(workloadInfo, descriptorName, 1);
852 
853  if (m_Inputs.size() <= 0)
854  {
855  throw InvalidArgumentException(descriptorName + ": At least one input needs to be provided.");
856  }
857  if (m_Outputs.size() <= 0)
858  {
859  throw InvalidArgumentException(descriptorName + ": At least one output needs to be provided.");
860  }
861 
862  if (workloadInfo.m_InputTensorInfos.size() <= 0)
863  {
864  throw InvalidArgumentException(descriptorName + ": At least one TensorInfo input needs to be provided.");
865  }
866  if (workloadInfo.m_OutputTensorInfos.size() <= 0)
867  {
868  throw InvalidArgumentException(descriptorName + ": At least one TensorInfo output needs to be provided.");
869  }
870 
871  if(m_Parameters.GetConcatAxis() > workloadInfo.m_InputTensorInfos[0].GetShape().GetNumDimensions())
872  {
873  throw InvalidArgumentException(descriptorName + ": Invalid concatenation axis provided.");
874  }
875 
876  if (workloadInfo.m_InputTensorInfos[0].GetShape().GetNumDimensions() - m_Parameters.GetConcatAxis() == 1)
877  {
878  return;
879  }
880 
881  if (workloadInfo.m_InputTensorInfos.size() != m_ViewOrigins.size())
882  {
884  descriptorName + ": Number of split windows "
885  "has to match number of workloadInfo.m_InputTensorInfos. "
886  "Number of windows: " +
887  to_string(m_ViewOrigins.size()) +
888  ". Number of workloadInfo.m_InputTensorInfos: " + to_string(workloadInfo.m_InputTensorInfos.size()));
889  }
890 
891  //The dimensionality of all the windows has to match the dimensionality (not shape) of the output.
892  std::size_t outputDims = workloadInfo.m_OutputTensorInfos[0].GetNumDimensions();
893  for(unsigned int w = 0; w < m_ViewOrigins.size(); ++w )
894  {
895  //Checks that the dimensionality of output is same as the split windows.
896  ViewOrigin const& e = m_ViewOrigins[w];
897  if (e.m_Origin.size() != outputDims)
898  {
899  throw InvalidArgumentException(descriptorName + ": Window origin have to "
900  "have the same dimensionality as the output tensor. "
901  "Window origin (index: " +
902  to_string(w) + ") has " + to_string(e.m_Origin.size()) +
903  " dimensions, the output "
904  "tensor has " +
905  to_string(outputDims) + " dimensions.");
906  }
907  //Checks that the merge windows are within the output tensor.
908  for (unsigned int i = 0; i < e.m_Origin.size(); ++i)
909  {
910  if (e.m_Origin[i] + workloadInfo.m_InputTensorInfos[w].GetShape()[i]
911  > workloadInfo.m_OutputTensorInfos[0].GetShape()[i])
912  {
913  throw InvalidArgumentException(descriptorName + ": Window extent coordinates have to "
914  "be smaller or equal than the size of the output in that coord.");
915  }
916  }
917  }
918 
919  // Check the supported data types
920  std::vector<DataType> supportedTypes =
921  {
930  };
931 
932  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
933  for (unsigned long i = 0ul; i < workloadInfo.m_InputTensorInfos.size(); ++i)
934  {
935  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[i];
936  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
937 
938  const std::string inputName = "input_" + std::to_string(i);
939  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, inputName, "output");
940  }
941 }
942 
943 void StackQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
944 {
945  const std::string descriptorName{"StackQueueDescriptor"};
946 
947  ValidateNumOutputs(workloadInfo, descriptorName, 1);
948 
949  if (m_Parameters.m_NumInputs != workloadInfo.m_InputTensorInfos.size())
950  {
951  throw InvalidArgumentException(descriptorName + ": Must have the defined number of input tensors.");
952  }
953 
954  // All inputs must have the same shape, which is defined in parameters
955  const TensorShape& inputShape = m_Parameters.m_InputShape;
956  for (unsigned int i = 0; i < workloadInfo.m_InputTensorInfos.size(); ++i)
957  {
958  if (workloadInfo.m_InputTensorInfos[i].GetShape() != inputShape)
959  {
960  throw InvalidArgumentException(descriptorName + ": All input tensor shapes must match the defined shape.");
961  }
962  }
963 
964  if (inputShape.GetNumDimensions() > 4)
965  {
966  throw InvalidArgumentException(descriptorName + ": Input tensor may have up to 4 dimensions.");
967  }
968 
969  // m_Axis is 0-based and may take values from 0 to the number of input dimensions (inclusive),
970  // since the output tensor has an additional dimension.
971  if (m_Parameters.m_Axis > inputShape.GetNumDimensions())
972  {
973  throw InvalidArgumentException(descriptorName + ": Axis may not be greater "
974  "than the number of input dimensions.");
975  }
976 
977  // Output shape must be as inferred from the input shape
978  const TensorShape& outputShape = workloadInfo.m_OutputTensorInfos[0].GetShape();
979  for (unsigned int i = 0; i < m_Parameters.m_Axis; ++i)
980  {
981  if (outputShape[i] != inputShape[i])
982  {
983  throw InvalidArgumentException(descriptorName + ": Output tensor must "
984  "match shape inferred from input tensor.");
985  }
986  }
987 
988  if (outputShape[m_Parameters.m_Axis] != m_Parameters.m_NumInputs)
989  {
990  throw InvalidArgumentException(descriptorName + ": Output tensor must "
991  "match shape inferred from input tensor.");
992  }
993 
994  for (unsigned int i = m_Parameters.m_Axis + 1; i < inputShape.GetNumDimensions() + 1; ++i)
995  {
996  if (outputShape[i] != inputShape[i-1])
997  {
998  throw InvalidArgumentException(descriptorName + ": Output tensor must "
999  "match shape inferred from input tensor.");
1000  }
1001  }
1002 
1003  if (outputShape.GetNumDimensions() > 5)
1004  {
1005  throw InvalidArgumentException(descriptorName + ": Output tensor may have up to 5 dimensions.");
1006  }
1007 
1008  // Check the supported data types
1009  std::vector<DataType> supportedTypes =
1010  {
1019  };
1020 
1021  ValidateDataTypes(workloadInfo.m_InputTensorInfos[0], supportedTypes, descriptorName);
1022 
1023  for (unsigned int i = 1ul; i < workloadInfo.m_InputTensorInfos.size(); ++i)
1024  {
1025  ValidateTensorDataTypesMatch(workloadInfo.m_InputTensorInfos[0],
1026  workloadInfo.m_InputTensorInfos[i],
1027  descriptorName,
1028  "input_0",
1029  "input_" + std::to_string(i));
1030  }
1031 
1032  ValidateTensorDataTypesMatch(workloadInfo.m_InputTensorInfos[0],
1033  workloadInfo.m_OutputTensorInfos[0],
1034  descriptorName,
1035  "input_0",
1036  "output");
1037 }
1038 
1039 void FillQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1040 {
1041  const std::string descriptorName{"FillQueueDescriptor"};
1042 
1043  ValidateNumInputs(workloadInfo, descriptorName, 1);
1044  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1045 
1046  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1047  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1048 
1049  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 1, "input");
1050 
1051  std::vector<DataType> supportedTypes =
1052  {
1057  };
1058 
1059  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1060 }
1061 
1063 {
1064  const std::string descriptorName{"FullyConnectedQueueDescriptor"};
1065 
1066  uint32_t numInputs = 2;
1068  {
1069  numInputs = 3;
1070  }
1071 
1072  ValidateNumInputs(workloadInfo, descriptorName, numInputs);
1073  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1074 
1075  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1076  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1077 
1078  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 2, "output");
1079 
1080  if (!(inputTensorInfo.GetNumDimensions() == 2 || inputTensorInfo.GetNumDimensions() == 4))
1081  {
1082  throw InvalidArgumentException(descriptorName + ": Input tensor must have 2 or 4 dimensions.");
1083  }
1084 
1085  TensorInfo weightTensorInfo = workloadInfo.m_InputTensorInfos[1];
1086  ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 2, "weight");
1087 
1089  {
1090  TensorInfo biasTensorInfo = workloadInfo.m_InputTensorInfos[2];
1091  // Validates type and quantization values.
1092  ValidateBiasTensorQuantization(biasTensorInfo, inputTensorInfo, weightTensorInfo, descriptorName);
1093  ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
1094  ValidateTensorNumDimensions(biasTensorInfo, descriptorName, 1, "bias");
1095  }
1096 
1097  // Check the supported data types
1098  std::vector<DataType> supportedTypes =
1099  {
1106  };
1107 
1108  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1109 
1110  // For FullyConnected, we allow to have BFloat16 input with Float32 output for optimization.
1111  if (inputTensorInfo.GetDataType() == DataType::BFloat16)
1112  {
1113  if (outputTensorInfo.GetDataType() != DataType::BFloat16 && outputTensorInfo.GetDataType() != DataType::Float32)
1114  {
1115  throw InvalidArgumentException(descriptorName + ": " + " Output tensor type must be BFloat16 or Float32 "
1116  "for BFloat16 input.");
1117  }
1118  }
1119  else
1120  {
1121  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1122  }
1123 }
1124 
1126 {
1127  const std::string descriptorName{"NormalizationQueueDescriptor"};
1128 
1129  ValidateNumInputs(workloadInfo, descriptorName, 1);
1130  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1131 
1132  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1133  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1134 
1135  // Check the supported data types
1136  std::vector<DataType> supportedTypes =
1137  {
1144  };
1145 
1146  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1147 
1148  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1149 
1150  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1151 }
1152 
1153 void AdditionQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1154 {
1155  const std::string descriptorName{"AdditionQueueDescriptor"};
1156 
1157  ValidateNumInputs(workloadInfo, descriptorName, 2);
1158  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1159 
1160  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
1161  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
1162  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1163 
1164  std::vector<DataType> supportedTypes =
1165  {
1173  };
1174 
1175  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
1176  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
1177  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1178 
1179  ValidateTensorDataTypesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
1180  ValidateTensorDataTypesMatch(inputTensorInfo1, outputTensorInfo, descriptorName, "input_1", "output");
1181 
1182  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
1183  inputTensorInfo1,
1184  outputTensorInfo,
1185  descriptorName,
1186  "input_0",
1187  "input_1");
1188 }
1189 
1191 {
1192  const std::string descriptorName{"MultiplicationQueueDescriptor"};
1193 
1194  ValidateNumInputs(workloadInfo, descriptorName, 2);
1195  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1196 
1197  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
1198  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
1199  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1200 
1201  std::vector<DataType> supportedTypes =
1202  {
1210  };
1211 
1212  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
1213  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
1214  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1215 
1216  ValidateTensorDataTypesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
1217  ValidateTensorDataTypesMatch(inputTensorInfo1, outputTensorInfo, descriptorName, "input_1", "output");
1218 
1219  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
1220  inputTensorInfo1,
1221  outputTensorInfo,
1222  descriptorName,
1223  "input_0",
1224  "input_1");
1225 }
1226 
1228 {
1229  const std::string descriptorName{"BatchNormalizationQueueDescriptor"};
1230 
1231  ValidateNumInputs(workloadInfo, descriptorName, 1);
1232  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1233 
1234  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1235  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1236 
1237  std::vector<DataType> supportedTypes =
1238  {
1245  };
1246 
1247  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1248  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1249 
1250  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1251  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1252 
1253  ValidatePointer(m_Mean, descriptorName, "mean");
1254  ValidatePointer(m_Variance, descriptorName, "variance");
1255  ValidatePointer(m_Beta, descriptorName, "beta");
1256  ValidatePointer(m_Gamma, descriptorName, "gamma");
1257 
1258  const TensorInfo& mean = m_Mean->GetTensorInfo();
1259  const TensorInfo& variance = m_Variance->GetTensorInfo();
1260  const TensorInfo& beta = m_Beta->GetTensorInfo();
1261  const TensorInfo& gamma = m_Gamma->GetTensorInfo();
1262 
1263  ValidateTensorNumDimensions(mean, descriptorName, 1, "mean");
1264  ValidateTensorNumDimensions(variance, descriptorName, 1, "variance");
1265  ValidateTensorNumDimensions(beta, descriptorName, 1, "beta");
1266  ValidateTensorNumDimensions(gamma, descriptorName, 1, "gamma");
1267 
1268  ValidateTensorShapesMatch(mean, variance, descriptorName, "mean", "variance");
1269  ValidateTensorShapesMatch(mean, beta, descriptorName, "mean", "beta");
1270  ValidateTensorShapesMatch(mean, gamma, descriptorName, "mean", "gamma");
1271 }
1272 
1274 {
1275  const std::string descriptorName{"Convolution2dQueueDescriptor"};
1276 
1277  uint32_t numInputs = 2;
1279  {
1280  numInputs = 3;
1281  }
1282 
1283  ValidateNumInputs(workloadInfo, descriptorName, numInputs);
1284  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1285 
1286  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1287  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1288 
1289  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1290  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1291 
1292  const TensorInfo& weightTensorInfo = workloadInfo.m_InputTensorInfos[1];
1293 
1294  ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 4, "weight");
1295 
1296  ValidateWeightDataType(inputTensorInfo, weightTensorInfo, descriptorName);
1297 
1298  Optional<TensorInfo> optionalBiasTensorInfo;
1300  {
1301  optionalBiasTensorInfo = MakeOptional<TensorInfo>(workloadInfo.m_InputTensorInfos[2]);
1302  const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value();
1303 
1304  ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
1305  ValidateBiasTensorQuantization(biasTensorInfo, inputTensorInfo, weightTensorInfo, descriptorName);
1306  }
1307 
1308  if (m_Parameters.m_StrideX <= 0 || m_Parameters.m_StrideY <= 0 )
1309  {
1311  fmt::format("{}: strideX (provided {}) and strideY (provided {}) "
1312  "cannot be either negative or 0.",
1313  descriptorName, m_Parameters.m_StrideX, m_Parameters.m_StrideY));
1314  }
1315 
1316  ValidatePerAxisQuantization(inputTensorInfo,
1317  outputTensorInfo,
1318  weightTensorInfo,
1319  optionalBiasTensorInfo,
1320  descriptorName);
1321 
1322  std::vector<DataType> supportedTypes =
1323  {
1331  };
1332 
1333  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1334 
1335  // For Convolution2d, we allow to have BFloat16 input with Float32 output for optimization.
1336  if (inputTensorInfo.GetDataType() == DataType::BFloat16)
1337  {
1338  if (outputTensorInfo.GetDataType() != DataType::BFloat16 && outputTensorInfo.GetDataType() != DataType::Float32)
1339  {
1340  throw InvalidArgumentException(descriptorName + ": " + " Output tensor type must be BFloat16 or Float32 "
1341  "for BFloat16 input.");
1342  }
1343  }
1344  else
1345  {
1346  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1347  }
1348 }
1349 
1351 {
1352  const std::string descriptorName{"Convolution3dQueueDescriptor"};
1353 
1354  uint32_t numInputs = 2;
1356  {
1357  numInputs = 3;
1358  }
1359  ValidateNumInputs(workloadInfo, descriptorName, numInputs);
1360  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1361 
1362  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1363  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1364 
1365  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 5, "input");
1366  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 5, "output");
1367 
1368  const TensorInfo& weightTensorInfo = workloadInfo.m_InputTensorInfos[1];
1369  ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 5, "weight");
1370 
1371  ValidateWeightDataType(inputTensorInfo, weightTensorInfo, descriptorName);
1372 
1373  Optional<TensorInfo> optionalBiasTensorInfo;
1375  {
1376  optionalBiasTensorInfo = MakeOptional<TensorInfo>(workloadInfo.m_InputTensorInfos[2]);
1377  const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value();
1378 
1379  ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
1380  ValidateBiasTensorQuantization(biasTensorInfo, inputTensorInfo, weightTensorInfo, descriptorName);
1381  }
1382 
1384  {
1386  fmt::format("{}: strideX (provided {}), strideY (provided {}) or strideZ (provided {})"
1387  "cannot be either negative or 0.",
1389  }
1390 
1391  ValidatePerAxisQuantization(inputTensorInfo,
1392  outputTensorInfo,
1393  weightTensorInfo,
1394  optionalBiasTensorInfo,
1395  descriptorName);
1396 
1397  std::vector<DataType> supportedTypes =
1398  {
1406  };
1407 
1408  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1409  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1410 }
1411 
1413 {
1414  const std::string descriptorName{"DepthwiseConvolution2dQueueDescriptor"};
1415 
1416  uint32_t numInputs = 2;
1418  {
1419  numInputs = 3;
1420  }
1421 
1422  ValidateNumInputs(workloadInfo, descriptorName, numInputs);
1423  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1424 
1425  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1426  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1427 
1428  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1429  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1430 
1431  const TensorInfo& weightTensorInfo = workloadInfo.m_InputTensorInfos[1];
1432  ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 4, "weight");
1433 
1435  {
1437  fmt::format("{}: dilationX (provided {}) and dilationY (provided {}) "
1438  "cannot be smaller than 1.",
1439  descriptorName, m_Parameters.m_DilationX, m_Parameters.m_DilationX));
1440  }
1441 
1442  if (m_Parameters.m_StrideX <= 0 || m_Parameters.m_StrideY <= 0 )
1443  {
1445  fmt::format("{}: strideX (provided {}) and strideY (provided {}) "
1446  "cannot be either negative or 0.",
1447  descriptorName, m_Parameters.m_StrideX, m_Parameters.m_StrideY));
1448  }
1449 
1450  if (weightTensorInfo.GetShape()[0] != 1)
1451  {
1452  throw InvalidArgumentException(fmt::format(
1453  "{0}: The weight format in armnn is expected to be [1, H, W, Cout]."
1454  "But first dimension is not equal to 1. Provided weight shape: [{1}, {2}, {3}, {4}]",
1455  descriptorName,
1456  weightTensorInfo.GetShape()[0],
1457  weightTensorInfo.GetShape()[1],
1458  weightTensorInfo.GetShape()[2],
1459  weightTensorInfo.GetShape()[3]));
1460  }
1461 
1462  const unsigned int channelIndex = (m_Parameters.m_DataLayout == DataLayout::NCHW) ? 1 : 3;
1463  const unsigned int numWeightOutputChannelsRefFormat = weightTensorInfo.GetShape()[3];
1464  const unsigned int numWeightOutputChannelsAclFormat = weightTensorInfo.GetShape()[1];
1465  const unsigned int numOutputChannels = outputTensorInfo.GetShape()[channelIndex];
1466 
1467  // Weights format has two valid options: [1, H, W, Cout] (CpuRef) or [1, Cout, H, W] (CpuAcc/GpuAcc).
1468  bool validRefFormat = (numWeightOutputChannelsRefFormat == numOutputChannels);
1469  bool validAclFormat = (numWeightOutputChannelsAclFormat == numOutputChannels);
1470 
1471  if (!(validRefFormat || validAclFormat))
1472  {
1473  throw InvalidArgumentException(fmt::format(
1474  "{0}: The weight format in armnn is expected to be [1, H, W, Cout] (CpuRef) or [1, Cout, H, W] "
1475  "(CpuAcc/GpuAcc). But neither the 4th (CpuRef) or 2nd (CpuAcc/GpuAcc) dimension is equal to Cout."
1476  "Cout = {1} Provided weight shape: [{2}, {3}, {4}, {5}]",
1477  descriptorName,
1478  numOutputChannels,
1479  weightTensorInfo.GetShape()[0],
1480  weightTensorInfo.GetShape()[1],
1481  weightTensorInfo.GetShape()[2],
1482  weightTensorInfo.GetShape()[3]));
1483  }
1484 
1485  ValidateWeightDataType(inputTensorInfo, weightTensorInfo, descriptorName);
1486 
1487  Optional<TensorInfo> optionalBiasTensorInfo;
1489  {
1490  optionalBiasTensorInfo = MakeOptional<TensorInfo>(workloadInfo.m_InputTensorInfos[2]);
1491  const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value();
1492 
1493  ValidateBiasTensorQuantization(biasTensorInfo, inputTensorInfo, weightTensorInfo, descriptorName);
1494  ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
1495  }
1496  ValidatePerAxisQuantization(inputTensorInfo,
1497  outputTensorInfo,
1498  weightTensorInfo,
1499  optionalBiasTensorInfo,
1500  descriptorName);
1501 
1502  std::vector<DataType> supportedTypes =
1503  {
1510  };
1511 
1512  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1513  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1514 }
1515 
1516 void PermuteQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1517 {
1518  const std::string descriptorName{"PermuteQueueDescriptor"};
1519 
1520  ValidateNumInputs(workloadInfo, descriptorName, 1);
1521  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1522 
1523  const PermutationVector& mapping = m_Parameters.m_DimMappings;
1524 
1525  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1526  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1527 
1528  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, mapping.GetSize(), "input");
1529  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, mapping.GetSize(), "output");
1530 
1531  for (unsigned int i = 0u; i < mapping.GetSize(); ++i)
1532  {
1533  if (inputTensorInfo.GetShape()[i] != outputTensorInfo.GetShape()[mapping[i]])
1534  {
1535  throw InvalidArgumentException(descriptorName + ": src dimension " + to_string(i) +
1536  " (=" + to_string(inputTensorInfo.GetShape()[i]) + ") " +
1537  "must match dst dimension " + to_string(mapping[i]) +
1538  " (=" + to_string(outputTensorInfo.GetShape()[mapping[i]]) + ")");
1539  }
1540  }
1541 
1542  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1543 }
1544 
1545 void Pooling2dQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1546 {
1547  const std::string descriptorName{"Pooling2dQueueDescriptor"};
1548 
1549  ValidateNumInputs(workloadInfo, descriptorName, 1);
1550  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1551 
1552  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1553  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1554 
1555  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1556  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1557 
1558  std::vector<DataType> supportedTypes =
1559  {
1566  };
1567 
1568  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1569  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1570 }
1571 
1572 void Pooling3dQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1573 {
1574  const std::string descriptorName{"Pooling3dQueueDescriptor"};
1575 
1576  ValidateNumInputs(workloadInfo, descriptorName, 1);
1577  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1578 
1579  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1580  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1581 
1582  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 5, "input");
1583  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 5, "output");
1584 
1585  std::vector<DataType> supportedTypes =
1586  {
1593  };
1594 
1595  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1596  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1597 }
1598 
1599 void ResizeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1600 {
1601  const std::string descriptorName{"ResizeQueueDescriptor"};
1602 
1603  ValidateNumInputs(workloadInfo, descriptorName, 1);
1604  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1605 
1606  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1607  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1608 
1609  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1610  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1611 
1612  std::vector<DataType> supportedTypes =
1613  {
1620  };
1621 
1622  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1623  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1624 
1625  // Resize only changes width and height: batch and channel count must match.
1626  const unsigned int inputBatchSize = inputTensorInfo.GetShape()[0];
1627  const unsigned int outputBatchSize = outputTensorInfo.GetShape()[0];
1628  if (inputBatchSize != outputBatchSize)
1629  {
1631  fmt::format("{}: Input batch size ({}) does not match output batch size ({})",
1632  descriptorName, inputBatchSize, outputBatchSize));
1633  }
1634 
1635  DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
1636  const unsigned int inputChannelCount = inputTensorInfo.GetShape()[dimensionIndices.GetChannelsIndex()];
1637  const unsigned int outputChannelCount = outputTensorInfo.GetShape()[dimensionIndices.GetChannelsIndex()];
1638  if (inputChannelCount != outputChannelCount)
1639  {
1641  fmt::format("{}: Input channel count ({}) does not match output channel count ({})",
1642  descriptorName, inputChannelCount, outputChannelCount));
1643  }
1644 }
1645 
1647 {
1648  const std::string descriptorName{"FakeQuantizationQueueDescriptor"};
1649 
1650  ValidateNumInputs(workloadInfo, descriptorName, 1);
1651  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1652 
1653  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1654  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1655 
1656  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 2, "input");
1657  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 2, "output");
1658 
1659  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1660 
1662  {
1663  throw InvalidArgumentException(descriptorName + ": min cannot be greater than max");
1664  }
1665 }
1666 
1668 {
1669  const std::string descriptorName{"InstanceNormalizationQueueDescriptor"};
1670 
1671  ValidateNumInputs(workloadInfo, descriptorName, 1);
1672  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1673 
1674  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1675  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1676 
1677  if (inputTensorInfo.GetNumDimensions() > 4)
1678  {
1679  throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
1680  }
1681 
1682  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1683 
1684  // Check the supported data types
1685  std::vector<DataType> supportedTypes =
1686  {
1690  };
1691 
1692  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1693  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1694 }
1695 
1697 {
1698  const std::string descriptorName{"L2NormalizationQueueDescriptor"};
1699 
1700  ValidateNumInputs(workloadInfo, descriptorName, 1);
1701  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1702 
1703  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1704  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1705 
1706  if (inputTensorInfo.GetNumDimensions() > 4)
1707  {
1708  throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
1709  }
1710 
1711  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1712 
1713  // Check the supported data types
1714  std::vector<DataType> supportedTypes =
1715  {
1722  };
1723 
1724  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1725  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1726 }
1727 
1728 void LogSoftmaxQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1729 {
1730  const std::string descriptorName{"LogSoftmaxQueueDescriptor"};
1731 
1732  ValidateNumInputs(workloadInfo, descriptorName, 1);
1733  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1734 
1735  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1736  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1737 
1738  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1739 
1740  std::vector<DataType> supportedTypes =
1741  {
1745  };
1746 
1747  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1748  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1749 }
1750 
1751 void ConstantQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1752 {
1753  const std::string descriptorName{"ConstantQueueDescriptor"};
1754 
1755  ValidateNumInputs(workloadInfo, descriptorName, 0);
1756  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1757 
1758  if (!m_LayerOutput)
1759  {
1760  throw InvalidArgumentException(descriptorName + ": No const input specified.");
1761  }
1762 
1763  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1764  ValidateTensorShapesMatch(m_LayerOutput->GetTensorInfo(), outputTensorInfo, descriptorName, "constant", "output");
1765 
1766  // Check the supported data types
1767  std::vector<DataType> supportedTypes =
1768  {
1777  };
1778 
1779  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1780 }
1781 
1782 void ReshapeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1783 {
1784  const std::string descriptorName{"ReshapeQueueDescriptor"};
1785 
1786  ValidateNumInputs(workloadInfo, descriptorName, 1);
1787  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1788 
1789  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1790  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1791 
1792  ValidateTensorNumElementsMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1793 
1794  // Check the supported data types
1795  std::vector<DataType> supportedTypes =
1796  {
1805  };
1806 
1807  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1808  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1809 }
1810 
1812 {
1813  const std::string descriptorName{"SpaceToBatchNdQueueDescriptor"};
1814 
1815  ValidateNumInputs(workloadInfo, descriptorName, 1);
1816  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1817 
1818  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1819  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1820 
1821  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1822  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1823 
1824  if (m_Parameters.m_BlockShape.size() != 2)
1825  {
1826  throw InvalidArgumentException(descriptorName + ": Block Shape must contain 2 spatial dimensions.");
1827  }
1828 
1829  if (m_Parameters.m_BlockShape.size() != m_Parameters.m_PadList.size())
1830  {
1831  throw InvalidArgumentException(descriptorName + ": Pad List must contain the same number of "
1832  "dimensions as Block Shape.");
1833  }
1834 
1835  const TensorShape& inputShape = inputTensorInfo.GetShape();
1836 
1837  std::pair<unsigned int, unsigned int> heightPad = m_Parameters.m_PadList[0];
1838  std::pair<unsigned int, unsigned int> widthPad = m_Parameters.m_PadList[1];
1839 
1840  DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
1841 
1842  const unsigned int inputWidth = inputShape[dimensionIndices.GetWidthIndex()] +
1843  widthPad.first + widthPad.second;
1844  const unsigned int inputHeight = inputShape[dimensionIndices.GetHeightIndex()] +
1845  heightPad.first + heightPad.second;
1846 
1847  const unsigned int numInputElements = inputShape[0] * inputHeight * inputWidth *
1848  inputShape[dimensionIndices.GetChannelsIndex()];
1849  const unsigned int numOutputElements = outputTensorInfo.GetNumElements();
1850 
1851  if (numOutputElements != numInputElements)
1852  {
1853  throw InvalidArgumentException(descriptorName + ": Input tensor has " +
1854  to_string(numInputElements) + " after padding but output tensor has " +
1855  to_string(numOutputElements) + " elements.");
1856  }
1857 
1858  if (inputHeight % m_Parameters.m_BlockShape[0] != 0 || inputWidth % m_Parameters.m_BlockShape[1] != 0)
1859  {
1860  throw InvalidArgumentException(descriptorName + ": Input shape after padding must be "
1861  "divisible by Block Shape in all spatial dimensions");
1862  }
1863 
1864  std::vector<DataType> supportedTypes =
1865  {
1872  };
1873 
1874  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1875  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1876 }
1877 
1879 {
1880  const std::string descriptorName{"SpaceToDepthQueueDescriptor"};
1881 
1882  ValidateNumInputs(workloadInfo, descriptorName, 1);
1883  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1884 
1885  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1886  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1887 
1888  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1889  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1890 
1891  std::vector<DataType> supportedTypes =
1892  {
1899  };
1900 
1901  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1902  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1903 
1904  ValidateTensorNumElementsMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1905 
1906  if (m_Parameters.m_BlockSize == 0)
1907  {
1908  throw InvalidArgumentException(descriptorName + ": Block size cannot be 0.");
1909  }
1910 
1911  DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
1912  const unsigned int wIndex = dimensionIndices.GetWidthIndex();
1913  const unsigned int hIndex = dimensionIndices.GetHeightIndex();
1914  const unsigned int cIndex = dimensionIndices.GetChannelsIndex();
1915 
1916  const TensorShape& inputShape = inputTensorInfo.GetShape();
1917  if (inputShape[hIndex] % m_Parameters.m_BlockSize != 0 || inputShape[wIndex] % m_Parameters.m_BlockSize != 0)
1918  {
1919  throw InvalidArgumentException(descriptorName + ": Input shape must be divisible "
1920  "by block size in all spatial dimensions");
1921  }
1922 
1923  const TensorShape& outputShape = outputTensorInfo.GetShape();
1924  if (outputShape[cIndex] % (m_Parameters.m_BlockSize * m_Parameters.m_BlockSize) != 0)
1925  {
1926  throw InvalidArgumentException(descriptorName + ": The depth of the output tensor"
1927  "must be divisible by the square of block size." );
1928  }
1929 }
1930 
1931 void FloorQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1932 {
1933  const std::string descriptorName{"FloorQueueDescriptor"};
1934 
1935  ValidateNumInputs(workloadInfo, descriptorName, 1);
1936  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1937 
1938  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1939  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1940 
1941  std::vector<DataType> supportedTypes =
1942  {
1947  };
1948 
1949  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1950  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1951  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1952  ValidateTensorQuantizationSpace(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1953 }
1954 
1955 void LstmQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1956 {
1957  // ported from android/ml/nn/common/operations/LSTM.cpp CheckInputTensorDimensions()
1958 
1959  const std::string descriptorName{"LstmQueueDescriptor"};
1960 
1961  // check dimensions of all inputs and outputs
1962  if (workloadInfo.m_InputTensorInfos.size() != 3)
1963  {
1964  throw InvalidArgumentException(descriptorName + ": Invalid number of inputs.");
1965  }
1966  if (workloadInfo.m_OutputTensorInfos.size() != 4)
1967  {
1968  throw InvalidArgumentException(descriptorName + ": Invalid number of outputs.");
1969  }
1970 
1971  std::vector<DataType> supportedTypes =
1972  {
1977  };
1978 
1979  // check for supported type of one input and match them with all the other input and output
1980  ValidateDataTypes(workloadInfo.m_InputTensorInfos[0], supportedTypes, descriptorName);
1981 
1982  // type matches all other inputs
1983  for (uint32_t i = 1u; i < workloadInfo.m_InputTensorInfos.size(); ++i)
1984  {
1985  ValidateTensorDataTypesMatch(workloadInfo.m_InputTensorInfos[0],
1986  workloadInfo.m_InputTensorInfos[i],
1987  descriptorName,
1988  "input_0",
1989  "input_" + std::to_string(i));
1990  }
1991  // type matches all other outputs
1992  for (uint32_t i = 0u; i < workloadInfo.m_OutputTensorInfos.size(); ++i)
1993  {
1994  ValidateTensorDataTypesMatch(workloadInfo.m_InputTensorInfos[0],
1995  workloadInfo.m_OutputTensorInfos[i],
1996  "LstmQueueDescriptor",
1997  "input_0",
1998  "output_" + std::to_string(i));
1999  }
2000 
2001  // Making sure clipping parameters have valid values.
2002  // == 0 means no clipping
2003  // > 0 means clipping
2004  if (m_Parameters.m_ClippingThresCell < 0.0f)
2005  {
2006  throw InvalidArgumentException(descriptorName + ": negative cell clipping threshold is invalid");
2007  }
2008  if (m_Parameters.m_ClippingThresProj < 0.0f)
2009  {
2010  throw InvalidArgumentException(descriptorName + ": negative projection clipping threshold is invalid");
2011  }
2012 
2013  // Inferring batch size, number of outputs and number of cells from the inputs.
2014  const uint32_t n_input = workloadInfo.m_InputTensorInfos[0].GetShape()[1];
2015  const uint32_t n_batch = workloadInfo.m_InputTensorInfos[0].GetShape()[0];
2016  ValidatePointer(m_InputToOutputWeights, "Null pointer check", "InputToOutputWeights");
2017  const uint32_t n_cell = m_InputToOutputWeights->GetShape()[0];
2018  ValidatePointer(m_RecurrentToOutputWeights, "Null pointer check", "RecurrentToOutputWeights");
2019  const uint32_t n_output = m_RecurrentToOutputWeights->GetShape()[1];
2020 
2021  // input tensor
2022  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[0], 2, (n_batch * n_input),
2023  descriptorName + " input_0");
2024  // outputStateInTensor
2025  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[1], 2, (n_batch * n_output),
2026  descriptorName + " input_1");
2027  // outputStateInTensor
2028  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[2], 2, (n_batch * n_cell),
2029  descriptorName + " input_2");
2030  // scratchBufferTensor
2031  unsigned int scratchBufferSize = m_Parameters.m_CifgEnabled ? n_cell * 3 : n_cell * 4;
2032  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[0], 2, (n_batch * scratchBufferSize),
2033  descriptorName + " output_0");
2034  // outputStateOutTensor
2035  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[1], 2, (n_batch * n_output),
2036  descriptorName + " output_1");
2037  // cellStateOutTensor
2038  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[2], 2, (n_batch * n_cell),
2039  descriptorName + " output_2");
2040  // outputTensor
2041  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[3], 2, (n_batch * n_output),
2042  descriptorName + " output_3");
2043 
2044  // check that dimensions of inputs/outputs and QueueDescriptor data match with each other
2045  if ( m_InputToInputWeights )
2046  {
2048  (n_cell * n_input), "InputLayerNormWeights");
2049  }
2050 
2051  ValidatePointer(m_InputToForgetWeights, "Null pointer check", "InputToForgetWeights");
2053  (n_cell * n_input), "InputToForgetWeights");
2054 
2055  ValidatePointer(m_InputToCellWeights, "Null pointer check", "InputToCellWeights");
2057  (n_cell * n_input), "InputToCellWeights");
2058 
2060  {
2062  (n_cell * n_output), "RecurrentToInputWeights");
2063  }
2064 
2065  ValidatePointer(m_RecurrentToForgetWeights, "Null pointer check", "RecurrentToForgetWeights");
2067  (n_cell * n_output), "RecurrentToForgetWeights");
2068 
2069  ValidatePointer(m_RecurrentToCellWeights, "Null pointer check", "RecurrentToCellWeights");
2071  (n_cell * n_output), "RecurrentToCellWeights");
2072 
2073  // Make sure the input-gate's parameters are either both present (regular
2074  // LSTM) or not at all (CIFG-LSTM). And CifgEnable is set accordingly.
2075  bool cifg_weights_all_or_none = ((m_InputToInputWeights && m_RecurrentToInputWeights &&
2079  if (!cifg_weights_all_or_none)
2080  {
2081  throw InvalidArgumentException(descriptorName + ": Input-Gate's parameters InputToInputWeights and "
2082  "RecurrentToInputWeights must either both be present (regular LSTM) "
2083  "or both not present (CIFG-LSTM). In addition CifgEnable must be set "
2084  "accordingly.");
2085  }
2086 
2087  if ( m_CellToInputWeights )
2088  {
2090  n_cell, "CellToInputWeights");
2091  }
2092  if ( m_CellToForgetWeights )
2093  {
2095  n_cell, "CellToForgetWeights");
2096  }
2097  if ( m_CellToOutputWeights )
2098  {
2100  n_cell, "CellToOutputWeights");
2101  }
2102 
2103  // Making sure the peephole weights are there all or none. And PeepholeEnable is set accordingly.
2104  bool peephole_weights_all_or_none =
2109  if (!peephole_weights_all_or_none)
2110  {
2111  throw InvalidArgumentException(descriptorName + ": Invalid combination of peephole parameters.");
2112  }
2113 
2114  // Make sure the input gate bias is present only when not a CIFG-LSTM.
2116  {
2117  if (m_InputGateBias)
2118  {
2119  throw InvalidArgumentException(descriptorName + ": InputGateBias is present and CIFG-LSTM is enabled.");
2120  }
2121  }
2122  else
2123  {
2124  if (!m_InputGateBias)
2125  {
2126  throw InvalidArgumentException(descriptorName + ": If CIFG-LSTM is disabled InputGateBias "
2127  "must be present.");
2128  }
2130  n_cell, "InputGateBias");
2131  }
2132 
2133  ValidatePointer(m_ForgetGateBias, "Null pointer check", "ForgetGateBias");
2134  ValidateTensorNumDimNumElem(m_ForgetGateBias->GetTensorInfo(), 1, n_cell, "ForgetGateBias");
2135 
2136  ValidatePointer(m_CellBias, "Null pointer check", "CellBias");
2137  ValidateTensorNumDimNumElem(m_CellBias->GetTensorInfo(), 1, n_cell, "CellBias");
2138 
2139  ValidatePointer(m_OutputGateBias, "Null pointer check", "OutputGateBias");
2140  ValidateTensorNumDimNumElem(m_OutputGateBias->GetTensorInfo(), 1, n_cell, "OutputGateBias");
2141 
2142  if (m_ProjectionWeights)
2143  {
2145  (n_cell * n_output), "ProjectionWeights");
2146  }
2147  if (m_ProjectionBias)
2148  {
2149  ValidateTensorNumDimNumElem(m_ProjectionBias->GetTensorInfo(), 1, n_output, "ProjectionBias");
2150  }
2151 
2152  // Making sure the projection tensors are consistent:
2153  // 1) If projection weight is not present, then projection bias should not be
2154  // present.
2155  // 2) If projection weight is present, then projection bias is optional.
2156  bool projecton_tensors_consistent = ((!m_ProjectionWeights && !m_ProjectionBias &&
2162  if (!projecton_tensors_consistent)
2163  {
2164  throw InvalidArgumentException(descriptorName + ": Projection tensors are inconsistent.");
2165  }
2166 
2167  // The four layer normalization weights either all have values or none of them have values. Additionally, if
2168  // CIFG is used, input layer normalization weights tensor is omitted and the other layer normalization weights
2169  // either all have values or none of them have values. Layer normalization is used when the values of all the
2170  // layer normalization weights are present
2172  {
2173  ValidateTensorNumDimNumElem(m_InputLayerNormWeights->GetTensorInfo(), 1, n_cell, "InputLayerNormWeights");
2174  }
2176  {
2177  ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
2178  }
2180  {
2181  ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
2182  }
2184  {
2185  ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
2186  }
2187 
2189  {
2191  {
2193  {
2194  throw InvalidArgumentException(descriptorName + ": Layer normalisation is enabled and CIFG-LSTM is "
2195  "disabled but InputLayerNormWeights are not present");
2196  }
2198  1, n_cell, "InputLayerNormWeights");
2199  }
2200  else if (m_InputLayerNormWeights)
2201  {
2202  throw InvalidArgumentException(descriptorName + ":InputLayerNormWeights are present while CIFG is "
2203  "enabled");
2204  }
2205 
2206  ValidatePointer(m_ForgetLayerNormWeights, "Null pointer check layer normalisation enabled",
2207  "ForgetLayerNormWeights");
2208  ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
2209 
2210  ValidatePointer(m_OutputLayerNormWeights, "Null pointer check layer normalisation enabled",
2211  "OutputLayerNormWeights");
2212  ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
2213 
2214  ValidatePointer(m_CellLayerNormWeights, "Null pointer check layer normalisation enabled",
2215  "CellLayerNormWeights");
2216  ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
2217  }
2219  {
2220  throw InvalidArgumentException(descriptorName + ": Layer normalisation is disabled but one or more layer "
2221  "normalisation weights are present.");
2222  }
2223 }
2224 
2226 {
2227  const std::string descriptorName{"ConvertFp32ToFp16QueueDescriptor"};
2228 
2229  ValidateNumInputs(workloadInfo, descriptorName, 1);
2230  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2231 
2232  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2233  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2234 
2235  if (inputTensorInfo.GetDataType() != DataType::Float32)
2236  {
2237  throw InvalidArgumentException(descriptorName + ": Input tensor type must be Float32.");
2238  }
2239 
2240  if (outputTensorInfo.GetDataType() != DataType::Float16)
2241  {
2242  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Float16.");
2243  }
2244 
2245  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2246 }
2247 
2249 {
2250  const std::string descriptorName{"ConvertFp16ToFp32QueueDescriptor"};
2251 
2252  ValidateNumInputs(workloadInfo, descriptorName, 1);
2253  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2254 
2255  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2256  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2257 
2258  if (inputTensorInfo.GetDataType() != DataType::Float16)
2259  {
2260  throw InvalidArgumentException(descriptorName + ": Input tensor type must be Float16.");
2261  }
2262 
2263  if (outputTensorInfo.GetDataType() != DataType::Float32)
2264  {
2265  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Float32.");
2266  }
2267 
2268  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2269 }
2270 
2271 void DivisionQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2272 {
2273  const std::string descriptorName{"DivisionQueueDescriptor"};
2274 
2275  ValidateNumInputs(workloadInfo, descriptorName, 2);
2276  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2277 
2278  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2279  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2280  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2281 
2282  std::vector<DataType> supportedTypes =
2283  {
2291  };
2292 
2293  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2294  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2295  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
2296 
2297  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2298  inputTensorInfo1,
2299  outputTensorInfo,
2300  descriptorName,
2301  "input_0",
2302  "input_1");
2303 }
2304 
2306 {
2307  const std::string descriptorName{"SubtractionQueueDescriptor"};
2308 
2309  ValidateNumInputs(workloadInfo, descriptorName, 2);
2310  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2311 
2312  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2313  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2314  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2315 
2316  std::vector<DataType> supportedTypes =
2317  {
2325  };
2326 
2327  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2328  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2329  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
2330 
2331  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2332  inputTensorInfo1,
2333  outputTensorInfo,
2334  descriptorName,
2335  "input_0",
2336  "input_1");
2337 }
2338 
2339 void MaximumQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2340 {
2341  const std::string descriptorName{"MaximumQueueDescriptor"};
2342 
2343  ValidateNumInputs(workloadInfo, descriptorName, 2);
2344  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2345 
2346  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2347  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2348  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2349 
2350  std::vector<DataType> supportedTypes =
2351  {
2359  };
2360 
2361  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2362  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2363  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
2364 
2365  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2366  inputTensorInfo1,
2367  outputTensorInfo,
2368  descriptorName,
2369  "input_0",
2370  "input_1");
2371 }
2372 
2373 void MeanQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2374 {
2375  const std::string descriptorName{"MeanQueueDescriptor"};
2376 
2377  ValidateNumInputs(workloadInfo, descriptorName, 1);
2378  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2379 
2380  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2381  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2382 
2383  std::vector<DataType> supportedTypes =
2384  {
2391  };
2392 
2393  // First check if input tensor data type is supported, then
2394  // check if this data type matches the output tensor data type
2395  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2396  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2397 
2399  {
2400  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, inputTensorInfo.GetNumDimensions(), "output");
2401  }
2402  else if (m_Parameters.m_Axis.empty())
2403  {
2404  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 1, "output");
2405  }
2406  else
2407  {
2408  unsigned int outputDim =
2409  inputTensorInfo.GetNumDimensions() - armnn::numeric_cast<unsigned int>(m_Parameters.m_Axis.size());
2410  ValidateTensorNumDimensions(outputTensorInfo,
2411  descriptorName,
2412  outputDim > 0 ? outputDim : 1,
2413  "output");
2414  }
2415 }
2416 
2417 void PadQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2418 {
2419  const std::string descriptorName{"PadQueueDescriptor"};
2420 
2421  ValidateNumInputs(workloadInfo, descriptorName, 1);
2422  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2423 
2424  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2425  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2426 
2427  // input and output should have the same number of dimensions
2428  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, inputTensorInfo.GetNumDimensions(), "output");
2429 
2430  // there should be entry in the pad list for each dimension in the input tensor
2431  if (m_Parameters.m_PadList.size() != inputTensorInfo.GetNumDimensions()) {
2432  throw InvalidArgumentException(descriptorName + ":Pad List should contain the same number of entries "
2433  "as there are dimensions in the input tensor that is " +
2434  std::to_string(inputTensorInfo.GetNumDimensions()) + " entries " +
2435  " not " + std::to_string(m_Parameters.m_PadList.size()) + " entries.");
2436  }
2437 }
2438 
2439 void QuantizeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2440 {
2441  const std::string descriptorName{"QuantizeQueueDescriptor"};
2442 
2443  ValidateNumInputs(workloadInfo, descriptorName, 1);
2444  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2445 
2446  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2447  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2448 
2449  std::vector<DataType> supportedTypes =
2450  {
2458  };
2459 
2460  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2461 
2462  if (!IsQuantizedType(outputTensorInfo.GetDataType()))
2463  {
2464  throw InvalidArgumentException(descriptorName + ": Output of quantized layer must be quantized type.");
2465  }
2466 }
2467 
2469 {
2470  const std::string descriptorName{"BatchToSpaceNdQueueDescriptor"};
2471 
2472  ValidateNumInputs(workloadInfo, descriptorName, 1);
2473  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2474 
2475  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2476  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2477 
2478  std::vector<DataType> supportedTypes =
2479  {
2486  };
2487 
2488  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2489  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2490 }
2491 
2493 {
2494  const std::string descriptorName{"StridedSliceQueueDescriptor"};
2495 
2496  ValidateNumInputs(workloadInfo, descriptorName, 1);
2497  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2498 
2499  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2500  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2501 
2502  std::vector<DataType> supportedTypes =
2503  {
2510  };
2511 
2512  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2513  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2514 
2515  ValidateTensorQuantizationSpace(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2516 
2517  const uint32_t rank = inputTensorInfo.GetNumDimensions();
2518  if (rank > 4)
2519  {
2520  throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
2521  }
2522 
2523  // Begin, End & Stride length must be of rank(input0)
2524  if (m_Parameters.m_Begin.size() != rank)
2525  {
2526  throw InvalidArgumentException(descriptorName + ": Begin length must be of rank " + std::to_string(rank));
2527  }
2528 
2529  if (m_Parameters.m_End.size() != rank)
2530  {
2531  throw InvalidArgumentException(descriptorName + ": End length must be of rank " + std::to_string(rank));
2532  }
2533 
2534  if (m_Parameters.m_Stride.size() != rank)
2535  {
2536  throw InvalidArgumentException(descriptorName + ": Stride length must be of rank " + std::to_string(rank));
2537  }
2538 
2539  // Stride entries must be non-zero
2540  for (auto& stride : m_Parameters.m_Stride)
2541  {
2542  if (stride == 0)
2543  {
2544  throw InvalidArgumentException(descriptorName + ": Stride entries must be non-zero.");
2545  }
2546  }
2547 }
2548 
2549 void MinimumQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2550 {
2551  const std::string descriptorName{"MinimumQueueDescriptor"};
2552 
2553  ValidateNumInputs(workloadInfo, descriptorName, 2);
2554  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2555 
2556  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2557  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2558  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2559 
2560  std::vector<DataType> supportedTypes =
2561  {
2569  };
2570 
2571  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2572  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2573  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
2574 
2575  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2576  inputTensorInfo1,
2577  outputTensorInfo,
2578  descriptorName,
2579  "input_0",
2580  "input_1");
2581 }
2582 
2583 void DebugQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2584 {
2585  const std::string descriptorName{"DebugQueueDescriptor"};
2586 
2587  ValidateNumInputs(workloadInfo, descriptorName, 1);
2588  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2589 }
2590 
2591 void EqualQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2592 {
2593  const std::string descriptorName{"EqualQueueDescriptor"};
2594 
2595  ValidateNumInputs(workloadInfo, descriptorName, 2);
2596  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2597 
2598  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2599  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2600  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2601 
2602  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2603  inputTensorInfo1,
2604  outputTensorInfo,
2605  descriptorName,
2606  "input_0",
2607  "input_1");
2608 
2609  if (outputTensorInfo.GetDataType() != DataType::Boolean)
2610  {
2611  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
2612  }
2613 }
2614 
2615 void GreaterQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2616 {
2617  const std::string descriptorName{"GreaterQueueDescriptor"};
2618 
2619  ValidateNumInputs(workloadInfo, descriptorName, 2);
2620  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2621 
2622  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2623  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2624  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2625 
2626  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2627  inputTensorInfo1,
2628  outputTensorInfo,
2629  descriptorName,
2630  "input_0",
2631  "input_1");
2632 
2633  if (outputTensorInfo.GetDataType() != DataType::Boolean)
2634  {
2635  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
2636  }
2637 }
2638 
2639 void RsqrtQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2640 {
2641  const std::string descriptorName{"RsqrtQueueDescriptor"};
2642 
2643  ValidateNumInputs(workloadInfo, descriptorName, 1);
2644  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2645 
2646  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2647  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2648 
2649  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2650 
2651  std::vector<DataType> supportedTypes =
2652  {
2659  };
2660 
2661  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2662  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2663 }
2664 
2665 void GatherNdQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2666 {
2667  const std::string descriptorName{"GatherNdQueueDescriptor"};
2668 
2669  ValidateNumInputs(workloadInfo, descriptorName, 2);
2670  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2671 
2672  const TensorInfo& indicesTensorInfo = workloadInfo.m_InputTensorInfos[1];
2673  if (indicesTensorInfo.GetDataType() != DataType::Signed32)
2674  {
2675  throw InvalidArgumentException(descriptorName + ": Indices tensor type must be Int32.");
2676  }
2677 
2678  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2679  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2680 
2681  std::vector<DataType> supportedTypes =
2682  {
2690  };
2691 
2692  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2693 
2694  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2695 
2696  unsigned int outputDim = outputTensorInfo.GetNumDimensions();
2697  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, outputDim, "output");
2698 }
2699 
2700 void GatherQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2701 {
2702  const std::string descriptorName{"GatherQueueDescriptor"};
2703 
2704  ValidateNumInputs(workloadInfo, descriptorName, 2);
2705  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2706 
2707  const TensorInfo& indicesTensorInfo = workloadInfo.m_InputTensorInfos[1];
2708  if (indicesTensorInfo.GetDataType() != DataType::Signed32)
2709  {
2710  throw InvalidArgumentException(descriptorName + ": Indices tensor type must be Int32.");
2711  }
2712 
2713  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2714  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2715 
2716  std::vector<DataType> supportedTypes =
2717  {
2725  };
2726 
2727  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2728 
2729  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2730 
2731  unsigned int outputDim = inputTensorInfo.GetNumDimensions() + indicesTensorInfo.GetNumDimensions() - 1;
2732  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, outputDim, "output");
2733 }
2734 
2736 {
2737  const std::string& descriptorName{"DetectionPostProcessQueueDescriptor"};
2738 
2739  ValidateNumInputs(workloadInfo, descriptorName, 2);
2740 
2741  if (workloadInfo.m_OutputTensorInfos.size() != 4)
2742  {
2743  throw InvalidArgumentException(descriptorName + ": Requires exactly four outputs. " +
2744  to_string(workloadInfo.m_OutputTensorInfos.size()) + " has been provided.");
2745  }
2746 
2747  if (m_Anchors == nullptr)
2748  {
2749  throw InvalidArgumentException(descriptorName + ": Anchors tensor descriptor is missing.");
2750  }
2751 
2752  const TensorInfo& boxEncodingsInfo = workloadInfo.m_InputTensorInfos[0];
2753  const TensorInfo& scoresInfo = workloadInfo.m_InputTensorInfos[1];
2754  const TensorInfo& anchorsInfo = m_Anchors->GetTensorInfo();
2755 
2756  const TensorInfo& detectionBoxesInfo = workloadInfo.m_OutputTensorInfos[0];
2757  const TensorInfo& detectionClassesInfo = workloadInfo.m_OutputTensorInfos[1];
2758  const TensorInfo& detectionScoresInfo = workloadInfo.m_OutputTensorInfos[2];
2759  const TensorInfo& numDetectionsInfo = workloadInfo.m_OutputTensorInfos[3];
2760 
2761  ValidateTensorNumDimensions(boxEncodingsInfo, descriptorName, 3, "box encodings");
2762  ValidateTensorNumDimensions(scoresInfo, descriptorName, 3, "scores");
2763  ValidateTensorNumDimensions(anchorsInfo, descriptorName, 2, "anchors");
2764 
2765  const std::vector<DataType> supportedInputTypes =
2766  {
2773  };
2774 
2775  ValidateDataTypes(boxEncodingsInfo, supportedInputTypes, descriptorName);
2776  ValidateDataTypes(scoresInfo, supportedInputTypes, descriptorName);
2777  ValidateDataTypes(anchorsInfo, supportedInputTypes, descriptorName);
2778 
2779  ValidateTensorNumDimensions(detectionBoxesInfo, descriptorName, 3, "detection boxes");
2780  ValidateTensorNumDimensions(detectionScoresInfo, descriptorName, 2, "detection scores");
2781  ValidateTensorNumDimensions(detectionClassesInfo, descriptorName, 2, "detection classes");
2782  ValidateTensorNumDimensions(numDetectionsInfo, descriptorName, 1, "num detections");
2783 
2784  // NOTE: Output is always Float32 regardless of input type
2785  ValidateTensorDataType(detectionBoxesInfo, DataType::Float32, descriptorName, "detection boxes");
2786  ValidateTensorDataType(detectionScoresInfo, DataType::Float32, descriptorName, "detection scores");
2787  ValidateTensorDataType(detectionClassesInfo, DataType::Float32, descriptorName, "detection classes");
2788  ValidateTensorDataType(numDetectionsInfo, DataType::Float32, descriptorName, "num detections");
2789 
2791  {
2792  throw InvalidArgumentException(descriptorName + ": Intersection over union threshold "
2793  "must be positive and less than or equal to 1.");
2794  }
2795 
2796  if (scoresInfo.GetShape()[2] != m_Parameters.m_NumClasses + 1)
2797  {
2798  throw InvalidArgumentException(descriptorName + ": Number of classes with background "
2799  "should be equal to number of classes + 1.");
2800  }
2801 }
2802 
2803 void DequantizeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2804 {
2805  const std::string& descriptorName{"DequantizeQueueDescriptor"};
2806 
2807  ValidateNumInputs(workloadInfo, descriptorName, 1);
2808  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2809 
2810  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2811  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2812 
2813  std::vector<DataType> inputSupportedTypes =
2814  {
2820  };
2821  ValidateDataTypes(inputTensorInfo, inputSupportedTypes, descriptorName);
2822 
2823  std::vector<DataType> outputSupportedTypes =
2824  {
2828  };
2829 
2830  ValidateDataTypes(outputTensorInfo, outputSupportedTypes, descriptorName);
2831 }
2832 
2833 void MergeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2834 {
2835  const std::string& descriptorName{"MergeQueueDescriptor"};
2836 
2837  ValidateNumInputs(workloadInfo, descriptorName, 2);
2838  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2839 
2840  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2841  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2842  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2843 
2844  ValidateTensorShapesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
2845  ValidateTensorShapesMatch(inputTensorInfo0, outputTensorInfo, descriptorName, "input_0", "output");
2846 
2847  ValidateTensorDataTypesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
2848  ValidateTensorDataTypesMatch(inputTensorInfo0, outputTensorInfo, descriptorName, "input_0", "output");
2849 }
2850 
2851 void ShapeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2852 {
2853  const std::string& descriptorName{"ShapeQueueDescriptor"};
2854 
2855  ValidateNumInputs(workloadInfo, descriptorName, 1);
2856  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2857 
2858  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2859  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2860 
2861  std::vector<DataType> supportedTypes =
2862  {
2872  };
2873 
2874  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2875  ValidateDataTypes(outputTensorInfo, {DataType::Signed32}, descriptorName);
2876 }
2877 
2878 void SwitchQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2879 {
2880  const std::string& descriptorName{"SwitchQueueDescriptor"};
2881 
2882  ValidateNumInputs(workloadInfo, descriptorName, 2);
2883  ValidateNumOutputs(workloadInfo, descriptorName, 2);
2884 
2885  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2886  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2887 
2888  const TensorInfo& outputTensorInfo0 = workloadInfo.m_OutputTensorInfos[0];
2889  const TensorInfo& outputTensorInfo1 = workloadInfo.m_OutputTensorInfos[1];
2890 
2891  std::vector<DataType> supportedTypes =
2892  {
2898  };
2899 
2900  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2901  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2902 
2903  ValidateDataTypes(outputTensorInfo0, supportedTypes, descriptorName);
2904  ValidateDataTypes(outputTensorInfo1, supportedTypes, descriptorName);
2905 
2906  ValidateTensorShapesMatch(inputTensorInfo0,
2907  outputTensorInfo0,
2908  descriptorName,
2909  "input_0",
2910  "output_0");
2911 
2912  ValidateTensorShapesMatch(inputTensorInfo0,
2913  outputTensorInfo1,
2914  descriptorName,
2915  "input_0",
2916  "output_1");
2917 }
2918 
2919 void PreCompiledQueueDescriptor::Validate(const WorkloadInfo& /*workloadInfo*/) const
2920 {
2921  // This is internally generated so it should not need validation.
2922 }
2923 
2924 void PreluQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2925 {
2926  const std::string& descriptorName{"PreluQueueDescriptor"};
2927 
2928  ValidateNumInputs(workloadInfo, descriptorName, 2);
2929  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2930 
2931  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2932  const TensorInfo& alphaTensorInfo = workloadInfo.m_InputTensorInfos[1];
2933  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2934 
2935  std::vector<DataType> supportedTypes
2936  {
2943  };
2944 
2945  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2946  ValidateDataTypes(alphaTensorInfo, supportedTypes, descriptorName);
2947 
2948  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
2949 
2950  ValidateTensorDataTypesMatch(inputTensorInfo, alphaTensorInfo, descriptorName, "input", "alpha");
2951  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "ouptut");
2952 
2953  ValidateBroadcastTensorShapesMatch(inputTensorInfo,
2954  alphaTensorInfo,
2955  outputTensorInfo,
2956  descriptorName,
2957  "input",
2958  "alpha");
2959 }
2960 
2962 {
2963  const std::string descriptorName{"TransposeConvolution2dQueueDescriptor"};
2964 
2965  ValidateNumInputs(workloadInfo, descriptorName, 1);
2966  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2967 
2968  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2969  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2970 
2971  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
2972  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
2973 
2974  ValidatePointer(m_Weight, descriptorName, "weight");
2975 
2976  const TensorInfo& weightTensorInfo = m_Weight->GetTensorInfo();
2977  ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 4, "weight");
2978 
2979  ValidateWeightDataType(inputTensorInfo, weightTensorInfo, descriptorName);
2980 
2981  Optional<TensorInfo> optionalBiasTensorInfo;
2983  {
2984  ValidatePointer(m_Bias, descriptorName, "bias");
2985 
2986  optionalBiasTensorInfo = MakeOptional<TensorInfo>(m_Bias->GetTensorInfo());
2987  const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value();
2988 
2989  ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
2990  ValidateBiasTensorQuantization(biasTensorInfo, inputTensorInfo, weightTensorInfo, descriptorName);
2991  }
2992 
2993  ValidatePerAxisQuantization(inputTensorInfo,
2994  outputTensorInfo,
2995  weightTensorInfo,
2996  optionalBiasTensorInfo,
2997  descriptorName);
2998 
2999  std::vector<DataType> supportedTypes =
3000  {
3007  };
3008 
3009  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3010  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3011 }
3012 
3013 void TransposeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3014 {
3015  const std::string descriptorName{"TransposeQueueDescriptor"};
3016 
3017  ValidateNumInputs(workloadInfo, descriptorName, 1);
3018  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3019 
3020  const PermutationVector& mapping = m_Parameters.m_DimMappings;
3021 
3022  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3023  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3024 
3025  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, mapping.GetSize(), "input");
3026  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, mapping.GetSize(), "output");
3027 
3028  for (unsigned int i = 0u; i < mapping.GetSize(); ++i)
3029  {
3030  if (inputTensorInfo.GetShape()[mapping[i]] != outputTensorInfo.GetShape()[i])
3031  {
3032  throw InvalidArgumentException(descriptorName + ": src dimension " + to_string(mapping[i]) +
3033  " (=" + to_string(inputTensorInfo.GetShape()[mapping[i]]) + ") " +
3034  "must match dst dimension " + to_string(i) +
3035  " (=" + to_string(outputTensorInfo.GetShape()[i]) + ")");
3036  }
3037  }
3038 
3039  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3040 }
3041 
3043 {
3044  const std::string descriptorName{"TransposeQueueDescriptor"};
3045 
3046  ValidateNumInputs(workloadInfo, descriptorName, 1);
3047  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3048 
3049  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3050  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3051 
3052  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3053 }
3054 
3055 void QLstmQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3056 {
3057  const std::string descriptorName{"QLstmQueueDescriptor"};
3058 
3059  // Validate number of inputs/outputs
3060  ValidateNumInputs(workloadInfo, descriptorName, 3);
3061  ValidateNumOutputs(workloadInfo, descriptorName, 3);
3062 
3063  // Input/output tensor info
3064  auto inputInfo = workloadInfo.m_InputTensorInfos[0];
3065  auto outputStateInInfo = workloadInfo.m_InputTensorInfos[1];
3066  auto cellStateInInfo = workloadInfo.m_InputTensorInfos[2];
3067 
3068  auto outputStateOutInfo = workloadInfo.m_OutputTensorInfos[0];
3069  auto cellStateOutInfo = workloadInfo.m_OutputTensorInfos[1];
3070  auto outputInfo = workloadInfo.m_OutputTensorInfos[2];
3071 
3072  // Supported types for various tensors in QLSTM
3073  std::vector<DataType> inputOutputSupportedTypes =
3074  {
3076  };
3077 
3078  std::vector<DataType> cellStateSupportedTypes =
3079  {
3081  };
3082 
3083  std::vector<DataType> weightsSupportedTypes =
3084  {
3086  };
3087 
3088  std::vector<DataType> layerNormPeepholeWeightsSupportedTypes =
3089  {
3091  };
3092 
3093  std::vector<DataType> biasSupportedTypes =
3094  {
3096  };
3097 
3098  // Validate types of input/output tensors
3099  ValidateDataTypes(inputInfo, inputOutputSupportedTypes, descriptorName);
3100  ValidateDataTypes(outputStateInInfo, inputOutputSupportedTypes, descriptorName);
3101  ValidateDataTypes(cellStateInInfo, cellStateSupportedTypes, descriptorName);
3102 
3103  ValidateDataTypes(outputStateOutInfo, inputOutputSupportedTypes, descriptorName);
3104  ValidateDataTypes(cellStateOutInfo, cellStateSupportedTypes, descriptorName);
3105  ValidateDataTypes(outputInfo, inputOutputSupportedTypes, descriptorName);
3106 
3107  // Validate matching types of input/output tensors
3108  ValidateTensorDataTypesMatch(inputInfo, outputStateInInfo, descriptorName, "input", "outputStateIn");
3109  ValidateTensorDataTypesMatch(outputStateInInfo, outputStateOutInfo, descriptorName,
3110  "outputStateIn", "outputStateOut");
3111  ValidateTensorDataTypesMatch(cellStateInInfo, cellStateOutInfo, descriptorName, "cellStateIn", "cellStateOut");
3112 
3113  // Infer number of batches, number of units, input size and output size from tensor dimensions
3114  const uint32_t numBatches = inputInfo.GetShape()[0];
3115  const uint32_t inputSize = inputInfo.GetShape()[1];
3116  const uint32_t outputSize = outputStateInInfo.GetShape()[1];
3117  const uint32_t numUnits = cellStateInInfo.GetShape()[1];
3118 
3119  // Validate number of dimensions and number of elements for input/output tensors
3120  ValidateTensorNumDimNumElem(inputInfo, 2, (numBatches * inputSize), descriptorName + " input");
3121  ValidateTensorNumDimNumElem(outputStateInInfo, 2, (numBatches * outputSize), descriptorName + " outputStateIn");
3122  ValidateTensorNumDimNumElem(cellStateInInfo, 2, (numBatches * numUnits), descriptorName + " cellStateIn");
3123 
3124  ValidateTensorNumDimNumElem(outputStateOutInfo, 2, (numBatches * outputSize), descriptorName + " outputStateOut");
3125  ValidateTensorNumDimNumElem(cellStateOutInfo, 2, (numBatches * numUnits), descriptorName + " cellStateOut");
3126  ValidateTensorNumDimNumElem(outputInfo, 2, (numBatches * outputSize), descriptorName + " output");
3127 
3128  // Validate number of dimensions and number of elements for MANDATORY weight tensors
3129  ValidatePointer(m_InputToForgetWeights, descriptorName, "InputToForgetWeights");
3130  auto inputToForgetWeightsInfo = m_InputToForgetWeights->GetTensorInfo();
3131  ValidateTensorNumDimNumElem(inputToForgetWeightsInfo, 2, (numUnits * inputSize), " InputToForgetWeights");
3132 
3133  ValidatePointer(m_InputToCellWeights, descriptorName, "InputToCellWeights");
3134  auto inputToCellWeightsInfo = m_InputToCellWeights->GetTensorInfo();
3135  ValidateTensorNumDimNumElem(inputToCellWeightsInfo, 2, (numUnits * inputSize), " InputToCellWeights");
3136 
3137  ValidatePointer(m_InputToOutputWeights, descriptorName, "InputToOutputWeights");
3138  auto inputToOutputWeightsInfo = m_InputToOutputWeights->GetTensorInfo();
3139  ValidateTensorNumDimNumElem(inputToOutputWeightsInfo, 2, (numUnits * inputSize), " InputToOutputWeights");
3140 
3141  ValidatePointer(m_RecurrentToForgetWeights, descriptorName, "RecurrentToForgetWeights");
3142  auto recurrentToForgetWeightsInfo = m_RecurrentToForgetWeights->GetTensorInfo();
3143  ValidateTensorNumDimNumElem(recurrentToForgetWeightsInfo, 2, (numUnits * outputSize),
3144  " RecurrentToForgetWeights");
3145 
3146  ValidatePointer(m_RecurrentToCellWeights, descriptorName, "RecurrentToCellWeights");
3147  auto recurrentToCellWeightsInfo = m_RecurrentToCellWeights->GetTensorInfo();
3148  ValidateTensorNumDimNumElem(recurrentToCellWeightsInfo, 2, (numUnits * outputSize), " RecurrentToCellWeights");
3149 
3150  ValidatePointer(m_RecurrentToOutputWeights, descriptorName, "RecurrentToOutputWeights");
3151  auto recurrentToOutputWeightsInfo = m_RecurrentToOutputWeights->GetTensorInfo();
3152  ValidateTensorNumDimNumElem(recurrentToOutputWeightsInfo, 2, (numUnits * outputSize), " RecurrentToCellWeights");
3153 
3154  // Validate data types for MANDATORY weights tensors (all should match each other)
3155  ValidateDataTypes(inputToForgetWeightsInfo, weightsSupportedTypes, descriptorName);
3156 
3157  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, inputToCellWeightsInfo, descriptorName,
3158  "inputToForgetWeights", "inputToCellWeights");
3159  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, inputToOutputWeightsInfo, descriptorName,
3160  "inputToForgetWeights", "inputToOutputWeights");
3161 
3162  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, recurrentToForgetWeightsInfo, descriptorName,
3163  "inputToForgetWeights", "recurrentToForgeteights");
3164  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, recurrentToCellWeightsInfo, descriptorName,
3165  "inputToForgetWeights", "recurrentToCellWeights");
3166  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, recurrentToOutputWeightsInfo, descriptorName,
3167  "inputToForgetWeights", "recurrentToOutputWeights");
3168 
3169  // Validate number of dimensions and number of elements for MANDATORY bias tensors
3170  ValidatePointer(m_ForgetGateBias, descriptorName, "ForgetGateBias");
3171  auto forgetGateBiasInfo = m_ForgetGateBias->GetTensorInfo();
3172  ValidateTensorNumDimNumElem(forgetGateBiasInfo, 1, numUnits, " ForgetGateBias");
3173 
3174  ValidatePointer(m_CellBias, descriptorName, "CellBias");
3175  auto cellBiasInfo = m_CellBias->GetTensorInfo();
3176  ValidateTensorNumDimNumElem(cellBiasInfo, 1, numUnits, " CellBias");
3177 
3178  ValidatePointer(m_OutputGateBias, descriptorName, "OutputGateBias");
3179  auto outputGateBiasInfo = m_OutputGateBias->GetTensorInfo();
3180  ValidateTensorNumDimNumElem(outputGateBiasInfo, 1, numUnits, " OutputGateBias");
3181 
3182  // Validate data types for MANDATORY bias tensors
3183  ValidateDataTypes(forgetGateBiasInfo, biasSupportedTypes, descriptorName);
3184 
3185  ValidateTensorDataTypesMatch(forgetGateBiasInfo, cellBiasInfo, descriptorName,
3186  "forgetGateBias", "cellBias");
3187  ValidateTensorDataTypesMatch(forgetGateBiasInfo, outputGateBiasInfo, descriptorName,
3188  "forgetGateBias", "outputGateBias");
3189 
3190  // Validate OPTIONAL params: CIFG (inputToInputWeights, recurrentToInputWeights, inputGateBias)
3191  const bool allCifgParamsPresentOrNot = ((m_InputToInputWeights && m_RecurrentToInputWeights && m_InputGateBias &&
3195 
3196  if (!allCifgParamsPresentOrNot)
3197  {
3198  throw InvalidArgumentException(descriptorName +
3199  ": InputToInputWeights, RecurrentToInputWeights and InputGateBias must either all be present "
3200  "(CIFG disabled) or not be present at all (CIFG enabled). m_Parameters.m_CifgEnabled should be "
3201  "set appropriately.");
3202  }
3203 
3205  {
3206  // Validate number of dimensions and number of elements
3207  auto inputToInputWeightsInfo = m_InputToInputWeights->GetTensorInfo();
3208  ValidateTensorNumDimNumElem(inputToInputWeightsInfo, 2, (numUnits * inputSize), " InputToInputWeights");
3209 
3210  auto recurrentToInputWeightsInfo = m_RecurrentToInputWeights->GetTensorInfo();
3211  ValidateTensorNumDimNumElem(recurrentToInputWeightsInfo, 2, (numUnits * outputSize),
3212  " RecurrentToInputWeights");
3213 
3214  auto inputGateBiasInfo = m_InputGateBias->GetTensorInfo();
3215  ValidateTensorNumDimNumElem(inputGateBiasInfo, 1, numUnits, " InputGateBias");
3216 
3217  // Validate data types
3218  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, inputToInputWeightsInfo, descriptorName,
3219  "inputToForgetWeights", "inputToInputWeights");
3220  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, recurrentToInputWeightsInfo, descriptorName,
3221  "inputToForgetWeights", "recurrentToInputWeights");
3222  ValidateTensorDataTypesMatch(forgetGateBiasInfo, inputGateBiasInfo, descriptorName,
3223  "forgetGateBias", "inputGateBias");
3224  }
3225 
3226  // Validate OPTIONAL params: Peephole (cellToInputWeights, cellToForgetWeights, cellToOutputWeights)
3227  bool allPeepholeWeightsPresentOrNot =
3232 
3233  if (!allPeepholeWeightsPresentOrNot)
3234  {
3235  throw InvalidArgumentException(descriptorName +
3236  ": CellToInputWeights, CellToForgetWeights and CellToOutputWeights should all be present (Peephole "
3237  "enabled) or not be present at all (Peephole disabled). CellToInputWeights should only be present "
3238  "when Peephole is enabled and CIFG is disabled. m_Parameters.m_PeepholeEnabled should be set "
3239  "appropriately.");
3240  }
3241 
3243  {
3244  auto cellToForgetWeightsInfo = m_CellToForgetWeights->GetTensorInfo();
3245  ValidateTensorNumDimNumElem(cellToForgetWeightsInfo, 1, numUnits, " cellToForgetWeights");
3246  ValidateDataTypes(cellToForgetWeightsInfo, layerNormPeepholeWeightsSupportedTypes, descriptorName);
3247 
3248  auto cellToOutputWeightsInfo = m_CellToOutputWeights->GetTensorInfo();
3249  ValidateTensorNumDimNumElem(cellToOutputWeightsInfo, 1, numUnits, " cellToOutputWeights");
3250  ValidateTensorDataTypesMatch(cellToForgetWeightsInfo, cellToOutputWeightsInfo, descriptorName,
3251  "cellToForgetWeight", "cellToOutputWeights");
3252 
3254  {
3255  auto cellToInputWeightsInfo = m_CellToInputWeights->GetTensorInfo();
3256  ValidateTensorNumDimNumElem(cellToInputWeightsInfo, 1, numUnits, " cellToInputWeights");
3257  ValidateTensorDataTypesMatch(cellToForgetWeightsInfo, cellToInputWeightsInfo, descriptorName,
3258  "cellToForgetWeights", "cellToInputWeights");
3259  }
3260  }
3261 
3262  // Validate OPTIONAL params: Layer Norm Weights
3263  bool allLayerNormWeightsPresentOrNot =
3268 
3269  if (!allLayerNormWeightsPresentOrNot)
3270  {
3271  throw InvalidArgumentException(descriptorName +
3272  ": InputLayerNormWeights, ForgetLayerNormWeights, m_OutputLayerNormWeights "
3273  "and CellLayerNormWeights should all be present (Layer Norm enabled) or not "
3274  "be present at all (Layer Norm disabled). InputLayerNormWeights should "
3275  "only be present when Layer Norm is enabled and CIFG is disabled. "
3276  "m_Parameters.m_LayerNormEnabled should be set appropriately.");
3277  }
3278 
3280  {
3281  auto forgetLayerNormWeightsInfo = m_ForgetLayerNormWeights->GetTensorInfo();
3282  ValidateTensorNumDimNumElem(forgetLayerNormWeightsInfo, 1, numUnits, " forgetLayerNormWeights");
3283  ValidateDataTypes(forgetLayerNormWeightsInfo, layerNormPeepholeWeightsSupportedTypes, descriptorName);
3284 
3285  auto cellLayerNormWeightsInfo = m_CellLayerNormWeights->GetTensorInfo();
3286  ValidateTensorNumDimNumElem(cellLayerNormWeightsInfo, 1, numUnits, " cellLayerNormWeights");
3287  ValidateTensorDataTypesMatch(forgetLayerNormWeightsInfo, cellLayerNormWeightsInfo, descriptorName,
3288  "forgetLayerNormWeights", "cellLayerNormWeights");
3289 
3290  auto outputLayerNormWeightsInfo = m_OutputLayerNormWeights->GetTensorInfo();
3291  ValidateTensorNumDimNumElem(outputLayerNormWeightsInfo, 1, numUnits, " outputLayerNormWeights");
3292  ValidateTensorDataTypesMatch(forgetLayerNormWeightsInfo, outputLayerNormWeightsInfo, descriptorName,
3293  "forgetLayerNormWeights", "outputLayerNormWeights");
3294 
3296  {
3297  auto inputLayerNormWeightsInfo = m_InputLayerNormWeights->GetTensorInfo();
3298  ValidateTensorNumDimNumElem(inputLayerNormWeightsInfo, 1, numUnits, " inputLayerNormWeights");
3299  ValidateTensorDataTypesMatch(forgetLayerNormWeightsInfo, inputLayerNormWeightsInfo, descriptorName,
3300  "forgetLayerNormWeights", "inputLayerNormWeights");
3301  }
3302  }
3303 
3304  // Validate OPTIONAL params: Projection (projectionWeights, projectionBias)
3305  bool correctProjectionTensorsPresent =
3309 
3310  if (!correctProjectionTensorsPresent)
3311  {
3312  throw InvalidArgumentException(descriptorName +
3313  ": If projection is enabled, ProjectionWeights should be present and "
3314  "ProjectionBias is optional. If projection is disabled, neither "
3315  "ProjectionWeights nor ProjectionBias should be present.");
3316  }
3317 
3319  {
3320  auto projectionWeightsInfo = m_ProjectionWeights->GetTensorInfo();
3321  ValidateTensorNumDimNumElem(projectionWeightsInfo, 2, (numUnits * outputSize), "ProjectionWeights");
3322  ValidateDataTypes(projectionWeightsInfo, weightsSupportedTypes, descriptorName);
3323 
3324  if (m_ProjectionBias)
3325  {
3326  auto projectionBiasInfo = m_ProjectionBias->GetTensorInfo();
3327  ValidateTensorNumDimNumElem(projectionBiasInfo, 1, outputSize, "ProjectionBias");
3328  ValidateDataTypes(projectionBiasInfo, biasSupportedTypes, descriptorName);
3329  }
3330 
3331  }
3332  else if ((outputInfo.GetQuantizationScale() != m_Parameters.m_HiddenStateScale) &&
3334  throw InvalidArgumentException(descriptorName +
3335  ": If projection is disabled, output quantization info (scale, offset) "
3336  "should match HiddenStateScale and HiddenStateZeroPoint.");
3337  }
3338 
3339 }
3340 
3342 {
3343  const std::string descriptorName{"QuantizedLstmQueueDescriptor"};
3344 
3345  // Validate number of inputs/outputs
3346  ValidateNumInputs(workloadInfo, descriptorName, 3);
3347  ValidateNumOutputs(workloadInfo, descriptorName, 2);
3348 
3349  // Input/output tensor infos
3350  auto inputInfo = workloadInfo.m_InputTensorInfos[0];
3351  auto cellStateInInfo = workloadInfo.m_InputTensorInfos[1];
3352  auto outputStateInInfo = workloadInfo.m_InputTensorInfos[2];
3353 
3354  auto cellStateOutInfo = workloadInfo.m_OutputTensorInfos[0];
3355  auto outputStateOutInfo = workloadInfo.m_OutputTensorInfos[1];
3356 
3357  std::vector<DataType> inputOutputSupportedTypes =
3358  {
3360  };
3361 
3362  std::vector<DataType> cellStateSupportedTypes =
3363  {
3365  };
3366 
3367  std::vector<DataType> weightsSupportedTypes =
3368  {
3370  };
3371 
3372  std::vector<DataType> biasSupportedTypes =
3373  {
3375  };
3376 
3377  // Validate types of input/output tensors
3378  ValidateDataTypes(inputInfo, inputOutputSupportedTypes, descriptorName);
3379  ValidateDataTypes(cellStateInInfo, cellStateSupportedTypes, descriptorName);
3380  ValidateDataTypes(outputStateInInfo, inputOutputSupportedTypes, descriptorName);
3381 
3382  ValidateDataTypes(cellStateOutInfo, cellStateSupportedTypes, descriptorName);
3383  ValidateDataTypes(outputStateOutInfo, inputOutputSupportedTypes, descriptorName);
3384 
3385  // Validate matching types of input/output tensors
3386  ValidateTensorDataTypesMatch(inputInfo, outputStateInInfo, descriptorName, "input", "outputStateIn");
3387  ValidateTensorDataTypesMatch(outputStateInInfo, outputStateOutInfo, descriptorName,
3388  "outputStateIn", "outputStateOut");
3389  ValidateTensorDataTypesMatch(cellStateInInfo, cellStateOutInfo, descriptorName, "cellStateIn", "cellStateOut");
3390 
3391  // Validate matching quantization info for input/output tensors
3392  ValidateTensorQuantizationSpace(inputInfo, outputStateInInfo, descriptorName, "input", "outputStateIn");
3393  ValidateTensorQuantizationSpace(inputInfo, outputStateOutInfo, descriptorName, "input", "outputStateOut");
3394  ValidateTensorQuantizationSpace(cellStateInInfo, cellStateOutInfo, descriptorName, "cellStateIn", "cellStateOut");
3395 
3396  // Infer number of batches, input size and output size from tensor dimensions
3397  const uint32_t numBatches = inputInfo.GetShape()[0];
3398  const uint32_t inputSize = inputInfo.GetShape()[1];
3399  const uint32_t outputSize = cellStateInInfo.GetShape()[1];
3400 
3401  // Validate number of dimensions and number of elements for input/output tensors
3402  ValidateTensorNumDimNumElem(inputInfo, 2, (numBatches * inputSize), descriptorName + " input");
3403  ValidateTensorNumDimNumElem(cellStateInInfo, 2, (numBatches * outputSize), descriptorName + " cellStateIn");
3404  ValidateTensorNumDimNumElem(outputStateInInfo, 2, (numBatches * outputSize), descriptorName + " outputStateIn");
3405  ValidateTensorNumDimNumElem(cellStateOutInfo, 2, (numBatches * outputSize), descriptorName + " cellStateOut");
3406  ValidateTensorNumDimNumElem(outputStateOutInfo, 2, (numBatches * outputSize), descriptorName + " outputStateOut");
3407 
3408  // Validate number of dimensions and number of elements for weights tensors
3409  ValidatePointer(m_InputToInputWeights, descriptorName, "InputToInputWeights");
3410  auto inputToInputWeightsInfo = m_InputToInputWeights->GetTensorInfo();
3411  ValidateTensorNumDimNumElem(inputToInputWeightsInfo, 2, (outputSize * inputSize), " InputToInputWeights");
3412 
3413  ValidatePointer(m_InputToForgetWeights, descriptorName, "InputToForgetWeights");
3414  auto inputToForgetWeightsInfo = m_InputToForgetWeights->GetTensorInfo();
3415  ValidateTensorNumDimNumElem(inputToForgetWeightsInfo, 2, (outputSize * inputSize), " InputToForgetWeights");
3416 
3417  ValidatePointer(m_InputToCellWeights, descriptorName, "InputToCellWeights");
3418  auto inputToCellWeightsInfo = m_InputToCellWeights->GetTensorInfo();
3419  ValidateTensorNumDimNumElem(inputToCellWeightsInfo, 2, (outputSize * inputSize), " InputToCellWeights");
3420 
3421  ValidatePointer(m_InputToOutputWeights, descriptorName, "InputToOutputWeights");
3422  auto inputToOutputWeightsInfo = m_InputToOutputWeights->GetTensorInfo();
3423  ValidateTensorNumDimNumElem(inputToOutputWeightsInfo, 2, (outputSize * inputSize), " InputToOutputWeights");
3424 
3425  ValidatePointer(m_RecurrentToInputWeights, descriptorName, "RecurrentToInputWeights");
3426  auto recurrentToInputWeightsInfo = m_RecurrentToInputWeights->GetTensorInfo();
3427  ValidateTensorNumDimNumElem(recurrentToInputWeightsInfo, 2, (outputSize * outputSize), " RecurrentToInputWeights");
3428 
3429  ValidatePointer(m_RecurrentToForgetWeights, descriptorName, "RecurrentToForgetWeights");
3430  auto recurrentToForgetWeightsInfo = m_RecurrentToForgetWeights->GetTensorInfo();
3431  ValidateTensorNumDimNumElem(recurrentToForgetWeightsInfo, 2, (outputSize * outputSize),
3432  " RecurrentToForgetWeights");
3433 
3434  ValidatePointer(m_RecurrentToCellWeights, descriptorName, "RecurrentToCellWeights");
3435  auto recurrentToCellWeightsInfo = m_RecurrentToCellWeights->GetTensorInfo();
3436  ValidateTensorNumDimNumElem(recurrentToCellWeightsInfo, 2, (outputSize * outputSize), " RecurrentToCellWeights");
3437 
3438  ValidatePointer(m_RecurrentToOutputWeights, descriptorName, "RecurrentToOutputWeights");
3439  auto recurrentToOutputWeightsInfo = m_RecurrentToOutputWeights->GetTensorInfo();
3440  ValidateTensorNumDimNumElem(recurrentToOutputWeightsInfo, 2, (outputSize * outputSize), " RecurrentToCellWeights");
3441 
3442  // Validate data types for weights tensors (all should match each other)
3443  ValidateDataTypes(inputToInputWeightsInfo, weightsSupportedTypes, descriptorName);
3444 
3445  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, inputToForgetWeightsInfo, descriptorName,
3446  "inputToInputWeights", "inputToForgetWeights");
3447  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, inputToCellWeightsInfo, descriptorName,
3448  "inputToInputWeights", "inputToCellWeights");
3449  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, inputToOutputWeightsInfo, descriptorName,
3450  "inputToInputWeights", "inputToOutputWeights");
3451 
3452  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToInputWeightsInfo, descriptorName,
3453  "inputToInputWeights", "recurrentToInputWeights");
3454  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToForgetWeightsInfo, descriptorName,
3455  "inputToInputWeights", "recurrentToForgeteights");
3456  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToCellWeightsInfo, descriptorName,
3457  "inputToInputWeights", "recurrentToCellWeights");
3458  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToOutputWeightsInfo, descriptorName,
3459  "inputToInputWeights", "recurrentToOutputWeights");
3460 
3461  // Validate matching quantization info for weight tensors (all should match each other)
3462  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, inputToForgetWeightsInfo,
3463  descriptorName, "inputToInputWeights", "inputToForgetWeights");
3464  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, inputToCellWeightsInfo,
3465  descriptorName, "inputToInputWeights", "inputToCellWeights");
3466  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, inputToOutputWeightsInfo,
3467  descriptorName, "inputToInputWeights", "inputToOutputWeights");
3468 
3469  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToInputWeightsInfo,
3470  descriptorName, "inputToInputWeights", "recurrentToInputWeights");
3471  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToForgetWeightsInfo,
3472  descriptorName, "inputToInputWeights", "recurrentToForgetWeights");
3473  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToCellWeightsInfo,
3474  descriptorName, "inputToInputWeights", "recurrentToCellWeights");
3475  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToOutputWeightsInfo,
3476  descriptorName, "inputToInputWeights", "recurrentToOutputWeights");
3477 
3478  // Validate number of dimensions and number of elements in bias tensors
3479  ValidatePointer(m_InputGateBias, descriptorName, "InputGateBias");
3480  auto inputGateBiasInfo = m_InputGateBias->GetTensorInfo();
3481  ValidateTensorNumDimNumElem(inputGateBiasInfo, 1, outputSize, " InputGateBias");
3482 
3483  ValidatePointer(m_ForgetGateBias, descriptorName, "ForgetGateBias");
3484  auto forgetGateBiasInfo = m_ForgetGateBias->GetTensorInfo();
3485  ValidateTensorNumDimNumElem(forgetGateBiasInfo, 1, outputSize, " ForgetGateBias");
3486 
3487  ValidatePointer(m_CellBias, descriptorName, "CellBias");
3488  auto cellBiasInfo = m_CellBias->GetTensorInfo();
3489  ValidateTensorNumDimNumElem(cellBiasInfo, 1, outputSize, " CellBias");
3490 
3491  ValidatePointer(m_OutputGateBias, descriptorName, "OutputGateBias");
3492  auto outputGateBiasInfo = m_OutputGateBias->GetTensorInfo();
3493  ValidateTensorNumDimNumElem(outputGateBiasInfo, 1, outputSize, " OutputGateBias");
3494 
3495  // Validate data types for bias tensors (all should match each other)
3496  ValidateDataTypes(inputGateBiasInfo, biasSupportedTypes, descriptorName);
3497 
3498  ValidateTensorDataTypesMatch(inputGateBiasInfo, forgetGateBiasInfo, descriptorName,
3499  "inputGateBias", "forgetGateBias");
3500  ValidateTensorDataTypesMatch(inputGateBiasInfo, cellBiasInfo, descriptorName,
3501  "inputGateBias", "cellBias");
3502  ValidateTensorDataTypesMatch(inputGateBiasInfo, outputGateBiasInfo, descriptorName,
3503  "inputGateBias", "outputGateBias");
3504 
3505  // Validate bias tensor quantization info
3506  ValidateBiasTensorQuantization(inputGateBiasInfo, inputInfo, inputToInputWeightsInfo, descriptorName);
3507  ValidateBiasTensorQuantization(forgetGateBiasInfo, inputInfo, inputToInputWeightsInfo, descriptorName);
3508  ValidateBiasTensorQuantization(cellBiasInfo, inputInfo, inputToInputWeightsInfo, descriptorName);
3509  ValidateBiasTensorQuantization(outputGateBiasInfo, inputInfo, inputToInputWeightsInfo, descriptorName);
3510 }
3511 
3512 void AbsQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3513 {
3514  const std::string descriptorName{"AbsQueueDescriptor"};
3515 
3516  ValidateNumInputs(workloadInfo, descriptorName, 1);
3517  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3518 
3519  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3520  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3521 
3522  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3523 
3524  std::vector<DataType> supportedTypes =
3525  {
3533  };
3534 
3535  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3536  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3537 }
3538 
3539 void SliceQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3540 {
3541  const std::string descriptorName{"SliceQueueDescriptor"};
3542 
3543  ValidateNumInputs(workloadInfo, descriptorName, 1);
3544  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3545 
3546  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3547  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3548 
3549  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3550 
3551  const unsigned int rank = inputTensorInfo.GetNumDimensions();
3552  if (rank > 4)
3553  {
3554  throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
3555  }
3556 
3557  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, rank, "output");
3558 
3559  // Check if m_Begin and m_Size have the expected length
3560  if (m_Parameters.m_Begin.size() != rank)
3561  {
3562  throw InvalidArgumentException(descriptorName +
3563  ": Length of begin offset descriptor must equal rank " + std::to_string(rank));
3564  }
3565  if (m_Parameters.m_Size.size() != rank)
3566  {
3567  throw InvalidArgumentException(descriptorName +
3568  ": Length of size descriptor must equal rank " + std::to_string(rank));
3569  }
3570 
3571  // Check if the shape of the output tensor matches m_Size
3572  const TensorShape& outputShape = outputTensorInfo.GetShape();
3573  for (unsigned int i = 0u; i < rank; ++i)
3574  {
3575  if (m_Parameters.m_Size[i] != outputShape[i])
3576  {
3577  throw InvalidArgumentException(descriptorName + ": Size descriptor does not match output tensor.");
3578  }
3579  }
3580 
3581  // Check if the sum of begin offset and size in a given dimension
3582  // does not exceed the size of corresponding input
3583  const TensorShape& inputShape = inputTensorInfo.GetShape();
3584  for(unsigned int i = 0u; i < rank; ++i)
3585  {
3586  if (m_Parameters.m_Begin[i] + m_Parameters.m_Size[i] > inputShape[i])
3587  {
3588  throw InvalidArgumentException(descriptorName + ": Sum of begin offset and size for dimension " +
3589  std::to_string(i) + " exceeds input size.");
3590  }
3591  }
3592 }
3593 
3595 {
3596  const std::string descriptorName{"DepthToSpaceQueueDescriptor"};
3597 
3598  ValidateNumInputs(workloadInfo, descriptorName, 1);
3599  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3600 
3601  const TensorInfo& inputInfo = workloadInfo.m_InputTensorInfos[0];
3602  const TensorInfo& outputInfo = workloadInfo.m_OutputTensorInfos[0];
3603 
3604  ValidateTensorNumDimensions(inputInfo, descriptorName, 4, "input");
3605  ValidateTensorNumDimensions(outputInfo, descriptorName, 4, "output");
3606 
3607  std::vector<DataType> supportedTypes =
3608  {
3615  };
3616 
3617  ValidateDataTypes(inputInfo, supportedTypes, descriptorName);
3618  ValidateDataTypes(outputInfo, supportedTypes, descriptorName);
3619 
3620  ValidateTensorNumElementsMatch(inputInfo, outputInfo, descriptorName, "input", "output");
3621 
3622  if (m_Parameters.m_BlockSize == 0)
3623  {
3624  throw InvalidArgumentException(descriptorName + ": Block size cannot be 0.");
3625  }
3626 
3627  DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
3628  const unsigned int wIndex = dimensionIndices.GetWidthIndex();
3629  const unsigned int hIndex = dimensionIndices.GetHeightIndex();
3630  const unsigned int cIndex = dimensionIndices.GetChannelsIndex();
3631 
3632  const TensorShape& outputShape = outputInfo.GetShape();
3633  if (outputShape[hIndex] % m_Parameters.m_BlockSize != 0 || outputShape[wIndex] % m_Parameters.m_BlockSize != 0)
3634  {
3635  throw InvalidArgumentException(descriptorName + ": Output width and height shape"
3636  "must be divisible by block size.");
3637  }
3638 
3639  const TensorShape& inputShape = inputInfo.GetShape();
3640  if (inputShape[cIndex] % (m_Parameters.m_BlockSize * m_Parameters.m_BlockSize) != 0)
3641  {
3642  throw InvalidArgumentException(descriptorName + ": The depth of the input tensor"
3643  "must be divisible by the square of block size." );
3644  }
3645 }
3646 
3647 void ComparisonQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3648 {
3649  const std::string descriptorName{"ComparisonQueueDescriptor"};
3650 
3651  ValidateNumInputs(workloadInfo, descriptorName, 2);
3652  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3653 
3654  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
3655  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
3656  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3657 
3658  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
3659  inputTensorInfo1,
3660  outputTensorInfo,
3661  descriptorName,
3662  "input_0",
3663  "input_1");
3664 
3665  if (outputTensorInfo.GetDataType() != DataType::Boolean)
3666  {
3667  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
3668  }
3669 }
3670 
3672 {
3673  const std::string descriptorName{"ElementwiseUnaryQueueDescriptor"};
3674 
3675  ValidateNumInputs(workloadInfo, descriptorName, 1);
3676  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3677 
3678  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3679  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3680 
3681  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3682 
3683  std::vector<DataType> supportedTypes =
3684  {
3692  };
3693 
3694  std::vector<DataType> logicalSupportedTypes =
3695  {
3697  };
3698 
3700  {
3701  ValidateDataTypes(inputTensorInfo, logicalSupportedTypes, descriptorName);
3702  }
3703  else
3704  {
3705  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3706  }
3707 
3708 
3709  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3710 }
3711 
3712 void RankQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3713 {
3714  const std::string descriptorName{"RankQueueDescriptor"};
3715 
3716  ValidateNumInputs(workloadInfo, descriptorName, 1);
3717  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3718 
3719  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3720  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3721 
3722  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 1, "output");
3723  ValidateTensorNumElements(outputTensorInfo, descriptorName, 1, "output");
3724 
3725  std::vector<DataType> supportedTypes =
3726  {
3735  };
3736 
3737  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3738  ValidateDataTypes(outputTensorInfo, { DataType::Signed32 }, descriptorName);
3739 }
3740 
3742 {
3743  const std::string descriptorName{"LogicalBinaryQueueDescriptor"};
3744 
3745  ValidateNumInputs(workloadInfo, descriptorName, 2);
3746  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3747 
3748  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
3749  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
3750  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3751 
3752  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
3753  inputTensorInfo1,
3754  outputTensorInfo,
3755  descriptorName,
3756  "input_0",
3757  "input_1");
3758 
3759  if (inputTensorInfo0.GetDataType() != DataType::Boolean)
3760  {
3761  throw InvalidArgumentException(descriptorName + ": Input tensor 0 type must be Boolean.");
3762  }
3763 
3764  if (inputTensorInfo1.GetDataType() != DataType::Boolean)
3765  {
3766  throw InvalidArgumentException(descriptorName + ": Input tensor 1 type must be Boolean.");
3767  }
3768 
3769  if (outputTensorInfo.GetDataType() != DataType::Boolean)
3770  {
3771  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
3772  }
3773 }
3774 
3775 void ReduceQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3776 {
3777  const std::string descriptorName{"ReduceQueueDescriptor"};
3778 
3779  ValidateNumInputs(workloadInfo, descriptorName, 1);
3780  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3781 
3782  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3783  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3784 
3785  std::vector<DataType> supportedTypes =
3786  {
3794  };
3795 
3796  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3797  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3798 }
3799 
3801 {
3802  // Modified from LstmQueueDescriptor::Validate to support UnidirectionalSequenceLstm
3803 
3804  const std::string descriptorName{"UnidirectionalSequenceLstmQueueDescriptor"};
3805 
3806  // check dimensions of all inputs and outputs
3807  if (workloadInfo.m_InputTensorInfos.size() != 3)
3808  {
3809  throw InvalidArgumentException(descriptorName + ": Invalid number of inputs.");
3810  }
3811  if (workloadInfo.m_OutputTensorInfos.size() != 3)
3812  {
3813  throw InvalidArgumentException(descriptorName + ": Invalid number of outputs.");
3814  }
3815 
3816  std::vector<DataType> supportedTypes =
3817  {
3820  };
3821 
3822  // check for supported type of one input and match them with all the other input and output
3823  ValidateDataTypes(workloadInfo.m_InputTensorInfos[0], supportedTypes, descriptorName);
3824 
3825  // Making sure clipping parameters have valid values.
3826  // == 0 means no clipping
3827  // > 0 means clipping
3828  if (m_Parameters.m_ClippingThresCell < 0.0f)
3829  {
3830  throw InvalidArgumentException(descriptorName + ": negative cell clipping threshold is invalid");
3831  }
3832  if (m_Parameters.m_ClippingThresProj < 0.0f)
3833  {
3834  throw InvalidArgumentException(descriptorName + ": negative projection clipping threshold is invalid");
3835  }
3836 
3837  unsigned int batchIndx = 0;
3838  unsigned int inputIndx = 1;
3839  uint32_t timeStep = 1;
3840  unsigned int timeIndx = 1;
3841  inputIndx = 2;
3843  {
3844  batchIndx = 1;
3845  timeIndx = 0;
3846 
3847  }
3848  timeStep = workloadInfo.m_InputTensorInfos[0].GetShape()[timeIndx];
3849 
3850  // Inferring batch size, number of outputs and number of cells from the inputs.
3851  const uint32_t n_input = workloadInfo.m_InputTensorInfos[0].GetShape()[inputIndx];
3852  const uint32_t n_batch = workloadInfo.m_InputTensorInfos[0].GetShape()[batchIndx];
3853  ValidatePointer(m_InputToOutputWeights, "Null pointer check", "InputToOutputWeights");
3854  const uint32_t n_cell = m_InputToOutputWeights->GetShape()[0];
3855  ValidatePointer(m_RecurrentToOutputWeights, "Null pointer check", "RecurrentToOutputWeights");
3856  const uint32_t n_output = m_RecurrentToOutputWeights->GetShape()[1];
3857 
3858  // input tensor
3859  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[0], 3, (timeStep * n_batch * n_input),
3860  descriptorName + " input_0");
3861  // outputStateInTensor
3862  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[1], 2, (n_batch * n_output),
3863  descriptorName + " input_1");
3864  // outputStateInTensor
3865  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[2], 2, (n_batch * n_cell),
3866  descriptorName + " input_2");
3867 
3868  // outputTensor
3869  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[2], 3, (timeStep * n_batch * n_output),
3870  descriptorName + " output_0");
3871 
3872  // check that dimensions of inputs/outputs and QueueDescriptor data match with each other
3873  if ( m_InputToInputWeights )
3874  {
3876  (n_cell * n_input), "InputLayerNormWeights");
3877  }
3878 
3879  ValidatePointer(m_InputToForgetWeights, "Null pointer check", "InputToForgetWeights");
3881  (n_cell * n_input), "InputToForgetWeights");
3882 
3883  ValidatePointer(m_InputToCellWeights, "Null pointer check", "InputToCellWeights");
3885  (n_cell * n_input), "InputToCellWeights");
3886 
3888  {
3890  (n_cell * n_output), "RecurrentToInputWeights");
3891  }
3892 
3893  ValidatePointer(m_RecurrentToForgetWeights, "Null pointer check", "RecurrentToForgetWeights");
3895  (n_cell * n_output), "RecurrentToForgetWeights");
3896 
3897  ValidatePointer(m_RecurrentToCellWeights, "Null pointer check", "RecurrentToCellWeights");
3899  (n_cell * n_output), "RecurrentToCellWeights");
3900 
3901  // Make sure the input-gate's parameters are either both present (regular
3902  // LSTM) or not at all (CIFG-LSTM). And CifgEnable is set accordingly.
3903  bool cifg_weights_all_or_none = ((m_InputToInputWeights && m_RecurrentToInputWeights &&
3907  if (!cifg_weights_all_or_none)
3908  {
3909  throw InvalidArgumentException(descriptorName + ": Input-Gate's parameters InputToInputWeights and "
3910  "RecurrentToInputWeights must either both be present (regular LSTM) "
3911  "or both not present (CIFG-LSTM). In addition CifgEnable must be set "
3912  "accordingly.");
3913  }
3914 
3915  if ( m_CellToInputWeights )
3916  {
3918  n_cell, "CellToInputWeights");
3919  }
3920  if ( m_CellToForgetWeights )
3921  {
3923  n_cell, "CellToForgetWeights");
3924  }
3925  if ( m_CellToOutputWeights )
3926  {
3928  n_cell, "CellToOutputWeights");
3929  }
3930 
3931  // Making sure the peephole weights are there all or none. And PeepholeEnable is set accordingly.
3932  bool peephole_weights_all_or_none =
3937  if (!peephole_weights_all_or_none)
3938  {
3939  throw InvalidArgumentException(descriptorName + ": Invalid combination of peephole parameters.");
3940  }
3941 
3942  // Make sure the input gate bias is present only when not a CIFG-LSTM.
3944  {
3945  if (m_InputGateBias)
3946  {
3947  throw InvalidArgumentException(descriptorName + ": InputGateBias is present and CIFG-LSTM is enabled.");
3948  }
3949  }
3950  else
3951  {
3952  if (!m_InputGateBias)
3953  {
3954  throw InvalidArgumentException(descriptorName + ": If CIFG-LSTM is disabled InputGateBias "
3955  "must be present.");
3956  }
3958  n_cell, "InputGateBias");
3959  }
3960 
3961  ValidatePointer(m_ForgetGateBias, "Null pointer check", "ForgetGateBias");
3962  ValidateTensorNumDimNumElem(m_ForgetGateBias->GetTensorInfo(), 1, n_cell, "ForgetGateBias");
3963 
3964  ValidatePointer(m_CellBias, "Null pointer check", "CellBias");
3965  ValidateTensorNumDimNumElem(m_CellBias->GetTensorInfo(), 1, n_cell, "CellBias");
3966 
3967  ValidatePointer(m_OutputGateBias, "Null pointer check", "OutputGateBias");
3968  ValidateTensorNumDimNumElem(m_OutputGateBias->GetTensorInfo(), 1, n_cell, "OutputGateBias");
3969 
3970  if (m_ProjectionWeights)
3971  {
3973  (n_cell * n_output), "ProjectionWeights");
3974  }
3975  if (m_ProjectionBias)
3976  {
3977  ValidateTensorNumDimNumElem(m_ProjectionBias->GetTensorInfo(), 1, n_output, "ProjectionBias");
3978  }
3979 
3980  // Making sure the projection tensors are consistent:
3981  // 1) If projection weight is not present, then projection bias should not be
3982  // present.
3983  // 2) If projection weight is present, then projection bias is optional.
3984  bool projecton_tensors_consistent = ((!m_ProjectionWeights && !m_ProjectionBias &&
3990  if (!projecton_tensors_consistent)
3991  {
3992  throw InvalidArgumentException(descriptorName + ": Projection tensors are inconsistent.");
3993  }
3994 
3995  // The four layer normalization weights either all have values or none of them have values. Additionally, if
3996  // CIFG is used, input layer normalization weights tensor is omitted and the other layer normalization weights
3997  // either all have values or none of them have values. Layer normalization is used when the values of all the
3998  // layer normalization weights are present
4000  {
4001  ValidateTensorNumDimNumElem(m_InputLayerNormWeights->GetTensorInfo(), 1, n_cell, "InputLayerNormWeights");
4002  }
4004  {
4005  ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
4006  }
4008  {
4009  ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
4010  }
4012  {
4013  ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
4014  }
4015 
4017  {
4019  {
4021  {
4022  throw InvalidArgumentException(descriptorName + ": Layer normalisation is enabled and CIFG-LSTM is "
4023  "disabled but InputLayerNormWeights are not present");
4024  }
4026  1, n_cell, "InputLayerNormWeights");
4027  }
4028  else if (m_InputLayerNormWeights)
4029  {
4030  throw InvalidArgumentException(descriptorName + ":InputLayerNormWeights are present while CIFG is "
4031  "enabled");
4032  }
4033 
4034  ValidatePointer(m_ForgetLayerNormWeights, "Null pointer check layer normalisation enabled",
4035  "ForgetLayerNormWeights");
4036  ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
4037 
4038  ValidatePointer(m_OutputLayerNormWeights, "Null pointer check layer normalisation enabled",
4039  "OutputLayerNormWeights");
4040  ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
4041 
4042  ValidatePointer(m_CellLayerNormWeights, "Null pointer check layer normalisation enabled",
4043  "CellLayerNormWeights");
4044  ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
4045  }
4047  {
4048  throw InvalidArgumentException(descriptorName + ": Layer normalisation is disabled but one or more layer "
4049  "normalisation weights are present.");
4050  }
4051 }
4052 
4054 {
4055  const std::string descriptorName{"BatchMatMulDescriptor"};
4056 
4057  ValidateNumInputs(workloadInfo, descriptorName, 2);
4058  ValidateNumOutputs(workloadInfo, descriptorName, 1);
4059 
4060  // Inputs must be: both 2D+
4061  // For inputs X and Y whose dimensions to be multiplied are (M,N) and (I,J) respectively,
4062  // axes N and I must be the same size
4063 
4064  const auto& inputXInfoBeforeParams = workloadInfo.m_InputTensorInfos[0];
4065  const auto& inputYInfoBeforeParams = workloadInfo.m_InputTensorInfos[1];
4066  const auto& outputInfo = workloadInfo.m_OutputTensorInfos[0];
4067  // Output info has already been inferred
4068 
4069  std::vector<DataType> supportedTypes =
4070  {
4077  };
4078 
4079  ValidateDataTypes(inputXInfoBeforeParams, supportedTypes, descriptorName);
4080  ValidateDataTypes(inputYInfoBeforeParams, supportedTypes, descriptorName);
4081  ValidateDataTypes(outputInfo, supportedTypes, descriptorName);
4082 
4083  if ((inputXInfoBeforeParams.GetNumDimensions() < 2) ||
4084  (inputYInfoBeforeParams.GetNumDimensions() < 2))
4085  {
4086  throw InvalidArgumentException(descriptorName + ": Input tensors are not 2D or greater.");
4087  }
4088 
4089  TensorInfo inputXInfoAfterParams;
4090  TensorInfo inputYInfoAfterParams;
4091 
4094  {
4095  throw InvalidArgumentException(descriptorName +
4096  ": Invalid descriptor parameters - Transpose and Adjoint "
4097  "cannot both be true for a given input tensor.");
4098  }
4100  {
4101  inputXInfoAfterParams = armnnUtils::Permuted(inputXInfoBeforeParams,
4104  inputXInfoBeforeParams.GetShape()));
4105  }
4106  else if(m_Parameters.m_AdjointX)
4107  {
4109  inputXInfoBeforeParams.GetShape());
4110  if(inputXInfoBeforeParams.GetShape()[axesToMul.first] !=
4111  inputXInfoBeforeParams.GetShape()[axesToMul.second])
4112  {
4113  throw InvalidArgumentException(descriptorName +
4114  ": Adjoint is set to true for input tensor X, but the axes to be adjointed are not square." );
4115  }
4116  // Shape remains the same as it's square
4117  inputXInfoAfterParams = inputXInfoBeforeParams;
4118  }
4119  else
4120  {
4121  inputXInfoAfterParams = inputXInfoBeforeParams;
4122  }
4123 
4125  {
4126  inputYInfoAfterParams = armnnUtils::Permuted(inputYInfoBeforeParams,
4129  inputYInfoBeforeParams.GetShape()));
4130  }
4131  else if(m_Parameters.m_AdjointY)
4132  {
4134  inputYInfoBeforeParams.GetShape());
4135  if(inputYInfoBeforeParams.GetShape()[axesToMul.first] !=
4136  inputYInfoBeforeParams.GetShape()[axesToMul.second])
4137  {
4138  throw InvalidArgumentException(descriptorName +
4139  ": Adjoint is set to true for input tensor Y, but the axes to be adjointed are not square." );
4140  }
4141  // Shape remains the same as it's square
4142  inputYInfoAfterParams = inputYInfoBeforeParams;
4143  }
4144  else
4145  {
4146  inputYInfoAfterParams = inputYInfoBeforeParams;
4147  }
4148 
4149  switch(m_Parameters.m_DataLayoutX)
4150  {
4151  case DataLayout::NCDHW:
4152  case DataLayout::NDHWC:
4153  if(inputXInfoAfterParams.GetNumDimensions() < 3)
4154  {
4155  throw InvalidArgumentException(descriptorName +
4156  ": Input tensor X does not have the correct "
4157  "number of dimensions for the Data Layout that it has been assigned.");
4158  }
4159  break;
4160  case DataLayout::NCHW:
4161  case DataLayout::NHWC:
4162  default:
4163  break;
4164  }
4165 
4166  switch(m_Parameters.m_DataLayoutY)
4167  {
4168  case DataLayout::NCDHW:
4169  case DataLayout::NDHWC:
4170  if(inputYInfoAfterParams.GetNumDimensions() < 3)
4171  {
4172  throw InvalidArgumentException(descriptorName +
4173  ": Input tensor Y does not have the correct "
4174  "number of dimensions for the Data Layout that it has been assigned.");
4175  }
4176  break;
4177  case DataLayout::NCHW:
4178  case DataLayout::NHWC:
4179  default:
4180  break;
4181  }
4182 
4184  inputXInfoAfterParams.GetShape());
4186  inputXInfoBeforeParams.GetShape());
4187 
4188  if(inputXInfoAfterParams.GetShape()[axesXToMul.second]
4189  != inputYInfoAfterParams.GetShape()[axesYToMul.first])
4190  {
4191  throw InvalidArgumentException(descriptorName +
4192  ": The final axis of input tensor X must be the same size as "
4193  "the second last axis of input tensor Y.");
4194  }
4195 
4196  { // Separate scope so we don't pollute the rest of the scope with our temp variables
4197  // e.g. NHWC isnt compatible with NCHW as of now
4200 
4201  if(xLayout == DataLayout::NCHW || xLayout == DataLayout::NCDHW)
4202  {
4203  if(yLayout == DataLayout::NHWC || yLayout == DataLayout::NDHWC)
4204  {
4205  throw InvalidArgumentException(descriptorName +
4206  ": Invalid input tensor data layout combination.");
4207  }
4208  }
4209  if(yLayout == DataLayout::NCHW || yLayout == DataLayout::NCDHW)
4210  {
4211  if(xLayout == DataLayout::NHWC || xLayout == DataLayout::NDHWC)
4212  {
4213  throw InvalidArgumentException(descriptorName +
4214  ": Invalid input tensor data layout combination.");
4215  }
4216  }
4217  }
4218 
4219  // Simulate aligning the ends of the matrix dims and prepending 1's to the beginning of the shorter one
4220  unsigned int outputTensorDimSize = std::max(inputXInfoAfterParams.GetNumDimensions(),
4221  inputYInfoAfterParams.GetNumDimensions());
4222  if(outputTensorDimSize-2 > 0)
4223  {
4224  TensorInfo tiXNotMul = TensorInfo(TensorShape(outputTensorDimSize-2),
4226  TensorInfo tiYNotMul = TensorInfo(TensorShape(outputTensorDimSize-2),
4228  TensorInfo tiOutNotMul = TensorInfo(TensorShape(outputTensorDimSize-2),
4230 
4231  auto doAxisExtension = [&](std::vector<unsigned int> axisIndices, TensorInfo& ti)
4232  {
4233  auto sizeDiff = (outputTensorDimSize-2) - axisIndices.size();
4234 
4235  for(unsigned int i = 0; i < sizeDiff; i++)
4236  {
4237  axisIndices.insert(axisIndices.begin(), 1);
4238  }
4239 
4240  for(unsigned int i = 0; i < ti.GetNumDimensions(); i++)
4241  {
4242  ti.GetShape()[i] = inputXInfoAfterParams.GetShape()[i];
4243  }
4244  };
4245 
4247  inputXInfoAfterParams.GetShape());
4249  inputYInfoAfterParams.GetShape());
4250 
4251  doAxisExtension(axesXNotMul, tiXNotMul);
4252  doAxisExtension(axesYNotMul, tiYNotMul);
4253 
4254  for(unsigned int i = 0; i < tiOutNotMul.GetNumDimensions(); i++)
4255  {
4256  tiOutNotMul.GetShape()[i] = std::max(tiXNotMul.GetShape()[i],
4257  tiYNotMul.GetShape()[i]);
4258  }
4259 
4260  ValidateBroadcastTensorShapesMatch(tiXNotMul,
4261  tiYNotMul,
4262  tiOutNotMul,
4263  descriptorName,
4264  "input_X",
4265  "input_Y");
4266  }
4267 }
4268 
4269 
4270 } // namespace armnn
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_RecurrentToForgetWeights
const ConstTensorHandle * m_RecurrentToForgetWeights
Definition: WorkloadData.hpp:718
armnn::QLstmDescriptor::m_LayerNormEnabled
bool m_LayerNormEnabled
Enable/disable layer normalization.
Definition: Descriptors.hpp:1371
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_OutputLayerNormWeights
const ConstTensorHandle * m_OutputLayerNormWeights
Definition: WorkloadData.hpp:733
armnn::FloorQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1931
armnn::BatchNormalizationQueueDescriptor::m_Variance
const ConstTensorHandle * m_Variance
Definition: WorkloadData.hpp:317
armnn::Pooling3dQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1572
armnn::LstmQueueDescriptor::m_CellToOutputWeights
const ConstTensorHandle * m_CellToOutputWeights
Definition: WorkloadData.hpp:432
armnn::LstmDescriptor::m_TimeMajor
bool m_TimeMajor
Enable/disable time major.
Definition: Descriptors.hpp:1101
armnn::ConcatQueueDescriptor::ViewOrigin
Definition: WorkloadData.hpp:132
armnn::StackDescriptor::m_InputShape
TensorShape m_InputShape
Required shape of all input tensors.
Definition: Descriptors.hpp:1224
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_RecurrentToOutputWeights
const ConstTensorHandle * m_RecurrentToOutputWeights
Definition: WorkloadData.hpp:720
armnn::Convolution2dQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1273
armnn::TensorInfo::GetQuantizationOffset
int32_t GetQuantizationOffset() const
Definition: Tensor.cpp:478
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:1559
armnn::MemCopyQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:519
armnn::TensorInfo::GetQuantizationScale
float GetQuantizationScale() const
Definition: Tensor.cpp:461
armnn::Convolution2dDescriptor::m_BiasEnabled
bool m_BiasEnabled
Enable/disable bias.
Definition: Descriptors.hpp:550
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_InputGateBias
const ConstTensorHandle * m_InputGateBias
Definition: WorkloadData.hpp:724
armnn::IsQuantized8BitType
constexpr bool IsQuantized8BitType(DataType dataType)
Definition: TypesUtils.hpp:289
armnn::DataType::QAsymmU8
@ QAsymmU8
armnn::FullyConnectedDescriptor::m_BiasEnabled
bool m_BiasEnabled
Enable/disable bias.
Definition: Descriptors.hpp:494
armnn::QLstmQueueDescriptor::m_RecurrentToForgetWeights
const ConstTensorHandle * m_RecurrentToForgetWeights
Definition: WorkloadData.hpp:589
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_CellToOutputWeights
const ConstTensorHandle * m_CellToOutputWeights
Definition: WorkloadData.hpp:723
armnn::QueueDescriptor::ValidateTensorNumDimNumElem
void ValidateTensorNumDimNumElem(const TensorInfo &tensorInfo, unsigned int numDimension, unsigned int numElements, std::string const &tensorName) const
Definition: WorkloadData.cpp:464
armnn::QueueDescriptor::ValidateInputsOutputs
void ValidateInputsOutputs(const std::string &descName, unsigned int numExpectedIn, unsigned int numExpectedOut) const
Definition: WorkloadData.cpp:475
armnn::DataLayout
DataLayout
Definition: Types.hpp:62
armnn::BatchNormalizationQueueDescriptor::m_Beta
const ConstTensorHandle * m_Beta
Definition: WorkloadData.hpp:318
DataLayoutIndexed.hpp
armnn::LstmQueueDescriptor::m_InputToOutputWeights
const ConstTensorHandle * m_InputToOutputWeights
Definition: WorkloadData.hpp:425
armnn::QuantizedLstmQueueDescriptor::m_InputToInputWeights
const ConstTensorHandle * m_InputToInputWeights
Definition: WorkloadData.hpp:628
armnn::LstmQueueDescriptor::m_CellLayerNormWeights
const ConstTensorHandle * m_CellLayerNormWeights
Definition: WorkloadData.hpp:441
armnn::SliceQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3539
armnn::SpaceToBatchNdQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1811
armnn::CastQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:723
armnn::RsqrtQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2639
CHECK_LOCATION
#define CHECK_LOCATION()
Definition: Exceptions.hpp:203
armnn::DataType::Float16
@ Float16
armnn::QueueDescriptor::m_AllowExpandedDims
bool m_AllowExpandedDims
Definition: WorkloadData.hpp:52
armnn::SplitterQueueDescriptor::ViewOrigin::m_Origin
std::vector< unsigned int > m_Origin
Definition: WorkloadData.hpp:119
armnn::DebugQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2583
armnn::FillQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1039
armnn::LstmQueueDescriptor::m_CellBias
const ConstTensorHandle * m_CellBias
Definition: WorkloadData.hpp:435
armnn::ConcatQueueDescriptor::ViewOrigin::m_Origin
std::vector< unsigned int > m_Origin
Definition: WorkloadData.hpp:138
armnn::UnmapQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:501
armnn::LstmQueueDescriptor::m_OutputGateBias
const ConstTensorHandle * m_OutputGateBias
Definition: WorkloadData.hpp:436
armnn::DepthwiseConvolution2dQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1412
armnn::QLstmQueueDescriptor::m_OutputGateBias
const ConstTensorHandle * m_OutputGateBias
Definition: WorkloadData.hpp:598
armnn::LogicalBinaryQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3741
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_ForgetGateBias
const ConstTensorHandle * m_ForgetGateBias
Definition: WorkloadData.hpp:725
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_CellToForgetWeights
const ConstTensorHandle * m_CellToForgetWeights
Definition: WorkloadData.hpp:722
armnn::ArgMinMaxQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:657
armnn::ArgMinMaxDescriptor::m_Axis
int m_Axis
Axis to reduce across the input tensor.
Definition: Descriptors.hpp:83
armnn::IsQuantizedType
constexpr bool IsQuantizedType()
Definition: TypesUtils.hpp:284
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:1016
armnn::PermuteDescriptor::m_DimMappings
PermutationVector m_DimMappings
Indicates how to translate tensor elements from a given source into the target destination,...
Definition: Descriptors.hpp:153
armnn::StridedSliceDescriptor::m_Begin
std::vector< int > m_Begin
Begin values for the input that will be sliced.
Definition: Descriptors.hpp:1289
armnn::LstmQueueDescriptor::m_InputToForgetWeights
const ConstTensorHandle * m_InputToForgetWeights
Definition: WorkloadData.hpp:423
armnn::FullyConnectedQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1062
armnn::TransposeConvolution2dDescriptor::m_BiasEnabled
bool m_BiasEnabled
Enable/disable bias.
Definition: Descriptors.hpp:1428
armnn::ConstantQueueDescriptor::m_LayerOutput
const ConstTensorHandle * m_LayerOutput
Definition: WorkloadData.hpp:370
armnn::StackQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:943
TensorUtils.hpp
armnnUtils::DataLayoutIndexed::GetWidthIndex
unsigned int GetWidthIndex() const
Definition: DataLayoutIndexed.hpp:25
armnn::NormalizationQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1125
armnn::DataType::Signed32
@ Signed32
armnn::LstmDescriptor::m_CifgEnabled
bool m_CifgEnabled
Enable/disable cifg (coupled input & forget gate).
Definition: Descriptors.hpp:1093
armnn::LstmDescriptor::m_LayerNormEnabled
bool m_LayerNormEnabled
Enable/disable layer normalization.
Definition: Descriptors.hpp:1099
TensorHandle.hpp
armnn::ChannelShuffleQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3042
armnn::UnidirectionalSequenceLstmQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3800
armnn::QLstmQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3055
armnn::PermutationVector::GetSize
SizeType GetSize() const
Definition: Types.hpp:338
armnn::DepthwiseConvolution2dDescriptor::m_BiasEnabled
bool m_BiasEnabled
Enable/disable bias.
Definition: Descriptors.hpp:676
armnn::MeanDescriptor::m_Axis
std::vector< unsigned int > m_Axis
Values for the dimensions to reduce.
Definition: Descriptors.hpp:1137
armnn::GetBiasDataType
DataType GetBiasDataType(DataType inputDataType)
Definition: WorkloadData.cpp:28
armnn::QLstmQueueDescriptor::m_InputToOutputWeights
const ConstTensorHandle * m_InputToOutputWeights
Definition: WorkloadData.hpp:587
armnn::DetectionPostProcessQueueDescriptor::m_Anchors
const ConstTensorHandle * m_Anchors
Definition: WorkloadData.hpp:241
armnn::Pooling2dQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1545
armnn::OriginsDescriptor::GetConcatAxis
unsigned int GetConcatAxis() const
Get the concatenation axis value.
Definition: Descriptors.cpp:162
armnn::ActivationQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:632
armnn::EqualQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2591
armnn::DataType::QAsymmS8
@ QAsymmS8
armnn::DepthwiseConvolution2dDescriptor::m_StrideX
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
Definition: Descriptors.hpp:668
armnn::MultiplicationQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1190
armnn::LstmQueueDescriptor::m_CellToInputWeights
const ConstTensorHandle * m_CellToInputWeights
Definition: WorkloadData.hpp:430
armnn::DepthwiseConvolution2dDescriptor::m_DilationX
uint32_t m_DilationX
Dilation factor value for width dimension.
Definition: Descriptors.hpp:672
armnn::ElementwiseUnaryQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3671
ARMNN_LOG
#define ARMNN_LOG(severity)
Definition: Logging.hpp:212
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_InputToInputWeights
const ConstTensorHandle * m_InputToInputWeights
Definition: WorkloadData.hpp:713
armnn::DepthToSpaceQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3594
armnn::LstmQueueDescriptor::m_ProjectionWeights
const ConstTensorHandle * m_ProjectionWeights
Definition: WorkloadData.hpp:437
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_CellBias
const ConstTensorHandle * m_CellBias
Definition: WorkloadData.hpp:726
armnn::ReshapeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1782
armnn::GatherNdQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2665
armnn::MemImportQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:555
armnn
Copyright (c) 2021 ARM Limited and Contributors.
Definition: 01_00_quick_start.dox:6
armnn::ComparisonQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3647
armnnUtils::DataLayoutIndexed::GetChannelsIndex
unsigned int GetChannelsIndex() const
Definition: DataLayoutIndexed.hpp:23
armnn::QLstmQueueDescriptor::m_ProjectionBias
const ConstTensorHandle * m_ProjectionBias
Definition: WorkloadData.hpp:600
armnn::OptionalReferenceSwitch< std::is_reference< T >::value, T >::value
const T & value() const
Definition: Optional.hpp:146
armnn::MapQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:483
armnnUtils
Definition: CompatibleTypes.hpp:10
armnn::AbsQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3512
armnn::StridedSliceDescriptor::m_End
std::vector< int > m_End
End values for the input that will be sliced.
Definition: Descriptors.hpp:1291
armnnUtils::Permuted
armnn::TensorShape Permuted(const armnn::TensorShape &srcShape, const armnn::PermutationVector &mappings)
Definition: Permute.cpp:98
armnn::ConcatQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:847
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_InputToForgetWeights
const ConstTensorHandle * m_InputToForgetWeights
Definition: WorkloadData.hpp:714
armnn::QuantizedLstmQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3341
armnn::QLstmQueueDescriptor::m_CellBias
const ConstTensorHandle * m_CellBias
Definition: WorkloadData.hpp:597
armnn::DequantizeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2803
armnn::DivisionQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2271
armnn::QLstmQueueDescriptor::m_ForgetGateBias
const ConstTensorHandle * m_ForgetGateBias
Definition: WorkloadData.hpp:596
armnn::ElementwiseUnaryDescriptor::m_Operation
UnaryOperation m_Operation
Specifies the elementwiseUnary operation to execute.
Definition: Descriptors.hpp:125
armnn::TransposeConvolution2dQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2961
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_OutputGateBias
const ConstTensorHandle * m_OutputGateBias
Definition: WorkloadData.hpp:727
armnn::QuantizedLstmQueueDescriptor::m_CellBias
const ConstTensorHandle * m_CellBias
Definition: WorkloadData.hpp:640
armnn::LstmQueueDescriptor::m_ProjectionBias
const ConstTensorHandle * m_ProjectionBias
Definition: WorkloadData.hpp:438
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_CellLayerNormWeights
const ConstTensorHandle * m_CellLayerNormWeights
Definition: WorkloadData.hpp:732
armnn::TensorShape
Definition: Tensor.hpp:20
armnn::Convolution3dDescriptor::m_StrideZ
uint32_t m_StrideZ
Stride value when proceeding through input for the depth dimension.
Definition: Descriptors.hpp:613
armnn::BatchNormalizationQueueDescriptor::m_Gamma
const ConstTensorHandle * m_Gamma
Definition: WorkloadData.hpp:319
armnn::PadQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2417
armnn::SpaceToDepthDescriptor::m_DataLayout
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Definition: Descriptors.hpp:1042
armnn::DepthwiseConvolution2dDescriptor::m_DilationY
uint32_t m_DilationY
Dilation factor value for height dimension.
Definition: Descriptors.hpp:674
armnn::SoftmaxQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:750
armnn::LstmQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1955
armnn::DataLayout::NCHW
@ NCHW
armnn::WorkloadInfo::m_OutputTensorInfos
std::vector< TensorInfo > m_OutputTensorInfos
Definition: WorkloadInfo.hpp:19
armnn::LstmQueueDescriptor::m_RecurrentToOutputWeights
const ConstTensorHandle * m_RecurrentToOutputWeights
Definition: WorkloadData.hpp:429
armnn::FakeQuantizationDescriptor::m_Max
float m_Max
Maximum value.
Definition: Descriptors.hpp:889
armnn::DepthwiseConvolution2dDescriptor::m_DataLayout
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Definition: Descriptors.hpp:678
armnn::Convolution3dQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1350
armnn::TensorInfo::IsQuantized
bool IsQuantized() const
Definition: Tensor.cpp:504
armnn::QuantizedLstmQueueDescriptor::m_InputToForgetWeights
const ConstTensorHandle * m_InputToForgetWeights
Definition: WorkloadData.hpp:629
armnn::PadDescriptor::m_PadList
std::vector< std::pair< unsigned int, unsigned int > > m_PadList
Specifies the padding for input dimension.
Definition: Descriptors.hpp:1165
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:1568
armnn::QLstmQueueDescriptor::m_InputToForgetWeights
const ConstTensorHandle * m_InputToForgetWeights
Definition: WorkloadData.hpp:585
armnn::TensorInfo::GetNumDimensions
unsigned int GetNumDimensions() const
Definition: Tensor.hpp:195
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::TransposeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3013
armnn::DataLayout::NCDHW
@ NCDHW
armnn::MergeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2833
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::QLstmQueueDescriptor::m_ForgetLayerNormWeights
const ConstTensorHandle * m_ForgetLayerNormWeights
Definition: WorkloadData.hpp:602
armnn::QueueDescriptor::ValidateTensorNumDimensions
void ValidateTensorNumDimensions(const TensorInfo &tensor, std::string const &descName, unsigned int numDimensions, std::string const &tensorName) const
Definition: WorkloadData.cpp:426
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_CellToInputWeights
const ConstTensorHandle * m_CellToInputWeights
Definition: WorkloadData.hpp:721
armnn::DataType::Float32
@ Float32
armnn::TensorInfo::GetNumElements
unsigned int GetNumElements() const
Definition: Tensor.hpp:196
armnn::BatchNormalizationQueueDescriptor::m_Mean
const ConstTensorHandle * m_Mean
Definition: WorkloadData.hpp:316
armnn::QuantizedLstmQueueDescriptor::m_InputToCellWeights
const ConstTensorHandle * m_InputToCellWeights
Definition: WorkloadData.hpp:630
armnn::LstmDescriptor::m_PeepholeEnabled
bool m_PeepholeEnabled
Enable/disable peephole.
Definition: Descriptors.hpp:1095
armnn::ReduceQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3775
armnn::L2NormalizationQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1696
armnn::BatchMatMulDescriptor::m_TransposeY
bool m_TransposeY
Definition: Descriptors.hpp:1560
armnn::TensorInfo
Definition: Tensor.hpp:152
armnn::DataType::Signed64
@ Signed64
armnn::SpaceToBatchNdDescriptor::m_DataLayout
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Definition: Descriptors.hpp:1018
armnn::ResizeDescriptor::m_DataLayout
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Definition: Descriptors.hpp:961
armnn::SpaceToDepthDescriptor::m_BlockSize
unsigned int m_BlockSize
Scalar specifying the input block size. It must be >= 1.
Definition: Descriptors.hpp:1039
armnn::StackDescriptor::m_NumInputs
uint32_t m_NumInputs
Number of input tensors.
Definition: Descriptors.hpp:1222
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_ProjectionWeights
const ConstTensorHandle * m_ProjectionWeights
Definition: WorkloadData.hpp:728
armnn::QLstmQueueDescriptor::m_CellToInputWeights
const ConstTensorHandle * m_CellToInputWeights
Definition: WorkloadData.hpp:592
armnn::QLstmQueueDescriptor::m_ProjectionWeights
const ConstTensorHandle * m_ProjectionWeights
Definition: WorkloadData.hpp:599
armnn::ConvertFp32ToFp16QueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2225
armnn::LstmQueueDescriptor::m_InputToCellWeights
const ConstTensorHandle * m_InputToCellWeights
Definition: WorkloadData.hpp:424
armnn::Convolution3dDescriptor::m_StrideX
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
Definition: Descriptors.hpp:609
armnn::PreCompiledQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2919
armnn::OptionalBase::has_value
bool has_value() const noexcept
Definition: Optional.hpp:53
armnn::TensorInfo::HasPerAxisQuantization
bool HasPerAxisQuantization() const
Definition: Tensor.cpp:446
Permute.hpp
armnn::SwitchQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2878
armnn::QuantizedLstmQueueDescriptor::m_InputToOutputWeights
const ConstTensorHandle * m_InputToOutputWeights
Definition: WorkloadData.hpp:631
armnn::QLstmQueueDescriptor::m_RecurrentToInputWeights
const ConstTensorHandle * m_RecurrentToInputWeights
Definition: WorkloadData.hpp:588
armnn::LstmQueueDescriptor::m_ForgetLayerNormWeights
const ConstTensorHandle * m_ForgetLayerNormWeights
Definition: WorkloadData.hpp:440
armnn::QuantizedLstmQueueDescriptor::m_RecurrentToOutputWeights
const ConstTensorHandle * m_RecurrentToOutputWeights
Definition: WorkloadData.hpp:636
armnn::ConstTensorHandle::GetTensorInfo
const TensorInfo & GetTensorInfo() const
Definition: TensorHandle.hpp:40
armnn::Convolution3dDescriptor::m_StrideY
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
Definition: Descriptors.hpp:611
WorkloadInfo.hpp
armnn::QLstmDescriptor::m_HiddenStateScale
float m_HiddenStateScale
Hidden State quantization scale.
Definition: Descriptors.hpp:1383
armnn::GreaterQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2615
armnn::TensorInfo::GetShape
const TensorShape & GetShape() const
Definition: Tensor.hpp:191
armnn::LstmQueueDescriptor::m_OutputLayerNormWeights
const ConstTensorHandle * m_OutputLayerNormWeights
Definition: WorkloadData.hpp:442
armnn::TransposeDescriptor::m_DimMappings
PermutationVector m_DimMappings
Indicates how to translate tensor elements from a given source into the target destination,...
Definition: Descriptors.hpp:1461
armnn::QLstmDescriptor::m_HiddenStateZeroPoint
int32_t m_HiddenStateZeroPoint
Hidden State zero point.
Definition: Descriptors.hpp:1381
armnn::StridedSliceDescriptor::m_Stride
std::vector< int > m_Stride
Stride values for the input that will be sliced.
Definition: Descriptors.hpp:1293
armnn::FakeQuantizationQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1646
armnn::DataLayout::NHWC
@ NHWC
armnn::QuantizedLstmQueueDescriptor::m_OutputGateBias
const ConstTensorHandle * m_OutputGateBias
Definition: WorkloadData.hpp:641
ARMNN_ASSERT_MSG
#define ARMNN_ASSERT_MSG(COND, MSG)
Definition: Assert.hpp:15
armnn::BatchNormalizationQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1227
armnn::DetectionPostProcessQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2735
armnn::QLstmQueueDescriptor::m_CellToOutputWeights
const ConstTensorHandle * m_CellToOutputWeights
Definition: WorkloadData.hpp:594
armnn::DetectionPostProcessDescriptor::m_NumClasses
uint32_t m_NumClasses
Number of classes.
Definition: Descriptors.hpp:723
armnn::LstmQueueDescriptor::m_RecurrentToForgetWeights
const ConstTensorHandle * m_RecurrentToForgetWeights
Definition: WorkloadData.hpp:427
armnn::Convolution2dDescriptor::m_StrideX
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
Definition: Descriptors.hpp:542
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_ForgetLayerNormWeights
const ConstTensorHandle * m_ForgetLayerNormWeights
Definition: WorkloadData.hpp:731
armnn::LstmQueueDescriptor::m_RecurrentToCellWeights
const ConstTensorHandle * m_RecurrentToCellWeights
Definition: WorkloadData.hpp:428
armnn::PermuteQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1516
armnn::MemSyncQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:611
armnn::WorkloadInfo
Contains information about TensorInfos of a layer.
Definition: WorkloadInfo.hpp:16
armnn::PermutationVector
Definition: Types.hpp:295
armnn::LstmQueueDescriptor::m_CellToForgetWeights
const ConstTensorHandle * m_CellToForgetWeights
Definition: WorkloadData.hpp:431
armnn::SpaceToBatchNdDescriptor::m_BlockShape
std::vector< unsigned int > m_BlockShape
Block shape value.
Definition: Descriptors.hpp:1013
armnn::QLstmQueueDescriptor::m_OutputLayerNormWeights
const ConstTensorHandle * m_OutputLayerNormWeights
Definition: WorkloadData.hpp:604
armnn::SliceDescriptor::m_Size
std::vector< unsigned int > m_Size
Size of the slice in each dimension.
Definition: Descriptors.hpp:1194
armnn::LstmDescriptor::m_ClippingThresCell
float m_ClippingThresCell
Clipping threshold value for the cell state.
Definition: Descriptors.hpp:1089
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_RecurrentToInputWeights
const ConstTensorHandle * m_RecurrentToInputWeights
Definition: WorkloadData.hpp:717
armnn::ConvertFp16ToFp32QueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2248
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::GatherQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2700
armnn::DataType
DataType
Definition: Types.hpp:48
armnn::InstanceNormalizationQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1667
armnn::ConstantQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1751
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_ProjectionBias
const ConstTensorHandle * m_ProjectionBias
Definition: WorkloadData.hpp:729
armnn::TensorInfo::GetQuantizationDim
Optional< unsigned int > GetQuantizationDim() const
Definition: Tensor.cpp:494
armnn::DataType::BFloat16
@ BFloat16
armnn::QLstmQueueDescriptor::m_CellLayerNormWeights
const ConstTensorHandle * m_CellLayerNormWeights
Definition: WorkloadData.hpp:603
armnn::SliceDescriptor::m_Begin
std::vector< unsigned int > m_Begin
Beginning indices of the slice in each dimension.
Definition: Descriptors.hpp:1191
armnnUtils::DataLayoutIndexed
Provides access to the appropriate indexes for Channels, Height and Width based on DataLayout.
Definition: DataLayoutIndexed.hpp:17
armnn::QLstmQueueDescriptor::m_InputToCellWeights
const ConstTensorHandle * m_InputToCellWeights
Definition: WorkloadData.hpp:586
armnn::QuantizeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2439
armnn::SplitterQueueDescriptor::m_ViewOrigins
std::vector< ViewOrigin > m_ViewOrigins
Definition: WorkloadData.hpp:124
armnn::FakeQuantizationDescriptor::m_Min
float m_Min
Minimum value.
Definition: Descriptors.hpp:887
armnn::LstmDescriptor::m_ProjectionEnabled
bool m_ProjectionEnabled
Enable/disable the projection layer.
Definition: Descriptors.hpp:1097
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_InputLayerNormWeights
const ConstTensorHandle * m_InputLayerNormWeights
Definition: WorkloadData.hpp:730
armnn::BatchMatMulDescriptor::m_DataLayoutY
DataLayout m_DataLayoutY
Definition: Descriptors.hpp:1569
armnn::UnaryOperation::LogicalNot
@ LogicalNot
armnn::PreluQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2924
armnn::LstmQueueDescriptor::m_InputToInputWeights
const ConstTensorHandle * m_InputToInputWeights
Definition: WorkloadData.hpp:422
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:1139
armnn::Optional< unsigned int >
armnn::MeanQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2373
armnn::TensorInfo::HasMultipleQuantizationScales
bool HasMultipleQuantizationScales() const
Definition: Tensor.hpp:201
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_InputToCellWeights
const ConstTensorHandle * m_InputToCellWeights
Definition: WorkloadData.hpp:715
armnnUtils::DataLayoutIndexed::GetHeightIndex
unsigned int GetHeightIndex() const
Definition: DataLayoutIndexed.hpp:24
armnn::QuantizedLstmQueueDescriptor::m_RecurrentToCellWeights
const ConstTensorHandle * m_RecurrentToCellWeights
Definition: WorkloadData.hpp:635
Logging.hpp
armnn::QLstmQueueDescriptor::m_RecurrentToOutputWeights
const ConstTensorHandle * m_RecurrentToOutputWeights
Definition: WorkloadData.hpp:591
armnn::DataType::QSymmS8
@ QSymmS8
armnn::QLstmDescriptor::m_CifgEnabled
bool m_CifgEnabled
Enable/disable CIFG (coupled input & forget gate).
Definition: Descriptors.hpp:1365
armnn::RankQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3712
armnn::ResizeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1599
armnn::LstmQueueDescriptor::m_RecurrentToInputWeights
const ConstTensorHandle * m_RecurrentToInputWeights
Definition: WorkloadData.hpp:426
armnn::QLstmQueueDescriptor::m_CellToForgetWeights
const ConstTensorHandle * m_CellToForgetWeights
Definition: WorkloadData.hpp:593
armnn::QueueDescriptor::m_Outputs
std::vector< ITensorHandle * > m_Outputs
Definition: WorkloadData.hpp:27
NumericCast.hpp
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_RecurrentToCellWeights
const ConstTensorHandle * m_RecurrentToCellWeights
Definition: WorkloadData.hpp:719
armnn::LstmQueueDescriptor::m_InputLayerNormWeights
const ConstTensorHandle * m_InputLayerNormWeights
Definition: WorkloadData.hpp:439
armnn::Convolution3dDescriptor::m_BiasEnabled
bool m_BiasEnabled
Enable/disable bias.
Definition: Descriptors.hpp:621
armnn::LstmDescriptor::m_ClippingThresProj
float m_ClippingThresProj
Clipping threshold value for the projection.
Definition: Descriptors.hpp:1091
armnn::DataType::QSymmS16
@ QSymmS16
armnn::SubtractionQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2305
armnn::QLstmDescriptor::m_PeepholeEnabled
bool m_PeepholeEnabled
Enable/disable peephole.
Definition: Descriptors.hpp:1367
armnn::TransposeConvolution2dQueueDescriptor::m_Bias
const ConstTensorHandle * m_Bias
Definition: WorkloadData.hpp:547
armnn::QLstmQueueDescriptor::m_InputToInputWeights
const ConstTensorHandle * m_InputToInputWeights
Definition: WorkloadData.hpp:584
armnn::AdditionQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1153
armnn::DepthwiseConvolution2dDescriptor::m_StrideY
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
Definition: Descriptors.hpp:670
armnn::QLstmQueueDescriptor::m_RecurrentToCellWeights
const ConstTensorHandle * m_RecurrentToCellWeights
Definition: WorkloadData.hpp:590
armnn::LogSoftmaxQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1728
armnn::QuantizedLstmQueueDescriptor::m_RecurrentToInputWeights
const ConstTensorHandle * m_RecurrentToInputWeights
Definition: WorkloadData.hpp:633
armnn::QuantizedLstmQueueDescriptor::m_ForgetGateBias
const ConstTensorHandle * m_ForgetGateBias
Definition: WorkloadData.hpp:639
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_InputToOutputWeights
const ConstTensorHandle * m_InputToOutputWeights
Definition: WorkloadData.hpp:716
armnn::BatchMatMulQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:4053
WorkloadData.hpp
armnn::Convolution2dDescriptor::m_StrideY
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
Definition: Descriptors.hpp:544
armnn::LstmQueueDescriptor::m_ForgetGateBias
const ConstTensorHandle * m_ForgetGateBias
Definition: WorkloadData.hpp:434
armnn::TensorInfo::GetQuantizationScales
std::vector< float > GetQuantizationScales() const
Definition: Tensor.cpp:451
armnn::QuantizedLstmQueueDescriptor::m_InputGateBias
const ConstTensorHandle * m_InputGateBias
Definition: WorkloadData.hpp:638
armnn::DetectionPostProcessDescriptor::m_NmsIouThreshold
float m_NmsIouThreshold
Intersection over union threshold.
Definition: Descriptors.hpp:721
armnn::LstmQueueDescriptor::m_InputGateBias
const ConstTensorHandle * m_InputGateBias
Definition: WorkloadData.hpp:433
armnn::SplitterQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:775
armnn::DataLayout::NDHWC
@ NDHWC
armnn::MaximumQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2339
armnn::SpaceToDepthQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1878
armnn::DataType::Boolean
@ Boolean
armnn::BatchMatMulDescriptor::GetPermuteVec
static PermutationVector GetPermuteVec(DataLayout dataLayout, const TensorShape &tensorShape)
Static helper to get the axes which will be transposed.
Definition: Descriptors.cpp:514
armnn::GetDataTypeName
constexpr const char * GetDataTypeName(DataType dataType)
Definition: TypesUtils.hpp:206
armnn::BatchMatMulDescriptor::m_AdjointY
bool m_AdjointY
Definition: Descriptors.hpp:1565
armnn::InvalidArgumentException
Definition: Exceptions.hpp:80
armnn::QLstmQueueDescriptor::m_InputGateBias
const ConstTensorHandle * m_InputGateBias
Definition: WorkloadData.hpp:595
armnn::ShapeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2851
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:1564
armnn::TransposeConvolution2dQueueDescriptor::m_Weight
const ConstTensorHandle * m_Weight
Definition: WorkloadData.hpp:546
armnn::StackDescriptor::m_Axis
uint32_t m_Axis
0-based axis along which to stack the input tensors.
Definition: Descriptors.hpp:1220
armnn::QuantizedLstmQueueDescriptor::m_RecurrentToForgetWeights
const ConstTensorHandle * m_RecurrentToForgetWeights
Definition: WorkloadData.hpp:634
armnn::QLstmDescriptor::m_ProjectionEnabled
bool m_ProjectionEnabled
Enable/disable the projection layer.
Definition: Descriptors.hpp:1369
armnn::StridedSliceQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2492
armnn::QLstmQueueDescriptor::m_InputLayerNormWeights
const ConstTensorHandle * m_InputLayerNormWeights
Definition: WorkloadData.hpp:601
armnn::BatchToSpaceNdQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2468
armnn::MinimumQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2549
armnn::ConcatQueueDescriptor::m_ViewOrigins
std::vector< ViewOrigin > m_ViewOrigins
Definition: WorkloadData.hpp:143
armnn::BatchMatMulDescriptor::GetAxesToMul
static std::pair< std::pair< unsigned int, unsigned int >, std::pair< unsigned int, unsigned int > > GetAxesToMul(const BatchMatMulDescriptor &desc, const TensorShape &tensorXShape, const TensorShape &tensorYShape)
Definition: Descriptors.cpp:459
armnn::TensorInfo::GetDataType
DataType GetDataType() const
Definition: Tensor.hpp:198
armnn::SplitterQueueDescriptor::ViewOrigin
Definition: WorkloadData.hpp:113
armnn::WorkloadInfo::m_InputTensorInfos
std::vector< TensorInfo > m_InputTensorInfos
Definition: WorkloadInfo.hpp:18
armnn::QueueDescriptor::m_Inputs
std::vector< ITensorHandle * > m_Inputs
Definition: WorkloadData.hpp:26
armnn::BoostLogSeverityMapping::info
@ info
armnn::BatchMatMulDescriptor::GetAxesNotMul
static std::pair< std::vector< unsigned int >, std::vector< unsigned int > > GetAxesNotMul(const BatchMatMulDescriptor &desc, const TensorShape &inputXShape, const TensorShape &inputYShape)
Definition: Descriptors.cpp:467
armnnUtils::GetUnsignedAxis
unsigned int GetUnsignedAxis(const unsigned int inputDimension, const int axis)
Definition: TensorUtils.cpp:196