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