ArmNN
 23.11
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  {
1596  };
1597 
1598  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1599  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1600 
1601  // Resize only changes width and height: batch and channel count must match.
1602  const unsigned int inputBatchSize = inputTensorInfo.GetShape()[0];
1603  const unsigned int outputBatchSize = outputTensorInfo.GetShape()[0];
1604  if (inputBatchSize != outputBatchSize)
1605  {
1607  fmt::format("{}: Input batch size ({}) does not match output batch size ({})",
1608  descriptorName, inputBatchSize, outputBatchSize));
1609  }
1610 
1611  DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
1612  const unsigned int inputChannelCount = inputTensorInfo.GetShape()[dimensionIndices.GetChannelsIndex()];
1613  const unsigned int outputChannelCount = outputTensorInfo.GetShape()[dimensionIndices.GetChannelsIndex()];
1614  if (inputChannelCount != outputChannelCount)
1615  {
1617  fmt::format("{}: Input channel count ({}) does not match output channel count ({})",
1618  descriptorName, inputChannelCount, outputChannelCount));
1619  }
1620 }
1621 
1622 void ReverseV2QueueDescriptor::Validate(const WorkloadInfo &workloadInfo) const
1623 {
1624  const std::string descriptorName{"ReverseV2QueueDescriptor"};
1625 
1626  // Backend restriction
1627  const unsigned int maxDimensions = 4;
1628 
1629  ValidateNumInputs(workloadInfo, descriptorName, 2);
1630  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1631 
1632  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1633  const TensorInfo& axisTensorInfo = workloadInfo.m_InputTensorInfos[1];
1634  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1635 
1636  const auto inputTensorNumDimensions = inputTensorInfo.GetNumDimensions();
1637  if (inputTensorNumDimensions > maxDimensions)
1638  {
1639  throw InvalidArgumentException(descriptorName +
1640  ": Input tensors with rank greater than " +
1641  std::to_string(maxDimensions) + " are not supported.");
1642  }
1643 
1644  const auto axisTensorNumDimensions = axisTensorInfo.GetNumDimensions();
1645  if (axisTensorNumDimensions > maxDimensions)
1646  {
1647  throw InvalidArgumentException(descriptorName +
1648  ": More than " + std::to_string(maxDimensions) + " axes cannot be specified.");
1649  }
1650 
1651  if (axisTensorNumDimensions > inputTensorNumDimensions)
1652  {
1653  throw InvalidArgumentException(descriptorName +
1654  ": More axes specified than the number of axes on the input tensor.");
1655  }
1656 
1657  std::vector<DataType> supportedTypes =
1658  {
1667  };
1668 
1669  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1670 
1671  std::vector<DataType> axisSupportedTypes =
1672  {
1674  };
1675 
1676  ValidateDataTypes(axisTensorInfo, axisSupportedTypes, descriptorName);
1677 
1678  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1679  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1680 }
1681 
1683 {
1684  const std::string descriptorName{"FakeQuantizationQueueDescriptor"};
1685 
1686  ValidateNumInputs(workloadInfo, descriptorName, 1);
1687  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1688 
1689  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1690  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1691 
1692  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 2, "input");
1693  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 2, "output");
1694 
1695  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1696 
1698  {
1699  throw InvalidArgumentException(descriptorName + ": min cannot be greater than max");
1700  }
1701 }
1702 
1704 {
1705  const std::string descriptorName{"InstanceNormalizationQueueDescriptor"};
1706 
1707  ValidateNumInputs(workloadInfo, descriptorName, 1);
1708  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1709 
1710  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1711  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1712 
1713  if (inputTensorInfo.GetNumDimensions() > 4)
1714  {
1715  throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
1716  }
1717 
1718  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1719 
1720  // Check the supported data types
1721  std::vector<DataType> supportedTypes =
1722  {
1726  };
1727 
1728  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1729  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1730 }
1731 
1733 {
1734  const std::string descriptorName{"L2NormalizationQueueDescriptor"};
1735 
1736  ValidateNumInputs(workloadInfo, descriptorName, 1);
1737  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1738 
1739  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1740  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1741 
1742  if (inputTensorInfo.GetNumDimensions() > 4)
1743  {
1744  throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
1745  }
1746 
1747  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1748 
1749  // Check the supported data types
1750  std::vector<DataType> supportedTypes =
1751  {
1758  };
1759 
1760  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1761  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1762 }
1763 
1764 void LogSoftmaxQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1765 {
1766  const std::string descriptorName{"LogSoftmaxQueueDescriptor"};
1767 
1768  ValidateNumInputs(workloadInfo, descriptorName, 1);
1769  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1770 
1771  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1772  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1773 
1774  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1775 
1776  std::vector<DataType> supportedTypes =
1777  {
1781  };
1782 
1783  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1784  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1785 }
1786 
1787 void ConstantQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1788 {
1789  const std::string descriptorName{"ConstantQueueDescriptor"};
1790 
1791  ValidateNumInputs(workloadInfo, descriptorName, 0);
1792  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1793 
1794  if (!m_LayerOutput)
1795  {
1796  throw InvalidArgumentException(descriptorName + ": No const input specified.");
1797  }
1798 
1799  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1800  ValidateTensorShapesMatch(m_LayerOutput->GetTensorInfo(), outputTensorInfo, descriptorName, "constant", "output");
1801 
1802  // Check the supported data types
1803  std::vector<DataType> supportedTypes =
1804  {
1813  };
1814 
1815  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1816 }
1817 
1818 void ReshapeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1819 {
1820  const std::string descriptorName{"ReshapeQueueDescriptor"};
1821 
1822  ValidateNumInputs(workloadInfo, descriptorName, 1);
1823  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1824 
1825  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1826  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1827 
1828  ValidateTensorNumElementsMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1829 
1830  // Check the supported data types
1831  std::vector<DataType> supportedTypes =
1832  {
1841  };
1842 
1843  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1844  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1845 }
1846 
1848 {
1849  const std::string descriptorName{"SpaceToBatchNdQueueDescriptor"};
1850 
1851  ValidateNumInputs(workloadInfo, descriptorName, 1);
1852  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1853 
1854  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1855  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1856 
1857  if (m_Parameters.m_BlockShape.size() != m_Parameters.m_PadList.size())
1858  {
1859  throw InvalidArgumentException(descriptorName + ": Pad List must contain the same number of "
1860  "dimensions as Block Shape.");
1861  }
1862 
1863  if (m_Parameters.m_BlockShape.size() == 2)
1864  {
1865  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1866  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1867  }
1868  else if (m_Parameters.m_BlockShape.size() == 1)
1869  {
1870  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 3, "input");
1871  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 3, "output");
1872  }
1873  else
1874  {
1875  throw InvalidArgumentException(descriptorName + ": Invalid Block and Crops size.");
1876  }
1877 
1878  // Check input + padding and output have the same number of elements
1879  DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
1880  const unsigned int inputHeight = inputTensorInfo.GetShape()[dimensionIndices.GetHeightIndex()] +
1881  m_Parameters.m_PadList[0].first + m_Parameters.m_PadList[0].second;
1882  const unsigned int inputWidth = (inputTensorInfo.GetNumDimensions() == 3) ? 1 :
1883  inputTensorInfo.GetShape()[dimensionIndices.GetWidthIndex()] +
1884  m_Parameters.m_PadList[1].first + m_Parameters.m_PadList[1].second;
1885 
1886  const int channelsIndex_int = (m_Parameters.m_DataLayout == DataLayout::NCHW) ? 1 : -1;
1887  const unsigned int channelsIndex = channelsIndex_int < 0 ?
1888  static_cast<unsigned int>(channelsIndex_int) + inputTensorInfo.GetNumDimensions()
1889  : static_cast<unsigned int>(channelsIndex_int);
1890 
1891  const unsigned int numInputElements = inputTensorInfo.GetShape()[0] *
1892  inputHeight *
1893  inputWidth *
1894  inputTensorInfo.GetShape()[channelsIndex];
1895 
1896  if (outputTensorInfo.GetNumElements() != numInputElements)
1897  {
1898  throw InvalidArgumentException(descriptorName + ": Input tensor has " +
1899  to_string(numInputElements) + " after padding but output tensor has " +
1900  to_string(outputTensorInfo.GetNumElements()) + " elements.");
1901  }
1902 
1903  // In a 4D tensor, there will be 2 spatialDimensions (H and W), and the for loop will run twice.
1904  // In a 3D tensor, there will be 1 spatialDimensions, and the for loop will run once.
1905  unsigned int firstSpatialDimension = m_Parameters.m_DataLayout == DataLayout::NCHW ? 2 : 1;
1906  for (unsigned int i = 0; i < m_Parameters.m_BlockShape.size(); ++i)
1907  {
1908  unsigned int spatialDimension = firstSpatialDimension + i;
1909  auto inputSize = inputTensorInfo.GetShape()[spatialDimension] +
1910  m_Parameters.m_PadList[i].first +
1911  m_Parameters.m_PadList[i].second;
1912  if (inputSize % m_Parameters.m_BlockShape[i] != 0)
1913  {
1914  throw InvalidArgumentException(descriptorName + ": Input dimension size after padding must be "
1915  "divisible by Block Shape in dimension: " + to_string(spatialDimension) + ".");
1916  }
1917  }
1918 
1919  std::vector<DataType> supportedTypes =
1920  {
1927  };
1928 
1929  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1930  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1931 }
1932 
1934 {
1935  const std::string descriptorName{"SpaceToDepthQueueDescriptor"};
1936 
1937  ValidateNumInputs(workloadInfo, descriptorName, 1);
1938  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1939 
1940  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1941  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1942 
1943  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1944  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1945 
1946  std::vector<DataType> supportedTypes =
1947  {
1954  };
1955 
1956  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1957  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1958 
1959  ValidateTensorNumElementsMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1960 
1961  if (m_Parameters.m_BlockSize == 0)
1962  {
1963  throw InvalidArgumentException(descriptorName + ": Block size cannot be 0.");
1964  }
1965 
1966  DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
1967  const unsigned int wIndex = dimensionIndices.GetWidthIndex();
1968  const unsigned int hIndex = dimensionIndices.GetHeightIndex();
1969  const unsigned int cIndex = dimensionIndices.GetChannelsIndex();
1970 
1971  const TensorShape& inputShape = inputTensorInfo.GetShape();
1972  if (inputShape[hIndex] % m_Parameters.m_BlockSize != 0 || inputShape[wIndex] % m_Parameters.m_BlockSize != 0)
1973  {
1974  throw InvalidArgumentException(descriptorName + ": Input shape must be divisible "
1975  "by block size in all spatial dimensions");
1976  }
1977 
1978  const TensorShape& outputShape = outputTensorInfo.GetShape();
1979  if (outputShape[cIndex] % (m_Parameters.m_BlockSize * m_Parameters.m_BlockSize) != 0)
1980  {
1981  throw InvalidArgumentException(descriptorName + ": The depth of the output tensor"
1982  "must be divisible by the square of block size." );
1983  }
1984 }
1985 
1986 void FloorQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1987 {
1988  const std::string descriptorName{"FloorQueueDescriptor"};
1989 
1990  ValidateNumInputs(workloadInfo, descriptorName, 1);
1991  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1992 
1993  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1994  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1995 
1996  std::vector<DataType> supportedTypes =
1997  {
2002  };
2003 
2004  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2005  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2006  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2007  ValidateTensorQuantizationSpace(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2008 }
2009 
2010 void LstmQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2011 {
2012  // ported from android/ml/nn/common/operations/LSTM.cpp CheckInputTensorDimensions()
2013 
2014  const std::string descriptorName{"LstmQueueDescriptor"};
2015 
2016  // check dimensions of all inputs and outputs
2017  if (workloadInfo.m_InputTensorInfos.size() != 3)
2018  {
2019  throw InvalidArgumentException(descriptorName + ": Invalid number of inputs.");
2020  }
2021  if (workloadInfo.m_OutputTensorInfos.size() != 4)
2022  {
2023  throw InvalidArgumentException(descriptorName + ": Invalid number of outputs.");
2024  }
2025 
2026  std::vector<DataType> supportedTypes =
2027  {
2032  };
2033 
2034  // check for supported type of one input and match them with all the other input and output
2035  ValidateDataTypes(workloadInfo.m_InputTensorInfos[0], supportedTypes, descriptorName);
2036 
2037  // type matches all other inputs
2038  for (uint32_t i = 1u; i < workloadInfo.m_InputTensorInfos.size(); ++i)
2039  {
2040  ValidateTensorDataTypesMatch(workloadInfo.m_InputTensorInfos[0],
2041  workloadInfo.m_InputTensorInfos[i],
2042  descriptorName,
2043  "input_0",
2044  "input_" + std::to_string(i));
2045  }
2046  // type matches all other outputs
2047  for (uint32_t i = 0u; i < workloadInfo.m_OutputTensorInfos.size(); ++i)
2048  {
2049  ValidateTensorDataTypesMatch(workloadInfo.m_InputTensorInfos[0],
2050  workloadInfo.m_OutputTensorInfos[i],
2051  "LstmQueueDescriptor",
2052  "input_0",
2053  "output_" + std::to_string(i));
2054  }
2055 
2056  // Making sure clipping parameters have valid values.
2057  // == 0 means no clipping
2058  // > 0 means clipping
2059  if (m_Parameters.m_ClippingThresCell < 0.0f)
2060  {
2061  throw InvalidArgumentException(descriptorName + ": negative cell clipping threshold is invalid");
2062  }
2063  if (m_Parameters.m_ClippingThresProj < 0.0f)
2064  {
2065  throw InvalidArgumentException(descriptorName + ": negative projection clipping threshold is invalid");
2066  }
2067 
2068  // Inferring batch size, number of outputs and number of cells from the inputs.
2069  const uint32_t n_input = workloadInfo.m_InputTensorInfos[0].GetShape()[1];
2070  const uint32_t n_batch = workloadInfo.m_InputTensorInfos[0].GetShape()[0];
2071  ValidatePointer(m_InputToOutputWeights, "Null pointer check", "InputToOutputWeights");
2072  const uint32_t n_cell = m_InputToOutputWeights->GetShape()[0];
2073  ValidatePointer(m_RecurrentToOutputWeights, "Null pointer check", "RecurrentToOutputWeights");
2074  const uint32_t n_output = m_RecurrentToOutputWeights->GetShape()[1];
2075 
2076  // input tensor
2077  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[0], 2, (n_batch * n_input),
2078  descriptorName + " input_0");
2079  // outputStateInTensor
2080  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[1], 2, (n_batch * n_output),
2081  descriptorName + " input_1");
2082  // outputStateInTensor
2083  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[2], 2, (n_batch * n_cell),
2084  descriptorName + " input_2");
2085  // scratchBufferTensor
2086  unsigned int scratchBufferSize = m_Parameters.m_CifgEnabled ? n_cell * 3 : n_cell * 4;
2087  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[0], 2, (n_batch * scratchBufferSize),
2088  descriptorName + " output_0");
2089  // outputStateOutTensor
2090  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[1], 2, (n_batch * n_output),
2091  descriptorName + " output_1");
2092  // cellStateOutTensor
2093  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[2], 2, (n_batch * n_cell),
2094  descriptorName + " output_2");
2095  // outputTensor
2096  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[3], 2, (n_batch * n_output),
2097  descriptorName + " output_3");
2098 
2099  // check that dimensions of inputs/outputs and QueueDescriptor data match with each other
2100  if ( m_InputToInputWeights )
2101  {
2103  (n_cell * n_input), "InputLayerNormWeights");
2104  }
2105 
2106  ValidatePointer(m_InputToForgetWeights, "Null pointer check", "InputToForgetWeights");
2108  (n_cell * n_input), "InputToForgetWeights");
2109 
2110  ValidatePointer(m_InputToCellWeights, "Null pointer check", "InputToCellWeights");
2112  (n_cell * n_input), "InputToCellWeights");
2113 
2115  {
2117  (n_cell * n_output), "RecurrentToInputWeights");
2118  }
2119 
2120  ValidatePointer(m_RecurrentToForgetWeights, "Null pointer check", "RecurrentToForgetWeights");
2122  (n_cell * n_output), "RecurrentToForgetWeights");
2123 
2124  ValidatePointer(m_RecurrentToCellWeights, "Null pointer check", "RecurrentToCellWeights");
2126  (n_cell * n_output), "RecurrentToCellWeights");
2127 
2128  // Make sure the input-gate's parameters are either both present (regular
2129  // LSTM) or not at all (CIFG-LSTM). And CifgEnable is set accordingly.
2130  bool cifg_weights_all_or_none = ((m_InputToInputWeights && m_RecurrentToInputWeights &&
2134  if (!cifg_weights_all_or_none)
2135  {
2136  throw InvalidArgumentException(descriptorName + ": Input-Gate's parameters InputToInputWeights and "
2137  "RecurrentToInputWeights must either both be present (regular LSTM) "
2138  "or both not present (CIFG-LSTM). In addition CifgEnable must be set "
2139  "accordingly.");
2140  }
2141 
2142  if ( m_CellToInputWeights )
2143  {
2145  n_cell, "CellToInputWeights");
2146  }
2147  if ( m_CellToForgetWeights )
2148  {
2150  n_cell, "CellToForgetWeights");
2151  }
2152  if ( m_CellToOutputWeights )
2153  {
2155  n_cell, "CellToOutputWeights");
2156  }
2157 
2158  // Making sure the peephole weights are there all or none. And PeepholeEnable is set accordingly.
2159  bool peephole_weights_all_or_none =
2164  if (!peephole_weights_all_or_none)
2165  {
2166  throw InvalidArgumentException(descriptorName + ": Invalid combination of peephole parameters.");
2167  }
2168 
2169  // Make sure the input gate bias is present only when not a CIFG-LSTM.
2171  {
2172  if (m_InputGateBias)
2173  {
2174  throw InvalidArgumentException(descriptorName + ": InputGateBias is present and CIFG-LSTM is enabled.");
2175  }
2176  }
2177  else
2178  {
2179  if (!m_InputGateBias)
2180  {
2181  throw InvalidArgumentException(descriptorName + ": If CIFG-LSTM is disabled InputGateBias "
2182  "must be present.");
2183  }
2185  n_cell, "InputGateBias");
2186  }
2187 
2188  ValidatePointer(m_ForgetGateBias, "Null pointer check", "ForgetGateBias");
2189  ValidateTensorNumDimNumElem(m_ForgetGateBias->GetTensorInfo(), 1, n_cell, "ForgetGateBias");
2190 
2191  ValidatePointer(m_CellBias, "Null pointer check", "CellBias");
2192  ValidateTensorNumDimNumElem(m_CellBias->GetTensorInfo(), 1, n_cell, "CellBias");
2193 
2194  ValidatePointer(m_OutputGateBias, "Null pointer check", "OutputGateBias");
2195  ValidateTensorNumDimNumElem(m_OutputGateBias->GetTensorInfo(), 1, n_cell, "OutputGateBias");
2196 
2197  if (m_ProjectionWeights)
2198  {
2200  (n_cell * n_output), "ProjectionWeights");
2201  }
2202  if (m_ProjectionBias)
2203  {
2204  ValidateTensorNumDimNumElem(m_ProjectionBias->GetTensorInfo(), 1, n_output, "ProjectionBias");
2205  }
2206 
2207  // Making sure the projection tensors are consistent:
2208  // 1) If projection weight is not present, then projection bias should not be
2209  // present.
2210  // 2) If projection weight is present, then projection bias is optional.
2211  bool projecton_tensors_consistent = ((!m_ProjectionWeights && !m_ProjectionBias &&
2217  if (!projecton_tensors_consistent)
2218  {
2219  throw InvalidArgumentException(descriptorName + ": Projection tensors are inconsistent.");
2220  }
2221 
2222  // The four layer normalization weights either all have values or none of them have values. Additionally, if
2223  // CIFG is used, input layer normalization weights tensor is omitted and the other layer normalization weights
2224  // either all have values or none of them have values. Layer normalization is used when the values of all the
2225  // layer normalization weights are present
2227  {
2228  ValidateTensorNumDimNumElem(m_InputLayerNormWeights->GetTensorInfo(), 1, n_cell, "InputLayerNormWeights");
2229  }
2231  {
2232  ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
2233  }
2235  {
2236  ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
2237  }
2239  {
2240  ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
2241  }
2242 
2244  {
2246  {
2248  {
2249  throw InvalidArgumentException(descriptorName + ": Layer normalisation is enabled and CIFG-LSTM is "
2250  "disabled but InputLayerNormWeights are not present");
2251  }
2253  1, n_cell, "InputLayerNormWeights");
2254  }
2255  else if (m_InputLayerNormWeights)
2256  {
2257  throw InvalidArgumentException(descriptorName + ":InputLayerNormWeights are present while CIFG is "
2258  "enabled");
2259  }
2260 
2261  ValidatePointer(m_ForgetLayerNormWeights, "Null pointer check layer normalisation enabled",
2262  "ForgetLayerNormWeights");
2263  ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
2264 
2265  ValidatePointer(m_OutputLayerNormWeights, "Null pointer check layer normalisation enabled",
2266  "OutputLayerNormWeights");
2267  ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
2268 
2269  ValidatePointer(m_CellLayerNormWeights, "Null pointer check layer normalisation enabled",
2270  "CellLayerNormWeights");
2271  ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
2272  }
2274  {
2275  throw InvalidArgumentException(descriptorName + ": Layer normalisation is disabled but one or more layer "
2276  "normalisation weights are present.");
2277  }
2278 }
2279 
2281 {
2282  const std::string descriptorName{"ConvertFp32ToFp16QueueDescriptor"};
2283 
2284  ValidateNumInputs(workloadInfo, descriptorName, 1);
2285  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2286 
2287  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2288  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2289 
2290  if (inputTensorInfo.GetDataType() != DataType::Float32)
2291  {
2292  throw InvalidArgumentException(descriptorName + ": Input tensor type must be Float32.");
2293  }
2294 
2295  if (outputTensorInfo.GetDataType() != DataType::Float16)
2296  {
2297  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Float16.");
2298  }
2299 
2300  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2301 }
2302 
2304 {
2305  const std::string descriptorName{"ConvertFp16ToFp32QueueDescriptor"};
2306 
2307  ValidateNumInputs(workloadInfo, descriptorName, 1);
2308  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2309 
2310  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2311  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2312 
2313  if (inputTensorInfo.GetDataType() != DataType::Float16)
2314  {
2315  throw InvalidArgumentException(descriptorName + ": Input tensor type must be Float16.");
2316  }
2317 
2318  if (outputTensorInfo.GetDataType() != DataType::Float32)
2319  {
2320  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Float32.");
2321  }
2322 
2323  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2324 }
2325 
2326 void DivisionQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2327 {
2328  const std::string descriptorName{"DivisionQueueDescriptor"};
2329 
2330  ValidateNumInputs(workloadInfo, descriptorName, 2);
2331  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2332 
2333  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2334  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2335  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2336 
2337  std::vector<DataType> supportedTypes =
2338  {
2346  };
2347 
2348  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2349  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2350  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
2351 
2352  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2353  inputTensorInfo1,
2354  outputTensorInfo,
2355  descriptorName,
2356  "input_0",
2357  "input_1");
2358 }
2359 
2361 {
2362  const std::string descriptorName{"SubtractionQueueDescriptor"};
2363 
2364  ValidateNumInputs(workloadInfo, descriptorName, 2);
2365  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2366 
2367  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2368  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2369  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2370 
2371  std::vector<DataType> supportedTypes =
2372  {
2380  };
2381 
2382  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2383  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2384  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
2385 
2386  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2387  inputTensorInfo1,
2388  outputTensorInfo,
2389  descriptorName,
2390  "input_0",
2391  "input_1");
2392 }
2393 
2394 void MaximumQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2395 {
2396  const std::string descriptorName{"MaximumQueueDescriptor"};
2397 
2398  ValidateNumInputs(workloadInfo, descriptorName, 2);
2399  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2400 
2401  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2402  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2403  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2404 
2405  std::vector<DataType> supportedTypes =
2406  {
2414  };
2415 
2416  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2417  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2418  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
2419 
2420  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2421  inputTensorInfo1,
2422  outputTensorInfo,
2423  descriptorName,
2424  "input_0",
2425  "input_1");
2426 }
2427 
2428 void MeanQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2429 {
2430  const std::string descriptorName{"MeanQueueDescriptor"};
2431 
2432  ValidateNumInputs(workloadInfo, descriptorName, 1);
2433  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2434 
2435  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2436  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2437 
2438  std::vector<DataType> supportedTypes =
2439  {
2446  };
2447 
2448  // First check if input tensor data type is supported, then
2449  // check if this data type matches the output tensor data type
2450  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2451  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2452 
2454  {
2455  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, inputTensorInfo.GetNumDimensions(), "output");
2456  }
2457  else if (m_Parameters.m_Axis.empty())
2458  {
2459  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 1, "output");
2460  }
2461  else
2462  {
2463  unsigned int outputDim =
2464  inputTensorInfo.GetNumDimensions() - armnn::numeric_cast<unsigned int>(m_Parameters.m_Axis.size());
2465  ValidateTensorNumDimensions(outputTensorInfo,
2466  descriptorName,
2467  outputDim > 0 ? outputDim : 1,
2468  "output");
2469  }
2470 }
2471 
2472 void PadQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2473 {
2474  const std::string descriptorName{"PadQueueDescriptor"};
2475 
2476  ValidateNumInputs(workloadInfo, descriptorName, 1);
2477  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2478 
2479  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2480  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2481 
2482  // input and output should have the same number of dimensions
2483  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, inputTensorInfo.GetNumDimensions(), "output");
2484 
2485  // there should be entry in the pad list for each dimension in the input tensor
2486  if (m_Parameters.m_PadList.size() != inputTensorInfo.GetNumDimensions()) {
2487  throw InvalidArgumentException(descriptorName + ":Pad List should contain the same number of entries "
2488  "as there are dimensions in the input tensor that is " +
2489  std::to_string(inputTensorInfo.GetNumDimensions()) + " entries " +
2490  " not " + std::to_string(m_Parameters.m_PadList.size()) + " entries.");
2491  }
2492 }
2493 
2494 void QuantizeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2495 {
2496  const std::string descriptorName{"QuantizeQueueDescriptor"};
2497 
2498  ValidateNumInputs(workloadInfo, descriptorName, 1);
2499  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2500 
2501  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2502  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2503 
2504  std::vector<DataType> supportedTypes =
2505  {
2513  };
2514 
2515  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2516 
2517  if (!IsQuantizedType(outputTensorInfo.GetDataType()))
2518  {
2519  throw InvalidArgumentException(descriptorName + ": Output of quantized layer must be quantized type.");
2520  }
2521 }
2522 
2524 {
2525  const std::string descriptorName{"BatchToSpaceNdQueueDescriptor"};
2526 
2527  ValidateNumInputs(workloadInfo, descriptorName, 1);
2528  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2529 
2530  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2531  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2532 
2533  if (m_Parameters.m_BlockShape.size() != m_Parameters.m_Crops.size())
2534  {
2535  throw InvalidArgumentException(descriptorName + ": Crops must contain the same number of "
2536  "dimensions as Block Shape.");
2537  }
2538 
2539  if (m_Parameters.m_BlockShape.size() == 2)
2540  {
2541  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
2542  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
2543  }
2544  else if (m_Parameters.m_BlockShape.size() == 1)
2545  {
2546  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 3, "input");
2547  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 3, "output");
2548  }
2549  else
2550  {
2551  throw InvalidArgumentException(descriptorName + ": Invalid Block and Crops size.");
2552  }
2553 
2554  // In a 4D tensor, there will be 2 spatialDimensions (H and W), and the for loop will run twice.
2555  // In a 3D tensor, there will be 1 spatialDimensions, and the for loop will run once.
2556  unsigned int firstSpatialDimension = m_Parameters.m_DataLayout == DataLayout::NCHW ? 2 : 1;
2557  for (unsigned int i = 0; i < m_Parameters.m_BlockShape.size(); ++i)
2558  {
2559  unsigned int spatialDimension = firstSpatialDimension + i;
2560  unsigned int cropSize = m_Parameters.m_Crops[i].first + m_Parameters.m_Crops[i].second;
2561  unsigned int outputSize = inputTensorInfo.GetShape()[spatialDimension] * m_Parameters.m_BlockShape[i];
2562  if (cropSize > outputSize)
2563  {
2564  throw InvalidArgumentException(descriptorName + ": CropSize must be less than or equal to the uncropped"
2565  "outputSize in dimension: " + to_string(spatialDimension) + ".");
2566  }
2567  }
2568 
2569  std::vector<DataType> supportedTypes =
2570  {
2577  };
2578 
2579  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2580  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2581 }
2582 
2584 {
2585  const std::string descriptorName{"StridedSliceQueueDescriptor"};
2586 
2587  ValidateNumInputs(workloadInfo, descriptorName, 1);
2588  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2589 
2590  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2591  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2592 
2593  std::vector<DataType> supportedTypes =
2594  {
2601  };
2602 
2603  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2604  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2605 
2606  ValidateTensorQuantizationSpace(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2607 
2608  const uint32_t rank = inputTensorInfo.GetNumDimensions();
2609  if (rank > 4)
2610  {
2611  throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
2612  }
2613 
2614  // Begin, End & Stride length must be of rank(input0)
2615  if (m_Parameters.m_Begin.size() != rank)
2616  {
2617  throw InvalidArgumentException(descriptorName + ": Begin length must be of rank " + std::to_string(rank));
2618  }
2619 
2620  if (m_Parameters.m_End.size() != rank)
2621  {
2622  throw InvalidArgumentException(descriptorName + ": End length must be of rank " + std::to_string(rank));
2623  }
2624 
2625  if (m_Parameters.m_Stride.size() != rank)
2626  {
2627  throw InvalidArgumentException(descriptorName + ": Stride length must be of rank " + std::to_string(rank));
2628  }
2629 
2630  // Stride entries must be non-zero
2631  for (auto& stride : m_Parameters.m_Stride)
2632  {
2633  if (stride == 0)
2634  {
2635  throw InvalidArgumentException(descriptorName + ": Stride entries must be non-zero.");
2636  }
2637  }
2638 }
2639 
2640 void MinimumQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2641 {
2642  const std::string descriptorName{"MinimumQueueDescriptor"};
2643 
2644  ValidateNumInputs(workloadInfo, descriptorName, 2);
2645  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2646 
2647  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2648  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2649  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2650 
2651  std::vector<DataType> supportedTypes =
2652  {
2660  };
2661 
2662  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2663  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2664  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
2665 
2666  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2667  inputTensorInfo1,
2668  outputTensorInfo,
2669  descriptorName,
2670  "input_0",
2671  "input_1");
2672 }
2673 
2674 void DebugQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2675 {
2676  const std::string descriptorName{"DebugQueueDescriptor"};
2677 
2678  ValidateNumInputs(workloadInfo, descriptorName, 1);
2679  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2680 }
2681 
2682 void EqualQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2683 {
2684  const std::string descriptorName{"EqualQueueDescriptor"};
2685 
2686  ValidateNumInputs(workloadInfo, descriptorName, 2);
2687  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2688 
2689  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2690  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2691  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2692 
2693  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2694  inputTensorInfo1,
2695  outputTensorInfo,
2696  descriptorName,
2697  "input_0",
2698  "input_1");
2699 
2700  if (outputTensorInfo.GetDataType() != DataType::Boolean)
2701  {
2702  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
2703  }
2704 }
2705 
2706 void GreaterQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2707 {
2708  const std::string descriptorName{"GreaterQueueDescriptor"};
2709 
2710  ValidateNumInputs(workloadInfo, descriptorName, 2);
2711  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2712 
2713  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2714  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2715  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2716 
2717  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2718  inputTensorInfo1,
2719  outputTensorInfo,
2720  descriptorName,
2721  "input_0",
2722  "input_1");
2723 
2724  if (outputTensorInfo.GetDataType() != DataType::Boolean)
2725  {
2726  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
2727  }
2728 }
2729 
2730 void RsqrtQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2731 {
2732  const std::string descriptorName{"RsqrtQueueDescriptor"};
2733 
2734  ValidateNumInputs(workloadInfo, descriptorName, 1);
2735  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2736 
2737  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2738  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2739 
2740  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2741 
2742  std::vector<DataType> supportedTypes =
2743  {
2750  };
2751 
2752  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2753  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2754 }
2755 
2756 void GatherNdQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2757 {
2758  const std::string descriptorName{"GatherNdQueueDescriptor"};
2759 
2760  ValidateNumInputs(workloadInfo, descriptorName, 2);
2761  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2762 
2763  const TensorInfo& indicesTensorInfo = workloadInfo.m_InputTensorInfos[1];
2764  if (indicesTensorInfo.GetDataType() != DataType::Signed32)
2765  {
2766  throw InvalidArgumentException(descriptorName + ": Indices tensor type must be Int32.");
2767  }
2768 
2769  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2770  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2771 
2772  std::vector<DataType> supportedTypes =
2773  {
2781  };
2782 
2783  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2784 
2785  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2786 
2787  unsigned int outputDim = outputTensorInfo.GetNumDimensions();
2788  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, outputDim, "output");
2789 }
2790 
2791 void GatherQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2792 {
2793  const std::string descriptorName{"GatherQueueDescriptor"};
2794 
2795  ValidateNumInputs(workloadInfo, descriptorName, 2);
2796  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2797 
2798  const TensorInfo& indicesTensorInfo = workloadInfo.m_InputTensorInfos[1];
2799  if (indicesTensorInfo.GetDataType() != DataType::Signed32)
2800  {
2801  throw InvalidArgumentException(descriptorName + ": Indices tensor type must be Int32.");
2802  }
2803 
2804  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2805  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2806 
2807  std::vector<DataType> supportedTypes =
2808  {
2816  };
2817 
2818  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2819 
2820  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2821 
2822  unsigned int outputDim = inputTensorInfo.GetNumDimensions() + indicesTensorInfo.GetNumDimensions() - 1;
2823  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, outputDim, "output");
2824 }
2825 
2827 {
2828  const std::string& descriptorName{"DetectionPostProcessQueueDescriptor"};
2829 
2830  ValidateNumInputs(workloadInfo, descriptorName, 2);
2831 
2832  if (workloadInfo.m_OutputTensorInfos.size() != 4)
2833  {
2834  throw InvalidArgumentException(descriptorName + ": Requires exactly four outputs. " +
2835  to_string(workloadInfo.m_OutputTensorInfos.size()) + " has been provided.");
2836  }
2837 
2838  if (m_Anchors == nullptr)
2839  {
2840  throw InvalidArgumentException(descriptorName + ": Anchors tensor descriptor is missing.");
2841  }
2842 
2843  const TensorInfo& boxEncodingsInfo = workloadInfo.m_InputTensorInfos[0];
2844  const TensorInfo& scoresInfo = workloadInfo.m_InputTensorInfos[1];
2845  const TensorInfo& anchorsInfo = m_Anchors->GetTensorInfo();
2846 
2847  const TensorInfo& detectionBoxesInfo = workloadInfo.m_OutputTensorInfos[0];
2848  const TensorInfo& detectionClassesInfo = workloadInfo.m_OutputTensorInfos[1];
2849  const TensorInfo& detectionScoresInfo = workloadInfo.m_OutputTensorInfos[2];
2850  const TensorInfo& numDetectionsInfo = workloadInfo.m_OutputTensorInfos[3];
2851 
2852  ValidateTensorNumDimensions(boxEncodingsInfo, descriptorName, 3, "box encodings");
2853  ValidateTensorNumDimensions(scoresInfo, descriptorName, 3, "scores");
2854  ValidateTensorNumDimensions(anchorsInfo, descriptorName, 2, "anchors");
2855 
2856  const std::vector<DataType> supportedInputTypes =
2857  {
2864  };
2865 
2866  ValidateDataTypes(boxEncodingsInfo, supportedInputTypes, descriptorName);
2867  ValidateDataTypes(scoresInfo, supportedInputTypes, descriptorName);
2868  ValidateDataTypes(anchorsInfo, supportedInputTypes, descriptorName);
2869 
2870  ValidateTensorNumDimensions(detectionBoxesInfo, descriptorName, 3, "detection boxes");
2871  ValidateTensorNumDimensions(detectionScoresInfo, descriptorName, 2, "detection scores");
2872  ValidateTensorNumDimensions(detectionClassesInfo, descriptorName, 2, "detection classes");
2873  ValidateTensorNumDimensions(numDetectionsInfo, descriptorName, 1, "num detections");
2874 
2875  // NOTE: Output is always Float32 regardless of input type
2876  ValidateTensorDataType(detectionBoxesInfo, DataType::Float32, descriptorName, "detection boxes");
2877  ValidateTensorDataType(detectionScoresInfo, DataType::Float32, descriptorName, "detection scores");
2878  ValidateTensorDataType(detectionClassesInfo, DataType::Float32, descriptorName, "detection classes");
2879  ValidateTensorDataType(numDetectionsInfo, DataType::Float32, descriptorName, "num detections");
2880 
2882  {
2883  throw InvalidArgumentException(descriptorName + ": Intersection over union threshold "
2884  "must be positive and less than or equal to 1.");
2885  }
2886 
2887  if (scoresInfo.GetShape()[2] != m_Parameters.m_NumClasses + 1)
2888  {
2889  throw InvalidArgumentException(descriptorName + ": Number of classes with background "
2890  "should be equal to number of classes + 1.");
2891  }
2892 }
2893 
2894 void DequantizeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2895 {
2896  const std::string& descriptorName{"DequantizeQueueDescriptor"};
2897 
2898  ValidateNumInputs(workloadInfo, descriptorName, 1);
2899  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2900 
2901  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2902  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2903 
2904  std::vector<DataType> inputSupportedTypes =
2905  {
2911  };
2912  ValidateDataTypes(inputTensorInfo, inputSupportedTypes, descriptorName);
2913 
2914  std::vector<DataType> outputSupportedTypes =
2915  {
2919  };
2920 
2921  ValidateDataTypes(outputTensorInfo, outputSupportedTypes, descriptorName);
2922 }
2923 
2924 void MergeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2925 {
2926  const std::string& descriptorName{"MergeQueueDescriptor"};
2927 
2928  ValidateNumInputs(workloadInfo, descriptorName, 2);
2929  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2930 
2931  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2932  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2933  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2934 
2935  ValidateTensorShapesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
2936  ValidateTensorShapesMatch(inputTensorInfo0, outputTensorInfo, descriptorName, "input_0", "output");
2937 
2938  ValidateTensorDataTypesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
2939  ValidateTensorDataTypesMatch(inputTensorInfo0, outputTensorInfo, descriptorName, "input_0", "output");
2940 }
2941 
2942 void ShapeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2943 {
2944  const std::string& descriptorName{"ShapeQueueDescriptor"};
2945 
2946  ValidateNumInputs(workloadInfo, descriptorName, 1);
2947  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2948 
2949  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2950  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2951 
2952  std::vector<DataType> supportedTypes =
2953  {
2962  };
2963 
2964  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2965  ValidateDataTypes(outputTensorInfo, {DataType::Signed32}, descriptorName);
2966 }
2967 
2968 void SwitchQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2969 {
2970  const std::string& descriptorName{"SwitchQueueDescriptor"};
2971 
2972  ValidateNumInputs(workloadInfo, descriptorName, 2);
2973  ValidateNumOutputs(workloadInfo, descriptorName, 2);
2974 
2975  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2976  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2977 
2978  const TensorInfo& outputTensorInfo0 = workloadInfo.m_OutputTensorInfos[0];
2979  const TensorInfo& outputTensorInfo1 = workloadInfo.m_OutputTensorInfos[1];
2980 
2981  std::vector<DataType> supportedTypes =
2982  {
2988  };
2989 
2990  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2991  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2992 
2993  ValidateDataTypes(outputTensorInfo0, supportedTypes, descriptorName);
2994  ValidateDataTypes(outputTensorInfo1, supportedTypes, descriptorName);
2995 
2996  ValidateTensorShapesMatch(inputTensorInfo0,
2997  outputTensorInfo0,
2998  descriptorName,
2999  "input_0",
3000  "output_0");
3001 
3002  ValidateTensorShapesMatch(inputTensorInfo0,
3003  outputTensorInfo1,
3004  descriptorName,
3005  "input_0",
3006  "output_1");
3007 }
3008 
3009 void PreCompiledQueueDescriptor::Validate(const WorkloadInfo& /*workloadInfo*/) const
3010 {
3011  // This is internally generated, so it should not need validation.
3012 }
3013 
3014 void PreluQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3015 {
3016  const std::string& descriptorName{"PreluQueueDescriptor"};
3017 
3018  ValidateNumInputs(workloadInfo, descriptorName, 2);
3019  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3020 
3021  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3022  const TensorInfo& alphaTensorInfo = workloadInfo.m_InputTensorInfos[1];
3023  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3024 
3025  std::vector<DataType> supportedTypes
3026  {
3033  };
3034 
3035  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3036  ValidateDataTypes(alphaTensorInfo, supportedTypes, descriptorName);
3037 
3038  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
3039 
3040  ValidateTensorDataTypesMatch(inputTensorInfo, alphaTensorInfo, descriptorName, "input", "alpha");
3041  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "ouptut");
3042 
3043  ValidateBroadcastTensorShapesMatch(inputTensorInfo,
3044  alphaTensorInfo,
3045  outputTensorInfo,
3046  descriptorName,
3047  "input",
3048  "alpha");
3049 }
3050 
3052 {
3053  const std::string descriptorName{"TransposeConvolution2dQueueDescriptor"};
3054 
3055  ValidateNumInputs(workloadInfo, descriptorName, 1);
3056  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3057 
3058  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3059  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3060 
3061  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
3062  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
3063 
3064  ValidatePointer(m_Weight, descriptorName, "weight");
3065 
3066  const TensorInfo& weightTensorInfo = m_Weight->GetTensorInfo();
3067  ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 4, "weight");
3068 
3069  ValidateWeightDataType(inputTensorInfo, weightTensorInfo, descriptorName);
3070 
3071  Optional<TensorInfo> optionalBiasTensorInfo;
3073  {
3074  ValidatePointer(m_Bias, descriptorName, "bias");
3075 
3076  optionalBiasTensorInfo = MakeOptional<TensorInfo>(m_Bias->GetTensorInfo());
3077  const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value();
3078 
3079  ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
3080  ValidateBiasTensorQuantization(biasTensorInfo, weightTensorInfo, descriptorName);
3081  }
3082 
3083  ValidatePerAxisQuantization(inputTensorInfo,
3084  outputTensorInfo,
3085  weightTensorInfo,
3086  optionalBiasTensorInfo,
3087  descriptorName);
3088 
3089  std::vector<DataType> supportedTypes =
3090  {
3097  };
3098 
3099  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3100  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3101 }
3102 
3103 void TransposeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3104 {
3105  const std::string descriptorName{"TransposeQueueDescriptor"};
3106 
3107  ValidateNumInputs(workloadInfo, descriptorName, 1);
3108  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3109 
3110  const PermutationVector& mapping = m_Parameters.m_DimMappings;
3111 
3112  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3113  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3114 
3115  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, mapping.GetSize(), "input");
3116  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, mapping.GetSize(), "output");
3117 
3118  for (unsigned int i = 0u; i < mapping.GetSize(); ++i)
3119  {
3120  if (inputTensorInfo.GetShape()[mapping[i]] != outputTensorInfo.GetShape()[i])
3121  {
3122  throw InvalidArgumentException(descriptorName + ": src dimension " + to_string(mapping[i]) +
3123  " (=" + to_string(inputTensorInfo.GetShape()[mapping[i]]) + ") " +
3124  "must match dst dimension " + to_string(i) +
3125  " (=" + to_string(outputTensorInfo.GetShape()[i]) + ")");
3126  }
3127  }
3128 
3129  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3130 }
3131 
3133 {
3134  const std::string descriptorName{"TransposeQueueDescriptor"};
3135 
3136  ValidateNumInputs(workloadInfo, descriptorName, 1);
3137  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3138 
3139  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3140  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3141 
3142  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3143 }
3144 
3145 void QLstmQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3146 {
3147  const std::string descriptorName{"QLstmQueueDescriptor"};
3148 
3149  // Validate number of inputs/outputs
3150  ValidateNumInputs(workloadInfo, descriptorName, 3);
3151  ValidateNumOutputs(workloadInfo, descriptorName, 3);
3152 
3153  // Input/output tensor info
3154  auto inputInfo = workloadInfo.m_InputTensorInfos[0];
3155  auto outputStateInInfo = workloadInfo.m_InputTensorInfos[1];
3156  auto cellStateInInfo = workloadInfo.m_InputTensorInfos[2];
3157 
3158  auto outputStateOutInfo = workloadInfo.m_OutputTensorInfos[0];
3159  auto cellStateOutInfo = workloadInfo.m_OutputTensorInfos[1];
3160  auto outputInfo = workloadInfo.m_OutputTensorInfos[2];
3161 
3162  // Supported types for various tensors in QLSTM
3163  std::vector<DataType> inputOutputSupportedTypes =
3164  {
3166  };
3167 
3168  std::vector<DataType> cellStateSupportedTypes =
3169  {
3171  };
3172 
3173  std::vector<DataType> weightsSupportedTypes =
3174  {
3176  };
3177 
3178  std::vector<DataType> layerNormPeepholeWeightsSupportedTypes =
3179  {
3181  };
3182 
3183  std::vector<DataType> biasSupportedTypes =
3184  {
3186  };
3187 
3188  // Validate types of input/output tensors
3189  ValidateDataTypes(inputInfo, inputOutputSupportedTypes, descriptorName);
3190  ValidateDataTypes(outputStateInInfo, inputOutputSupportedTypes, descriptorName);
3191  ValidateDataTypes(cellStateInInfo, cellStateSupportedTypes, descriptorName);
3192 
3193  ValidateDataTypes(outputStateOutInfo, inputOutputSupportedTypes, descriptorName);
3194  ValidateDataTypes(cellStateOutInfo, cellStateSupportedTypes, descriptorName);
3195  ValidateDataTypes(outputInfo, inputOutputSupportedTypes, descriptorName);
3196 
3197  // Validate matching types of input/output tensors
3198  ValidateTensorDataTypesMatch(inputInfo, outputStateInInfo, descriptorName, "input", "outputStateIn");
3199  ValidateTensorDataTypesMatch(outputStateInInfo, outputStateOutInfo, descriptorName,
3200  "outputStateIn", "outputStateOut");
3201  ValidateTensorDataTypesMatch(cellStateInInfo, cellStateOutInfo, descriptorName, "cellStateIn", "cellStateOut");
3202 
3203  // Infer number of batches, number of units, input size and output size from tensor dimensions
3204  const uint32_t numBatches = inputInfo.GetShape()[0];
3205  const uint32_t inputSize = inputInfo.GetShape()[1];
3206  const uint32_t outputSize = outputStateInInfo.GetShape()[1];
3207  const uint32_t numUnits = cellStateInInfo.GetShape()[1];
3208 
3209  // Validate number of dimensions and number of elements for input/output tensors
3210  ValidateTensorNumDimNumElem(inputInfo, 2, (numBatches * inputSize), descriptorName + " input");
3211  ValidateTensorNumDimNumElem(outputStateInInfo, 2, (numBatches * outputSize), descriptorName + " outputStateIn");
3212  ValidateTensorNumDimNumElem(cellStateInInfo, 2, (numBatches * numUnits), descriptorName + " cellStateIn");
3213 
3214  ValidateTensorNumDimNumElem(outputStateOutInfo, 2, (numBatches * outputSize), descriptorName + " outputStateOut");
3215  ValidateTensorNumDimNumElem(cellStateOutInfo, 2, (numBatches * numUnits), descriptorName + " cellStateOut");
3216  ValidateTensorNumDimNumElem(outputInfo, 2, (numBatches * outputSize), descriptorName + " output");
3217 
3218  // Validate number of dimensions and number of elements for MANDATORY weight tensors
3219  ValidatePointer(m_InputToForgetWeights, descriptorName, "InputToForgetWeights");
3220  auto inputToForgetWeightsInfo = m_InputToForgetWeights->GetTensorInfo();
3221  ValidateTensorNumDimNumElem(inputToForgetWeightsInfo, 2, (numUnits * inputSize), " InputToForgetWeights");
3222 
3223  ValidatePointer(m_InputToCellWeights, descriptorName, "InputToCellWeights");
3224  auto inputToCellWeightsInfo = m_InputToCellWeights->GetTensorInfo();
3225  ValidateTensorNumDimNumElem(inputToCellWeightsInfo, 2, (numUnits * inputSize), " InputToCellWeights");
3226 
3227  ValidatePointer(m_InputToOutputWeights, descriptorName, "InputToOutputWeights");
3228  auto inputToOutputWeightsInfo = m_InputToOutputWeights->GetTensorInfo();
3229  ValidateTensorNumDimNumElem(inputToOutputWeightsInfo, 2, (numUnits * inputSize), " InputToOutputWeights");
3230 
3231  ValidatePointer(m_RecurrentToForgetWeights, descriptorName, "RecurrentToForgetWeights");
3232  auto recurrentToForgetWeightsInfo = m_RecurrentToForgetWeights->GetTensorInfo();
3233  ValidateTensorNumDimNumElem(recurrentToForgetWeightsInfo, 2, (numUnits * outputSize),
3234  " RecurrentToForgetWeights");
3235 
3236  ValidatePointer(m_RecurrentToCellWeights, descriptorName, "RecurrentToCellWeights");
3237  auto recurrentToCellWeightsInfo = m_RecurrentToCellWeights->GetTensorInfo();
3238  ValidateTensorNumDimNumElem(recurrentToCellWeightsInfo, 2, (numUnits * outputSize), " RecurrentToCellWeights");
3239 
3240  ValidatePointer(m_RecurrentToOutputWeights, descriptorName, "RecurrentToOutputWeights");
3241  auto recurrentToOutputWeightsInfo = m_RecurrentToOutputWeights->GetTensorInfo();
3242  ValidateTensorNumDimNumElem(recurrentToOutputWeightsInfo, 2, (numUnits * outputSize), " RecurrentToCellWeights");
3243 
3244  // Validate data types for MANDATORY weights tensors (all should match each other)
3245  ValidateDataTypes(inputToForgetWeightsInfo, weightsSupportedTypes, descriptorName);
3246 
3247  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, inputToCellWeightsInfo, descriptorName,
3248  "inputToForgetWeights", "inputToCellWeights");
3249  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, inputToOutputWeightsInfo, descriptorName,
3250  "inputToForgetWeights", "inputToOutputWeights");
3251 
3252  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, recurrentToForgetWeightsInfo, descriptorName,
3253  "inputToForgetWeights", "recurrentToForgeteights");
3254  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, recurrentToCellWeightsInfo, descriptorName,
3255  "inputToForgetWeights", "recurrentToCellWeights");
3256  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, recurrentToOutputWeightsInfo, descriptorName,
3257  "inputToForgetWeights", "recurrentToOutputWeights");
3258 
3259  // Validate number of dimensions and number of elements for MANDATORY bias tensors
3260  ValidatePointer(m_ForgetGateBias, descriptorName, "ForgetGateBias");
3261  auto forgetGateBiasInfo = m_ForgetGateBias->GetTensorInfo();
3262  ValidateTensorNumDimNumElem(forgetGateBiasInfo, 1, numUnits, " ForgetGateBias");
3263 
3264  ValidatePointer(m_CellBias, descriptorName, "CellBias");
3265  auto cellBiasInfo = m_CellBias->GetTensorInfo();
3266  ValidateTensorNumDimNumElem(cellBiasInfo, 1, numUnits, " CellBias");
3267 
3268  ValidatePointer(m_OutputGateBias, descriptorName, "OutputGateBias");
3269  auto outputGateBiasInfo = m_OutputGateBias->GetTensorInfo();
3270  ValidateTensorNumDimNumElem(outputGateBiasInfo, 1, numUnits, " OutputGateBias");
3271 
3272  // Validate data types for MANDATORY bias tensors
3273  ValidateDataTypes(forgetGateBiasInfo, biasSupportedTypes, descriptorName);
3274 
3275  ValidateTensorDataTypesMatch(forgetGateBiasInfo, cellBiasInfo, descriptorName,
3276  "forgetGateBias", "cellBias");
3277  ValidateTensorDataTypesMatch(forgetGateBiasInfo, outputGateBiasInfo, descriptorName,
3278  "forgetGateBias", "outputGateBias");
3279 
3280  // Validate OPTIONAL params: CIFG (inputToInputWeights, recurrentToInputWeights, inputGateBias)
3281  const bool allCifgParamsPresentOrNot = ((m_InputToInputWeights && m_RecurrentToInputWeights && m_InputGateBias &&
3285 
3286  if (!allCifgParamsPresentOrNot)
3287  {
3288  throw InvalidArgumentException(descriptorName +
3289  ": InputToInputWeights, RecurrentToInputWeights and InputGateBias must either all be present "
3290  "(CIFG disabled) or not be present at all (CIFG enabled). m_Parameters.m_CifgEnabled should be "
3291  "set appropriately.");
3292  }
3293 
3295  {
3296  // Validate number of dimensions and number of elements
3297  auto inputToInputWeightsInfo = m_InputToInputWeights->GetTensorInfo();
3298  ValidateTensorNumDimNumElem(inputToInputWeightsInfo, 2, (numUnits * inputSize), " InputToInputWeights");
3299 
3300  auto recurrentToInputWeightsInfo = m_RecurrentToInputWeights->GetTensorInfo();
3301  ValidateTensorNumDimNumElem(recurrentToInputWeightsInfo, 2, (numUnits * outputSize),
3302  " RecurrentToInputWeights");
3303 
3304  auto inputGateBiasInfo = m_InputGateBias->GetTensorInfo();
3305  ValidateTensorNumDimNumElem(inputGateBiasInfo, 1, numUnits, " InputGateBias");
3306 
3307  // Validate data types
3308  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, inputToInputWeightsInfo, descriptorName,
3309  "inputToForgetWeights", "inputToInputWeights");
3310  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, recurrentToInputWeightsInfo, descriptorName,
3311  "inputToForgetWeights", "recurrentToInputWeights");
3312  ValidateTensorDataTypesMatch(forgetGateBiasInfo, inputGateBiasInfo, descriptorName,
3313  "forgetGateBias", "inputGateBias");
3314  }
3315 
3316  // Validate OPTIONAL params: Peephole (cellToInputWeights, cellToForgetWeights, cellToOutputWeights)
3317  bool allPeepholeWeightsPresentOrNot =
3322 
3323  if (!allPeepholeWeightsPresentOrNot)
3324  {
3325  throw InvalidArgumentException(descriptorName +
3326  ": CellToInputWeights, CellToForgetWeights and CellToOutputWeights should all be present (Peephole "
3327  "enabled) or not be present at all (Peephole disabled). CellToInputWeights should only be present "
3328  "when Peephole is enabled and CIFG is disabled. m_Parameters.m_PeepholeEnabled should be set "
3329  "appropriately.");
3330  }
3331 
3333  {
3334  auto cellToForgetWeightsInfo = m_CellToForgetWeights->GetTensorInfo();
3335  ValidateTensorNumDimNumElem(cellToForgetWeightsInfo, 1, numUnits, " cellToForgetWeights");
3336  ValidateDataTypes(cellToForgetWeightsInfo, layerNormPeepholeWeightsSupportedTypes, descriptorName);
3337 
3338  auto cellToOutputWeightsInfo = m_CellToOutputWeights->GetTensorInfo();
3339  ValidateTensorNumDimNumElem(cellToOutputWeightsInfo, 1, numUnits, " cellToOutputWeights");
3340  ValidateTensorDataTypesMatch(cellToForgetWeightsInfo, cellToOutputWeightsInfo, descriptorName,
3341  "cellToForgetWeight", "cellToOutputWeights");
3342 
3344  {
3345  auto cellToInputWeightsInfo = m_CellToInputWeights->GetTensorInfo();
3346  ValidateTensorNumDimNumElem(cellToInputWeightsInfo, 1, numUnits, " cellToInputWeights");
3347  ValidateTensorDataTypesMatch(cellToForgetWeightsInfo, cellToInputWeightsInfo, descriptorName,
3348  "cellToForgetWeights", "cellToInputWeights");
3349  }
3350  }
3351 
3352  // Validate OPTIONAL params: Layer Norm Weights
3353  bool allLayerNormWeightsPresentOrNot =
3358 
3359  if (!allLayerNormWeightsPresentOrNot)
3360  {
3361  throw InvalidArgumentException(descriptorName +
3362  ": InputLayerNormWeights, ForgetLayerNormWeights, m_OutputLayerNormWeights "
3363  "and CellLayerNormWeights should all be present (Layer Norm enabled) or not "
3364  "be present at all (Layer Norm disabled). InputLayerNormWeights should "
3365  "only be present when Layer Norm is enabled and CIFG is disabled. "
3366  "m_Parameters.m_LayerNormEnabled should be set appropriately.");
3367  }
3368 
3370  {
3371  auto forgetLayerNormWeightsInfo = m_ForgetLayerNormWeights->GetTensorInfo();
3372  ValidateTensorNumDimNumElem(forgetLayerNormWeightsInfo, 1, numUnits, " forgetLayerNormWeights");
3373  ValidateDataTypes(forgetLayerNormWeightsInfo, layerNormPeepholeWeightsSupportedTypes, descriptorName);
3374 
3375  auto cellLayerNormWeightsInfo = m_CellLayerNormWeights->GetTensorInfo();
3376  ValidateTensorNumDimNumElem(cellLayerNormWeightsInfo, 1, numUnits, " cellLayerNormWeights");
3377  ValidateTensorDataTypesMatch(forgetLayerNormWeightsInfo, cellLayerNormWeightsInfo, descriptorName,
3378  "forgetLayerNormWeights", "cellLayerNormWeights");
3379 
3380  auto outputLayerNormWeightsInfo = m_OutputLayerNormWeights->GetTensorInfo();
3381  ValidateTensorNumDimNumElem(outputLayerNormWeightsInfo, 1, numUnits, " outputLayerNormWeights");
3382  ValidateTensorDataTypesMatch(forgetLayerNormWeightsInfo, outputLayerNormWeightsInfo, descriptorName,
3383  "forgetLayerNormWeights", "outputLayerNormWeights");
3384 
3386  {
3387  auto inputLayerNormWeightsInfo = m_InputLayerNormWeights->GetTensorInfo();
3388  ValidateTensorNumDimNumElem(inputLayerNormWeightsInfo, 1, numUnits, " inputLayerNormWeights");
3389  ValidateTensorDataTypesMatch(forgetLayerNormWeightsInfo, inputLayerNormWeightsInfo, descriptorName,
3390  "forgetLayerNormWeights", "inputLayerNormWeights");
3391  }
3392  }
3393 
3394  // Validate OPTIONAL params: Projection (projectionWeights, projectionBias)
3395  bool correctProjectionTensorsPresent =
3399 
3400  if (!correctProjectionTensorsPresent)
3401  {
3402  throw InvalidArgumentException(descriptorName +
3403  ": If projection is enabled, ProjectionWeights should be present and "
3404  "ProjectionBias is optional. If projection is disabled, neither "
3405  "ProjectionWeights nor ProjectionBias should be present.");
3406  }
3407 
3409  {
3410  auto projectionWeightsInfo = m_ProjectionWeights->GetTensorInfo();
3411  ValidateTensorNumDimNumElem(projectionWeightsInfo, 2, (numUnits * outputSize), "ProjectionWeights");
3412  ValidateDataTypes(projectionWeightsInfo, weightsSupportedTypes, descriptorName);
3413 
3414  if (m_ProjectionBias)
3415  {
3416  auto projectionBiasInfo = m_ProjectionBias->GetTensorInfo();
3417  ValidateTensorNumDimNumElem(projectionBiasInfo, 1, outputSize, "ProjectionBias");
3418  ValidateDataTypes(projectionBiasInfo, biasSupportedTypes, descriptorName);
3419  }
3420 
3421  }
3422  else if ((outputInfo.GetQuantizationScale() != m_Parameters.m_HiddenStateScale) &&
3424  throw InvalidArgumentException(descriptorName +
3425  ": If projection is disabled, output quantization info (scale, offset) "
3426  "should match HiddenStateScale and HiddenStateZeroPoint.");
3427  }
3428 
3429 }
3430 
3432 {
3433  const std::string descriptorName{"QuantizedLstmQueueDescriptor"};
3434 
3435  // Validate number of inputs/outputs
3436  ValidateNumInputs(workloadInfo, descriptorName, 3);
3437  ValidateNumOutputs(workloadInfo, descriptorName, 2);
3438 
3439  // Input/output tensor infos
3440  auto inputInfo = workloadInfo.m_InputTensorInfos[0];
3441  auto cellStateInInfo = workloadInfo.m_InputTensorInfos[1];
3442  auto outputStateInInfo = workloadInfo.m_InputTensorInfos[2];
3443 
3444  auto cellStateOutInfo = workloadInfo.m_OutputTensorInfos[0];
3445  auto outputStateOutInfo = workloadInfo.m_OutputTensorInfos[1];
3446 
3447  std::vector<DataType> inputOutputSupportedTypes =
3448  {
3450  };
3451 
3452  std::vector<DataType> cellStateSupportedTypes =
3453  {
3455  };
3456 
3457  std::vector<DataType> weightsSupportedTypes =
3458  {
3460  };
3461 
3462  std::vector<DataType> biasSupportedTypes =
3463  {
3465  };
3466 
3467  // Validate types of input/output tensors
3468  ValidateDataTypes(inputInfo, inputOutputSupportedTypes, descriptorName);
3469  ValidateDataTypes(cellStateInInfo, cellStateSupportedTypes, descriptorName);
3470  ValidateDataTypes(outputStateInInfo, inputOutputSupportedTypes, descriptorName);
3471 
3472  ValidateDataTypes(cellStateOutInfo, cellStateSupportedTypes, descriptorName);
3473  ValidateDataTypes(outputStateOutInfo, inputOutputSupportedTypes, descriptorName);
3474 
3475  // Validate matching types of input/output tensors
3476  ValidateTensorDataTypesMatch(inputInfo, outputStateInInfo, descriptorName, "input", "outputStateIn");
3477  ValidateTensorDataTypesMatch(outputStateInInfo, outputStateOutInfo, descriptorName,
3478  "outputStateIn", "outputStateOut");
3479  ValidateTensorDataTypesMatch(cellStateInInfo, cellStateOutInfo, descriptorName, "cellStateIn", "cellStateOut");
3480 
3481  // Validate matching quantization info for input/output tensors
3482  ValidateTensorQuantizationSpace(inputInfo, outputStateInInfo, descriptorName, "input", "outputStateIn");
3483  ValidateTensorQuantizationSpace(inputInfo, outputStateOutInfo, descriptorName, "input", "outputStateOut");
3484  ValidateTensorQuantizationSpace(cellStateInInfo, cellStateOutInfo, descriptorName, "cellStateIn", "cellStateOut");
3485 
3486  // Infer number of batches, input size and output size from tensor dimensions
3487  const uint32_t numBatches = inputInfo.GetShape()[0];
3488  const uint32_t inputSize = inputInfo.GetShape()[1];
3489  const uint32_t outputSize = cellStateInInfo.GetShape()[1];
3490 
3491  // Validate number of dimensions and number of elements for input/output tensors
3492  ValidateTensorNumDimNumElem(inputInfo, 2, (numBatches * inputSize), descriptorName + " input");
3493  ValidateTensorNumDimNumElem(cellStateInInfo, 2, (numBatches * outputSize), descriptorName + " cellStateIn");
3494  ValidateTensorNumDimNumElem(outputStateInInfo, 2, (numBatches * outputSize), descriptorName + " outputStateIn");
3495  ValidateTensorNumDimNumElem(cellStateOutInfo, 2, (numBatches * outputSize), descriptorName + " cellStateOut");
3496  ValidateTensorNumDimNumElem(outputStateOutInfo, 2, (numBatches * outputSize), descriptorName + " outputStateOut");
3497 
3498  // Validate number of dimensions and number of elements for weights tensors
3499  ValidatePointer(m_InputToInputWeights, descriptorName, "InputToInputWeights");
3500  auto inputToInputWeightsInfo = m_InputToInputWeights->GetTensorInfo();
3501  ValidateTensorNumDimNumElem(inputToInputWeightsInfo, 2, (outputSize * inputSize), " InputToInputWeights");
3502 
3503  ValidatePointer(m_InputToForgetWeights, descriptorName, "InputToForgetWeights");
3504  auto inputToForgetWeightsInfo = m_InputToForgetWeights->GetTensorInfo();
3505  ValidateTensorNumDimNumElem(inputToForgetWeightsInfo, 2, (outputSize * inputSize), " InputToForgetWeights");
3506 
3507  ValidatePointer(m_InputToCellWeights, descriptorName, "InputToCellWeights");
3508  auto inputToCellWeightsInfo = m_InputToCellWeights->GetTensorInfo();
3509  ValidateTensorNumDimNumElem(inputToCellWeightsInfo, 2, (outputSize * inputSize), " InputToCellWeights");
3510 
3511  ValidatePointer(m_InputToOutputWeights, descriptorName, "InputToOutputWeights");
3512  auto inputToOutputWeightsInfo = m_InputToOutputWeights->GetTensorInfo();
3513  ValidateTensorNumDimNumElem(inputToOutputWeightsInfo, 2, (outputSize * inputSize), " InputToOutputWeights");
3514 
3515  ValidatePointer(m_RecurrentToInputWeights, descriptorName, "RecurrentToInputWeights");
3516  auto recurrentToInputWeightsInfo = m_RecurrentToInputWeights->GetTensorInfo();
3517  ValidateTensorNumDimNumElem(recurrentToInputWeightsInfo, 2, (outputSize * outputSize), " RecurrentToInputWeights");
3518 
3519  ValidatePointer(m_RecurrentToForgetWeights, descriptorName, "RecurrentToForgetWeights");
3520  auto recurrentToForgetWeightsInfo = m_RecurrentToForgetWeights->GetTensorInfo();
3521  ValidateTensorNumDimNumElem(recurrentToForgetWeightsInfo, 2, (outputSize * outputSize),
3522  " RecurrentToForgetWeights");
3523 
3524  ValidatePointer(m_RecurrentToCellWeights, descriptorName, "RecurrentToCellWeights");
3525  auto recurrentToCellWeightsInfo = m_RecurrentToCellWeights->GetTensorInfo();
3526  ValidateTensorNumDimNumElem(recurrentToCellWeightsInfo, 2, (outputSize * outputSize), " RecurrentToCellWeights");
3527 
3528  ValidatePointer(m_RecurrentToOutputWeights, descriptorName, "RecurrentToOutputWeights");
3529  auto recurrentToOutputWeightsInfo = m_RecurrentToOutputWeights->GetTensorInfo();
3530  ValidateTensorNumDimNumElem(recurrentToOutputWeightsInfo, 2, (outputSize * outputSize), " RecurrentToCellWeights");
3531 
3532  // Validate data types for weights tensors (all should match each other)
3533  ValidateDataTypes(inputToInputWeightsInfo, weightsSupportedTypes, descriptorName);
3534 
3535  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, inputToForgetWeightsInfo, descriptorName,
3536  "inputToInputWeights", "inputToForgetWeights");
3537  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, inputToCellWeightsInfo, descriptorName,
3538  "inputToInputWeights", "inputToCellWeights");
3539  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, inputToOutputWeightsInfo, descriptorName,
3540  "inputToInputWeights", "inputToOutputWeights");
3541 
3542  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToInputWeightsInfo, descriptorName,
3543  "inputToInputWeights", "recurrentToInputWeights");
3544  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToForgetWeightsInfo, descriptorName,
3545  "inputToInputWeights", "recurrentToForgeteights");
3546  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToCellWeightsInfo, descriptorName,
3547  "inputToInputWeights", "recurrentToCellWeights");
3548  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToOutputWeightsInfo, descriptorName,
3549  "inputToInputWeights", "recurrentToOutputWeights");
3550 
3551  // Validate matching quantization info for weight tensors (all should match each other)
3552  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, inputToForgetWeightsInfo,
3553  descriptorName, "inputToInputWeights", "inputToForgetWeights");
3554  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, inputToCellWeightsInfo,
3555  descriptorName, "inputToInputWeights", "inputToCellWeights");
3556  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, inputToOutputWeightsInfo,
3557  descriptorName, "inputToInputWeights", "inputToOutputWeights");
3558 
3559  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToInputWeightsInfo,
3560  descriptorName, "inputToInputWeights", "recurrentToInputWeights");
3561  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToForgetWeightsInfo,
3562  descriptorName, "inputToInputWeights", "recurrentToForgetWeights");
3563  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToCellWeightsInfo,
3564  descriptorName, "inputToInputWeights", "recurrentToCellWeights");
3565  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToOutputWeightsInfo,
3566  descriptorName, "inputToInputWeights", "recurrentToOutputWeights");
3567 
3568  // Validate number of dimensions and number of elements in bias tensors
3569  ValidatePointer(m_InputGateBias, descriptorName, "InputGateBias");
3570  auto inputGateBiasInfo = m_InputGateBias->GetTensorInfo();
3571  ValidateTensorNumDimNumElem(inputGateBiasInfo, 1, outputSize, " InputGateBias");
3572 
3573  ValidatePointer(m_ForgetGateBias, descriptorName, "ForgetGateBias");
3574  auto forgetGateBiasInfo = m_ForgetGateBias->GetTensorInfo();
3575  ValidateTensorNumDimNumElem(forgetGateBiasInfo, 1, outputSize, " ForgetGateBias");
3576 
3577  ValidatePointer(m_CellBias, descriptorName, "CellBias");
3578  auto cellBiasInfo = m_CellBias->GetTensorInfo();
3579  ValidateTensorNumDimNumElem(cellBiasInfo, 1, outputSize, " CellBias");
3580 
3581  ValidatePointer(m_OutputGateBias, descriptorName, "OutputGateBias");
3582  auto outputGateBiasInfo = m_OutputGateBias->GetTensorInfo();
3583  ValidateTensorNumDimNumElem(outputGateBiasInfo, 1, outputSize, " OutputGateBias");
3584 
3585  // Validate data types for bias tensors (all should match each other)
3586  ValidateDataTypes(inputGateBiasInfo, biasSupportedTypes, descriptorName);
3587 
3588  ValidateTensorDataTypesMatch(inputGateBiasInfo, forgetGateBiasInfo, descriptorName,
3589  "inputGateBias", "forgetGateBias");
3590  ValidateTensorDataTypesMatch(inputGateBiasInfo, cellBiasInfo, descriptorName,
3591  "inputGateBias", "cellBias");
3592  ValidateTensorDataTypesMatch(inputGateBiasInfo, outputGateBiasInfo, descriptorName,
3593  "inputGateBias", "outputGateBias");
3594 
3595  // Validate bias tensor quantization info
3596  ValidateBiasTensorQuantization(inputGateBiasInfo, inputToInputWeightsInfo, descriptorName);
3597  ValidateBiasTensorQuantization(forgetGateBiasInfo, inputToInputWeightsInfo, descriptorName);
3598  ValidateBiasTensorQuantization(cellBiasInfo, inputToInputWeightsInfo, descriptorName);
3599  ValidateBiasTensorQuantization(outputGateBiasInfo, inputToInputWeightsInfo, descriptorName);
3600 }
3601 
3602 void AbsQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3603 {
3604  const std::string descriptorName{"AbsQueueDescriptor"};
3605 
3606  ValidateNumInputs(workloadInfo, descriptorName, 1);
3607  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3608 
3609  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3610  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3611 
3612  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3613 
3614  std::vector<DataType> supportedTypes =
3615  {
3623  };
3624 
3625  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3626  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3627 }
3628 
3629 void SliceQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3630 {
3631  const std::string descriptorName{"SliceQueueDescriptor"};
3632 
3633  ValidateNumInputs(workloadInfo, descriptorName, 1);
3634  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3635 
3636  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3637  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3638 
3639  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3640 
3641  const unsigned int rank = inputTensorInfo.GetNumDimensions();
3642  if (rank > 4)
3643  {
3644  throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
3645  }
3646 
3647  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, rank, "output");
3648 
3649  // Check if m_Begin and m_Size have the expected length
3650  if (m_Parameters.m_Begin.size() != rank)
3651  {
3652  throw InvalidArgumentException(descriptorName +
3653  ": Length of begin offset descriptor must equal rank " + std::to_string(rank));
3654  }
3655  if (m_Parameters.m_Size.size() != rank)
3656  {
3657  throw InvalidArgumentException(descriptorName +
3658  ": Length of size descriptor must equal rank " + std::to_string(rank));
3659  }
3660 
3661  // Check if the shape of the output tensor matches m_Size
3662  const TensorShape& outputShape = outputTensorInfo.GetShape();
3663  for (unsigned int i = 0u; i < rank; ++i)
3664  {
3665  if (m_Parameters.m_Size[i] != outputShape[i])
3666  {
3667  throw InvalidArgumentException(descriptorName + ": Size descriptor does not match output tensor.");
3668  }
3669  }
3670 
3671  // Check if the sum of begin offset and size in a given dimension
3672  // does not exceed the size of corresponding input
3673  const TensorShape& inputShape = inputTensorInfo.GetShape();
3674  for(unsigned int i = 0u; i < rank; ++i)
3675  {
3676  if (m_Parameters.m_Begin[i] + m_Parameters.m_Size[i] > inputShape[i])
3677  {
3678  throw InvalidArgumentException(descriptorName + ": Sum of begin offset and size for dimension " +
3679  std::to_string(i) + " exceeds input size.");
3680  }
3681  }
3682 }
3683 
3685 {
3686  const std::string descriptorName{"DepthToSpaceQueueDescriptor"};
3687 
3688  ValidateNumInputs(workloadInfo, descriptorName, 1);
3689  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3690 
3691  const TensorInfo& inputInfo = workloadInfo.m_InputTensorInfos[0];
3692  const TensorInfo& outputInfo = workloadInfo.m_OutputTensorInfos[0];
3693 
3694  ValidateTensorNumDimensions(inputInfo, descriptorName, 4, "input");
3695  ValidateTensorNumDimensions(outputInfo, descriptorName, 4, "output");
3696 
3697  std::vector<DataType> supportedTypes =
3698  {
3705  };
3706 
3707  ValidateDataTypes(inputInfo, supportedTypes, descriptorName);
3708  ValidateDataTypes(outputInfo, supportedTypes, descriptorName);
3709 
3710  ValidateTensorNumElementsMatch(inputInfo, outputInfo, descriptorName, "input", "output");
3711 
3712  if (m_Parameters.m_BlockSize == 0)
3713  {
3714  throw InvalidArgumentException(descriptorName + ": Block size cannot be 0.");
3715  }
3716 
3717  DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
3718  const unsigned int wIndex = dimensionIndices.GetWidthIndex();
3719  const unsigned int hIndex = dimensionIndices.GetHeightIndex();
3720  const unsigned int cIndex = dimensionIndices.GetChannelsIndex();
3721 
3722  const TensorShape& outputShape = outputInfo.GetShape();
3723  if (outputShape[hIndex] % m_Parameters.m_BlockSize != 0 || outputShape[wIndex] % m_Parameters.m_BlockSize != 0)
3724  {
3725  throw InvalidArgumentException(descriptorName + ": Output width and height shape"
3726  "must be divisible by block size.");
3727  }
3728 
3729  const TensorShape& inputShape = inputInfo.GetShape();
3730  if (inputShape[cIndex] % (m_Parameters.m_BlockSize * m_Parameters.m_BlockSize) != 0)
3731  {
3732  throw InvalidArgumentException(descriptorName + ": The depth of the input tensor"
3733  "must be divisible by the square of block size." );
3734  }
3735 }
3736 
3737 void ComparisonQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3738 {
3739  const std::string descriptorName{"ComparisonQueueDescriptor"};
3740 
3741  ValidateNumInputs(workloadInfo, descriptorName, 2);
3742  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3743 
3744  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
3745  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
3746  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3747 
3748  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
3749  inputTensorInfo1,
3750  outputTensorInfo,
3751  descriptorName,
3752  "input_0",
3753  "input_1");
3754 
3755  if (outputTensorInfo.GetDataType() != DataType::Boolean)
3756  {
3757  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
3758  }
3759 }
3760 
3762 {
3763  const std::string descriptorName{"ElementwiseBinaryQueueDescriptor"};
3764 
3765  ValidateNumInputs(workloadInfo, descriptorName, 2);
3766  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3767 
3768  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
3769  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
3770  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3771 
3772  std::vector<DataType> supportedTypes =
3773  {
3781  };
3782 
3783  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
3784  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
3785 
3786  ValidateTensorDataTypesMatch(inputTensorInfo0, outputTensorInfo, descriptorName, "input", "output");
3787  ValidateTensorDataTypesMatch(inputTensorInfo1, outputTensorInfo, descriptorName, "input", "output");
3788 }
3789 
3791 {
3792  const std::string descriptorName{"ElementwiseUnaryQueueDescriptor"};
3793 
3794  ValidateNumInputs(workloadInfo, descriptorName, 1);
3795  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3796 
3797  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3798  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3799 
3800  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3801 
3802  std::vector<DataType> supportedTypes =
3803  {
3811  };
3812 
3813  std::vector<DataType> logicalSupportedTypes =
3814  {
3816  };
3817 
3819  {
3820  ValidateDataTypes(inputTensorInfo, logicalSupportedTypes, descriptorName);
3821  }
3822  else
3823  {
3824  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3825  }
3826 
3827 
3828  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3829 }
3830 
3831 void RankQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3832 {
3833  const std::string descriptorName{"RankQueueDescriptor"};
3834 
3835  ValidateNumInputs(workloadInfo, descriptorName, 1);
3836  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3837 
3838  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3839  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3840 
3841  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 1, "output");
3842  ValidateTensorNumElements(outputTensorInfo, descriptorName, 1, "output");
3843 
3844  std::vector<DataType> supportedTypes =
3845  {
3854  };
3855 
3856  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3857  ValidateDataTypes(outputTensorInfo, { DataType::Signed32 }, descriptorName);
3858 }
3859 
3861 {
3862  const std::string descriptorName{"LogicalBinaryQueueDescriptor"};
3863 
3864  ValidateNumInputs(workloadInfo, descriptorName, 2);
3865  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3866 
3867  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
3868  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
3869  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3870 
3871  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
3872  inputTensorInfo1,
3873  outputTensorInfo,
3874  descriptorName,
3875  "input_0",
3876  "input_1");
3877 
3878  if (inputTensorInfo0.GetDataType() != DataType::Boolean)
3879  {
3880  throw InvalidArgumentException(descriptorName + ": Input tensor 0 type must be Boolean.");
3881  }
3882 
3883  if (inputTensorInfo1.GetDataType() != DataType::Boolean)
3884  {
3885  throw InvalidArgumentException(descriptorName + ": Input tensor 1 type must be Boolean.");
3886  }
3887 
3888  if (outputTensorInfo.GetDataType() != DataType::Boolean)
3889  {
3890  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
3891  }
3892 }
3893 
3894 void ReduceQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3895 {
3896  const std::string descriptorName{"ReduceQueueDescriptor"};
3897 
3898  ValidateNumInputs(workloadInfo, descriptorName, 1);
3899  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3900 
3901  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3902  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3903 
3904  std::vector<DataType> supportedTypes =
3905  {
3913  };
3914 
3915  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3916  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3917 }
3918 
3920 {
3921  // Modified from LstmQueueDescriptor::Validate to support UnidirectionalSequenceLstm
3922 
3923  const std::string descriptorName{"UnidirectionalSequenceLstmQueueDescriptor"};
3924 
3925  // check dimensions of all inputs and outputs
3926  if (workloadInfo.m_InputTensorInfos.size() != 3)
3927  {
3928  throw InvalidArgumentException(descriptorName + ": Invalid number of inputs.");
3929  }
3930  if (workloadInfo.m_OutputTensorInfos.size() != 3)
3931  {
3932  throw InvalidArgumentException(descriptorName + ": Invalid number of outputs.");
3933  }
3934 
3935  std::vector<DataType> supportedTypes =
3936  {
3939  };
3940 
3941  // check for supported type of one input and match them with all the other input and output
3942  ValidateDataTypes(workloadInfo.m_InputTensorInfos[0], supportedTypes, descriptorName);
3943 
3944  // Making sure clipping parameters have valid values.
3945  // == 0 means no clipping
3946  // > 0 means clipping
3947  if (m_Parameters.m_ClippingThresCell < 0.0f)
3948  {
3949  throw InvalidArgumentException(descriptorName + ": negative cell clipping threshold is invalid");
3950  }
3951  if (m_Parameters.m_ClippingThresProj < 0.0f)
3952  {
3953  throw InvalidArgumentException(descriptorName + ": negative projection clipping threshold is invalid");
3954  }
3955 
3956  unsigned int batchIndx = 0;
3957  unsigned int inputIndx = 1;
3958  uint32_t timeStep = 1;
3959  unsigned int timeIndx = 1;
3960  inputIndx = 2;
3962  {
3963  batchIndx = 1;
3964  timeIndx = 0;
3965 
3966  }
3967  timeStep = workloadInfo.m_InputTensorInfos[0].GetShape()[timeIndx];
3968 
3969  // Inferring batch size, number of outputs and number of cells from the inputs.
3970  const uint32_t n_input = workloadInfo.m_InputTensorInfos[0].GetShape()[inputIndx];
3971  const uint32_t n_batch = workloadInfo.m_InputTensorInfos[0].GetShape()[batchIndx];
3972  ValidatePointer(m_InputToOutputWeights, "Null pointer check", "InputToOutputWeights");
3973  const uint32_t n_cell = m_InputToOutputWeights->GetShape()[0];
3974  ValidatePointer(m_RecurrentToOutputWeights, "Null pointer check", "RecurrentToOutputWeights");
3975  const uint32_t n_output = m_RecurrentToOutputWeights->GetShape()[1];
3976 
3977  // input tensor
3978  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[0], 3, (timeStep * n_batch * n_input),
3979  descriptorName + " input_0");
3980  // outputStateInTensor
3981  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[1], 2, (n_batch * n_output),
3982  descriptorName + " input_1");
3983  // outputStateInTensor
3984  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[2], 2, (n_batch * n_cell),
3985  descriptorName + " input_2");
3986 
3987  // outputTensor
3988  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[2], 3, (timeStep * n_batch * n_output),
3989  descriptorName + " output_0");
3990 
3991  // check that dimensions of inputs/outputs and QueueDescriptor data match with each other
3992  if ( m_InputToInputWeights )
3993  {
3995  (n_cell * n_input), "InputLayerNormWeights");
3996  }
3997 
3998  ValidatePointer(m_InputToForgetWeights, "Null pointer check", "InputToForgetWeights");
4000  (n_cell * n_input), "InputToForgetWeights");
4001 
4002  ValidatePointer(m_InputToCellWeights, "Null pointer check", "InputToCellWeights");
4004  (n_cell * n_input), "InputToCellWeights");
4005 
4007  {
4009  (n_cell * n_output), "RecurrentToInputWeights");
4010  }
4011 
4012  ValidatePointer(m_RecurrentToForgetWeights, "Null pointer check", "RecurrentToForgetWeights");
4014  (n_cell * n_output), "RecurrentToForgetWeights");
4015 
4016  ValidatePointer(m_RecurrentToCellWeights, "Null pointer check", "RecurrentToCellWeights");
4018  (n_cell * n_output), "RecurrentToCellWeights");
4019 
4020  // Make sure the input-gate's parameters are either both present (regular
4021  // LSTM) or not at all (CIFG-LSTM). And CifgEnable is set accordingly.
4022  bool cifg_weights_all_or_none = ((m_InputToInputWeights && m_RecurrentToInputWeights &&
4026  if (!cifg_weights_all_or_none)
4027  {
4028  throw InvalidArgumentException(descriptorName + ": Input-Gate's parameters InputToInputWeights and "
4029  "RecurrentToInputWeights must either both be present (regular LSTM) "
4030  "or both not present (CIFG-LSTM). In addition CifgEnable must be set "
4031  "accordingly.");
4032  }
4033 
4034  if ( m_CellToInputWeights )
4035  {
4037  n_cell, "CellToInputWeights");
4038  }
4039  if ( m_CellToForgetWeights )
4040  {
4042  n_cell, "CellToForgetWeights");
4043  }
4044  if ( m_CellToOutputWeights )
4045  {
4047  n_cell, "CellToOutputWeights");
4048  }
4049 
4050  // Making sure the peephole weights are there all or none. And PeepholeEnable is set accordingly.
4051  bool peephole_weights_all_or_none =
4056  if (!peephole_weights_all_or_none)
4057  {
4058  throw InvalidArgumentException(descriptorName + ": Invalid combination of peephole parameters.");
4059  }
4060 
4061  // Make sure the input gate bias is present only when not a CIFG-LSTM.
4063  {
4064  if (m_InputGateBias)
4065  {
4066  throw InvalidArgumentException(descriptorName + ": InputGateBias is present and CIFG-LSTM is enabled.");
4067  }
4068  }
4069  else
4070  {
4071  if (!m_InputGateBias)
4072  {
4073  throw InvalidArgumentException(descriptorName + ": If CIFG-LSTM is disabled InputGateBias "
4074  "must be present.");
4075  }
4077  n_cell, "InputGateBias");
4078  }
4079 
4080  ValidatePointer(m_ForgetGateBias, "Null pointer check", "ForgetGateBias");
4081  ValidateTensorNumDimNumElem(m_ForgetGateBias->GetTensorInfo(), 1, n_cell, "ForgetGateBias");
4082 
4083  ValidatePointer(m_CellBias, "Null pointer check", "CellBias");
4084  ValidateTensorNumDimNumElem(m_CellBias->GetTensorInfo(), 1, n_cell, "CellBias");
4085 
4086  ValidatePointer(m_OutputGateBias, "Null pointer check", "OutputGateBias");
4087  ValidateTensorNumDimNumElem(m_OutputGateBias->GetTensorInfo(), 1, n_cell, "OutputGateBias");
4088 
4089  if (m_ProjectionWeights)
4090  {
4092  (n_cell * n_output), "ProjectionWeights");
4093  }
4094  if (m_ProjectionBias)
4095  {
4096  ValidateTensorNumDimNumElem(m_ProjectionBias->GetTensorInfo(), 1, n_output, "ProjectionBias");
4097  }
4098 
4099  // Making sure the projection tensors are consistent:
4100  // 1) If projection weight is not present, then projection bias should not be
4101  // present.
4102  // 2) If projection weight is present, then projection bias is optional.
4103  bool projecton_tensors_consistent = ((!m_ProjectionWeights && !m_ProjectionBias &&
4109  if (!projecton_tensors_consistent)
4110  {
4111  throw InvalidArgumentException(descriptorName + ": Projection tensors are inconsistent.");
4112  }
4113 
4114  // The four layer normalization weights either all have values or none of them have values. Additionally, if
4115  // CIFG is used, input layer normalization weights tensor is omitted and the other layer normalization weights
4116  // either all have values or none of them have values. Layer normalization is used when the values of all the
4117  // layer normalization weights are present
4119  {
4120  ValidateTensorNumDimNumElem(m_InputLayerNormWeights->GetTensorInfo(), 1, n_cell, "InputLayerNormWeights");
4121  }
4123  {
4124  ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
4125  }
4127  {
4128  ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
4129  }
4131  {
4132  ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
4133  }
4134 
4136  {
4138  {
4140  {
4141  throw InvalidArgumentException(descriptorName + ": Layer normalisation is enabled and CIFG-LSTM is "
4142  "disabled but InputLayerNormWeights are not present");
4143  }
4145  1, n_cell, "InputLayerNormWeights");
4146  }
4147  else if (m_InputLayerNormWeights)
4148  {
4149  throw InvalidArgumentException(descriptorName + ":InputLayerNormWeights are present while CIFG is "
4150  "enabled");
4151  }
4152 
4153  ValidatePointer(m_ForgetLayerNormWeights, "Null pointer check layer normalisation enabled",
4154  "ForgetLayerNormWeights");
4155  ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
4156 
4157  ValidatePointer(m_OutputLayerNormWeights, "Null pointer check layer normalisation enabled",
4158  "OutputLayerNormWeights");
4159  ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
4160 
4161  ValidatePointer(m_CellLayerNormWeights, "Null pointer check layer normalisation enabled",
4162  "CellLayerNormWeights");
4163  ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
4164  }
4166  {
4167  throw InvalidArgumentException(descriptorName + ": Layer normalisation is disabled but one or more layer "
4168  "normalisation weights are present.");
4169  }
4170 }
4171 
4173 {
4174  const std::string descriptorName{"BatchMatMulDescriptor"};
4175 
4176  ValidateNumInputs(workloadInfo, descriptorName, 2);
4177  ValidateNumOutputs(workloadInfo, descriptorName, 1);
4178 
4179  // Inputs must be: both 2D+
4180  // For inputs X and Y whose dimensions to be multiplied are (M,N) and (I,J) respectively,
4181  // axes N and I must be the same size
4182 
4183  const auto& inputXInfoBeforeParams = workloadInfo.m_InputTensorInfos[0];
4184  const auto& inputYInfoBeforeParams = workloadInfo.m_InputTensorInfos[1];
4185  const auto& outputInfo = workloadInfo.m_OutputTensorInfos[0];
4186  // Output info has already been inferred
4187 
4188  std::vector<DataType> supportedTypes =
4189  {
4196  };
4197 
4198  ValidateDataTypes(inputXInfoBeforeParams, supportedTypes, descriptorName);
4199  ValidateDataTypes(inputYInfoBeforeParams, supportedTypes, descriptorName);
4200  ValidateDataTypes(outputInfo, supportedTypes, descriptorName);
4201 
4202  if ((inputXInfoBeforeParams.GetNumDimensions() < 2) ||
4203  (inputYInfoBeforeParams.GetNumDimensions() < 2))
4204  {
4205  throw InvalidArgumentException(descriptorName + ": Input tensors are not 2D or greater.");
4206  }
4207 
4208  TensorInfo inputXInfoAfterParams;
4209  TensorInfo inputYInfoAfterParams;
4210 
4213  {
4214  throw InvalidArgumentException(descriptorName +
4215  ": Invalid descriptor parameters - Transpose and Adjoint "
4216  "cannot both be true for a given input tensor.");
4217  }
4219  {
4220  inputXInfoAfterParams = armnnUtils::Permuted(inputXInfoBeforeParams,
4223  inputXInfoBeforeParams.GetShape()));
4224  }
4225  else if(m_Parameters.m_AdjointX)
4226  {
4228  inputXInfoBeforeParams.GetShape());
4229  if(inputXInfoBeforeParams.GetShape()[axesToMul.first] !=
4230  inputXInfoBeforeParams.GetShape()[axesToMul.second])
4231  {
4232  throw InvalidArgumentException(descriptorName +
4233  ": Adjoint is set to true for input tensor X, but the axes to be adjointed are not square." );
4234  }
4235  // Shape remains the same as it's square
4236  inputXInfoAfterParams = inputXInfoBeforeParams;
4237  }
4238  else
4239  {
4240  inputXInfoAfterParams = inputXInfoBeforeParams;
4241  }
4242 
4244  {
4245  inputYInfoAfterParams = armnnUtils::Permuted(inputYInfoBeforeParams,
4248  inputYInfoBeforeParams.GetShape()));
4249  }
4250  else if(m_Parameters.m_AdjointY)
4251  {
4253  inputYInfoBeforeParams.GetShape());
4254  if(inputYInfoBeforeParams.GetShape()[axesToMul.first] !=
4255  inputYInfoBeforeParams.GetShape()[axesToMul.second])
4256  {
4257  throw InvalidArgumentException(descriptorName +
4258  ": Adjoint is set to true for input tensor Y, but the axes to be adjointed are not square." );
4259  }
4260  // Shape remains the same as it's square
4261  inputYInfoAfterParams = inputYInfoBeforeParams;
4262  }
4263  else
4264  {
4265  inputYInfoAfterParams = inputYInfoBeforeParams;
4266  }
4267 
4268  switch(m_Parameters.m_DataLayoutX)
4269  {
4270  case DataLayout::NCDHW:
4271  case DataLayout::NDHWC:
4272  if(inputXInfoAfterParams.GetNumDimensions() < 3)
4273  {
4274  throw InvalidArgumentException(descriptorName +
4275  ": Input tensor X does not have the correct "
4276  "number of dimensions for the Data Layout that it has been assigned.");
4277  }
4278  break;
4279  case DataLayout::NCHW:
4280  case DataLayout::NHWC:
4281  default:
4282  break;
4283  }
4284 
4285  switch(m_Parameters.m_DataLayoutY)
4286  {
4287  case DataLayout::NCDHW:
4288  case DataLayout::NDHWC:
4289  if(inputYInfoAfterParams.GetNumDimensions() < 3)
4290  {
4291  throw InvalidArgumentException(descriptorName +
4292  ": Input tensor Y does not have the correct "
4293  "number of dimensions for the Data Layout that it has been assigned.");
4294  }
4295  break;
4296  case DataLayout::NCHW:
4297  case DataLayout::NHWC:
4298  default:
4299  break;
4300  }
4301 
4303  inputXInfoAfterParams.GetShape());
4305  inputXInfoBeforeParams.GetShape());
4306 
4307  if(inputXInfoAfterParams.GetShape()[axesXToMul.second]
4308  != inputYInfoAfterParams.GetShape()[axesYToMul.first])
4309  {
4310  throw InvalidArgumentException(descriptorName +
4311  ": The final axis of input tensor X must be the same size as "
4312  "the second last axis of input tensor Y.");
4313  }
4314 
4315  { // Separate scope so we don't pollute the rest of the scope with our temp variables
4316  // e.g. NHWC isnt compatible with NCHW as of now
4319 
4320  if(xLayout == DataLayout::NCHW || xLayout == DataLayout::NCDHW)
4321  {
4322  if(yLayout == DataLayout::NHWC || yLayout == DataLayout::NDHWC)
4323  {
4324  throw InvalidArgumentException(descriptorName +
4325  ": Invalid input tensor data layout combination.");
4326  }
4327  }
4328  if(yLayout == DataLayout::NCHW || yLayout == DataLayout::NCDHW)
4329  {
4330  if(xLayout == DataLayout::NHWC || xLayout == DataLayout::NDHWC)
4331  {
4332  throw InvalidArgumentException(descriptorName +
4333  ": Invalid input tensor data layout combination.");
4334  }
4335  }
4336  }
4337 
4338  // Simulate aligning the ends of the matrix dims and prepending 1's to the beginning of the shorter one
4339  unsigned int outputTensorDimSize = std::max(inputXInfoAfterParams.GetNumDimensions(),
4340  inputYInfoAfterParams.GetNumDimensions());
4341  if(outputTensorDimSize-2 > 0)
4342  {
4343  TensorInfo tiXNotMul = TensorInfo(TensorShape(outputTensorDimSize-2),
4345  TensorInfo tiYNotMul = TensorInfo(TensorShape(outputTensorDimSize-2),
4347  TensorInfo tiOutNotMul = TensorInfo(TensorShape(outputTensorDimSize-2),
4349 
4350  auto doAxisExtension = [&](std::vector<unsigned int> axisIndices, TensorInfo& ti)
4351  {
4352  auto sizeDiff = (outputTensorDimSize-2) - axisIndices.size();
4353 
4354  for(unsigned int i = 0; i < sizeDiff; i++)
4355  {
4356  axisIndices.insert(axisIndices.begin(), 1);
4357  }
4358 
4359  for(unsigned int i = 0; i < ti.GetNumDimensions(); i++)
4360  {
4361  ti.GetShape()[i] = inputXInfoAfterParams.GetShape()[i];
4362  }
4363  };
4364 
4366  inputXInfoAfterParams.GetShape());
4368  inputYInfoAfterParams.GetShape());
4369 
4370  doAxisExtension(axesXNotMul, tiXNotMul);
4371  doAxisExtension(axesYNotMul, tiYNotMul);
4372 
4373  for(unsigned int i = 0; i < tiOutNotMul.GetNumDimensions(); i++)
4374  {
4375  tiOutNotMul.GetShape()[i] = std::max(tiXNotMul.GetShape()[i],
4376  tiYNotMul.GetShape()[i]);
4377  }
4378 
4379  ValidateBroadcastTensorShapesMatch(tiXNotMul,
4380  tiYNotMul,
4381  tiOutNotMul,
4382  descriptorName,
4383  "input_X",
4384  "input_Y");
4385  }
4386 }
4387 
4388 void TileQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
4389 {
4390  const std::string& descriptorName{"TileQueueDescriptor"};
4391 
4392  ValidateNumInputs(workloadInfo, descriptorName, 1);
4393  ValidateNumOutputs(workloadInfo, descriptorName, 1);
4394 
4395  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
4396  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
4397 
4398  std::vector<DataType> supportedTypes =
4399  {
4407  };
4408 
4409  // Multiples length must be the same as the number of dimensions in input.
4410  if (m_Parameters.m_Multiples.size() != inputTensorInfo.GetNumDimensions())
4411  {
4412  throw InvalidArgumentException(descriptorName +
4413  ": Multiples length is not same as the number of dimensions in Input.");
4414  }
4415 
4416  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
4417  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
4418 }
4419 
4421 {
4422  const std::string& descriptorName{"BroadcastToQueueDescriptor"};
4423 
4424  ValidateNumInputs(workloadInfo, descriptorName, 1);
4425  ValidateNumOutputs(workloadInfo, descriptorName, 1);
4426 
4427  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
4428  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
4429 
4430  std::vector<DataType> supportedTypes =
4431  {
4440  };
4441 
4442  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
4443  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
4444 }
4445 
4446 } // 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:2942
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:196
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:2640
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:4420
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:2583
WorkloadData.hpp
armnn::PreCompiledQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3009
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:2682
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:2894
armnn::QLstmQueueDescriptor::m_InputLayerNormWeights
const ConstTensorHandle * m_InputLayerNormWeights
Definition: WorkloadData.hpp:606
armnn::LogSoftmaxQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1764
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:3145
armnn::TensorInfo::GetNumDimensions
unsigned int GetNumDimensions() const
Definition: Tensor.hpp:195
armnn::QuantizedLstmQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3431
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:3103
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:3919
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:3790
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:2791
armnn::ReverseV2QueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1622
armnn::QLstmQueueDescriptor::m_InputToInputWeights
const ConstTensorHandle * m_InputToInputWeights
Definition: WorkloadData.hpp:589
armnn::BatchMatMulQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:4172
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:1986
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:3602
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:1703
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:2826
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:1682
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:2394
Logging.hpp
armnn::DebugQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2674
armnn::ElementwiseBinaryQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3761
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:201
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:3831
armnn::TileQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:4388
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:3860
armnn::SubtractionQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2360
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:3132
armnn::BatchMatMulDescriptor::m_DataLayoutY
DataLayout m_DataLayoutY
Definition: Descriptors.hpp:1622
armnn::MeanQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2428
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:2326
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:1787
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:3014
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:2706
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:198
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:2730
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:3684
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:2523
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:3051
armnn::SpaceToDepthQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1933
armnn::PermutationVector::GetSize
SizeType GetSize() const
Definition: Types.hpp:357
armnn::MergeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2924
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:2756
armnn::TensorInfo::GetShape
const TensorShape & GetShape() const
Definition: Tensor.hpp:191
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:2968
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:3737
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:3629
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:1847
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:2280
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:3894
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:2472
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:2010
armnn::LstmQueueDescriptor::m_OutputGateBias
const ConstTensorHandle * m_OutputGateBias
Definition: WorkloadData.hpp:441
armnn::L2NormalizationQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1732
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:2303
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:2494
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:1818
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