ArmNN
 23.08
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 
1097 {
1098  const std::string descriptorName{"NormalizationQueueDescriptor"};
1099 
1100  ValidateNumInputs(workloadInfo, descriptorName, 1);
1101  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1102 
1103  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1104  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1105 
1106  // Check the supported data types
1107  std::vector<DataType> supportedTypes =
1108  {
1115  };
1116 
1117  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1118 
1119  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1120 
1121  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1122 }
1123 
1124 void AdditionQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1125 {
1126  const std::string descriptorName{"AdditionQueueDescriptor"};
1127 
1128  ValidateNumInputs(workloadInfo, descriptorName, 2);
1129  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1130 
1131  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
1132  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
1133  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1134 
1135  std::vector<DataType> supportedTypes =
1136  {
1144  };
1145 
1146  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
1147  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
1148  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1149 
1150  ValidateTensorDataTypesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
1151  ValidateTensorDataTypesMatch(inputTensorInfo1, outputTensorInfo, descriptorName, "input_1", "output");
1152 
1153  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
1154  inputTensorInfo1,
1155  outputTensorInfo,
1156  descriptorName,
1157  "input_0",
1158  "input_1");
1159 }
1160 
1162 {
1163  const std::string descriptorName{"MultiplicationQueueDescriptor"};
1164 
1165  ValidateNumInputs(workloadInfo, descriptorName, 2);
1166  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1167 
1168  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
1169  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
1170  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1171 
1172  std::vector<DataType> supportedTypes =
1173  {
1181  };
1182 
1183  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
1184  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
1185  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1186 
1187  ValidateTensorDataTypesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
1188  ValidateTensorDataTypesMatch(inputTensorInfo1, outputTensorInfo, descriptorName, "input_1", "output");
1189 
1190  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
1191  inputTensorInfo1,
1192  outputTensorInfo,
1193  descriptorName,
1194  "input_0",
1195  "input_1");
1196 }
1197 
1199 {
1200  const std::string descriptorName{"BatchNormalizationQueueDescriptor"};
1201 
1202  ValidateNumInputs(workloadInfo, descriptorName, 1);
1203  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1204 
1205  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1206  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1207 
1208  std::vector<DataType> supportedTypes =
1209  {
1216  };
1217 
1218  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1219  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1220 
1221  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1222  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1223 
1224  ValidatePointer(m_Mean, descriptorName, "mean");
1225  ValidatePointer(m_Variance, descriptorName, "variance");
1226  ValidatePointer(m_Beta, descriptorName, "beta");
1227  ValidatePointer(m_Gamma, descriptorName, "gamma");
1228 
1229  const TensorInfo& mean = m_Mean->GetTensorInfo();
1230  const TensorInfo& variance = m_Variance->GetTensorInfo();
1231  const TensorInfo& beta = m_Beta->GetTensorInfo();
1232  const TensorInfo& gamma = m_Gamma->GetTensorInfo();
1233 
1234  ValidateTensorNumDimensions(mean, descriptorName, 1, "mean");
1235  ValidateTensorNumDimensions(variance, descriptorName, 1, "variance");
1236  ValidateTensorNumDimensions(beta, descriptorName, 1, "beta");
1237  ValidateTensorNumDimensions(gamma, descriptorName, 1, "gamma");
1238 
1239  ValidateTensorShapesMatch(mean, variance, descriptorName, "mean", "variance");
1240  ValidateTensorShapesMatch(mean, beta, descriptorName, "mean", "beta");
1241  ValidateTensorShapesMatch(mean, gamma, descriptorName, "mean", "gamma");
1242 }
1243 
1245 {
1246  const std::string descriptorName{"Convolution2dQueueDescriptor"};
1247 
1248  uint32_t numInputs = 2;
1250  {
1251  numInputs = 3;
1252  }
1253 
1254  ValidateNumInputs(workloadInfo, descriptorName, numInputs);
1255  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1256 
1257  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1258  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1259 
1260  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1261  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1262 
1263  const TensorInfo& weightTensorInfo = workloadInfo.m_InputTensorInfos[1];
1264 
1265  ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 4, "weight");
1266 
1267  ValidateWeightDataType(inputTensorInfo, weightTensorInfo, descriptorName);
1268 
1269  Optional<TensorInfo> optionalBiasTensorInfo;
1271  {
1272  optionalBiasTensorInfo = MakeOptional<TensorInfo>(workloadInfo.m_InputTensorInfos[2]);
1273  const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value();
1274 
1275  ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
1276  ValidateBiasTensorQuantization(biasTensorInfo, weightTensorInfo, descriptorName);
1277  }
1278 
1279  if (m_Parameters.m_StrideX <= 0 || m_Parameters.m_StrideY <= 0 )
1280  {
1282  fmt::format("{}: strideX (provided {}) and strideY (provided {}) "
1283  "cannot be either negative or 0.",
1284  descriptorName, m_Parameters.m_StrideX, m_Parameters.m_StrideY));
1285  }
1286 
1287  ValidatePerAxisQuantization(inputTensorInfo,
1288  outputTensorInfo,
1289  weightTensorInfo,
1290  optionalBiasTensorInfo,
1291  descriptorName);
1292 
1293  std::vector<DataType> supportedTypes =
1294  {
1302  };
1303 
1304  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1305 
1306  // For Convolution2d, we allow to have BFloat16 input with Float32 output for optimization.
1307  if (inputTensorInfo.GetDataType() == DataType::BFloat16)
1308  {
1309  if (outputTensorInfo.GetDataType() != DataType::BFloat16 && outputTensorInfo.GetDataType() != DataType::Float32)
1310  {
1311  throw InvalidArgumentException(descriptorName + ": " + " Output tensor type must be BFloat16 or Float32 "
1312  "for BFloat16 input.");
1313  }
1314  }
1315  else
1316  {
1317  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1318  }
1319 }
1320 
1322 {
1323  const std::string descriptorName{"Convolution3dQueueDescriptor"};
1324 
1325  uint32_t numInputs = 2;
1327  {
1328  numInputs = 3;
1329  }
1330  ValidateNumInputs(workloadInfo, descriptorName, numInputs);
1331  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1332 
1333  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1334  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1335 
1336  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 5, "input");
1337  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 5, "output");
1338 
1339  const TensorInfo& weightTensorInfo = workloadInfo.m_InputTensorInfos[1];
1340  ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 5, "weight");
1341 
1342  ValidateWeightDataType(inputTensorInfo, weightTensorInfo, descriptorName);
1343 
1344  Optional<TensorInfo> optionalBiasTensorInfo;
1346  {
1347  optionalBiasTensorInfo = MakeOptional<TensorInfo>(workloadInfo.m_InputTensorInfos[2]);
1348  const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value();
1349 
1350  ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
1351  ValidateBiasTensorQuantization(biasTensorInfo, weightTensorInfo, descriptorName);
1352  }
1353 
1355  {
1357  fmt::format("{}: strideX (provided {}), strideY (provided {}) or strideZ (provided {})"
1358  "cannot be either negative or 0.",
1360  }
1361 
1362  ValidatePerAxisQuantization(inputTensorInfo,
1363  outputTensorInfo,
1364  weightTensorInfo,
1365  optionalBiasTensorInfo,
1366  descriptorName);
1367 
1368  std::vector<DataType> supportedTypes =
1369  {
1377  };
1378 
1379  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1380  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1381 }
1382 
1384 {
1385  const std::string descriptorName{"DepthwiseConvolution2dQueueDescriptor"};
1386 
1387  uint32_t numInputs = 2;
1389  {
1390  numInputs = 3;
1391  }
1392 
1393  ValidateNumInputs(workloadInfo, descriptorName, numInputs);
1394  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1395 
1396  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1397  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1398 
1399  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1400  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1401 
1402  const TensorInfo& weightTensorInfo = workloadInfo.m_InputTensorInfos[1];
1403  ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 4, "weight");
1404 
1406  {
1408  fmt::format("{}: dilationX (provided {}) and dilationY (provided {}) "
1409  "cannot be smaller than 1.",
1410  descriptorName, m_Parameters.m_DilationX, m_Parameters.m_DilationX));
1411  }
1412 
1413  if (m_Parameters.m_StrideX <= 0 || m_Parameters.m_StrideY <= 0 )
1414  {
1416  fmt::format("{}: strideX (provided {}) and strideY (provided {}) "
1417  "cannot be either negative or 0.",
1418  descriptorName, m_Parameters.m_StrideX, m_Parameters.m_StrideY));
1419  }
1420 
1421  if (weightTensorInfo.GetShape()[0] != 1)
1422  {
1423  throw InvalidArgumentException(fmt::format(
1424  "{0}: The weight format in armnn is expected to be [1, H, W, Cout]."
1425  "But first dimension is not equal to 1. Provided weight shape: [{1}, {2}, {3}, {4}]",
1426  descriptorName,
1427  weightTensorInfo.GetShape()[0],
1428  weightTensorInfo.GetShape()[1],
1429  weightTensorInfo.GetShape()[2],
1430  weightTensorInfo.GetShape()[3]));
1431  }
1432 
1433  const unsigned int channelIndex = (m_Parameters.m_DataLayout == DataLayout::NCHW) ? 1 : 3;
1434  const unsigned int numWeightOutputChannelsRefFormat = weightTensorInfo.GetShape()[3];
1435  const unsigned int numWeightOutputChannelsAclFormat = weightTensorInfo.GetShape()[1];
1436  const unsigned int numOutputChannels = outputTensorInfo.GetShape()[channelIndex];
1437 
1438  // Weights format has two valid options: [1, H, W, Cout] (CpuRef) or [1, Cout, H, W] (CpuAcc/GpuAcc).
1439  bool validRefFormat = (numWeightOutputChannelsRefFormat == numOutputChannels);
1440  bool validAclFormat = (numWeightOutputChannelsAclFormat == numOutputChannels);
1441 
1442  if (!(validRefFormat || validAclFormat))
1443  {
1444  throw InvalidArgumentException(fmt::format(
1445  "{0}: The weight format in armnn is expected to be [1, H, W, Cout] (CpuRef) or [1, Cout, H, W] "
1446  "(CpuAcc/GpuAcc). But neither the 4th (CpuRef) or 2nd (CpuAcc/GpuAcc) dimension is equal to Cout."
1447  "Cout = {1} Provided weight shape: [{2}, {3}, {4}, {5}]",
1448  descriptorName,
1449  numOutputChannels,
1450  weightTensorInfo.GetShape()[0],
1451  weightTensorInfo.GetShape()[1],
1452  weightTensorInfo.GetShape()[2],
1453  weightTensorInfo.GetShape()[3]));
1454  }
1455 
1456  ValidateWeightDataType(inputTensorInfo, weightTensorInfo, descriptorName);
1457 
1458  Optional<TensorInfo> optionalBiasTensorInfo;
1460  {
1461  optionalBiasTensorInfo = MakeOptional<TensorInfo>(workloadInfo.m_InputTensorInfos[2]);
1462  const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value();
1463 
1464  ValidateBiasTensorQuantization(biasTensorInfo, weightTensorInfo, descriptorName);
1465  ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
1466  }
1467  ValidatePerAxisQuantization(inputTensorInfo,
1468  outputTensorInfo,
1469  weightTensorInfo,
1470  optionalBiasTensorInfo,
1471  descriptorName);
1472 
1473  std::vector<DataType> supportedTypes =
1474  {
1481  };
1482 
1483  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1484  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1485 }
1486 
1487 void PermuteQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1488 {
1489  const std::string descriptorName{"PermuteQueueDescriptor"};
1490 
1491  ValidateNumInputs(workloadInfo, descriptorName, 1);
1492  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1493 
1494  const PermutationVector& mapping = m_Parameters.m_DimMappings;
1495 
1496  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1497  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1498 
1499  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, mapping.GetSize(), "input");
1500  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, mapping.GetSize(), "output");
1501 
1502  for (unsigned int i = 0u; i < mapping.GetSize(); ++i)
1503  {
1504  if (inputTensorInfo.GetShape()[i] != outputTensorInfo.GetShape()[mapping[i]])
1505  {
1506  throw InvalidArgumentException(descriptorName + ": src dimension " + to_string(i) +
1507  " (=" + to_string(inputTensorInfo.GetShape()[i]) + ") " +
1508  "must match dst dimension " + to_string(mapping[i]) +
1509  " (=" + to_string(outputTensorInfo.GetShape()[mapping[i]]) + ")");
1510  }
1511  }
1512 
1513  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1514 }
1515 
1516 void Pooling2dQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1517 {
1518  const std::string descriptorName{"Pooling2dQueueDescriptor"};
1519 
1520  ValidateNumInputs(workloadInfo, descriptorName, 1);
1521  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1522 
1523  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1524  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1525 
1526  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1527  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1528 
1529  std::vector<DataType> supportedTypes =
1530  {
1537  };
1538 
1539  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1540  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1541 }
1542 
1543 void Pooling3dQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1544 {
1545  const std::string descriptorName{"Pooling3dQueueDescriptor"};
1546 
1547  ValidateNumInputs(workloadInfo, descriptorName, 1);
1548  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1549 
1550  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1551  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1552 
1553  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 5, "input");
1554  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 5, "output");
1555 
1556  std::vector<DataType> supportedTypes =
1557  {
1564  };
1565 
1566  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1567  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1568 }
1569 
1570 void ResizeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1571 {
1572  const std::string descriptorName{"ResizeQueueDescriptor"};
1573 
1574  ValidateNumInputs(workloadInfo, descriptorName, 1);
1575  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1576 
1577  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1578  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1579 
1580  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1581  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1582 
1583  std::vector<DataType> supportedTypes =
1584  {
1591  };
1592 
1593  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1594  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1595 
1596  // Resize only changes width and height: batch and channel count must match.
1597  const unsigned int inputBatchSize = inputTensorInfo.GetShape()[0];
1598  const unsigned int outputBatchSize = outputTensorInfo.GetShape()[0];
1599  if (inputBatchSize != outputBatchSize)
1600  {
1602  fmt::format("{}: Input batch size ({}) does not match output batch size ({})",
1603  descriptorName, inputBatchSize, outputBatchSize));
1604  }
1605 
1606  DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
1607  const unsigned int inputChannelCount = inputTensorInfo.GetShape()[dimensionIndices.GetChannelsIndex()];
1608  const unsigned int outputChannelCount = outputTensorInfo.GetShape()[dimensionIndices.GetChannelsIndex()];
1609  if (inputChannelCount != outputChannelCount)
1610  {
1612  fmt::format("{}: Input channel count ({}) does not match output channel count ({})",
1613  descriptorName, inputChannelCount, outputChannelCount));
1614  }
1615 }
1616 
1617 void ReverseV2QueueDescriptor::Validate(const WorkloadInfo &workloadInfo) const
1618 {
1619  const std::string descriptorName{"ReverseV2QueueDescriptor"};
1620 
1621  // Backend restriction
1622  const unsigned int maxDimensions = 4;
1623 
1624  ValidateNumInputs(workloadInfo, descriptorName, 2);
1625  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1626 
1627  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1628  const TensorInfo& axisTensorInfo = workloadInfo.m_InputTensorInfos[1];
1629  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1630 
1631  const auto inputTensorNumDimensions = inputTensorInfo.GetNumDimensions();
1632  if (inputTensorNumDimensions > maxDimensions)
1633  {
1634  throw InvalidArgumentException(descriptorName +
1635  ": Input tensors with rank greater than " +
1636  std::to_string(maxDimensions) + " are not supported.");
1637  }
1638 
1639  const auto axisTensorNumDimensions = axisTensorInfo.GetNumDimensions();
1640  if (axisTensorNumDimensions > maxDimensions)
1641  {
1642  throw InvalidArgumentException(descriptorName +
1643  ": More than " + std::to_string(maxDimensions) + " axes cannot be specified.");
1644  }
1645 
1646  if (axisTensorNumDimensions > inputTensorNumDimensions)
1647  {
1648  throw InvalidArgumentException(descriptorName +
1649  ": More axes specified than the number of axes on the input tensor.");
1650  }
1651 
1652  std::vector<DataType> supportedTypes =
1653  {
1662  };
1663 
1664  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1665 
1666  std::vector<DataType> axisSupportedTypes =
1667  {
1669  };
1670 
1671  ValidateDataTypes(axisTensorInfo, axisSupportedTypes, descriptorName);
1672 
1673  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1674  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1675 }
1676 
1678 {
1679  const std::string descriptorName{"FakeQuantizationQueueDescriptor"};
1680 
1681  ValidateNumInputs(workloadInfo, descriptorName, 1);
1682  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1683 
1684  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1685  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1686 
1687  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 2, "input");
1688  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 2, "output");
1689 
1690  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1691 
1693  {
1694  throw InvalidArgumentException(descriptorName + ": min cannot be greater than max");
1695  }
1696 }
1697 
1699 {
1700  const std::string descriptorName{"InstanceNormalizationQueueDescriptor"};
1701 
1702  ValidateNumInputs(workloadInfo, descriptorName, 1);
1703  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1704 
1705  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1706  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1707 
1708  if (inputTensorInfo.GetNumDimensions() > 4)
1709  {
1710  throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
1711  }
1712 
1713  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1714 
1715  // Check the supported data types
1716  std::vector<DataType> supportedTypes =
1717  {
1721  };
1722 
1723  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1724  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1725 }
1726 
1728 {
1729  const std::string descriptorName{"L2NormalizationQueueDescriptor"};
1730 
1731  ValidateNumInputs(workloadInfo, descriptorName, 1);
1732  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1733 
1734  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1735  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1736 
1737  if (inputTensorInfo.GetNumDimensions() > 4)
1738  {
1739  throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
1740  }
1741 
1742  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1743 
1744  // Check the supported data types
1745  std::vector<DataType> supportedTypes =
1746  {
1753  };
1754 
1755  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1756  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1757 }
1758 
1759 void LogSoftmaxQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1760 {
1761  const std::string descriptorName{"LogSoftmaxQueueDescriptor"};
1762 
1763  ValidateNumInputs(workloadInfo, descriptorName, 1);
1764  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1765 
1766  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1767  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1768 
1769  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1770 
1771  std::vector<DataType> supportedTypes =
1772  {
1776  };
1777 
1778  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1779  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1780 }
1781 
1782 void ConstantQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1783 {
1784  const std::string descriptorName{"ConstantQueueDescriptor"};
1785 
1786  ValidateNumInputs(workloadInfo, descriptorName, 0);
1787  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1788 
1789  if (!m_LayerOutput)
1790  {
1791  throw InvalidArgumentException(descriptorName + ": No const input specified.");
1792  }
1793 
1794  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1795  ValidateTensorShapesMatch(m_LayerOutput->GetTensorInfo(), outputTensorInfo, descriptorName, "constant", "output");
1796 
1797  // Check the supported data types
1798  std::vector<DataType> supportedTypes =
1799  {
1808  };
1809 
1810  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1811 }
1812 
1813 void ReshapeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1814 {
1815  const std::string descriptorName{"ReshapeQueueDescriptor"};
1816 
1817  ValidateNumInputs(workloadInfo, descriptorName, 1);
1818  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1819 
1820  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1821  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1822 
1823  ValidateTensorNumElementsMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1824 
1825  // Check the supported data types
1826  std::vector<DataType> supportedTypes =
1827  {
1836  };
1837 
1838  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1839  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1840 }
1841 
1843 {
1844  const std::string descriptorName{"SpaceToBatchNdQueueDescriptor"};
1845 
1846  ValidateNumInputs(workloadInfo, descriptorName, 1);
1847  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1848 
1849  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1850  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1851 
1852  if (m_Parameters.m_BlockShape.size() != m_Parameters.m_PadList.size())
1853  {
1854  throw InvalidArgumentException(descriptorName + ": Pad List must contain the same number of "
1855  "dimensions as Block Shape.");
1856  }
1857 
1858  if (m_Parameters.m_BlockShape.size() == 2)
1859  {
1860  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1861  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1862  }
1863  else if (m_Parameters.m_BlockShape.size() == 1)
1864  {
1865  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 3, "input");
1866  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 3, "output");
1867  }
1868  else
1869  {
1870  throw InvalidArgumentException(descriptorName + ": Invalid Block and Crops size.");
1871  }
1872 
1873  // Check input + padding and output have the same number of elements
1874  DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
1875  const unsigned int inputHeight = inputTensorInfo.GetShape()[dimensionIndices.GetHeightIndex()] +
1876  m_Parameters.m_PadList[0].first + m_Parameters.m_PadList[0].second;
1877  const unsigned int inputWidth = (inputTensorInfo.GetNumDimensions() == 3) ? 1 :
1878  inputTensorInfo.GetShape()[dimensionIndices.GetWidthIndex()] +
1879  m_Parameters.m_PadList[1].first + m_Parameters.m_PadList[1].second;
1880 
1881  const int channelsIndex_int = (m_Parameters.m_DataLayout == DataLayout::NCHW) ? 1 : -1;
1882  const unsigned int channelsIndex = channelsIndex_int < 0 ?
1883  static_cast<unsigned int>(channelsIndex_int) + inputTensorInfo.GetNumDimensions()
1884  : static_cast<unsigned int>(channelsIndex_int);
1885 
1886  const unsigned int numInputElements = inputTensorInfo.GetShape()[0] *
1887  inputHeight *
1888  inputWidth *
1889  inputTensorInfo.GetShape()[channelsIndex];
1890 
1891  if (outputTensorInfo.GetNumElements() != numInputElements)
1892  {
1893  throw InvalidArgumentException(descriptorName + ": Input tensor has " +
1894  to_string(numInputElements) + " after padding but output tensor has " +
1895  to_string(outputTensorInfo.GetNumElements()) + " elements.");
1896  }
1897 
1898  // In a 4D tensor, there will be 2 spatialDimensions (H and W), and the for loop will run twice.
1899  // In a 3D tensor, there will be 1 spatialDimensions, and the for loop will run once.
1900  unsigned int firstSpatialDimension = m_Parameters.m_DataLayout == DataLayout::NCHW ? 2 : 1;
1901  for (unsigned int i = 0; i < m_Parameters.m_BlockShape.size(); ++i)
1902  {
1903  unsigned int spatialDimension = firstSpatialDimension + i;
1904  auto inputSize = inputTensorInfo.GetShape()[spatialDimension] +
1905  m_Parameters.m_PadList[i].first +
1906  m_Parameters.m_PadList[i].second;
1907  if (inputSize % m_Parameters.m_BlockShape[i] != 0)
1908  {
1909  throw InvalidArgumentException(descriptorName + ": Input dimension size after padding must be "
1910  "divisible by Block Shape in dimension: " + to_string(spatialDimension) + ".");
1911  }
1912  }
1913 
1914  std::vector<DataType> supportedTypes =
1915  {
1922  };
1923 
1924  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1925  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1926 }
1927 
1929 {
1930  const std::string descriptorName{"SpaceToDepthQueueDescriptor"};
1931 
1932  ValidateNumInputs(workloadInfo, descriptorName, 1);
1933  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1934 
1935  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1936  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1937 
1938  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
1939  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
1940 
1941  std::vector<DataType> supportedTypes =
1942  {
1949  };
1950 
1951  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
1952  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
1953 
1954  ValidateTensorNumElementsMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
1955 
1956  if (m_Parameters.m_BlockSize == 0)
1957  {
1958  throw InvalidArgumentException(descriptorName + ": Block size cannot be 0.");
1959  }
1960 
1961  DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
1962  const unsigned int wIndex = dimensionIndices.GetWidthIndex();
1963  const unsigned int hIndex = dimensionIndices.GetHeightIndex();
1964  const unsigned int cIndex = dimensionIndices.GetChannelsIndex();
1965 
1966  const TensorShape& inputShape = inputTensorInfo.GetShape();
1967  if (inputShape[hIndex] % m_Parameters.m_BlockSize != 0 || inputShape[wIndex] % m_Parameters.m_BlockSize != 0)
1968  {
1969  throw InvalidArgumentException(descriptorName + ": Input shape must be divisible "
1970  "by block size in all spatial dimensions");
1971  }
1972 
1973  const TensorShape& outputShape = outputTensorInfo.GetShape();
1974  if (outputShape[cIndex] % (m_Parameters.m_BlockSize * m_Parameters.m_BlockSize) != 0)
1975  {
1976  throw InvalidArgumentException(descriptorName + ": The depth of the output tensor"
1977  "must be divisible by the square of block size." );
1978  }
1979 }
1980 
1981 void FloorQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1982 {
1983  const std::string descriptorName{"FloorQueueDescriptor"};
1984 
1985  ValidateNumInputs(workloadInfo, descriptorName, 1);
1986  ValidateNumOutputs(workloadInfo, descriptorName, 1);
1987 
1988  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
1989  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
1990 
1991  std::vector<DataType> supportedTypes =
1992  {
1997  };
1998 
1999  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2000  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2001  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2002  ValidateTensorQuantizationSpace(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2003 }
2004 
2005 void LstmQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2006 {
2007  // ported from android/ml/nn/common/operations/LSTM.cpp CheckInputTensorDimensions()
2008 
2009  const std::string descriptorName{"LstmQueueDescriptor"};
2010 
2011  // check dimensions of all inputs and outputs
2012  if (workloadInfo.m_InputTensorInfos.size() != 3)
2013  {
2014  throw InvalidArgumentException(descriptorName + ": Invalid number of inputs.");
2015  }
2016  if (workloadInfo.m_OutputTensorInfos.size() != 4)
2017  {
2018  throw InvalidArgumentException(descriptorName + ": Invalid number of outputs.");
2019  }
2020 
2021  std::vector<DataType> supportedTypes =
2022  {
2027  };
2028 
2029  // check for supported type of one input and match them with all the other input and output
2030  ValidateDataTypes(workloadInfo.m_InputTensorInfos[0], supportedTypes, descriptorName);
2031 
2032  // type matches all other inputs
2033  for (uint32_t i = 1u; i < workloadInfo.m_InputTensorInfos.size(); ++i)
2034  {
2035  ValidateTensorDataTypesMatch(workloadInfo.m_InputTensorInfos[0],
2036  workloadInfo.m_InputTensorInfos[i],
2037  descriptorName,
2038  "input_0",
2039  "input_" + std::to_string(i));
2040  }
2041  // type matches all other outputs
2042  for (uint32_t i = 0u; i < workloadInfo.m_OutputTensorInfos.size(); ++i)
2043  {
2044  ValidateTensorDataTypesMatch(workloadInfo.m_InputTensorInfos[0],
2045  workloadInfo.m_OutputTensorInfos[i],
2046  "LstmQueueDescriptor",
2047  "input_0",
2048  "output_" + std::to_string(i));
2049  }
2050 
2051  // Making sure clipping parameters have valid values.
2052  // == 0 means no clipping
2053  // > 0 means clipping
2054  if (m_Parameters.m_ClippingThresCell < 0.0f)
2055  {
2056  throw InvalidArgumentException(descriptorName + ": negative cell clipping threshold is invalid");
2057  }
2058  if (m_Parameters.m_ClippingThresProj < 0.0f)
2059  {
2060  throw InvalidArgumentException(descriptorName + ": negative projection clipping threshold is invalid");
2061  }
2062 
2063  // Inferring batch size, number of outputs and number of cells from the inputs.
2064  const uint32_t n_input = workloadInfo.m_InputTensorInfos[0].GetShape()[1];
2065  const uint32_t n_batch = workloadInfo.m_InputTensorInfos[0].GetShape()[0];
2066  ValidatePointer(m_InputToOutputWeights, "Null pointer check", "InputToOutputWeights");
2067  const uint32_t n_cell = m_InputToOutputWeights->GetShape()[0];
2068  ValidatePointer(m_RecurrentToOutputWeights, "Null pointer check", "RecurrentToOutputWeights");
2069  const uint32_t n_output = m_RecurrentToOutputWeights->GetShape()[1];
2070 
2071  // input tensor
2072  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[0], 2, (n_batch * n_input),
2073  descriptorName + " input_0");
2074  // outputStateInTensor
2075  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[1], 2, (n_batch * n_output),
2076  descriptorName + " input_1");
2077  // outputStateInTensor
2078  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[2], 2, (n_batch * n_cell),
2079  descriptorName + " input_2");
2080  // scratchBufferTensor
2081  unsigned int scratchBufferSize = m_Parameters.m_CifgEnabled ? n_cell * 3 : n_cell * 4;
2082  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[0], 2, (n_batch * scratchBufferSize),
2083  descriptorName + " output_0");
2084  // outputStateOutTensor
2085  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[1], 2, (n_batch * n_output),
2086  descriptorName + " output_1");
2087  // cellStateOutTensor
2088  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[2], 2, (n_batch * n_cell),
2089  descriptorName + " output_2");
2090  // outputTensor
2091  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[3], 2, (n_batch * n_output),
2092  descriptorName + " output_3");
2093 
2094  // check that dimensions of inputs/outputs and QueueDescriptor data match with each other
2095  if ( m_InputToInputWeights )
2096  {
2098  (n_cell * n_input), "InputLayerNormWeights");
2099  }
2100 
2101  ValidatePointer(m_InputToForgetWeights, "Null pointer check", "InputToForgetWeights");
2103  (n_cell * n_input), "InputToForgetWeights");
2104 
2105  ValidatePointer(m_InputToCellWeights, "Null pointer check", "InputToCellWeights");
2107  (n_cell * n_input), "InputToCellWeights");
2108 
2110  {
2112  (n_cell * n_output), "RecurrentToInputWeights");
2113  }
2114 
2115  ValidatePointer(m_RecurrentToForgetWeights, "Null pointer check", "RecurrentToForgetWeights");
2117  (n_cell * n_output), "RecurrentToForgetWeights");
2118 
2119  ValidatePointer(m_RecurrentToCellWeights, "Null pointer check", "RecurrentToCellWeights");
2121  (n_cell * n_output), "RecurrentToCellWeights");
2122 
2123  // Make sure the input-gate's parameters are either both present (regular
2124  // LSTM) or not at all (CIFG-LSTM). And CifgEnable is set accordingly.
2125  bool cifg_weights_all_or_none = ((m_InputToInputWeights && m_RecurrentToInputWeights &&
2129  if (!cifg_weights_all_or_none)
2130  {
2131  throw InvalidArgumentException(descriptorName + ": Input-Gate's parameters InputToInputWeights and "
2132  "RecurrentToInputWeights must either both be present (regular LSTM) "
2133  "or both not present (CIFG-LSTM). In addition CifgEnable must be set "
2134  "accordingly.");
2135  }
2136 
2137  if ( m_CellToInputWeights )
2138  {
2140  n_cell, "CellToInputWeights");
2141  }
2142  if ( m_CellToForgetWeights )
2143  {
2145  n_cell, "CellToForgetWeights");
2146  }
2147  if ( m_CellToOutputWeights )
2148  {
2150  n_cell, "CellToOutputWeights");
2151  }
2152 
2153  // Making sure the peephole weights are there all or none. And PeepholeEnable is set accordingly.
2154  bool peephole_weights_all_or_none =
2159  if (!peephole_weights_all_or_none)
2160  {
2161  throw InvalidArgumentException(descriptorName + ": Invalid combination of peephole parameters.");
2162  }
2163 
2164  // Make sure the input gate bias is present only when not a CIFG-LSTM.
2166  {
2167  if (m_InputGateBias)
2168  {
2169  throw InvalidArgumentException(descriptorName + ": InputGateBias is present and CIFG-LSTM is enabled.");
2170  }
2171  }
2172  else
2173  {
2174  if (!m_InputGateBias)
2175  {
2176  throw InvalidArgumentException(descriptorName + ": If CIFG-LSTM is disabled InputGateBias "
2177  "must be present.");
2178  }
2180  n_cell, "InputGateBias");
2181  }
2182 
2183  ValidatePointer(m_ForgetGateBias, "Null pointer check", "ForgetGateBias");
2184  ValidateTensorNumDimNumElem(m_ForgetGateBias->GetTensorInfo(), 1, n_cell, "ForgetGateBias");
2185 
2186  ValidatePointer(m_CellBias, "Null pointer check", "CellBias");
2187  ValidateTensorNumDimNumElem(m_CellBias->GetTensorInfo(), 1, n_cell, "CellBias");
2188 
2189  ValidatePointer(m_OutputGateBias, "Null pointer check", "OutputGateBias");
2190  ValidateTensorNumDimNumElem(m_OutputGateBias->GetTensorInfo(), 1, n_cell, "OutputGateBias");
2191 
2192  if (m_ProjectionWeights)
2193  {
2195  (n_cell * n_output), "ProjectionWeights");
2196  }
2197  if (m_ProjectionBias)
2198  {
2199  ValidateTensorNumDimNumElem(m_ProjectionBias->GetTensorInfo(), 1, n_output, "ProjectionBias");
2200  }
2201 
2202  // Making sure the projection tensors are consistent:
2203  // 1) If projection weight is not present, then projection bias should not be
2204  // present.
2205  // 2) If projection weight is present, then projection bias is optional.
2206  bool projecton_tensors_consistent = ((!m_ProjectionWeights && !m_ProjectionBias &&
2212  if (!projecton_tensors_consistent)
2213  {
2214  throw InvalidArgumentException(descriptorName + ": Projection tensors are inconsistent.");
2215  }
2216 
2217  // The four layer normalization weights either all have values or none of them have values. Additionally, if
2218  // CIFG is used, input layer normalization weights tensor is omitted and the other layer normalization weights
2219  // either all have values or none of them have values. Layer normalization is used when the values of all the
2220  // layer normalization weights are present
2222  {
2223  ValidateTensorNumDimNumElem(m_InputLayerNormWeights->GetTensorInfo(), 1, n_cell, "InputLayerNormWeights");
2224  }
2226  {
2227  ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
2228  }
2230  {
2231  ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
2232  }
2234  {
2235  ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
2236  }
2237 
2239  {
2241  {
2243  {
2244  throw InvalidArgumentException(descriptorName + ": Layer normalisation is enabled and CIFG-LSTM is "
2245  "disabled but InputLayerNormWeights are not present");
2246  }
2248  1, n_cell, "InputLayerNormWeights");
2249  }
2250  else if (m_InputLayerNormWeights)
2251  {
2252  throw InvalidArgumentException(descriptorName + ":InputLayerNormWeights are present while CIFG is "
2253  "enabled");
2254  }
2255 
2256  ValidatePointer(m_ForgetLayerNormWeights, "Null pointer check layer normalisation enabled",
2257  "ForgetLayerNormWeights");
2258  ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
2259 
2260  ValidatePointer(m_OutputLayerNormWeights, "Null pointer check layer normalisation enabled",
2261  "OutputLayerNormWeights");
2262  ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
2263 
2264  ValidatePointer(m_CellLayerNormWeights, "Null pointer check layer normalisation enabled",
2265  "CellLayerNormWeights");
2266  ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
2267  }
2269  {
2270  throw InvalidArgumentException(descriptorName + ": Layer normalisation is disabled but one or more layer "
2271  "normalisation weights are present.");
2272  }
2273 }
2274 
2276 {
2277  const std::string descriptorName{"ConvertFp32ToFp16QueueDescriptor"};
2278 
2279  ValidateNumInputs(workloadInfo, descriptorName, 1);
2280  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2281 
2282  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2283  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2284 
2285  if (inputTensorInfo.GetDataType() != DataType::Float32)
2286  {
2287  throw InvalidArgumentException(descriptorName + ": Input tensor type must be Float32.");
2288  }
2289 
2290  if (outputTensorInfo.GetDataType() != DataType::Float16)
2291  {
2292  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Float16.");
2293  }
2294 
2295  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2296 }
2297 
2299 {
2300  const std::string descriptorName{"ConvertFp16ToFp32QueueDescriptor"};
2301 
2302  ValidateNumInputs(workloadInfo, descriptorName, 1);
2303  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2304 
2305  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2306  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2307 
2308  if (inputTensorInfo.GetDataType() != DataType::Float16)
2309  {
2310  throw InvalidArgumentException(descriptorName + ": Input tensor type must be Float16.");
2311  }
2312 
2313  if (outputTensorInfo.GetDataType() != DataType::Float32)
2314  {
2315  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Float32.");
2316  }
2317 
2318  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2319 }
2320 
2321 void DivisionQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2322 {
2323  const std::string descriptorName{"DivisionQueueDescriptor"};
2324 
2325  ValidateNumInputs(workloadInfo, descriptorName, 2);
2326  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2327 
2328  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2329  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2330  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2331 
2332  std::vector<DataType> supportedTypes =
2333  {
2341  };
2342 
2343  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2344  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2345  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
2346 
2347  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2348  inputTensorInfo1,
2349  outputTensorInfo,
2350  descriptorName,
2351  "input_0",
2352  "input_1");
2353 }
2354 
2356 {
2357  const std::string descriptorName{"SubtractionQueueDescriptor"};
2358 
2359  ValidateNumInputs(workloadInfo, descriptorName, 2);
2360  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2361 
2362  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2363  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2364  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2365 
2366  std::vector<DataType> supportedTypes =
2367  {
2375  };
2376 
2377  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2378  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2379  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
2380 
2381  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2382  inputTensorInfo1,
2383  outputTensorInfo,
2384  descriptorName,
2385  "input_0",
2386  "input_1");
2387 }
2388 
2389 void MaximumQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2390 {
2391  const std::string descriptorName{"MaximumQueueDescriptor"};
2392 
2393  ValidateNumInputs(workloadInfo, descriptorName, 2);
2394  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2395 
2396  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2397  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2398  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2399 
2400  std::vector<DataType> supportedTypes =
2401  {
2409  };
2410 
2411  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2412  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2413  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
2414 
2415  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2416  inputTensorInfo1,
2417  outputTensorInfo,
2418  descriptorName,
2419  "input_0",
2420  "input_1");
2421 }
2422 
2423 void MeanQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2424 {
2425  const std::string descriptorName{"MeanQueueDescriptor"};
2426 
2427  ValidateNumInputs(workloadInfo, descriptorName, 1);
2428  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2429 
2430  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2431  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2432 
2433  std::vector<DataType> supportedTypes =
2434  {
2441  };
2442 
2443  // First check if input tensor data type is supported, then
2444  // check if this data type matches the output tensor data type
2445  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2446  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2447 
2449  {
2450  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, inputTensorInfo.GetNumDimensions(), "output");
2451  }
2452  else if (m_Parameters.m_Axis.empty())
2453  {
2454  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 1, "output");
2455  }
2456  else
2457  {
2458  unsigned int outputDim =
2459  inputTensorInfo.GetNumDimensions() - armnn::numeric_cast<unsigned int>(m_Parameters.m_Axis.size());
2460  ValidateTensorNumDimensions(outputTensorInfo,
2461  descriptorName,
2462  outputDim > 0 ? outputDim : 1,
2463  "output");
2464  }
2465 }
2466 
2467 void PadQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2468 {
2469  const std::string descriptorName{"PadQueueDescriptor"};
2470 
2471  ValidateNumInputs(workloadInfo, descriptorName, 1);
2472  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2473 
2474  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2475  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2476 
2477  // input and output should have the same number of dimensions
2478  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, inputTensorInfo.GetNumDimensions(), "output");
2479 
2480  // there should be entry in the pad list for each dimension in the input tensor
2481  if (m_Parameters.m_PadList.size() != inputTensorInfo.GetNumDimensions()) {
2482  throw InvalidArgumentException(descriptorName + ":Pad List should contain the same number of entries "
2483  "as there are dimensions in the input tensor that is " +
2484  std::to_string(inputTensorInfo.GetNumDimensions()) + " entries " +
2485  " not " + std::to_string(m_Parameters.m_PadList.size()) + " entries.");
2486  }
2487 }
2488 
2489 void QuantizeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2490 {
2491  const std::string descriptorName{"QuantizeQueueDescriptor"};
2492 
2493  ValidateNumInputs(workloadInfo, descriptorName, 1);
2494  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2495 
2496  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2497  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2498 
2499  std::vector<DataType> supportedTypes =
2500  {
2508  };
2509 
2510  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2511 
2512  if (!IsQuantizedType(outputTensorInfo.GetDataType()))
2513  {
2514  throw InvalidArgumentException(descriptorName + ": Output of quantized layer must be quantized type.");
2515  }
2516 }
2517 
2519 {
2520  const std::string descriptorName{"BatchToSpaceNdQueueDescriptor"};
2521 
2522  ValidateNumInputs(workloadInfo, descriptorName, 1);
2523  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2524 
2525  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2526  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2527 
2528  if (m_Parameters.m_BlockShape.size() != m_Parameters.m_Crops.size())
2529  {
2530  throw InvalidArgumentException(descriptorName + ": Crops must contain the same number of "
2531  "dimensions as Block Shape.");
2532  }
2533 
2534  if (m_Parameters.m_BlockShape.size() == 2)
2535  {
2536  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
2537  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
2538  }
2539  else if (m_Parameters.m_BlockShape.size() == 1)
2540  {
2541  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 3, "input");
2542  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 3, "output");
2543  }
2544  else
2545  {
2546  throw InvalidArgumentException(descriptorName + ": Invalid Block and Crops size.");
2547  }
2548 
2549  // In a 4D tensor, there will be 2 spatialDimensions (H and W), and the for loop will run twice.
2550  // In a 3D tensor, there will be 1 spatialDimensions, and the for loop will run once.
2551  unsigned int firstSpatialDimension = m_Parameters.m_DataLayout == DataLayout::NCHW ? 2 : 1;
2552  for (unsigned int i = 0; i < m_Parameters.m_BlockShape.size(); ++i)
2553  {
2554  unsigned int spatialDimension = firstSpatialDimension + i;
2555  unsigned int cropSize = m_Parameters.m_Crops[i].first + m_Parameters.m_Crops[i].second;
2556  unsigned int outputSize = inputTensorInfo.GetShape()[spatialDimension] * m_Parameters.m_BlockShape[i];
2557  if (cropSize > outputSize)
2558  {
2559  throw InvalidArgumentException(descriptorName + ": CropSize must be less than or equal to the uncropped"
2560  "outputSize in dimension: " + to_string(spatialDimension) + ".");
2561  }
2562  }
2563 
2564  std::vector<DataType> supportedTypes =
2565  {
2572  };
2573 
2574  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2575  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2576 }
2577 
2579 {
2580  const std::string descriptorName{"StridedSliceQueueDescriptor"};
2581 
2582  ValidateNumInputs(workloadInfo, descriptorName, 1);
2583  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2584 
2585  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2586  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2587 
2588  std::vector<DataType> supportedTypes =
2589  {
2596  };
2597 
2598  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2599  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2600 
2601  ValidateTensorQuantizationSpace(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2602 
2603  const uint32_t rank = inputTensorInfo.GetNumDimensions();
2604  if (rank > 4)
2605  {
2606  throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
2607  }
2608 
2609  // Begin, End & Stride length must be of rank(input0)
2610  if (m_Parameters.m_Begin.size() != rank)
2611  {
2612  throw InvalidArgumentException(descriptorName + ": Begin length must be of rank " + std::to_string(rank));
2613  }
2614 
2615  if (m_Parameters.m_End.size() != rank)
2616  {
2617  throw InvalidArgumentException(descriptorName + ": End length must be of rank " + std::to_string(rank));
2618  }
2619 
2620  if (m_Parameters.m_Stride.size() != rank)
2621  {
2622  throw InvalidArgumentException(descriptorName + ": Stride length must be of rank " + std::to_string(rank));
2623  }
2624 
2625  // Stride entries must be non-zero
2626  for (auto& stride : m_Parameters.m_Stride)
2627  {
2628  if (stride == 0)
2629  {
2630  throw InvalidArgumentException(descriptorName + ": Stride entries must be non-zero.");
2631  }
2632  }
2633 }
2634 
2635 void MinimumQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2636 {
2637  const std::string descriptorName{"MinimumQueueDescriptor"};
2638 
2639  ValidateNumInputs(workloadInfo, descriptorName, 2);
2640  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2641 
2642  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2643  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2644  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2645 
2646  std::vector<DataType> supportedTypes =
2647  {
2655  };
2656 
2657  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2658  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2659  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
2660 
2661  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2662  inputTensorInfo1,
2663  outputTensorInfo,
2664  descriptorName,
2665  "input_0",
2666  "input_1");
2667 }
2668 
2669 void DebugQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2670 {
2671  const std::string descriptorName{"DebugQueueDescriptor"};
2672 
2673  ValidateNumInputs(workloadInfo, descriptorName, 1);
2674  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2675 }
2676 
2677 void EqualQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2678 {
2679  const std::string descriptorName{"EqualQueueDescriptor"};
2680 
2681  ValidateNumInputs(workloadInfo, descriptorName, 2);
2682  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2683 
2684  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2685  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2686  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2687 
2688  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2689  inputTensorInfo1,
2690  outputTensorInfo,
2691  descriptorName,
2692  "input_0",
2693  "input_1");
2694 
2695  if (outputTensorInfo.GetDataType() != DataType::Boolean)
2696  {
2697  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
2698  }
2699 }
2700 
2701 void GreaterQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2702 {
2703  const std::string descriptorName{"GreaterQueueDescriptor"};
2704 
2705  ValidateNumInputs(workloadInfo, descriptorName, 2);
2706  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2707 
2708  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2709  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2710  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2711 
2712  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
2713  inputTensorInfo1,
2714  outputTensorInfo,
2715  descriptorName,
2716  "input_0",
2717  "input_1");
2718 
2719  if (outputTensorInfo.GetDataType() != DataType::Boolean)
2720  {
2721  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
2722  }
2723 }
2724 
2725 void RsqrtQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2726 {
2727  const std::string descriptorName{"RsqrtQueueDescriptor"};
2728 
2729  ValidateNumInputs(workloadInfo, descriptorName, 1);
2730  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2731 
2732  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2733  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2734 
2735  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2736 
2737  std::vector<DataType> supportedTypes =
2738  {
2745  };
2746 
2747  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2748  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2749 }
2750 
2751 void GatherNdQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2752 {
2753  const std::string descriptorName{"GatherNdQueueDescriptor"};
2754 
2755  ValidateNumInputs(workloadInfo, descriptorName, 2);
2756  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2757 
2758  const TensorInfo& indicesTensorInfo = workloadInfo.m_InputTensorInfos[1];
2759  if (indicesTensorInfo.GetDataType() != DataType::Signed32)
2760  {
2761  throw InvalidArgumentException(descriptorName + ": Indices tensor type must be Int32.");
2762  }
2763 
2764  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2765  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2766 
2767  std::vector<DataType> supportedTypes =
2768  {
2776  };
2777 
2778  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2779 
2780  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2781 
2782  unsigned int outputDim = outputTensorInfo.GetNumDimensions();
2783  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, outputDim, "output");
2784 }
2785 
2786 void GatherQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2787 {
2788  const std::string descriptorName{"GatherQueueDescriptor"};
2789 
2790  ValidateNumInputs(workloadInfo, descriptorName, 2);
2791  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2792 
2793  const TensorInfo& indicesTensorInfo = workloadInfo.m_InputTensorInfos[1];
2794  if (indicesTensorInfo.GetDataType() != DataType::Signed32)
2795  {
2796  throw InvalidArgumentException(descriptorName + ": Indices tensor type must be Int32.");
2797  }
2798 
2799  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2800  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2801 
2802  std::vector<DataType> supportedTypes =
2803  {
2811  };
2812 
2813  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2814 
2815  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
2816 
2817  unsigned int outputDim = inputTensorInfo.GetNumDimensions() + indicesTensorInfo.GetNumDimensions() - 1;
2818  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, outputDim, "output");
2819 }
2820 
2822 {
2823  const std::string& descriptorName{"DetectionPostProcessQueueDescriptor"};
2824 
2825  ValidateNumInputs(workloadInfo, descriptorName, 2);
2826 
2827  if (workloadInfo.m_OutputTensorInfos.size() != 4)
2828  {
2829  throw InvalidArgumentException(descriptorName + ": Requires exactly four outputs. " +
2830  to_string(workloadInfo.m_OutputTensorInfos.size()) + " has been provided.");
2831  }
2832 
2833  if (m_Anchors == nullptr)
2834  {
2835  throw InvalidArgumentException(descriptorName + ": Anchors tensor descriptor is missing.");
2836  }
2837 
2838  const TensorInfo& boxEncodingsInfo = workloadInfo.m_InputTensorInfos[0];
2839  const TensorInfo& scoresInfo = workloadInfo.m_InputTensorInfos[1];
2840  const TensorInfo& anchorsInfo = m_Anchors->GetTensorInfo();
2841 
2842  const TensorInfo& detectionBoxesInfo = workloadInfo.m_OutputTensorInfos[0];
2843  const TensorInfo& detectionClassesInfo = workloadInfo.m_OutputTensorInfos[1];
2844  const TensorInfo& detectionScoresInfo = workloadInfo.m_OutputTensorInfos[2];
2845  const TensorInfo& numDetectionsInfo = workloadInfo.m_OutputTensorInfos[3];
2846 
2847  ValidateTensorNumDimensions(boxEncodingsInfo, descriptorName, 3, "box encodings");
2848  ValidateTensorNumDimensions(scoresInfo, descriptorName, 3, "scores");
2849  ValidateTensorNumDimensions(anchorsInfo, descriptorName, 2, "anchors");
2850 
2851  const std::vector<DataType> supportedInputTypes =
2852  {
2859  };
2860 
2861  ValidateDataTypes(boxEncodingsInfo, supportedInputTypes, descriptorName);
2862  ValidateDataTypes(scoresInfo, supportedInputTypes, descriptorName);
2863  ValidateDataTypes(anchorsInfo, supportedInputTypes, descriptorName);
2864 
2865  ValidateTensorNumDimensions(detectionBoxesInfo, descriptorName, 3, "detection boxes");
2866  ValidateTensorNumDimensions(detectionScoresInfo, descriptorName, 2, "detection scores");
2867  ValidateTensorNumDimensions(detectionClassesInfo, descriptorName, 2, "detection classes");
2868  ValidateTensorNumDimensions(numDetectionsInfo, descriptorName, 1, "num detections");
2869 
2870  // NOTE: Output is always Float32 regardless of input type
2871  ValidateTensorDataType(detectionBoxesInfo, DataType::Float32, descriptorName, "detection boxes");
2872  ValidateTensorDataType(detectionScoresInfo, DataType::Float32, descriptorName, "detection scores");
2873  ValidateTensorDataType(detectionClassesInfo, DataType::Float32, descriptorName, "detection classes");
2874  ValidateTensorDataType(numDetectionsInfo, DataType::Float32, descriptorName, "num detections");
2875 
2877  {
2878  throw InvalidArgumentException(descriptorName + ": Intersection over union threshold "
2879  "must be positive and less than or equal to 1.");
2880  }
2881 
2882  if (scoresInfo.GetShape()[2] != m_Parameters.m_NumClasses + 1)
2883  {
2884  throw InvalidArgumentException(descriptorName + ": Number of classes with background "
2885  "should be equal to number of classes + 1.");
2886  }
2887 }
2888 
2889 void DequantizeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2890 {
2891  const std::string& descriptorName{"DequantizeQueueDescriptor"};
2892 
2893  ValidateNumInputs(workloadInfo, descriptorName, 1);
2894  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2895 
2896  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2897  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2898 
2899  std::vector<DataType> inputSupportedTypes =
2900  {
2906  };
2907  ValidateDataTypes(inputTensorInfo, inputSupportedTypes, descriptorName);
2908 
2909  std::vector<DataType> outputSupportedTypes =
2910  {
2914  };
2915 
2916  ValidateDataTypes(outputTensorInfo, outputSupportedTypes, descriptorName);
2917 }
2918 
2919 void MergeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2920 {
2921  const std::string& descriptorName{"MergeQueueDescriptor"};
2922 
2923  ValidateNumInputs(workloadInfo, descriptorName, 2);
2924  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2925 
2926  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2927  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2928  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2929 
2930  ValidateTensorShapesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
2931  ValidateTensorShapesMatch(inputTensorInfo0, outputTensorInfo, descriptorName, "input_0", "output");
2932 
2933  ValidateTensorDataTypesMatch(inputTensorInfo0, inputTensorInfo1, descriptorName, "input_0", "input_1");
2934  ValidateTensorDataTypesMatch(inputTensorInfo0, outputTensorInfo, descriptorName, "input_0", "output");
2935 }
2936 
2937 void ShapeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2938 {
2939  const std::string& descriptorName{"ShapeQueueDescriptor"};
2940 
2941  ValidateNumInputs(workloadInfo, descriptorName, 1);
2942  ValidateNumOutputs(workloadInfo, descriptorName, 1);
2943 
2944  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
2945  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
2946 
2947  std::vector<DataType> supportedTypes =
2948  {
2957  };
2958 
2959  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
2960  ValidateDataTypes(outputTensorInfo, {DataType::Signed32}, descriptorName);
2961 }
2962 
2963 void SwitchQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
2964 {
2965  const std::string& descriptorName{"SwitchQueueDescriptor"};
2966 
2967  ValidateNumInputs(workloadInfo, descriptorName, 2);
2968  ValidateNumOutputs(workloadInfo, descriptorName, 2);
2969 
2970  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
2971  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
2972 
2973  const TensorInfo& outputTensorInfo0 = workloadInfo.m_OutputTensorInfos[0];
2974  const TensorInfo& outputTensorInfo1 = workloadInfo.m_OutputTensorInfos[1];
2975 
2976  std::vector<DataType> supportedTypes =
2977  {
2983  };
2984 
2985  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
2986  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
2987 
2988  ValidateDataTypes(outputTensorInfo0, supportedTypes, descriptorName);
2989  ValidateDataTypes(outputTensorInfo1, supportedTypes, descriptorName);
2990 
2991  ValidateTensorShapesMatch(inputTensorInfo0,
2992  outputTensorInfo0,
2993  descriptorName,
2994  "input_0",
2995  "output_0");
2996 
2997  ValidateTensorShapesMatch(inputTensorInfo0,
2998  outputTensorInfo1,
2999  descriptorName,
3000  "input_0",
3001  "output_1");
3002 }
3003 
3004 void PreCompiledQueueDescriptor::Validate(const WorkloadInfo& /*workloadInfo*/) const
3005 {
3006  // This is internally generated so it should not need validation.
3007 }
3008 
3009 void PreluQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3010 {
3011  const std::string& descriptorName{"PreluQueueDescriptor"};
3012 
3013  ValidateNumInputs(workloadInfo, descriptorName, 2);
3014  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3015 
3016  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3017  const TensorInfo& alphaTensorInfo = workloadInfo.m_InputTensorInfos[1];
3018  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3019 
3020  std::vector<DataType> supportedTypes
3021  {
3028  };
3029 
3030  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3031  ValidateDataTypes(alphaTensorInfo, supportedTypes, descriptorName);
3032 
3033  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
3034 
3035  ValidateTensorDataTypesMatch(inputTensorInfo, alphaTensorInfo, descriptorName, "input", "alpha");
3036  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "ouptut");
3037 
3038  ValidateBroadcastTensorShapesMatch(inputTensorInfo,
3039  alphaTensorInfo,
3040  outputTensorInfo,
3041  descriptorName,
3042  "input",
3043  "alpha");
3044 }
3045 
3047 {
3048  const std::string descriptorName{"TransposeConvolution2dQueueDescriptor"};
3049 
3050  ValidateNumInputs(workloadInfo, descriptorName, 1);
3051  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3052 
3053  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3054  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3055 
3056  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
3057  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
3058 
3059  ValidatePointer(m_Weight, descriptorName, "weight");
3060 
3061  const TensorInfo& weightTensorInfo = m_Weight->GetTensorInfo();
3062  ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 4, "weight");
3063 
3064  ValidateWeightDataType(inputTensorInfo, weightTensorInfo, descriptorName);
3065 
3066  Optional<TensorInfo> optionalBiasTensorInfo;
3068  {
3069  ValidatePointer(m_Bias, descriptorName, "bias");
3070 
3071  optionalBiasTensorInfo = MakeOptional<TensorInfo>(m_Bias->GetTensorInfo());
3072  const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value();
3073 
3074  ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
3075  ValidateBiasTensorQuantization(biasTensorInfo, weightTensorInfo, descriptorName);
3076  }
3077 
3078  ValidatePerAxisQuantization(inputTensorInfo,
3079  outputTensorInfo,
3080  weightTensorInfo,
3081  optionalBiasTensorInfo,
3082  descriptorName);
3083 
3084  std::vector<DataType> supportedTypes =
3085  {
3092  };
3093 
3094  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3095  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3096 }
3097 
3098 void TransposeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3099 {
3100  const std::string descriptorName{"TransposeQueueDescriptor"};
3101 
3102  ValidateNumInputs(workloadInfo, descriptorName, 1);
3103  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3104 
3105  const PermutationVector& mapping = m_Parameters.m_DimMappings;
3106 
3107  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3108  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3109 
3110  ValidateTensorNumDimensions(inputTensorInfo, descriptorName, mapping.GetSize(), "input");
3111  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, mapping.GetSize(), "output");
3112 
3113  for (unsigned int i = 0u; i < mapping.GetSize(); ++i)
3114  {
3115  if (inputTensorInfo.GetShape()[mapping[i]] != outputTensorInfo.GetShape()[i])
3116  {
3117  throw InvalidArgumentException(descriptorName + ": src dimension " + to_string(mapping[i]) +
3118  " (=" + to_string(inputTensorInfo.GetShape()[mapping[i]]) + ") " +
3119  "must match dst dimension " + to_string(i) +
3120  " (=" + to_string(outputTensorInfo.GetShape()[i]) + ")");
3121  }
3122  }
3123 
3124  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3125 }
3126 
3128 {
3129  const std::string descriptorName{"TransposeQueueDescriptor"};
3130 
3131  ValidateNumInputs(workloadInfo, descriptorName, 1);
3132  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3133 
3134  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3135  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3136 
3137  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3138 }
3139 
3140 void QLstmQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3141 {
3142  const std::string descriptorName{"QLstmQueueDescriptor"};
3143 
3144  // Validate number of inputs/outputs
3145  ValidateNumInputs(workloadInfo, descriptorName, 3);
3146  ValidateNumOutputs(workloadInfo, descriptorName, 3);
3147 
3148  // Input/output tensor info
3149  auto inputInfo = workloadInfo.m_InputTensorInfos[0];
3150  auto outputStateInInfo = workloadInfo.m_InputTensorInfos[1];
3151  auto cellStateInInfo = workloadInfo.m_InputTensorInfos[2];
3152 
3153  auto outputStateOutInfo = workloadInfo.m_OutputTensorInfos[0];
3154  auto cellStateOutInfo = workloadInfo.m_OutputTensorInfos[1];
3155  auto outputInfo = workloadInfo.m_OutputTensorInfos[2];
3156 
3157  // Supported types for various tensors in QLSTM
3158  std::vector<DataType> inputOutputSupportedTypes =
3159  {
3161  };
3162 
3163  std::vector<DataType> cellStateSupportedTypes =
3164  {
3166  };
3167 
3168  std::vector<DataType> weightsSupportedTypes =
3169  {
3171  };
3172 
3173  std::vector<DataType> layerNormPeepholeWeightsSupportedTypes =
3174  {
3176  };
3177 
3178  std::vector<DataType> biasSupportedTypes =
3179  {
3181  };
3182 
3183  // Validate types of input/output tensors
3184  ValidateDataTypes(inputInfo, inputOutputSupportedTypes, descriptorName);
3185  ValidateDataTypes(outputStateInInfo, inputOutputSupportedTypes, descriptorName);
3186  ValidateDataTypes(cellStateInInfo, cellStateSupportedTypes, descriptorName);
3187 
3188  ValidateDataTypes(outputStateOutInfo, inputOutputSupportedTypes, descriptorName);
3189  ValidateDataTypes(cellStateOutInfo, cellStateSupportedTypes, descriptorName);
3190  ValidateDataTypes(outputInfo, inputOutputSupportedTypes, descriptorName);
3191 
3192  // Validate matching types of input/output tensors
3193  ValidateTensorDataTypesMatch(inputInfo, outputStateInInfo, descriptorName, "input", "outputStateIn");
3194  ValidateTensorDataTypesMatch(outputStateInInfo, outputStateOutInfo, descriptorName,
3195  "outputStateIn", "outputStateOut");
3196  ValidateTensorDataTypesMatch(cellStateInInfo, cellStateOutInfo, descriptorName, "cellStateIn", "cellStateOut");
3197 
3198  // Infer number of batches, number of units, input size and output size from tensor dimensions
3199  const uint32_t numBatches = inputInfo.GetShape()[0];
3200  const uint32_t inputSize = inputInfo.GetShape()[1];
3201  const uint32_t outputSize = outputStateInInfo.GetShape()[1];
3202  const uint32_t numUnits = cellStateInInfo.GetShape()[1];
3203 
3204  // Validate number of dimensions and number of elements for input/output tensors
3205  ValidateTensorNumDimNumElem(inputInfo, 2, (numBatches * inputSize), descriptorName + " input");
3206  ValidateTensorNumDimNumElem(outputStateInInfo, 2, (numBatches * outputSize), descriptorName + " outputStateIn");
3207  ValidateTensorNumDimNumElem(cellStateInInfo, 2, (numBatches * numUnits), descriptorName + " cellStateIn");
3208 
3209  ValidateTensorNumDimNumElem(outputStateOutInfo, 2, (numBatches * outputSize), descriptorName + " outputStateOut");
3210  ValidateTensorNumDimNumElem(cellStateOutInfo, 2, (numBatches * numUnits), descriptorName + " cellStateOut");
3211  ValidateTensorNumDimNumElem(outputInfo, 2, (numBatches * outputSize), descriptorName + " output");
3212 
3213  // Validate number of dimensions and number of elements for MANDATORY weight tensors
3214  ValidatePointer(m_InputToForgetWeights, descriptorName, "InputToForgetWeights");
3215  auto inputToForgetWeightsInfo = m_InputToForgetWeights->GetTensorInfo();
3216  ValidateTensorNumDimNumElem(inputToForgetWeightsInfo, 2, (numUnits * inputSize), " InputToForgetWeights");
3217 
3218  ValidatePointer(m_InputToCellWeights, descriptorName, "InputToCellWeights");
3219  auto inputToCellWeightsInfo = m_InputToCellWeights->GetTensorInfo();
3220  ValidateTensorNumDimNumElem(inputToCellWeightsInfo, 2, (numUnits * inputSize), " InputToCellWeights");
3221 
3222  ValidatePointer(m_InputToOutputWeights, descriptorName, "InputToOutputWeights");
3223  auto inputToOutputWeightsInfo = m_InputToOutputWeights->GetTensorInfo();
3224  ValidateTensorNumDimNumElem(inputToOutputWeightsInfo, 2, (numUnits * inputSize), " InputToOutputWeights");
3225 
3226  ValidatePointer(m_RecurrentToForgetWeights, descriptorName, "RecurrentToForgetWeights");
3227  auto recurrentToForgetWeightsInfo = m_RecurrentToForgetWeights->GetTensorInfo();
3228  ValidateTensorNumDimNumElem(recurrentToForgetWeightsInfo, 2, (numUnits * outputSize),
3229  " RecurrentToForgetWeights");
3230 
3231  ValidatePointer(m_RecurrentToCellWeights, descriptorName, "RecurrentToCellWeights");
3232  auto recurrentToCellWeightsInfo = m_RecurrentToCellWeights->GetTensorInfo();
3233  ValidateTensorNumDimNumElem(recurrentToCellWeightsInfo, 2, (numUnits * outputSize), " RecurrentToCellWeights");
3234 
3235  ValidatePointer(m_RecurrentToOutputWeights, descriptorName, "RecurrentToOutputWeights");
3236  auto recurrentToOutputWeightsInfo = m_RecurrentToOutputWeights->GetTensorInfo();
3237  ValidateTensorNumDimNumElem(recurrentToOutputWeightsInfo, 2, (numUnits * outputSize), " RecurrentToCellWeights");
3238 
3239  // Validate data types for MANDATORY weights tensors (all should match each other)
3240  ValidateDataTypes(inputToForgetWeightsInfo, weightsSupportedTypes, descriptorName);
3241 
3242  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, inputToCellWeightsInfo, descriptorName,
3243  "inputToForgetWeights", "inputToCellWeights");
3244  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, inputToOutputWeightsInfo, descriptorName,
3245  "inputToForgetWeights", "inputToOutputWeights");
3246 
3247  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, recurrentToForgetWeightsInfo, descriptorName,
3248  "inputToForgetWeights", "recurrentToForgeteights");
3249  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, recurrentToCellWeightsInfo, descriptorName,
3250  "inputToForgetWeights", "recurrentToCellWeights");
3251  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, recurrentToOutputWeightsInfo, descriptorName,
3252  "inputToForgetWeights", "recurrentToOutputWeights");
3253 
3254  // Validate number of dimensions and number of elements for MANDATORY bias tensors
3255  ValidatePointer(m_ForgetGateBias, descriptorName, "ForgetGateBias");
3256  auto forgetGateBiasInfo = m_ForgetGateBias->GetTensorInfo();
3257  ValidateTensorNumDimNumElem(forgetGateBiasInfo, 1, numUnits, " ForgetGateBias");
3258 
3259  ValidatePointer(m_CellBias, descriptorName, "CellBias");
3260  auto cellBiasInfo = m_CellBias->GetTensorInfo();
3261  ValidateTensorNumDimNumElem(cellBiasInfo, 1, numUnits, " CellBias");
3262 
3263  ValidatePointer(m_OutputGateBias, descriptorName, "OutputGateBias");
3264  auto outputGateBiasInfo = m_OutputGateBias->GetTensorInfo();
3265  ValidateTensorNumDimNumElem(outputGateBiasInfo, 1, numUnits, " OutputGateBias");
3266 
3267  // Validate data types for MANDATORY bias tensors
3268  ValidateDataTypes(forgetGateBiasInfo, biasSupportedTypes, descriptorName);
3269 
3270  ValidateTensorDataTypesMatch(forgetGateBiasInfo, cellBiasInfo, descriptorName,
3271  "forgetGateBias", "cellBias");
3272  ValidateTensorDataTypesMatch(forgetGateBiasInfo, outputGateBiasInfo, descriptorName,
3273  "forgetGateBias", "outputGateBias");
3274 
3275  // Validate OPTIONAL params: CIFG (inputToInputWeights, recurrentToInputWeights, inputGateBias)
3276  const bool allCifgParamsPresentOrNot = ((m_InputToInputWeights && m_RecurrentToInputWeights && m_InputGateBias &&
3280 
3281  if (!allCifgParamsPresentOrNot)
3282  {
3283  throw InvalidArgumentException(descriptorName +
3284  ": InputToInputWeights, RecurrentToInputWeights and InputGateBias must either all be present "
3285  "(CIFG disabled) or not be present at all (CIFG enabled). m_Parameters.m_CifgEnabled should be "
3286  "set appropriately.");
3287  }
3288 
3290  {
3291  // Validate number of dimensions and number of elements
3292  auto inputToInputWeightsInfo = m_InputToInputWeights->GetTensorInfo();
3293  ValidateTensorNumDimNumElem(inputToInputWeightsInfo, 2, (numUnits * inputSize), " InputToInputWeights");
3294 
3295  auto recurrentToInputWeightsInfo = m_RecurrentToInputWeights->GetTensorInfo();
3296  ValidateTensorNumDimNumElem(recurrentToInputWeightsInfo, 2, (numUnits * outputSize),
3297  " RecurrentToInputWeights");
3298 
3299  auto inputGateBiasInfo = m_InputGateBias->GetTensorInfo();
3300  ValidateTensorNumDimNumElem(inputGateBiasInfo, 1, numUnits, " InputGateBias");
3301 
3302  // Validate data types
3303  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, inputToInputWeightsInfo, descriptorName,
3304  "inputToForgetWeights", "inputToInputWeights");
3305  ValidateTensorDataTypesMatch(inputToForgetWeightsInfo, recurrentToInputWeightsInfo, descriptorName,
3306  "inputToForgetWeights", "recurrentToInputWeights");
3307  ValidateTensorDataTypesMatch(forgetGateBiasInfo, inputGateBiasInfo, descriptorName,
3308  "forgetGateBias", "inputGateBias");
3309  }
3310 
3311  // Validate OPTIONAL params: Peephole (cellToInputWeights, cellToForgetWeights, cellToOutputWeights)
3312  bool allPeepholeWeightsPresentOrNot =
3317 
3318  if (!allPeepholeWeightsPresentOrNot)
3319  {
3320  throw InvalidArgumentException(descriptorName +
3321  ": CellToInputWeights, CellToForgetWeights and CellToOutputWeights should all be present (Peephole "
3322  "enabled) or not be present at all (Peephole disabled). CellToInputWeights should only be present "
3323  "when Peephole is enabled and CIFG is disabled. m_Parameters.m_PeepholeEnabled should be set "
3324  "appropriately.");
3325  }
3326 
3328  {
3329  auto cellToForgetWeightsInfo = m_CellToForgetWeights->GetTensorInfo();
3330  ValidateTensorNumDimNumElem(cellToForgetWeightsInfo, 1, numUnits, " cellToForgetWeights");
3331  ValidateDataTypes(cellToForgetWeightsInfo, layerNormPeepholeWeightsSupportedTypes, descriptorName);
3332 
3333  auto cellToOutputWeightsInfo = m_CellToOutputWeights->GetTensorInfo();
3334  ValidateTensorNumDimNumElem(cellToOutputWeightsInfo, 1, numUnits, " cellToOutputWeights");
3335  ValidateTensorDataTypesMatch(cellToForgetWeightsInfo, cellToOutputWeightsInfo, descriptorName,
3336  "cellToForgetWeight", "cellToOutputWeights");
3337 
3339  {
3340  auto cellToInputWeightsInfo = m_CellToInputWeights->GetTensorInfo();
3341  ValidateTensorNumDimNumElem(cellToInputWeightsInfo, 1, numUnits, " cellToInputWeights");
3342  ValidateTensorDataTypesMatch(cellToForgetWeightsInfo, cellToInputWeightsInfo, descriptorName,
3343  "cellToForgetWeights", "cellToInputWeights");
3344  }
3345  }
3346 
3347  // Validate OPTIONAL params: Layer Norm Weights
3348  bool allLayerNormWeightsPresentOrNot =
3353 
3354  if (!allLayerNormWeightsPresentOrNot)
3355  {
3356  throw InvalidArgumentException(descriptorName +
3357  ": InputLayerNormWeights, ForgetLayerNormWeights, m_OutputLayerNormWeights "
3358  "and CellLayerNormWeights should all be present (Layer Norm enabled) or not "
3359  "be present at all (Layer Norm disabled). InputLayerNormWeights should "
3360  "only be present when Layer Norm is enabled and CIFG is disabled. "
3361  "m_Parameters.m_LayerNormEnabled should be set appropriately.");
3362  }
3363 
3365  {
3366  auto forgetLayerNormWeightsInfo = m_ForgetLayerNormWeights->GetTensorInfo();
3367  ValidateTensorNumDimNumElem(forgetLayerNormWeightsInfo, 1, numUnits, " forgetLayerNormWeights");
3368  ValidateDataTypes(forgetLayerNormWeightsInfo, layerNormPeepholeWeightsSupportedTypes, descriptorName);
3369 
3370  auto cellLayerNormWeightsInfo = m_CellLayerNormWeights->GetTensorInfo();
3371  ValidateTensorNumDimNumElem(cellLayerNormWeightsInfo, 1, numUnits, " cellLayerNormWeights");
3372  ValidateTensorDataTypesMatch(forgetLayerNormWeightsInfo, cellLayerNormWeightsInfo, descriptorName,
3373  "forgetLayerNormWeights", "cellLayerNormWeights");
3374 
3375  auto outputLayerNormWeightsInfo = m_OutputLayerNormWeights->GetTensorInfo();
3376  ValidateTensorNumDimNumElem(outputLayerNormWeightsInfo, 1, numUnits, " outputLayerNormWeights");
3377  ValidateTensorDataTypesMatch(forgetLayerNormWeightsInfo, outputLayerNormWeightsInfo, descriptorName,
3378  "forgetLayerNormWeights", "outputLayerNormWeights");
3379 
3381  {
3382  auto inputLayerNormWeightsInfo = m_InputLayerNormWeights->GetTensorInfo();
3383  ValidateTensorNumDimNumElem(inputLayerNormWeightsInfo, 1, numUnits, " inputLayerNormWeights");
3384  ValidateTensorDataTypesMatch(forgetLayerNormWeightsInfo, inputLayerNormWeightsInfo, descriptorName,
3385  "forgetLayerNormWeights", "inputLayerNormWeights");
3386  }
3387  }
3388 
3389  // Validate OPTIONAL params: Projection (projectionWeights, projectionBias)
3390  bool correctProjectionTensorsPresent =
3394 
3395  if (!correctProjectionTensorsPresent)
3396  {
3397  throw InvalidArgumentException(descriptorName +
3398  ": If projection is enabled, ProjectionWeights should be present and "
3399  "ProjectionBias is optional. If projection is disabled, neither "
3400  "ProjectionWeights nor ProjectionBias should be present.");
3401  }
3402 
3404  {
3405  auto projectionWeightsInfo = m_ProjectionWeights->GetTensorInfo();
3406  ValidateTensorNumDimNumElem(projectionWeightsInfo, 2, (numUnits * outputSize), "ProjectionWeights");
3407  ValidateDataTypes(projectionWeightsInfo, weightsSupportedTypes, descriptorName);
3408 
3409  if (m_ProjectionBias)
3410  {
3411  auto projectionBiasInfo = m_ProjectionBias->GetTensorInfo();
3412  ValidateTensorNumDimNumElem(projectionBiasInfo, 1, outputSize, "ProjectionBias");
3413  ValidateDataTypes(projectionBiasInfo, biasSupportedTypes, descriptorName);
3414  }
3415 
3416  }
3417  else if ((outputInfo.GetQuantizationScale() != m_Parameters.m_HiddenStateScale) &&
3419  throw InvalidArgumentException(descriptorName +
3420  ": If projection is disabled, output quantization info (scale, offset) "
3421  "should match HiddenStateScale and HiddenStateZeroPoint.");
3422  }
3423 
3424 }
3425 
3427 {
3428  const std::string descriptorName{"QuantizedLstmQueueDescriptor"};
3429 
3430  // Validate number of inputs/outputs
3431  ValidateNumInputs(workloadInfo, descriptorName, 3);
3432  ValidateNumOutputs(workloadInfo, descriptorName, 2);
3433 
3434  // Input/output tensor infos
3435  auto inputInfo = workloadInfo.m_InputTensorInfos[0];
3436  auto cellStateInInfo = workloadInfo.m_InputTensorInfos[1];
3437  auto outputStateInInfo = workloadInfo.m_InputTensorInfos[2];
3438 
3439  auto cellStateOutInfo = workloadInfo.m_OutputTensorInfos[0];
3440  auto outputStateOutInfo = workloadInfo.m_OutputTensorInfos[1];
3441 
3442  std::vector<DataType> inputOutputSupportedTypes =
3443  {
3445  };
3446 
3447  std::vector<DataType> cellStateSupportedTypes =
3448  {
3450  };
3451 
3452  std::vector<DataType> weightsSupportedTypes =
3453  {
3455  };
3456 
3457  std::vector<DataType> biasSupportedTypes =
3458  {
3460  };
3461 
3462  // Validate types of input/output tensors
3463  ValidateDataTypes(inputInfo, inputOutputSupportedTypes, descriptorName);
3464  ValidateDataTypes(cellStateInInfo, cellStateSupportedTypes, descriptorName);
3465  ValidateDataTypes(outputStateInInfo, inputOutputSupportedTypes, descriptorName);
3466 
3467  ValidateDataTypes(cellStateOutInfo, cellStateSupportedTypes, descriptorName);
3468  ValidateDataTypes(outputStateOutInfo, inputOutputSupportedTypes, descriptorName);
3469 
3470  // Validate matching types of input/output tensors
3471  ValidateTensorDataTypesMatch(inputInfo, outputStateInInfo, descriptorName, "input", "outputStateIn");
3472  ValidateTensorDataTypesMatch(outputStateInInfo, outputStateOutInfo, descriptorName,
3473  "outputStateIn", "outputStateOut");
3474  ValidateTensorDataTypesMatch(cellStateInInfo, cellStateOutInfo, descriptorName, "cellStateIn", "cellStateOut");
3475 
3476  // Validate matching quantization info for input/output tensors
3477  ValidateTensorQuantizationSpace(inputInfo, outputStateInInfo, descriptorName, "input", "outputStateIn");
3478  ValidateTensorQuantizationSpace(inputInfo, outputStateOutInfo, descriptorName, "input", "outputStateOut");
3479  ValidateTensorQuantizationSpace(cellStateInInfo, cellStateOutInfo, descriptorName, "cellStateIn", "cellStateOut");
3480 
3481  // Infer number of batches, input size and output size from tensor dimensions
3482  const uint32_t numBatches = inputInfo.GetShape()[0];
3483  const uint32_t inputSize = inputInfo.GetShape()[1];
3484  const uint32_t outputSize = cellStateInInfo.GetShape()[1];
3485 
3486  // Validate number of dimensions and number of elements for input/output tensors
3487  ValidateTensorNumDimNumElem(inputInfo, 2, (numBatches * inputSize), descriptorName + " input");
3488  ValidateTensorNumDimNumElem(cellStateInInfo, 2, (numBatches * outputSize), descriptorName + " cellStateIn");
3489  ValidateTensorNumDimNumElem(outputStateInInfo, 2, (numBatches * outputSize), descriptorName + " outputStateIn");
3490  ValidateTensorNumDimNumElem(cellStateOutInfo, 2, (numBatches * outputSize), descriptorName + " cellStateOut");
3491  ValidateTensorNumDimNumElem(outputStateOutInfo, 2, (numBatches * outputSize), descriptorName + " outputStateOut");
3492 
3493  // Validate number of dimensions and number of elements for weights tensors
3494  ValidatePointer(m_InputToInputWeights, descriptorName, "InputToInputWeights");
3495  auto inputToInputWeightsInfo = m_InputToInputWeights->GetTensorInfo();
3496  ValidateTensorNumDimNumElem(inputToInputWeightsInfo, 2, (outputSize * inputSize), " InputToInputWeights");
3497 
3498  ValidatePointer(m_InputToForgetWeights, descriptorName, "InputToForgetWeights");
3499  auto inputToForgetWeightsInfo = m_InputToForgetWeights->GetTensorInfo();
3500  ValidateTensorNumDimNumElem(inputToForgetWeightsInfo, 2, (outputSize * inputSize), " InputToForgetWeights");
3501 
3502  ValidatePointer(m_InputToCellWeights, descriptorName, "InputToCellWeights");
3503  auto inputToCellWeightsInfo = m_InputToCellWeights->GetTensorInfo();
3504  ValidateTensorNumDimNumElem(inputToCellWeightsInfo, 2, (outputSize * inputSize), " InputToCellWeights");
3505 
3506  ValidatePointer(m_InputToOutputWeights, descriptorName, "InputToOutputWeights");
3507  auto inputToOutputWeightsInfo = m_InputToOutputWeights->GetTensorInfo();
3508  ValidateTensorNumDimNumElem(inputToOutputWeightsInfo, 2, (outputSize * inputSize), " InputToOutputWeights");
3509 
3510  ValidatePointer(m_RecurrentToInputWeights, descriptorName, "RecurrentToInputWeights");
3511  auto recurrentToInputWeightsInfo = m_RecurrentToInputWeights->GetTensorInfo();
3512  ValidateTensorNumDimNumElem(recurrentToInputWeightsInfo, 2, (outputSize * outputSize), " RecurrentToInputWeights");
3513 
3514  ValidatePointer(m_RecurrentToForgetWeights, descriptorName, "RecurrentToForgetWeights");
3515  auto recurrentToForgetWeightsInfo = m_RecurrentToForgetWeights->GetTensorInfo();
3516  ValidateTensorNumDimNumElem(recurrentToForgetWeightsInfo, 2, (outputSize * outputSize),
3517  " RecurrentToForgetWeights");
3518 
3519  ValidatePointer(m_RecurrentToCellWeights, descriptorName, "RecurrentToCellWeights");
3520  auto recurrentToCellWeightsInfo = m_RecurrentToCellWeights->GetTensorInfo();
3521  ValidateTensorNumDimNumElem(recurrentToCellWeightsInfo, 2, (outputSize * outputSize), " RecurrentToCellWeights");
3522 
3523  ValidatePointer(m_RecurrentToOutputWeights, descriptorName, "RecurrentToOutputWeights");
3524  auto recurrentToOutputWeightsInfo = m_RecurrentToOutputWeights->GetTensorInfo();
3525  ValidateTensorNumDimNumElem(recurrentToOutputWeightsInfo, 2, (outputSize * outputSize), " RecurrentToCellWeights");
3526 
3527  // Validate data types for weights tensors (all should match each other)
3528  ValidateDataTypes(inputToInputWeightsInfo, weightsSupportedTypes, descriptorName);
3529 
3530  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, inputToForgetWeightsInfo, descriptorName,
3531  "inputToInputWeights", "inputToForgetWeights");
3532  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, inputToCellWeightsInfo, descriptorName,
3533  "inputToInputWeights", "inputToCellWeights");
3534  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, inputToOutputWeightsInfo, descriptorName,
3535  "inputToInputWeights", "inputToOutputWeights");
3536 
3537  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToInputWeightsInfo, descriptorName,
3538  "inputToInputWeights", "recurrentToInputWeights");
3539  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToForgetWeightsInfo, descriptorName,
3540  "inputToInputWeights", "recurrentToForgeteights");
3541  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToCellWeightsInfo, descriptorName,
3542  "inputToInputWeights", "recurrentToCellWeights");
3543  ValidateTensorDataTypesMatch(inputToInputWeightsInfo, recurrentToOutputWeightsInfo, descriptorName,
3544  "inputToInputWeights", "recurrentToOutputWeights");
3545 
3546  // Validate matching quantization info for weight tensors (all should match each other)
3547  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, inputToForgetWeightsInfo,
3548  descriptorName, "inputToInputWeights", "inputToForgetWeights");
3549  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, inputToCellWeightsInfo,
3550  descriptorName, "inputToInputWeights", "inputToCellWeights");
3551  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, inputToOutputWeightsInfo,
3552  descriptorName, "inputToInputWeights", "inputToOutputWeights");
3553 
3554  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToInputWeightsInfo,
3555  descriptorName, "inputToInputWeights", "recurrentToInputWeights");
3556  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToForgetWeightsInfo,
3557  descriptorName, "inputToInputWeights", "recurrentToForgetWeights");
3558  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToCellWeightsInfo,
3559  descriptorName, "inputToInputWeights", "recurrentToCellWeights");
3560  ValidateTensorQuantizationSpace(inputToInputWeightsInfo, recurrentToOutputWeightsInfo,
3561  descriptorName, "inputToInputWeights", "recurrentToOutputWeights");
3562 
3563  // Validate number of dimensions and number of elements in bias tensors
3564  ValidatePointer(m_InputGateBias, descriptorName, "InputGateBias");
3565  auto inputGateBiasInfo = m_InputGateBias->GetTensorInfo();
3566  ValidateTensorNumDimNumElem(inputGateBiasInfo, 1, outputSize, " InputGateBias");
3567 
3568  ValidatePointer(m_ForgetGateBias, descriptorName, "ForgetGateBias");
3569  auto forgetGateBiasInfo = m_ForgetGateBias->GetTensorInfo();
3570  ValidateTensorNumDimNumElem(forgetGateBiasInfo, 1, outputSize, " ForgetGateBias");
3571 
3572  ValidatePointer(m_CellBias, descriptorName, "CellBias");
3573  auto cellBiasInfo = m_CellBias->GetTensorInfo();
3574  ValidateTensorNumDimNumElem(cellBiasInfo, 1, outputSize, " CellBias");
3575 
3576  ValidatePointer(m_OutputGateBias, descriptorName, "OutputGateBias");
3577  auto outputGateBiasInfo = m_OutputGateBias->GetTensorInfo();
3578  ValidateTensorNumDimNumElem(outputGateBiasInfo, 1, outputSize, " OutputGateBias");
3579 
3580  // Validate data types for bias tensors (all should match each other)
3581  ValidateDataTypes(inputGateBiasInfo, biasSupportedTypes, descriptorName);
3582 
3583  ValidateTensorDataTypesMatch(inputGateBiasInfo, forgetGateBiasInfo, descriptorName,
3584  "inputGateBias", "forgetGateBias");
3585  ValidateTensorDataTypesMatch(inputGateBiasInfo, cellBiasInfo, descriptorName,
3586  "inputGateBias", "cellBias");
3587  ValidateTensorDataTypesMatch(inputGateBiasInfo, outputGateBiasInfo, descriptorName,
3588  "inputGateBias", "outputGateBias");
3589 
3590  // Validate bias tensor quantization info
3591  ValidateBiasTensorQuantization(inputGateBiasInfo, inputToInputWeightsInfo, descriptorName);
3592  ValidateBiasTensorQuantization(forgetGateBiasInfo, inputToInputWeightsInfo, descriptorName);
3593  ValidateBiasTensorQuantization(cellBiasInfo, inputToInputWeightsInfo, descriptorName);
3594  ValidateBiasTensorQuantization(outputGateBiasInfo, inputToInputWeightsInfo, descriptorName);
3595 }
3596 
3597 void AbsQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3598 {
3599  const std::string descriptorName{"AbsQueueDescriptor"};
3600 
3601  ValidateNumInputs(workloadInfo, descriptorName, 1);
3602  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3603 
3604  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3605  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3606 
3607  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3608 
3609  std::vector<DataType> supportedTypes =
3610  {
3618  };
3619 
3620  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3621  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3622 }
3623 
3624 void SliceQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3625 {
3626  const std::string descriptorName{"SliceQueueDescriptor"};
3627 
3628  ValidateNumInputs(workloadInfo, descriptorName, 1);
3629  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3630 
3631  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3632  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3633 
3634  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3635 
3636  const unsigned int rank = inputTensorInfo.GetNumDimensions();
3637  if (rank > 4)
3638  {
3639  throw InvalidArgumentException(descriptorName + ": Input tensors with rank greater than 4 are not supported.");
3640  }
3641 
3642  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, rank, "output");
3643 
3644  // Check if m_Begin and m_Size have the expected length
3645  if (m_Parameters.m_Begin.size() != rank)
3646  {
3647  throw InvalidArgumentException(descriptorName +
3648  ": Length of begin offset descriptor must equal rank " + std::to_string(rank));
3649  }
3650  if (m_Parameters.m_Size.size() != rank)
3651  {
3652  throw InvalidArgumentException(descriptorName +
3653  ": Length of size descriptor must equal rank " + std::to_string(rank));
3654  }
3655 
3656  // Check if the shape of the output tensor matches m_Size
3657  const TensorShape& outputShape = outputTensorInfo.GetShape();
3658  for (unsigned int i = 0u; i < rank; ++i)
3659  {
3660  if (m_Parameters.m_Size[i] != outputShape[i])
3661  {
3662  throw InvalidArgumentException(descriptorName + ": Size descriptor does not match output tensor.");
3663  }
3664  }
3665 
3666  // Check if the sum of begin offset and size in a given dimension
3667  // does not exceed the size of corresponding input
3668  const TensorShape& inputShape = inputTensorInfo.GetShape();
3669  for(unsigned int i = 0u; i < rank; ++i)
3670  {
3671  if (m_Parameters.m_Begin[i] + m_Parameters.m_Size[i] > inputShape[i])
3672  {
3673  throw InvalidArgumentException(descriptorName + ": Sum of begin offset and size for dimension " +
3674  std::to_string(i) + " exceeds input size.");
3675  }
3676  }
3677 }
3678 
3680 {
3681  const std::string descriptorName{"DepthToSpaceQueueDescriptor"};
3682 
3683  ValidateNumInputs(workloadInfo, descriptorName, 1);
3684  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3685 
3686  const TensorInfo& inputInfo = workloadInfo.m_InputTensorInfos[0];
3687  const TensorInfo& outputInfo = workloadInfo.m_OutputTensorInfos[0];
3688 
3689  ValidateTensorNumDimensions(inputInfo, descriptorName, 4, "input");
3690  ValidateTensorNumDimensions(outputInfo, descriptorName, 4, "output");
3691 
3692  std::vector<DataType> supportedTypes =
3693  {
3700  };
3701 
3702  ValidateDataTypes(inputInfo, supportedTypes, descriptorName);
3703  ValidateDataTypes(outputInfo, supportedTypes, descriptorName);
3704 
3705  ValidateTensorNumElementsMatch(inputInfo, outputInfo, descriptorName, "input", "output");
3706 
3707  if (m_Parameters.m_BlockSize == 0)
3708  {
3709  throw InvalidArgumentException(descriptorName + ": Block size cannot be 0.");
3710  }
3711 
3712  DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
3713  const unsigned int wIndex = dimensionIndices.GetWidthIndex();
3714  const unsigned int hIndex = dimensionIndices.GetHeightIndex();
3715  const unsigned int cIndex = dimensionIndices.GetChannelsIndex();
3716 
3717  const TensorShape& outputShape = outputInfo.GetShape();
3718  if (outputShape[hIndex] % m_Parameters.m_BlockSize != 0 || outputShape[wIndex] % m_Parameters.m_BlockSize != 0)
3719  {
3720  throw InvalidArgumentException(descriptorName + ": Output width and height shape"
3721  "must be divisible by block size.");
3722  }
3723 
3724  const TensorShape& inputShape = inputInfo.GetShape();
3725  if (inputShape[cIndex] % (m_Parameters.m_BlockSize * m_Parameters.m_BlockSize) != 0)
3726  {
3727  throw InvalidArgumentException(descriptorName + ": The depth of the input tensor"
3728  "must be divisible by the square of block size." );
3729  }
3730 }
3731 
3732 void ComparisonQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3733 {
3734  const std::string descriptorName{"ComparisonQueueDescriptor"};
3735 
3736  ValidateNumInputs(workloadInfo, descriptorName, 2);
3737  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3738 
3739  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
3740  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
3741  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3742 
3743  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
3744  inputTensorInfo1,
3745  outputTensorInfo,
3746  descriptorName,
3747  "input_0",
3748  "input_1");
3749 
3750  if (outputTensorInfo.GetDataType() != DataType::Boolean)
3751  {
3752  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
3753  }
3754 }
3755 
3757 {
3758  const std::string descriptorName{"ElementwiseBinaryQueueDescriptor"};
3759 
3760  ValidateNumInputs(workloadInfo, descriptorName, 2);
3761  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3762 
3763  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
3764  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
3765  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3766 
3767  std::vector<DataType> supportedTypes =
3768  {
3776  };
3777 
3778  ValidateDataTypes(inputTensorInfo0, supportedTypes, descriptorName);
3779  ValidateDataTypes(inputTensorInfo1, supportedTypes, descriptorName);
3780 
3781  ValidateTensorDataTypesMatch(inputTensorInfo0, outputTensorInfo, descriptorName, "input", "output");
3782  ValidateTensorDataTypesMatch(inputTensorInfo1, outputTensorInfo, descriptorName, "input", "output");
3783 }
3784 
3786 {
3787  const std::string descriptorName{"ElementwiseUnaryQueueDescriptor"};
3788 
3789  ValidateNumInputs(workloadInfo, descriptorName, 1);
3790  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3791 
3792  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3793  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3794 
3795  ValidateTensorShapesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3796 
3797  std::vector<DataType> supportedTypes =
3798  {
3806  };
3807 
3808  std::vector<DataType> logicalSupportedTypes =
3809  {
3811  };
3812 
3814  {
3815  ValidateDataTypes(inputTensorInfo, logicalSupportedTypes, descriptorName);
3816  }
3817  else
3818  {
3819  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3820  }
3821 
3822 
3823  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3824 }
3825 
3826 void RankQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3827 {
3828  const std::string descriptorName{"RankQueueDescriptor"};
3829 
3830  ValidateNumInputs(workloadInfo, descriptorName, 1);
3831  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3832 
3833  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3834  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3835 
3836  ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 1, "output");
3837  ValidateTensorNumElements(outputTensorInfo, descriptorName, 1, "output");
3838 
3839  std::vector<DataType> supportedTypes =
3840  {
3849  };
3850 
3851  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3852  ValidateDataTypes(outputTensorInfo, { DataType::Signed32 }, descriptorName);
3853 }
3854 
3856 {
3857  const std::string descriptorName{"LogicalBinaryQueueDescriptor"};
3858 
3859  ValidateNumInputs(workloadInfo, descriptorName, 2);
3860  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3861 
3862  const TensorInfo& inputTensorInfo0 = workloadInfo.m_InputTensorInfos[0];
3863  const TensorInfo& inputTensorInfo1 = workloadInfo.m_InputTensorInfos[1];
3864  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3865 
3866  ValidateBroadcastTensorShapesMatch(inputTensorInfo0,
3867  inputTensorInfo1,
3868  outputTensorInfo,
3869  descriptorName,
3870  "input_0",
3871  "input_1");
3872 
3873  if (inputTensorInfo0.GetDataType() != DataType::Boolean)
3874  {
3875  throw InvalidArgumentException(descriptorName + ": Input tensor 0 type must be Boolean.");
3876  }
3877 
3878  if (inputTensorInfo1.GetDataType() != DataType::Boolean)
3879  {
3880  throw InvalidArgumentException(descriptorName + ": Input tensor 1 type must be Boolean.");
3881  }
3882 
3883  if (outputTensorInfo.GetDataType() != DataType::Boolean)
3884  {
3885  throw InvalidArgumentException(descriptorName + ": Output tensor type must be Boolean.");
3886  }
3887 }
3888 
3889 void ReduceQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
3890 {
3891  const std::string descriptorName{"ReduceQueueDescriptor"};
3892 
3893  ValidateNumInputs(workloadInfo, descriptorName, 1);
3894  ValidateNumOutputs(workloadInfo, descriptorName, 1);
3895 
3896  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
3897  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
3898 
3899  std::vector<DataType> supportedTypes =
3900  {
3908  };
3909 
3910  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
3911  ValidateTensorDataTypesMatch(inputTensorInfo, outputTensorInfo, descriptorName, "input", "output");
3912 }
3913 
3915 {
3916  // Modified from LstmQueueDescriptor::Validate to support UnidirectionalSequenceLstm
3917 
3918  const std::string descriptorName{"UnidirectionalSequenceLstmQueueDescriptor"};
3919 
3920  // check dimensions of all inputs and outputs
3921  if (workloadInfo.m_InputTensorInfos.size() != 3)
3922  {
3923  throw InvalidArgumentException(descriptorName + ": Invalid number of inputs.");
3924  }
3925  if (workloadInfo.m_OutputTensorInfos.size() != 3)
3926  {
3927  throw InvalidArgumentException(descriptorName + ": Invalid number of outputs.");
3928  }
3929 
3930  std::vector<DataType> supportedTypes =
3931  {
3934  };
3935 
3936  // check for supported type of one input and match them with all the other input and output
3937  ValidateDataTypes(workloadInfo.m_InputTensorInfos[0], supportedTypes, descriptorName);
3938 
3939  // Making sure clipping parameters have valid values.
3940  // == 0 means no clipping
3941  // > 0 means clipping
3942  if (m_Parameters.m_ClippingThresCell < 0.0f)
3943  {
3944  throw InvalidArgumentException(descriptorName + ": negative cell clipping threshold is invalid");
3945  }
3946  if (m_Parameters.m_ClippingThresProj < 0.0f)
3947  {
3948  throw InvalidArgumentException(descriptorName + ": negative projection clipping threshold is invalid");
3949  }
3950 
3951  unsigned int batchIndx = 0;
3952  unsigned int inputIndx = 1;
3953  uint32_t timeStep = 1;
3954  unsigned int timeIndx = 1;
3955  inputIndx = 2;
3957  {
3958  batchIndx = 1;
3959  timeIndx = 0;
3960 
3961  }
3962  timeStep = workloadInfo.m_InputTensorInfos[0].GetShape()[timeIndx];
3963 
3964  // Inferring batch size, number of outputs and number of cells from the inputs.
3965  const uint32_t n_input = workloadInfo.m_InputTensorInfos[0].GetShape()[inputIndx];
3966  const uint32_t n_batch = workloadInfo.m_InputTensorInfos[0].GetShape()[batchIndx];
3967  ValidatePointer(m_InputToOutputWeights, "Null pointer check", "InputToOutputWeights");
3968  const uint32_t n_cell = m_InputToOutputWeights->GetShape()[0];
3969  ValidatePointer(m_RecurrentToOutputWeights, "Null pointer check", "RecurrentToOutputWeights");
3970  const uint32_t n_output = m_RecurrentToOutputWeights->GetShape()[1];
3971 
3972  // input tensor
3973  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[0], 3, (timeStep * n_batch * n_input),
3974  descriptorName + " input_0");
3975  // outputStateInTensor
3976  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[1], 2, (n_batch * n_output),
3977  descriptorName + " input_1");
3978  // outputStateInTensor
3979  ValidateTensorNumDimNumElem(workloadInfo.m_InputTensorInfos[2], 2, (n_batch * n_cell),
3980  descriptorName + " input_2");
3981 
3982  // outputTensor
3983  ValidateTensorNumDimNumElem(workloadInfo.m_OutputTensorInfos[2], 3, (timeStep * n_batch * n_output),
3984  descriptorName + " output_0");
3985 
3986  // check that dimensions of inputs/outputs and QueueDescriptor data match with each other
3987  if ( m_InputToInputWeights )
3988  {
3990  (n_cell * n_input), "InputLayerNormWeights");
3991  }
3992 
3993  ValidatePointer(m_InputToForgetWeights, "Null pointer check", "InputToForgetWeights");
3995  (n_cell * n_input), "InputToForgetWeights");
3996 
3997  ValidatePointer(m_InputToCellWeights, "Null pointer check", "InputToCellWeights");
3999  (n_cell * n_input), "InputToCellWeights");
4000 
4002  {
4004  (n_cell * n_output), "RecurrentToInputWeights");
4005  }
4006 
4007  ValidatePointer(m_RecurrentToForgetWeights, "Null pointer check", "RecurrentToForgetWeights");
4009  (n_cell * n_output), "RecurrentToForgetWeights");
4010 
4011  ValidatePointer(m_RecurrentToCellWeights, "Null pointer check", "RecurrentToCellWeights");
4013  (n_cell * n_output), "RecurrentToCellWeights");
4014 
4015  // Make sure the input-gate's parameters are either both present (regular
4016  // LSTM) or not at all (CIFG-LSTM). And CifgEnable is set accordingly.
4017  bool cifg_weights_all_or_none = ((m_InputToInputWeights && m_RecurrentToInputWeights &&
4021  if (!cifg_weights_all_or_none)
4022  {
4023  throw InvalidArgumentException(descriptorName + ": Input-Gate's parameters InputToInputWeights and "
4024  "RecurrentToInputWeights must either both be present (regular LSTM) "
4025  "or both not present (CIFG-LSTM). In addition CifgEnable must be set "
4026  "accordingly.");
4027  }
4028 
4029  if ( m_CellToInputWeights )
4030  {
4032  n_cell, "CellToInputWeights");
4033  }
4034  if ( m_CellToForgetWeights )
4035  {
4037  n_cell, "CellToForgetWeights");
4038  }
4039  if ( m_CellToOutputWeights )
4040  {
4042  n_cell, "CellToOutputWeights");
4043  }
4044 
4045  // Making sure the peephole weights are there all or none. And PeepholeEnable is set accordingly.
4046  bool peephole_weights_all_or_none =
4051  if (!peephole_weights_all_or_none)
4052  {
4053  throw InvalidArgumentException(descriptorName + ": Invalid combination of peephole parameters.");
4054  }
4055 
4056  // Make sure the input gate bias is present only when not a CIFG-LSTM.
4058  {
4059  if (m_InputGateBias)
4060  {
4061  throw InvalidArgumentException(descriptorName + ": InputGateBias is present and CIFG-LSTM is enabled.");
4062  }
4063  }
4064  else
4065  {
4066  if (!m_InputGateBias)
4067  {
4068  throw InvalidArgumentException(descriptorName + ": If CIFG-LSTM is disabled InputGateBias "
4069  "must be present.");
4070  }
4072  n_cell, "InputGateBias");
4073  }
4074 
4075  ValidatePointer(m_ForgetGateBias, "Null pointer check", "ForgetGateBias");
4076  ValidateTensorNumDimNumElem(m_ForgetGateBias->GetTensorInfo(), 1, n_cell, "ForgetGateBias");
4077 
4078  ValidatePointer(m_CellBias, "Null pointer check", "CellBias");
4079  ValidateTensorNumDimNumElem(m_CellBias->GetTensorInfo(), 1, n_cell, "CellBias");
4080 
4081  ValidatePointer(m_OutputGateBias, "Null pointer check", "OutputGateBias");
4082  ValidateTensorNumDimNumElem(m_OutputGateBias->GetTensorInfo(), 1, n_cell, "OutputGateBias");
4083 
4084  if (m_ProjectionWeights)
4085  {
4087  (n_cell * n_output), "ProjectionWeights");
4088  }
4089  if (m_ProjectionBias)
4090  {
4091  ValidateTensorNumDimNumElem(m_ProjectionBias->GetTensorInfo(), 1, n_output, "ProjectionBias");
4092  }
4093 
4094  // Making sure the projection tensors are consistent:
4095  // 1) If projection weight is not present, then projection bias should not be
4096  // present.
4097  // 2) If projection weight is present, then projection bias is optional.
4098  bool projecton_tensors_consistent = ((!m_ProjectionWeights && !m_ProjectionBias &&
4104  if (!projecton_tensors_consistent)
4105  {
4106  throw InvalidArgumentException(descriptorName + ": Projection tensors are inconsistent.");
4107  }
4108 
4109  // The four layer normalization weights either all have values or none of them have values. Additionally, if
4110  // CIFG is used, input layer normalization weights tensor is omitted and the other layer normalization weights
4111  // either all have values or none of them have values. Layer normalization is used when the values of all the
4112  // layer normalization weights are present
4114  {
4115  ValidateTensorNumDimNumElem(m_InputLayerNormWeights->GetTensorInfo(), 1, n_cell, "InputLayerNormWeights");
4116  }
4118  {
4119  ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
4120  }
4122  {
4123  ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
4124  }
4126  {
4127  ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
4128  }
4129 
4131  {
4133  {
4135  {
4136  throw InvalidArgumentException(descriptorName + ": Layer normalisation is enabled and CIFG-LSTM is "
4137  "disabled but InputLayerNormWeights are not present");
4138  }
4140  1, n_cell, "InputLayerNormWeights");
4141  }
4142  else if (m_InputLayerNormWeights)
4143  {
4144  throw InvalidArgumentException(descriptorName + ":InputLayerNormWeights are present while CIFG is "
4145  "enabled");
4146  }
4147 
4148  ValidatePointer(m_ForgetLayerNormWeights, "Null pointer check layer normalisation enabled",
4149  "ForgetLayerNormWeights");
4150  ValidateTensorNumDimNumElem(m_ForgetLayerNormWeights->GetTensorInfo(), 1, n_cell, "ForgetLayerNormWeights");
4151 
4152  ValidatePointer(m_OutputLayerNormWeights, "Null pointer check layer normalisation enabled",
4153  "OutputLayerNormWeights");
4154  ValidateTensorNumDimNumElem(m_OutputLayerNormWeights->GetTensorInfo(), 1, n_cell, "OutputLayerNormWeights");
4155 
4156  ValidatePointer(m_CellLayerNormWeights, "Null pointer check layer normalisation enabled",
4157  "CellLayerNormWeights");
4158  ValidateTensorNumDimNumElem(m_CellLayerNormWeights->GetTensorInfo(), 1, n_cell, "CellLayerNormWeights");
4159  }
4161  {
4162  throw InvalidArgumentException(descriptorName + ": Layer normalisation is disabled but one or more layer "
4163  "normalisation weights are present.");
4164  }
4165 }
4166 
4168 {
4169  const std::string descriptorName{"BatchMatMulDescriptor"};
4170 
4171  ValidateNumInputs(workloadInfo, descriptorName, 2);
4172  ValidateNumOutputs(workloadInfo, descriptorName, 1);
4173 
4174  // Inputs must be: both 2D+
4175  // For inputs X and Y whose dimensions to be multiplied are (M,N) and (I,J) respectively,
4176  // axes N and I must be the same size
4177 
4178  const auto& inputXInfoBeforeParams = workloadInfo.m_InputTensorInfos[0];
4179  const auto& inputYInfoBeforeParams = workloadInfo.m_InputTensorInfos[1];
4180  const auto& outputInfo = workloadInfo.m_OutputTensorInfos[0];
4181  // Output info has already been inferred
4182 
4183  std::vector<DataType> supportedTypes =
4184  {
4191  };
4192 
4193  ValidateDataTypes(inputXInfoBeforeParams, supportedTypes, descriptorName);
4194  ValidateDataTypes(inputYInfoBeforeParams, supportedTypes, descriptorName);
4195  ValidateDataTypes(outputInfo, supportedTypes, descriptorName);
4196 
4197  if ((inputXInfoBeforeParams.GetNumDimensions() < 2) ||
4198  (inputYInfoBeforeParams.GetNumDimensions() < 2))
4199  {
4200  throw InvalidArgumentException(descriptorName + ": Input tensors are not 2D or greater.");
4201  }
4202 
4203  TensorInfo inputXInfoAfterParams;
4204  TensorInfo inputYInfoAfterParams;
4205 
4208  {
4209  throw InvalidArgumentException(descriptorName +
4210  ": Invalid descriptor parameters - Transpose and Adjoint "
4211  "cannot both be true for a given input tensor.");
4212  }
4214  {
4215  inputXInfoAfterParams = armnnUtils::Permuted(inputXInfoBeforeParams,
4218  inputXInfoBeforeParams.GetShape()));
4219  }
4220  else if(m_Parameters.m_AdjointX)
4221  {
4223  inputXInfoBeforeParams.GetShape());
4224  if(inputXInfoBeforeParams.GetShape()[axesToMul.first] !=
4225  inputXInfoBeforeParams.GetShape()[axesToMul.second])
4226  {
4227  throw InvalidArgumentException(descriptorName +
4228  ": Adjoint is set to true for input tensor X, but the axes to be adjointed are not square." );
4229  }
4230  // Shape remains the same as it's square
4231  inputXInfoAfterParams = inputXInfoBeforeParams;
4232  }
4233  else
4234  {
4235  inputXInfoAfterParams = inputXInfoBeforeParams;
4236  }
4237 
4239  {
4240  inputYInfoAfterParams = armnnUtils::Permuted(inputYInfoBeforeParams,
4243  inputYInfoBeforeParams.GetShape()));
4244  }
4245  else if(m_Parameters.m_AdjointY)
4246  {
4248  inputYInfoBeforeParams.GetShape());
4249  if(inputYInfoBeforeParams.GetShape()[axesToMul.first] !=
4250  inputYInfoBeforeParams.GetShape()[axesToMul.second])
4251  {
4252  throw InvalidArgumentException(descriptorName +
4253  ": Adjoint is set to true for input tensor Y, but the axes to be adjointed are not square." );
4254  }
4255  // Shape remains the same as it's square
4256  inputYInfoAfterParams = inputYInfoBeforeParams;
4257  }
4258  else
4259  {
4260  inputYInfoAfterParams = inputYInfoBeforeParams;
4261  }
4262 
4263  switch(m_Parameters.m_DataLayoutX)
4264  {
4265  case DataLayout::NCDHW:
4266  case DataLayout::NDHWC:
4267  if(inputXInfoAfterParams.GetNumDimensions() < 3)
4268  {
4269  throw InvalidArgumentException(descriptorName +
4270  ": Input tensor X does not have the correct "
4271  "number of dimensions for the Data Layout that it has been assigned.");
4272  }
4273  break;
4274  case DataLayout::NCHW:
4275  case DataLayout::NHWC:
4276  default:
4277  break;
4278  }
4279 
4280  switch(m_Parameters.m_DataLayoutY)
4281  {
4282  case DataLayout::NCDHW:
4283  case DataLayout::NDHWC:
4284  if(inputYInfoAfterParams.GetNumDimensions() < 3)
4285  {
4286  throw InvalidArgumentException(descriptorName +
4287  ": Input tensor Y does not have the correct "
4288  "number of dimensions for the Data Layout that it has been assigned.");
4289  }
4290  break;
4291  case DataLayout::NCHW:
4292  case DataLayout::NHWC:
4293  default:
4294  break;
4295  }
4296 
4298  inputXInfoAfterParams.GetShape());
4300  inputXInfoBeforeParams.GetShape());
4301 
4302  if(inputXInfoAfterParams.GetShape()[axesXToMul.second]
4303  != inputYInfoAfterParams.GetShape()[axesYToMul.first])
4304  {
4305  throw InvalidArgumentException(descriptorName +
4306  ": The final axis of input tensor X must be the same size as "
4307  "the second last axis of input tensor Y.");
4308  }
4309 
4310  { // Separate scope so we don't pollute the rest of the scope with our temp variables
4311  // e.g. NHWC isnt compatible with NCHW as of now
4314 
4315  if(xLayout == DataLayout::NCHW || xLayout == DataLayout::NCDHW)
4316  {
4317  if(yLayout == DataLayout::NHWC || yLayout == DataLayout::NDHWC)
4318  {
4319  throw InvalidArgumentException(descriptorName +
4320  ": Invalid input tensor data layout combination.");
4321  }
4322  }
4323  if(yLayout == DataLayout::NCHW || yLayout == DataLayout::NCDHW)
4324  {
4325  if(xLayout == DataLayout::NHWC || xLayout == DataLayout::NDHWC)
4326  {
4327  throw InvalidArgumentException(descriptorName +
4328  ": Invalid input tensor data layout combination.");
4329  }
4330  }
4331  }
4332 
4333  // Simulate aligning the ends of the matrix dims and prepending 1's to the beginning of the shorter one
4334  unsigned int outputTensorDimSize = std::max(inputXInfoAfterParams.GetNumDimensions(),
4335  inputYInfoAfterParams.GetNumDimensions());
4336  if(outputTensorDimSize-2 > 0)
4337  {
4338  TensorInfo tiXNotMul = TensorInfo(TensorShape(outputTensorDimSize-2),
4340  TensorInfo tiYNotMul = TensorInfo(TensorShape(outputTensorDimSize-2),
4342  TensorInfo tiOutNotMul = TensorInfo(TensorShape(outputTensorDimSize-2),
4344 
4345  auto doAxisExtension = [&](std::vector<unsigned int> axisIndices, TensorInfo& ti)
4346  {
4347  auto sizeDiff = (outputTensorDimSize-2) - axisIndices.size();
4348 
4349  for(unsigned int i = 0; i < sizeDiff; i++)
4350  {
4351  axisIndices.insert(axisIndices.begin(), 1);
4352  }
4353 
4354  for(unsigned int i = 0; i < ti.GetNumDimensions(); i++)
4355  {
4356  ti.GetShape()[i] = inputXInfoAfterParams.GetShape()[i];
4357  }
4358  };
4359 
4361  inputXInfoAfterParams.GetShape());
4363  inputYInfoAfterParams.GetShape());
4364 
4365  doAxisExtension(axesXNotMul, tiXNotMul);
4366  doAxisExtension(axesYNotMul, tiYNotMul);
4367 
4368  for(unsigned int i = 0; i < tiOutNotMul.GetNumDimensions(); i++)
4369  {
4370  tiOutNotMul.GetShape()[i] = std::max(tiXNotMul.GetShape()[i],
4371  tiYNotMul.GetShape()[i]);
4372  }
4373 
4374  ValidateBroadcastTensorShapesMatch(tiXNotMul,
4375  tiYNotMul,
4376  tiOutNotMul,
4377  descriptorName,
4378  "input_X",
4379  "input_Y");
4380  }
4381 }
4382 
4383 void TileQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
4384 {
4385  const std::string& descriptorName{"TileQueueDescriptor"};
4386 
4387  ValidateNumInputs(workloadInfo, descriptorName, 1);
4388  ValidateNumOutputs(workloadInfo, descriptorName, 1);
4389 
4390  const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0];
4391  const TensorInfo& outputTensorInfo = workloadInfo.m_OutputTensorInfos[0];
4392 
4393  std::vector<DataType> supportedTypes =
4394  {
4402  };
4403 
4404  // Multiples length must be the same as the number of dimensions in input.
4405  if (m_Parameters.m_Multiples.size() != inputTensorInfo.GetNumDimensions())
4406  {
4407  throw InvalidArgumentException(descriptorName +
4408  ": Multiples length is not same as the number of dimensions in Input.");
4409  }
4410 
4411  ValidateDataTypes(inputTensorInfo, supportedTypes, descriptorName);
4412  ValidateDataTypes(outputTensorInfo, supportedTypes, descriptorName);
4413 }
4414 
4415 } // namespace armnn
armnn::LstmQueueDescriptor::m_ForgetLayerNormWeights
const ConstTensorHandle * m_ForgetLayerNormWeights
Definition: WorkloadData.hpp:440
armnn::LstmQueueDescriptor::m_CellBias
const ConstTensorHandle * m_CellBias
Definition: WorkloadData.hpp:435
armnn::SliceDescriptor::m_Begin
std::vector< unsigned int > m_Begin
Beginning indices of the slice in each dimension.
Definition: Descriptors.hpp:1223
armnn::QuantizedLstmQueueDescriptor::m_CellBias
const ConstTensorHandle * m_CellBias
Definition: WorkloadData.hpp:640
armnn::ShapeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2937
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:1591
armnn::QuantizedLstmQueueDescriptor::m_RecurrentToInputWeights
const ConstTensorHandle * m_RecurrentToInputWeights
Definition: WorkloadData.hpp:633
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:2635
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_CellBias
const ConstTensorHandle * m_CellBias
Definition: WorkloadData.hpp:731
armnn::QuantizedLstmQueueDescriptor::m_InputToForgetWeights
const ConstTensorHandle * m_InputToForgetWeights
Definition: WorkloadData.hpp:629
armnn::Optional< unsigned int >
armnn::DataLayout::NCDHW
@ NCDHW
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_RecurrentToCellWeights
const ConstTensorHandle * m_RecurrentToCellWeights
Definition: WorkloadData.hpp:724
armnn::IsQuantized8BitType
constexpr bool IsQuantized8BitType(DataType dataType)
Definition: TypesUtils.hpp:306
armnn::QLstmDescriptor::m_ProjectionEnabled
bool m_ProjectionEnabled
Enable/disable the projection layer.
Definition: Descriptors.hpp:1401
armnn::LstmDescriptor::m_TimeMajor
bool m_TimeMajor
Enable/disable time major.
Definition: Descriptors.hpp:1133
armnn::BatchNormalizationQueueDescriptor::m_Gamma
const ConstTensorHandle * m_Gamma
Definition: WorkloadData.hpp:319
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:1050
armnn::StridedSliceQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2578
WorkloadData.hpp
armnn::PreCompiledQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3004
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:1321
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:1596
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:476
armnn::EqualQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2677
armnn::LstmQueueDescriptor::m_InputToInputWeights
const ConstTensorHandle * m_InputToInputWeights
Definition: WorkloadData.hpp:422
armnn::QueueDescriptor::ValidateInputsOutputs
void ValidateInputsOutputs(const std::string &descName, unsigned int numExpectedIn, unsigned int numExpectedOut) const
Definition: WorkloadData.cpp:446
armnn::QLstmQueueDescriptor::m_InputToForgetWeights
const ConstTensorHandle * m_InputToForgetWeights
Definition: WorkloadData.hpp:585
armnnUtils::GetUnsignedAxis
unsigned int GetUnsignedAxis(const unsigned int inputDimension, const int axis)
Definition: TensorUtils.cpp:221
armnn::DequantizeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2889
armnn::QLstmQueueDescriptor::m_InputLayerNormWeights
const ConstTensorHandle * m_InputLayerNormWeights
Definition: WorkloadData.hpp:601
armnn::LogSoftmaxQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1759
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:317
armnn::LstmQueueDescriptor::m_ForgetGateBias
const ConstTensorHandle * m_ForgetGateBias
Definition: WorkloadData.hpp:434
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:1600
armnn::TensorInfo
Definition: Tensor.hpp:152
armnn::Pooling3dQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1543
armnn::LstmQueueDescriptor::m_InputToForgetWeights
const ConstTensorHandle * m_InputToForgetWeights
Definition: WorkloadData.hpp:423
armnn::GetDataTypeName
constexpr const char * GetDataTypeName(DataType dataType)
Definition: TypesUtils.hpp:223
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:3140
armnn::TensorInfo::GetNumDimensions
unsigned int GetNumDimensions() const
Definition: Tensor.hpp:195
armnn::QuantizedLstmQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3426
armnn::TransposeConvolution2dQueueDescriptor::m_Weight
const ConstTensorHandle * m_Weight
Definition: WorkloadData.hpp:546
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:3098
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:514
armnn::ResizeDescriptor::m_DataLayout
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Definition: Descriptors.hpp:993
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:735
armnn::SpaceToBatchNdDescriptor::m_BlockShape
std::vector< unsigned int > m_BlockShape
Block shape value.
Definition: Descriptors.hpp:1045
armnn::BatchNormalizationQueueDescriptor::m_Mean
const ConstTensorHandle * m_Mean
Definition: WorkloadData.hpp:316
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_InputToOutputWeights
const ConstTensorHandle * m_InputToOutputWeights
Definition: WorkloadData.hpp:721
armnn::BatchMatMulDescriptor::m_AdjointY
bool m_AdjointY
Definition: Descriptors.hpp:1597
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_OutputLayerNormWeights
const ConstTensorHandle * m_OutputLayerNormWeights
Definition: WorkloadData.hpp:738
armnn::QuantizedLstmQueueDescriptor::m_RecurrentToOutputWeights
const ConstTensorHandle * m_RecurrentToOutputWeights
Definition: WorkloadData.hpp:636
armnn::QuantizedLstmQueueDescriptor::m_InputGateBias
const ConstTensorHandle * m_InputGateBias
Definition: WorkloadData.hpp:638
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:3914
armnn::DataType::QSymmS8
@ QSymmS8
armnn::DepthwiseConvolution2dQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1383
armnn::LstmQueueDescriptor::m_InputToCellWeights
const ConstTensorHandle * m_InputToCellWeights
Definition: WorkloadData.hpp:424
armnn::ElementwiseUnaryQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3785
armnnUtils::Permuted
armnn::TensorShape Permuted(const armnn::TensorShape &srcShape, const armnn::PermutationVector &mappings)
Definition: Permute.cpp:98
armnn::GatherQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2786
armnn::ReverseV2QueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1617
armnn::QLstmQueueDescriptor::m_InputToInputWeights
const ConstTensorHandle * m_InputToInputWeights
Definition: WorkloadData.hpp:584
armnn::BatchMatMulQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:4167
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:1981
armnn::DetectionPostProcessQueueDescriptor::m_Anchors
const ConstTensorHandle * m_Anchors
Definition: WorkloadData.hpp:241
armnn::DataType::QSymmS16
@ QSymmS16
armnn::AbsQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3597
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_OutputGateBias
const ConstTensorHandle * m_OutputGateBias
Definition: WorkloadData.hpp:732
NumericCast.hpp
armnn::DataType::BFloat16
@ BFloat16
armnn::QLstmQueueDescriptor::m_ProjectionWeights
const ConstTensorHandle * m_ProjectionWeights
Definition: WorkloadData.hpp:599
armnn::QLstmQueueDescriptor::m_ForgetLayerNormWeights
const ConstTensorHandle * m_ForgetLayerNormWeights
Definition: WorkloadData.hpp:602
armnn::LstmQueueDescriptor::m_CellToOutputWeights
const ConstTensorHandle * m_CellToOutputWeights
Definition: WorkloadData.hpp:432
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_ForgetLayerNormWeights
const ConstTensorHandle * m_ForgetLayerNormWeights
Definition: WorkloadData.hpp:736
armnn::InstanceNormalizationQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1698
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_InputToForgetWeights
const ConstTensorHandle * m_InputToForgetWeights
Definition: WorkloadData.hpp:719
TensorUtils.hpp
armnn::QLstmQueueDescriptor::m_RecurrentToOutputWeights
const ConstTensorHandle * m_RecurrentToOutputWeights
Definition: WorkloadData.hpp:591
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:1171
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_RecurrentToOutputWeights
const ConstTensorHandle * m_RecurrentToOutputWeights
Definition: WorkloadData.hpp:725
armnn::DetectionPostProcessQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2821
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:733
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:1048
armnn::LstmDescriptor::m_PeepholeEnabled
bool m_PeepholeEnabled
Enable/disable peephole.
Definition: Descriptors.hpp:1127
armnn::TensorShape
Definition: Tensor.hpp:20
armnn::FakeQuantizationQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1677
armnn::StackDescriptor::m_NumInputs
uint32_t m_NumInputs
Number of input tensors.
Definition: Descriptors.hpp:1254
armnn::QuantizedLstmQueueDescriptor::m_RecurrentToCellWeights
const ConstTensorHandle * m_RecurrentToCellWeights
Definition: WorkloadData.hpp:635
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:1198
armnn::QLstmQueueDescriptor::m_CellToOutputWeights
const ConstTensorHandle * m_CellToOutputWeights
Definition: WorkloadData.hpp:594
armnn::ConcatQueueDescriptor::ViewOrigin
Definition: WorkloadData.hpp:132
armnn::LstmDescriptor::m_ClippingThresProj
float m_ClippingThresProj
Clipping threshold value for the projection.
Definition: Descriptors.hpp:1123
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:593
armnn::PermuteQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1487
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:2389
Logging.hpp
armnn::DebugQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2669
armnn::ElementwiseBinaryQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3756
armnn::QuantizedLstmQueueDescriptor::m_InputToInputWeights
const ConstTensorHandle * m_InputToInputWeights
Definition: WorkloadData.hpp:628
armnn::MemImportQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:526
armnn::BatchMatMulDescriptor::m_TransposeY
bool m_TransposeY
Definition: Descriptors.hpp:1592
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:1252
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:3826
armnn::TileQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:4383
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:3855
armnn::SubtractionQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2355
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:3127
armnn::BatchMatMulDescriptor::m_DataLayoutY
DataLayout m_DataLayoutY
Definition: Descriptors.hpp:1601
armnn::MeanQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2423
armnn::QLstmQueueDescriptor::m_OutputLayerNormWeights
const ConstTensorHandle * m_OutputLayerNormWeights
Definition: WorkloadData.hpp:604
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:595
armnn::BatchNormalizationQueueDescriptor::m_Beta
const ConstTensorHandle * m_Beta
Definition: WorkloadData.hpp:318
armnn::QuantizedLstmQueueDescriptor::m_RecurrentToForgetWeights
const ConstTensorHandle * m_RecurrentToForgetWeights
Definition: WorkloadData.hpp:634
armnn::QLstmQueueDescriptor::m_OutputGateBias
const ConstTensorHandle * m_OutputGateBias
Definition: WorkloadData.hpp:598
armnn::ResizeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1570
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_ForgetGateBias
const ConstTensorHandle * m_ForgetGateBias
Definition: WorkloadData.hpp:730
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_InputGateBias
const ConstTensorHandle * m_InputGateBias
Definition: WorkloadData.hpp:729
armnn::DivisionQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2321
armnn::QLstmQueueDescriptor::m_ForgetGateBias
const ConstTensorHandle * m_ForgetGateBias
Definition: WorkloadData.hpp:596
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:1782
armnn::QuantizedLstmQueueDescriptor::m_InputToCellWeights
const ConstTensorHandle * m_InputToCellWeights
Definition: WorkloadData.hpp:630
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:3009
armnn::LstmQueueDescriptor::m_InputGateBias
const ConstTensorHandle * m_InputGateBias
Definition: WorkloadData.hpp:433
armnn::PermutationVector
Definition: Types.hpp:308
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_CellToInputWeights
const ConstTensorHandle * m_CellToInputWeights
Definition: WorkloadData.hpp:726
armnn::Pooling2dQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1516
armnnUtils::DataLayoutIndexed::GetWidthIndex
unsigned int GetWidthIndex() const
Definition: DataLayoutIndexed.hpp:25
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_CellToOutputWeights
const ConstTensorHandle * m_CellToOutputWeights
Definition: WorkloadData.hpp:728
armnn::GreaterQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2701
armnn::TransposeConvolution2dQueueDescriptor::m_Bias
const ConstTensorHandle * m_Bias
Definition: WorkloadData.hpp:547
armnn::LstmQueueDescriptor::m_RecurrentToCellWeights
const ConstTensorHandle * m_RecurrentToCellWeights
Definition: WorkloadData.hpp:428
armnn::QLstmQueueDescriptor::m_RecurrentToInputWeights
const ConstTensorHandle * m_RecurrentToInputWeights
Definition: WorkloadData.hpp:588
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:1256
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:441
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:2725
armnn::QuantizedLstmQueueDescriptor::m_InputToOutputWeights
const ConstTensorHandle * m_InputToOutputWeights
Definition: WorkloadData.hpp:631
armnn::DataType::Signed32
@ Signed32
armnn::QLstmQueueDescriptor::m_RecurrentToForgetWeights
const ConstTensorHandle * m_RecurrentToForgetWeights
Definition: WorkloadData.hpp:589
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_RecurrentToForgetWeights
const ConstTensorHandle * m_RecurrentToForgetWeights
Definition: WorkloadData.hpp:723
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_CellToForgetWeights
const ConstTensorHandle * m_CellToForgetWeights
Definition: WorkloadData.hpp:727
armnn::DataType::QAsymmS8
@ QAsymmS8
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_RecurrentToInputWeights
const ConstTensorHandle * m_RecurrentToInputWeights
Definition: WorkloadData.hpp:722
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:1244
armnn::FullyConnectedQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1033
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_InputToInputWeights
const ConstTensorHandle * m_InputToInputWeights
Definition: WorkloadData.hpp:718
armnn::ConstantQueueDescriptor::m_LayerOutput
const ConstTensorHandle * m_LayerOutput
Definition: WorkloadData.hpp:370
armnn::DepthToSpaceQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3679
armnn::SpaceToDepthDescriptor::m_BlockSize
unsigned int m_BlockSize
Scalar specifying the input block size. It must be >= 1.
Definition: Descriptors.hpp:1071
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:2518
armnn::StridedSliceDescriptor::m_Stride
std::vector< int > m_Stride
Stride values for the input that will be sliced.
Definition: Descriptors.hpp:1325
armnn::TransposeConvolution2dQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3046
armnn::SpaceToDepthQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1928
armnn::PermutationVector::GetSize
SizeType GetSize() const
Definition: Types.hpp:351
armnn::MergeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2919
armnn::TransposeDescriptor::m_DimMappings
PermutationVector m_DimMappings
Indicates how to translate tensor elements from a given source into the target destination,...
Definition: Descriptors.hpp:1493
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:1635
armnn::MeanDescriptor::m_Axis
std::vector< unsigned int > m_Axis
Values for the dimensions to reduce.
Definition: Descriptors.hpp:1169
armnn::LstmDescriptor::m_CifgEnabled
bool m_CifgEnabled
Enable/disable cifg (coupled input & forget gate).
Definition: Descriptors.hpp:1125
armnn::LstmQueueDescriptor::m_RecurrentToOutputWeights
const ConstTensorHandle * m_RecurrentToOutputWeights
Definition: WorkloadData.hpp:429
armnn::QLstmQueueDescriptor::m_InputToOutputWeights
const ConstTensorHandle * m_InputToOutputWeights
Definition: WorkloadData.hpp:587
armnn::GatherNdQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2751
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:1413
armnn::NormalizationQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1096
armnn::LstmQueueDescriptor::m_InputLayerNormWeights
const ConstTensorHandle * m_InputLayerNormWeights
Definition: WorkloadData.hpp:439
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:1197
armnn::LstmDescriptor::m_LayerNormEnabled
bool m_LayerNormEnabled
Enable/disable layer normalization.
Definition: Descriptors.hpp:1131
armnn::MemSyncQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:582
armnn::LstmQueueDescriptor::m_RecurrentToForgetWeights
const ConstTensorHandle * m_RecurrentToForgetWeights
Definition: WorkloadData.hpp:427
armnn::SwitchQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2963
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:1397
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_ProjectionBias
const ConstTensorHandle * m_ProjectionBias
Definition: WorkloadData.hpp:734
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:3732
armnn::LstmQueueDescriptor::m_ProjectionWeights
const ConstTensorHandle * m_ProjectionWeights
Definition: WorkloadData.hpp:437
armnn::LstmQueueDescriptor::m_CellToInputWeights
const ConstTensorHandle * m_CellToInputWeights
Definition: WorkloadData.hpp:430
armnn::IsQuantizedType
constexpr bool IsQuantizedType()
Definition: TypesUtils.hpp:301
armnn::SliceQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:3624
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:1842
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:2275
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:3889
armnn::QLstmDescriptor::m_HiddenStateScale
float m_HiddenStateScale
Hidden State quantization scale.
Definition: Descriptors.hpp:1415
armnn::FakeQuantizationDescriptor::m_Min
float m_Min
Minimum value.
Definition: Descriptors.hpp:919
armnn::LstmQueueDescriptor::m_RecurrentToInputWeights
const ConstTensorHandle * m_RecurrentToInputWeights
Definition: WorkloadData.hpp:426
armnn::LstmDescriptor::m_ProjectionEnabled
bool m_ProjectionEnabled
Enable/disable the projection layer.
Definition: Descriptors.hpp:1129
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_InputToCellWeights
const ConstTensorHandle * m_InputToCellWeights
Definition: WorkloadData.hpp:720
armnn::StridedSliceDescriptor::m_End
std::vector< int > m_End
End values for the input that will be sliced.
Definition: Descriptors.hpp:1323
armnn::LstmQueueDescriptor::m_ProjectionBias
const ConstTensorHandle * m_ProjectionBias
Definition: WorkloadData.hpp:438
armnn::PadQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2467
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:2005
armnn::LstmQueueDescriptor::m_OutputGateBias
const ConstTensorHandle * m_OutputGateBias
Definition: WorkloadData.hpp:436
armnn::L2NormalizationQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1727
armnn::QLstmQueueDescriptor::m_ProjectionBias
const ConstTensorHandle * m_ProjectionBias
Definition: WorkloadData.hpp:600
armnn::QLstmQueueDescriptor::m_CellToInputWeights
const ConstTensorHandle * m_CellToInputWeights
Definition: WorkloadData.hpp:592
armnn::ConvertFp16ToFp32QueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2298
armnn::TransposeConvolution2dDescriptor::m_BiasEnabled
bool m_BiasEnabled
Enable/disable bias.
Definition: Descriptors.hpp:1460
armnn::QLstmDescriptor::m_LayerNormEnabled
bool m_LayerNormEnabled
Enable/disable layer normalization.
Definition: Descriptors.hpp:1403
armnn::DataType::Signed64
@ Signed64
armnn::SliceDescriptor::m_Size
std::vector< unsigned int > m_Size
Size of the slice in each dimension.
Definition: Descriptors.hpp:1226
armnn::QLstmQueueDescriptor::m_CellBias
const ConstTensorHandle * m_CellBias
Definition: WorkloadData.hpp:597
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:431
armnn::LstmQueueDescriptor::m_InputToOutputWeights
const ConstTensorHandle * m_InputToOutputWeights
Definition: WorkloadData.hpp:425
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:586
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:1121
armnn::QuantizeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:2489
armnn::LstmQueueDescriptor::m_OutputLayerNormWeights
const ConstTensorHandle * m_OutputLayerNormWeights
Definition: WorkloadData.hpp:442
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:497
DataLayoutIndexed.hpp
armnn::UnidirectionalSequenceLstmQueueDescriptor::m_CellLayerNormWeights
const ConstTensorHandle * m_CellLayerNormWeights
Definition: WorkloadData.hpp:737
armnn::QLstmDescriptor::m_PeepholeEnabled
bool m_PeepholeEnabled
Enable/disable peephole.
Definition: Descriptors.hpp:1399
armnn::ReshapeQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1813
armnn::QuantizedLstmQueueDescriptor::m_OutputGateBias
const ConstTensorHandle * m_OutputGateBias
Definition: WorkloadData.hpp:641
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:1161
armnn::QLstmQueueDescriptor::m_CellLayerNormWeights
const ConstTensorHandle * m_CellLayerNormWeights
Definition: WorkloadData.hpp:603
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:590
armnn::DataLayout::NCHW
@ NCHW
armnn::QuantizedLstmQueueDescriptor::m_ForgetGateBias
const ConstTensorHandle * m_ForgetGateBias
Definition: WorkloadData.hpp:639
armnn::Convolution3dQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1321
armnn::AdditionQueueDescriptor::Validate
void Validate(const WorkloadInfo &workloadInfo) const
Definition: WorkloadData.cpp:1124
armnn::SpaceToDepthDescriptor::m_DataLayout
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Definition: Descriptors.hpp:1074
armnn::DepthwiseConvolution2dDescriptor::m_StrideX
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
Definition: Descriptors.hpp:700