blob: 5ca492888f9682419df1339173a8903c1109ca34 [file] [log] [blame]
telsoa014fcda012018-03-09 14:13:49 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
telsoa014fcda012018-03-09 14:13:49 +00004//
5#include "WorkloadData.hpp"
6
7#include "CpuTensorHandle.hpp"
telsoa014fcda012018-03-09 14:13:49 +00008
Matteo Martincigh21350152018-11-28 16:22:22 +00009#include <DataLayoutIndexed.hpp>
Matthew Bentham8800c002018-11-19 13:19:28 +000010
telsoa014fcda012018-03-09 14:13:49 +000011#include <algorithm>
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000012#include <iomanip>
telsoa014fcda012018-03-09 14:13:49 +000013#include <string>
14#include <sstream>
telsoa014fcda012018-03-09 14:13:49 +000015
16#include <boost/format.hpp>
Aron Virginas-Tard4f0fea2019-04-09 14:08:06 +010017#include <boost/numeric/conversion/cast.hpp>
telsoa014fcda012018-03-09 14:13:49 +000018
Matteo Martincigh21350152018-11-28 16:22:22 +000019using namespace armnnUtils;
20
telsoa014fcda012018-03-09 14:13:49 +000021namespace armnn
22{
23
24//---------------------------------------------------------------
25DataType GetBiasDataType(DataType inputDataType)
26{
27 switch (inputDataType)
28 {
telsoa01c577f2c2018-08-31 09:22:23 +010029 case DataType::Float16:
30 return DataType::Float16;
telsoa014fcda012018-03-09 14:13:49 +000031 case DataType::Float32:
32 return DataType::Float32;
33 case DataType::QuantisedAsymm8:
34 return DataType::Signed32;
Ruomei Yan88d44b82019-05-23 14:29:06 +010035 case DataType::QuantisedSymm16:
36 return DataType::Signed32;
telsoa014fcda012018-03-09 14:13:49 +000037 default:
38 BOOST_ASSERT_MSG(false, "Invalid input data type");
39 return DataType::Float32;
40 }
41}
42
43namespace
44{
45
46//---------------------------------------------------------------
47//android ndk does not support std::to_string function.
48template <typename T>
49std::string to_string(T value)
50{
51 std::ostringstream os;
52 os << value;
53 return os.str();
54}
55
56//---------------------------------------------------------------
57void ValidatePointer(const void* ptr, std::string const& descName, std::string const& paramName)
58{
59 if (!ptr)
60 {
61 throw InvalidArgumentException(descName + ": Invalid null pointer. The " +
62 paramName + " parameter must be set.");
63 }
64}
65
66//---------------------------------------------------------------
67void ValidateTensorShapesMatch(const TensorInfo& first,
68 const TensorInfo& second,
69 std::string const& descName,
70 std::string const& firstName,
71 std::string const& secondName)
72{
73 if (first.GetShape() != second.GetShape())
74 {
75 throw InvalidArgumentException(descName + ": "
76 + firstName + " & " + secondName + " must have identical shapes");
77 }
78}
79
80//---------------------------------------------------------------
Sadik Armaganeff363d2019-04-05 15:25:46 +010081void ValidateNumInputs(const WorkloadInfo& workloadInfo, std::string const& descName, const unsigned int expectedSize)
telsoa014fcda012018-03-09 14:13:49 +000082{
Sadik Armaganeff363d2019-04-05 15:25:46 +010083 if (workloadInfo.m_InputTensorInfos.size() != expectedSize)
telsoa014fcda012018-03-09 14:13:49 +000084 {
85 throw InvalidArgumentException(descName +
Sadik Armaganeff363d2019-04-05 15:25:46 +010086 ": Requires exactly " + to_string(expectedSize) + "input(s). " +
telsoa014fcda012018-03-09 14:13:49 +000087 to_string(workloadInfo.m_InputTensorInfos.size()) + " have been provided.");
88 }
89}
90
91//---------------------------------------------------------------
Sadik Armaganeff363d2019-04-05 15:25:46 +010092void ValidateNumOutputs(const WorkloadInfo& workloadInfo, std::string const& descName, const unsigned int expectedSize)
telsoa014fcda012018-03-09 14:13:49 +000093{
Sadik Armaganeff363d2019-04-05 15:25:46 +010094 if (workloadInfo.m_OutputTensorInfos.size() != expectedSize)
telsoa014fcda012018-03-09 14:13:49 +000095 {
96 throw InvalidArgumentException(descName +
Sadik Armaganeff363d2019-04-05 15:25:46 +010097 ": Requires exactly " + to_string(expectedSize) + " output(s). " +
telsoa014fcda012018-03-09 14:13:49 +000098 to_string(workloadInfo.m_OutputTensorInfos.size()) + " has been provided.");
99 }
100}
101
102//---------------------------------------------------------------
103void ValidateTensorNumDimensions(const TensorInfo& tensor,
104 std::string const& descName,
105 unsigned int numDimensions,
106 std::string const& tensorName)
107{
108 if (tensor.GetNumDimensions() != numDimensions)
109 {
110 throw InvalidArgumentException(descName + ": Expected " + to_string(numDimensions) + " but got " +
111 to_string(tensor.GetNumDimensions()) + " dimensions for " +
112 tensorName + " tensor.");
113 }
114}
115
116//---------------------------------------------------------------
117void ValidateTensorDataType(const TensorInfo& tensor, DataType dataType,
118 const std::string& descName, std::string const& tensorName)
119{
120 if (tensor.GetDataType() != dataType)
121 {
122 throw InvalidArgumentException(descName + ": Expected data type " + GetDataTypeName(dataType) + " but got " +
123 GetDataTypeName(tensor.GetDataType()) + " for " + tensorName + " tensor.");
124 }
125}
126
127//---------------------------------------------------------------
Matteo Martincighe851b3d2019-05-28 14:31:20 +0100128void ValidateTensorQuantizationSpace(const TensorInfo& first,
129 const TensorInfo& second,
130 const std::string& descName,
131 std::string const& firstName,
132 std::string const& secondName)
133{
134 if (!first.IsQuantized() ||
135 !second.IsQuantized())
136 {
137 // Not a quantized type, ignore the validation
138 return;
139 }
140
141 DataType firstDataType = first.GetDataType();
142 DataType secondDataType = second.GetDataType();
143
144 if (firstDataType != secondDataType)
145 {
146 throw InvalidArgumentException(descName + ": " + firstName + " and " + secondName +
147 " must be of the same quantized type, " +
148 firstName + " is " + GetDataTypeName(firstDataType) + ", " +
149 secondName + " is " + GetDataTypeName(secondDataType));
150 }
151
152 if (!first.IsTypeSpaceMatch(second))
153 {
154 throw InvalidArgumentException(descName + ": " + firstName + " and " + secondName +
155 " must have the same quantization space, " +
156 firstName + " has offset " + to_string(first.GetQuantizationOffset()) +
157 " and scale " + to_string(first.GetQuantizationScale()) + ", " +
158 secondName + " has offset " + to_string(second.GetQuantizationOffset()) +
159 " and scale " + to_string(second.GetQuantizationScale()));
160 }
161}
162
163//---------------------------------------------------------------
telsoa014fcda012018-03-09 14:13:49 +0000164void ValidateBiasTensorQuantization(const TensorInfo& biasTensor, const TensorInfo& inputTensorInfo,
165 const TensorInfo& weightsTensorInfo, const std::string& descName)
166{
167 if (biasTensor.GetQuantizationOffset() != 0)
168 {
169 throw InvalidArgumentException(descName + ": Expected zero quantization offset for bias tensor but got " +
170 to_string(biasTensor.GetQuantizationOffset()));
171 }
172 const float expectedScale = inputTensorInfo.GetQuantizationScale() * weightsTensorInfo.GetQuantizationScale();
kevmay016c46dd32018-12-17 15:32:45 +0000173 if (std::abs(biasTensor.GetQuantizationScale() - expectedScale) > 0.00000001f)
telsoa014fcda012018-03-09 14:13:49 +0000174 {
175 // Print the float values with extra precision to see very small differences
176 std::stringstream msg;
177 msg << std::setprecision(10) << descName << ": Expected " << expectedScale <<
178 " quantization scale for bias tensor (the product of the input and weight scales), but got " <<
179 biasTensor.GetQuantizationScale();
180 throw InvalidArgumentException(msg.str());
181 }
182}
183
184//---------------------------------------------------------------
185void ValidateTensors(const std::vector<ITensorHandle*>& vec,
186 unsigned int numExpected,
187 const std::string& descName,
188 const std::string& varName)
189{
190 if (vec.empty() && numExpected > 0)
191 {
192 throw InvalidArgumentException(descName + ": Invalid empty " + varName + " array.");
193 }
194
195 for (unsigned int i = 0; i < numExpected; ++i)
196 {
197 if (!vec[i])
198 {
199 throw InvalidArgumentException(descName + ": Invalid NULL for " + varName + to_string(i));
200 }
201 }
202}
203
204//---------------------------------------------------------------
205void ValidateBroadcastTensorShapesMatch(const TensorInfo& first,
206 const TensorInfo& second,
207 const TensorInfo& output,
208 std::string const& descName,
209 std::string const& firstName,
210 std::string const& secondName)
211{
212 // Tensors must have the same number of dimensions in order to be explicit about which dimensions will get
213 // broadcasted.
214 if (first.GetNumDimensions() != second.GetNumDimensions())
215 {
216 throw InvalidArgumentException(descName + ": Tensors "
217 + firstName + " & " + secondName
218 + " must have the same number of dimensions in order to be broadcasted");
219 }
220 uint32_t numDims = first.GetNumDimensions();
221 std::vector<uint32_t> outputDims(numDims, 0u);
222 for (uint32_t i = 0; i < numDims; i++)
223 {
224 const bool dimsNotEqual = first.GetShape()[i] != second.GetShape()[i];
225 const bool dimsNotOne = (first.GetShape()[i] != 1) && (second.GetShape()[i] != 1);
226 if (dimsNotEqual && dimsNotOne)
227 {
228 throw InvalidArgumentException("Broadcasting is not possible for incompatible shapes");
229 }
230 outputDims[i] = std::max(first.GetShape()[i], second.GetShape()[i]);
231 }
232 TensorShape broadcastShape = TensorShape(boost::numeric_cast<unsigned int>(outputDims.size()), outputDims.data());
233 if (broadcastShape != output.GetShape())
234 {
235 throw InvalidArgumentException(descName + ": The tensor shape resulting from adding "
236 + firstName + " & " + secondName
237 + " does not match the output shape");
238 }
239}
240
241//---------------------------------------------------------------
242/// Validates that the output tensor's quantization scale is greater than the product
243/// of the two input tensors' quantization scales. This is a requirement of the implementation of
244/// the quantized multiplication.
245void ValidateTensorQuantizationMultiplier(const TensorInfo& inputTensor1, const TensorInfo& inputTensor2,
246 const TensorInfo& outputTensorInfo, std::string const& descName,
247 const std::string& inputTensor1Name, const std::string& inputTensor2Name, const std::string& outputTensorName)
248{
249 if (outputTensorInfo.GetDataType() == DataType::QuantisedAsymm8)
250 {
251 if (outputTensorInfo.GetQuantizationScale() <=
252 inputTensor1.GetQuantizationScale() * inputTensor2.GetQuantizationScale())
253 {
254 std::stringstream msg;
255 msg << descName << ": Quantization scale of " << outputTensorName << " is not greater than " <<
256 "the product of the " << inputTensor1Name << " and " << inputTensor2Name << " tensors";
257 throw InvalidArgumentException(msg.str());
258 }
259 }
260}
261
Sadik Armaganeff363d2019-04-05 15:25:46 +0100262//---------------------------------------------------------------
263void ValidateDataTypes(const TensorInfo& info,
264 const std::vector<armnn::DataType>& supportedTypes,
265 std::string const& descName)
266{
267 auto iterator = std::find(supportedTypes.begin(), supportedTypes.end(), info.GetDataType());
268 if (iterator == supportedTypes.end())
269 {
270 throw InvalidArgumentException(descName + ": " + " Tensor type is not supported.");
271 }
272}
273
James Conroy4d1ff582019-06-10 17:06:39 +0100274//---------------------------------------------------------------
275void ValidateTensorDataTypesMatch(const TensorInfo& first,
276 const TensorInfo& second,
277 std::string const& descName,
278 std::string const& firstName,
279 std::string const& secondName)
280{
281 if (first.GetDataType() != second.GetDataType())
282 {
283 throw InvalidArgumentException(descName + ": " + firstName + " & " + secondName +
284 " must have identical data types.");
285 }
286}
287
telsoa014fcda012018-03-09 14:13:49 +0000288} //namespace
289
290void QueueDescriptor::ValidateInputsOutputs(const std::string& descName,
291 unsigned int numExpectedIn, unsigned int numExpectedOut) const
292{
293 ValidateTensors(m_Inputs, numExpectedIn, descName, "input");
294 ValidateTensors(m_Outputs, numExpectedOut, descName, "output");
295}
296
297//---------------------------------------------------------------
298void MemCopyQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
299{
Sadik Armaganeff363d2019-04-05 15:25:46 +0100300 ValidateNumInputs(workloadInfo, "MemCopyQueueDescriptor", 1);
301 ValidateNumOutputs(workloadInfo, "MemCopyQueueDescriptor" , 1);
telsoa014fcda012018-03-09 14:13:49 +0000302
303 if (workloadInfo.m_InputTensorInfos.size() != workloadInfo.m_OutputTensorInfos.size())
304 {
305 throw InvalidArgumentException(boost::str(
306 boost::format("Number of input infos (%1%) does not match the number of output infos (%2%)")
307 % workloadInfo.m_InputTensorInfos.size() % workloadInfo.m_OutputTensorInfos.size()));
308 }
309
310 for (std::size_t i = 0; i < workloadInfo.m_InputTensorInfos.size(); ++i)
311 {
312 if (workloadInfo.m_InputTensorInfos[i].GetNumElements() !=
313 workloadInfo.m_OutputTensorInfos[i].GetNumElements())
314 {
315 throw InvalidArgumentException(boost::str(
316 boost::format("Number of elements for tensor input and output %1% does not match")
317 % i ));
318 }
319 }
320
321 if (m_Inputs.size() != m_Outputs.size())
322 {
323 throw InvalidArgumentException(boost::str(
324 boost::format("Number of inputs (%1%) does not match the number of outputs (%2%)")
325 % m_Inputs.size() % m_Outputs.size()));
326 }
327
328 for (unsigned int i = 0; i < m_Inputs.size(); ++i)
329 {
330 if (!m_Inputs[i])
331 {
332 throw InvalidArgumentException(boost::str(boost::format("Invalid null input %1%") % i));
333 }
334
335 if (!m_Outputs[i])
336 {
337 throw InvalidArgumentException(boost::str(boost::format("Invalid null output %1%") % i));
338 }
339 }
340}
341
342//---------------------------------------------------------------
343void ActivationQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
344{
Sadik Armaganeff363d2019-04-05 15:25:46 +0100345 ValidateNumInputs(workloadInfo, "ActivationQueueDescriptor", 1);
346 ValidateNumOutputs(workloadInfo, "ActivationQueueDescriptor", 1);
telsoa014fcda012018-03-09 14:13:49 +0000347 ValidateTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
348 workloadInfo.m_OutputTensorInfos[0],
349 "ActivationQueueDescriptor",
350 "input",
351 "output");
Nattapat Chaimanowongae2c5f02019-04-24 16:19:57 +0100352
353 std::vector<DataType> supportedTypes = {
354 DataType::Float32,
355 DataType::Float16,
Teresa Charlin18515e22019-04-24 10:17:46 +0100356 DataType::QuantisedAsymm8,
357 DataType::QuantisedSymm16
Nattapat Chaimanowongae2c5f02019-04-24 16:19:57 +0100358 };
359
360 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
361 supportedTypes,
362 "ActivationQueueDescriptor");
363
364 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
365 {workloadInfo.m_InputTensorInfos[0].GetDataType()},
366 "ActivationQueueDescriptor");
telsoa014fcda012018-03-09 14:13:49 +0000367}
368
369//---------------------------------------------------------------
370void SoftmaxQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
371{
Sadik Armaganeff363d2019-04-05 15:25:46 +0100372 ValidateNumInputs(workloadInfo, "SoftmaxQueueDescriptor", 1);
373 ValidateNumOutputs(workloadInfo, "SoftmaxQueueDescriptor", 1);
telsoa014fcda012018-03-09 14:13:49 +0000374
375 ValidateTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
376 workloadInfo.m_OutputTensorInfos[0],
377 "SoftmaxQueueDescriptor",
378 "input",
379 "output");
nikraj01248683f2019-05-29 16:46:50 +0100380
381 std::vector<DataType> supportedTypes =
382 {
383 DataType::Float16,
384 DataType::Float32,
385 DataType::QuantisedAsymm8,
386 DataType::QuantisedSymm16
387 };
388
389 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
390 supportedTypes,
391 "SoftmaxQueueDescriptor");
392
393 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
394 {workloadInfo.m_InputTensorInfos[0].GetDataType()},
395 "SoftmaxQueueDescriptor");
telsoa014fcda012018-03-09 14:13:49 +0000396}
397
398//---------------------------------------------------------------
399void SplitterQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
400{
Sadik Armaganeff363d2019-04-05 15:25:46 +0100401 ValidateNumInputs(workloadInfo, "SplitterQueueDescriptor", 1);
telsoa014fcda012018-03-09 14:13:49 +0000402
Ruomei Yan25339c32019-05-28 16:48:20 +0100403 // Check the supported data types
404 std::vector<DataType> supportedTypes =
405 {
406 DataType::Float32,
407 DataType::Float16,
408 DataType::Boolean,
409 DataType::Signed32,
410 DataType::QuantisedAsymm8,
411 DataType::QuantisedSymm16
412 };
413
414 for (unsigned long i = 0; i < workloadInfo.m_OutputTensorInfos.size(); ++i)
415 {
416 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[i],
417 supportedTypes,
418 "SplitterQueueDescriptor");
419 }
420 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
421 {workloadInfo.m_InputTensorInfos[0].GetDataType()},
422 "SplitterQueueDescriptor");
423
telsoa014fcda012018-03-09 14:13:49 +0000424 if (workloadInfo.m_OutputTensorInfos.size() <= 0)
425 {
426 throw InvalidArgumentException("SplitterQueueDescriptor: At least one output needs to be provided.");
427 }
428
429 if (workloadInfo.m_OutputTensorInfos.size() != m_ViewOrigins.size())
430 {
431 throw InvalidArgumentException(
432 "SplitterQueueDescriptor: Number of split windows "
433 "has to match number of workloadInfo.m_OutputTensorInfos. "
434 "Number of windows: " +
435 to_string(m_ViewOrigins.size()) +
436 ". Number of workloadInfo.m_OutputTensorInfos: " + to_string(workloadInfo.m_OutputTensorInfos.size()));
437 }
438
telsoa01c577f2c2018-08-31 09:22:23 +0100439 //The dimensionality of all the windows has to match the dimensionality (not shape) of the input.
telsoa014fcda012018-03-09 14:13:49 +0000440 std::size_t inputDims = workloadInfo.m_InputTensorInfos[0].GetNumDimensions();
441 for(unsigned int w = 0; w < m_ViewOrigins.size(); ++w )
442 {
telsoa01c577f2c2018-08-31 09:22:23 +0100443 //Checks that the dimensionality of input is same as the split windows.
telsoa014fcda012018-03-09 14:13:49 +0000444 ViewOrigin const& e = m_ViewOrigins[w];
445 if (e.m_Origin.size() != inputDims)
446 {
447 throw InvalidArgumentException("SplitterQueueDescriptor: Window origin have to "
448 "have the same dimensionality as the input tensor. "
449 "Window origin (index: " +
450 to_string(w) + ") has " + to_string(e.m_Origin.size()) +
451 " dimensions, the input "
452 "tensor has " +
453 to_string(inputDims) + " dimensions.");
454 }
455 for (unsigned int i = 0; i < e.m_Origin.size(); ++i)
456 {
457 if (e.m_Origin[i] + workloadInfo.m_OutputTensorInfos[w].GetShape()[i] >
458 workloadInfo.m_InputTensorInfos[0].GetShape()[i])
459 {
460 throw InvalidArgumentException("SplitterQueueDescriptor: Window extent coordinates have to "
461 "be smaller or equal than the size of the input in that coord.");
462 }
463 }
464 }
465}
466
467//---------------------------------------------------------------
Jim Flynne242f2d2019-05-22 14:24:13 +0100468void ConcatQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
telsoa014fcda012018-03-09 14:13:49 +0000469{
Jim Flynne242f2d2019-05-22 14:24:13 +0100470 ValidateNumOutputs(workloadInfo, "ConcatQueueDescriptor", 1);
telsoa014fcda012018-03-09 14:13:49 +0000471
472 if (m_Inputs.size() <= 0)
473 {
Jim Flynne242f2d2019-05-22 14:24:13 +0100474 throw InvalidArgumentException("ConcatQueueDescriptor: At least one input needs to be provided.");
telsoa014fcda012018-03-09 14:13:49 +0000475 }
476 if (m_Outputs.size() <= 0)
477 {
Jim Flynne242f2d2019-05-22 14:24:13 +0100478 throw InvalidArgumentException("ConcatQueueDescriptor: At least one output needs to be provided.");
telsoa014fcda012018-03-09 14:13:49 +0000479 }
480
481 if (workloadInfo.m_InputTensorInfos.size() <= 0)
482 {
Jim Flynne242f2d2019-05-22 14:24:13 +0100483 throw InvalidArgumentException("ConcatQueueDescriptor: At least one TensorInfo input needs to be provided.");
telsoa014fcda012018-03-09 14:13:49 +0000484 }
485 if (workloadInfo.m_OutputTensorInfos.size() <= 0)
486 {
Jim Flynne242f2d2019-05-22 14:24:13 +0100487 throw InvalidArgumentException("ConcatQueueDescriptor: At least one TensorInfo output needs to be provided.");
telsoa014fcda012018-03-09 14:13:49 +0000488 }
489
Nikhil Raj8599a412018-11-19 14:51:07 +0000490 if(m_Parameters.GetConcatAxis() > workloadInfo.m_InputTensorInfos[0].GetShape().GetNumDimensions())
491 {
492 throw InvalidArgumentException("Invalid Concatenation Axis provided");
493 }
494
495 if (workloadInfo.m_InputTensorInfos[0].GetShape().GetNumDimensions() - m_Parameters.GetConcatAxis() == 1)
496 {
497 return;
498 }
499
telsoa014fcda012018-03-09 14:13:49 +0000500 if (workloadInfo.m_InputTensorInfos.size() != m_ViewOrigins.size())
501 {
502 throw InvalidArgumentException(
Jim Flynne242f2d2019-05-22 14:24:13 +0100503 "ConcatQueueDescriptor: Number of split windows "
telsoa014fcda012018-03-09 14:13:49 +0000504 "has to match number of workloadInfo.m_InputTensorInfos. "
505 "Number of windows: " +
506 to_string(m_ViewOrigins.size()) +
507 ". Number of workloadInfo.m_InputTensorInfos: " + to_string(workloadInfo.m_InputTensorInfos.size()));
508 }
509
telsoa01c577f2c2018-08-31 09:22:23 +0100510 //The dimensionality of all the windows has to match the dimensionality (not shape) of the output.
telsoa014fcda012018-03-09 14:13:49 +0000511 std::size_t outputDims = workloadInfo.m_OutputTensorInfos[0].GetNumDimensions();
512 for(unsigned int w = 0; w < m_ViewOrigins.size(); ++w )
513 {
telsoa01c577f2c2018-08-31 09:22:23 +0100514 //Checks that the dimensionality of output is same as the split windows.
telsoa014fcda012018-03-09 14:13:49 +0000515 ViewOrigin const& e = m_ViewOrigins[w];
516 if (e.m_Origin.size() != outputDims)
517 {
Jim Flynne242f2d2019-05-22 14:24:13 +0100518 throw InvalidArgumentException("ConcatQueueDescriptor: Window origin have to "
telsoa014fcda012018-03-09 14:13:49 +0000519 "have the same dimensionality as the output tensor. "
520 "Window origin (index: " +
521 to_string(w) + ") has " + to_string(e.m_Origin.size()) +
522 " dimensions, the output "
523 "tensor has " +
524 to_string(outputDims) + " dimensions.");
525 }
telsoa01c577f2c2018-08-31 09:22:23 +0100526 //Checks that the merge windows are within the output tensor.
telsoa014fcda012018-03-09 14:13:49 +0000527 for (unsigned int i = 0; i < e.m_Origin.size(); ++i)
528 {
529 if (e.m_Origin[i] + workloadInfo.m_InputTensorInfos[w].GetShape()[i]
530 > workloadInfo.m_OutputTensorInfos[0].GetShape()[i])
531 {
Jim Flynne242f2d2019-05-22 14:24:13 +0100532 throw InvalidArgumentException("ConcatQueueDescriptor: Window extent coordinates have to "
telsoa014fcda012018-03-09 14:13:49 +0000533 "be smaller or equal than the size of the output in that coord.");
534 }
535 }
536 }
Jim Flynncbb66aa2019-05-15 13:03:54 +0100537
538 // Check the supported data types
539 std::vector<DataType> supportedTypes =
540 {
541 DataType::Float32,
542 DataType::Float16,
543 DataType::Boolean,
544 DataType::Signed32,
545 DataType::QuantisedAsymm8,
546 DataType::QuantisedSymm16
547 };
548
549 for (unsigned long i = 0; i < workloadInfo.m_InputTensorInfos.size(); ++i)
550 {
551 ValidateDataTypes(workloadInfo.m_InputTensorInfos[i],
552 supportedTypes,
Jim Flynne242f2d2019-05-22 14:24:13 +0100553 "ConcatQueueDescriptor");
Jim Flynncbb66aa2019-05-15 13:03:54 +0100554 }
555 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
556 {workloadInfo.m_InputTensorInfos[0].GetDataType()},
Jim Flynne242f2d2019-05-22 14:24:13 +0100557 "ConcatQueueDescriptor");
telsoa014fcda012018-03-09 14:13:49 +0000558}
559
560//---------------------------------------------------------------
561void FullyConnectedQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
562{
Sadik Armaganeff363d2019-04-05 15:25:46 +0100563 ValidateNumInputs(workloadInfo, "FullyConnectedQueueDescriptor", 1);
564 ValidateNumOutputs(workloadInfo, "FullyConnectedQueueDescriptor", 1);
telsoa014fcda012018-03-09 14:13:49 +0000565 ValidateTensorNumDimensions(workloadInfo.m_OutputTensorInfos[0], "FullyConnectedQueueDescriptor", 2, "output");
566
567 if (!(workloadInfo.m_InputTensorInfos[0].GetNumDimensions() == 2 ||
568 workloadInfo.m_InputTensorInfos[0].GetNumDimensions() == 4))
569 {
570 throw InvalidArgumentException("FullyConnectedQueueDescriptor: Input tensor must have 2 or 4 dimensions.");
571 }
572
573 if (m_Weight == nullptr)
574 {
575 throw InvalidArgumentException("FullyConnectedQueueDescriptor: Weight tensor descriptor is missing.");
576 }
577
578 ValidateTensorNumDimensions(m_Weight->GetTensorInfo(), "FullyConnectedQueueDescriptor", 2, "weight");
579
580 if (m_Parameters.m_BiasEnabled)
581 {
582 if (m_Bias == nullptr)
583 {
584 throw InvalidArgumentException("FullyConnectedQueueDescriptor: Bias is enabled but "
585 "bias value tensor descriptor is missing.");
586 }
587
telsoa01c577f2c2018-08-31 09:22:23 +0100588 // Validates type and quantization values.
telsoa014fcda012018-03-09 14:13:49 +0000589 ValidateBiasTensorQuantization(m_Bias->GetTensorInfo(),
590 workloadInfo.m_InputTensorInfos[0], m_Weight->GetTensorInfo(), "FullyConnectedQueueDescriptor");
591
592 ValidateTensorDataType(m_Bias->GetTensorInfo(),
593 GetBiasDataType(workloadInfo.m_InputTensorInfos[0].GetDataType()),
594 "FullyConnectedQueueDescriptor", "bias");
595
596 ValidateTensorNumDimensions(m_Bias->GetTensorInfo(), "FullyConnectedQueueDescriptor", 1, "bias");
597 }
598
599 ValidateTensorQuantizationMultiplier(workloadInfo.m_InputTensorInfos[0], m_Weight->GetTensorInfo(),
600 workloadInfo.m_OutputTensorInfos[0], "FullyConnectedQueueDescriptor", "input", "weights", "output");
Francis Murtagh46c09d02019-05-28 08:15:28 +0100601
602 // Check the supported data types
603 std::vector<DataType> supportedTypes =
604 {
605 DataType::Float32,
606 DataType::Float16,
607 DataType::QuantisedAsymm8,
608 DataType::QuantisedSymm16
609 };
610
611 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
612 supportedTypes,
613 "FullyConnectedQueueDescriptor");
614
615 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
616 {workloadInfo.m_InputTensorInfos[0].GetDataType()},
617 "FullyConnectedQueueDescriptor");
telsoa014fcda012018-03-09 14:13:49 +0000618}
619
620//---------------------------------------------------------------
621void NormalizationQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
622{
Sadik Armaganeff363d2019-04-05 15:25:46 +0100623 ValidateNumInputs(workloadInfo, "NormalizationQueueDescriptor", 1);
624 ValidateNumOutputs(workloadInfo, "NormalizationQueueDescriptor", 1);
Matteo Martincigh2fc70c52019-06-05 14:12:48 +0100625
626 // Check the supported data types
627 std::vector<DataType> supportedTypes =
628 {
629 DataType::Float16,
630 DataType::Float32,
Matteo Martincigh6aeb7712019-06-05 17:23:29 +0100631 DataType::QuantisedAsymm8,
632 DataType::QuantisedSymm16
Matteo Martincigh2fc70c52019-06-05 14:12:48 +0100633 };
634
635 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
636 supportedTypes,
637 "NormalizationQueueDescriptor");
638
639 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
640 { workloadInfo.m_InputTensorInfos[0].GetDataType() },
641 "NormalizationQueueDescriptor");
642
telsoa014fcda012018-03-09 14:13:49 +0000643 ValidateTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
644 workloadInfo.m_OutputTensorInfos[0],
645 "NormalizationQueueDescriptor",
646 "input",
647 "output");
648}
649
650void AdditionQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
651{
Sadik Armaganeff363d2019-04-05 15:25:46 +0100652 ValidateNumInputs(workloadInfo, "AdditionQueueDescriptor", 2);
653 ValidateNumOutputs(workloadInfo, "AdditionQueueDescriptor", 1);
telsoa014fcda012018-03-09 14:13:49 +0000654
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100655 std::vector<DataType> supportedTypes = {
656 DataType::Float32,
Sadik Armagan2999a022019-04-09 14:20:12 +0100657 DataType::QuantisedAsymm8,
Jim Flynn82fbe7c2019-04-02 15:19:08 +0100658 DataType::QuantisedSymm16,
659 DataType::Float16
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100660 };
661
662 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
663 supportedTypes,
664 "AdditionQueueDescriptor");
665
666 ValidateDataTypes(workloadInfo.m_InputTensorInfos[1],
667 supportedTypes,
668 "AdditionQueueDescriptor");
669
670 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
671 supportedTypes,
672 "AdditionQueueDescriptor");
673
telsoa014fcda012018-03-09 14:13:49 +0000674 ValidateBroadcastTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
675 workloadInfo.m_InputTensorInfos[1],
676 workloadInfo.m_OutputTensorInfos[0],
677 "AdditionQueueDescriptor",
678 "first input",
679 "second input");
telsoa014fcda012018-03-09 14:13:49 +0000680}
681
682//---------------------------------------------------------------
683void MultiplicationQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
684{
Sadik Armaganeff363d2019-04-05 15:25:46 +0100685 ValidateNumInputs(workloadInfo, "MultiplicationQueueDescriptor", 2);
686 ValidateNumOutputs(workloadInfo, "MultiplicationQueueDescriptor", 1);
surmeh01bceff2f2018-03-29 16:29:27 +0100687
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100688 std::vector<DataType> supportedTypes = {
689 DataType::Float32,
Sadik Armagan2999a022019-04-09 14:20:12 +0100690 DataType::QuantisedAsymm8,
Jim Flynn82fbe7c2019-04-02 15:19:08 +0100691 DataType::QuantisedSymm16,
692 DataType::Float16
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +0100693 };
694
695 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
696 supportedTypes,
697 "MultiplicationQueueDescriptor");
698
699 ValidateDataTypes(workloadInfo.m_InputTensorInfos[1],
700 supportedTypes,
701 "MultiplicationQueueDescriptor");
702
703 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
704 supportedTypes,
705 "MultiplicationQueueDescriptor");
706
surmeh01bceff2f2018-03-29 16:29:27 +0100707 ValidateBroadcastTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
708 workloadInfo.m_InputTensorInfos[1],
709 workloadInfo.m_OutputTensorInfos[0],
710 "MultiplicationQueueDescriptor",
711 "first input",
712 "second input");
telsoa014fcda012018-03-09 14:13:49 +0000713}
714
715void BatchNormalizationQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
716{
Sadik Armaganeff363d2019-04-05 15:25:46 +0100717 ValidateNumInputs(workloadInfo, "BatchNormalizationQueueDescriptor", 1);
718 ValidateNumOutputs(workloadInfo, "BatchNormalizationQueueDescriptor", 1);
Matteo Martincigh3122bd52019-06-03 16:54:25 +0100719
720 const TensorInfo& input = workloadInfo.m_InputTensorInfos[0];
721 const TensorInfo& output = workloadInfo.m_OutputTensorInfos[0];
722
723 std::vector<DataType> supportedTypes =
724 {
725 DataType::Float16,
726 DataType::Float32,
Matteo Martincighf5507132019-06-04 10:59:47 +0100727 DataType::QuantisedAsymm8,
728 DataType::QuantisedSymm16
Matteo Martincigh3122bd52019-06-03 16:54:25 +0100729 };
730
731 ValidateDataTypes(input, supportedTypes, "BatchNormalizationQueueDescriptor");
732 ValidateDataTypes(output, supportedTypes, "BatchNormalizationQueueDescriptor");
733
734 ValidateDataTypes(output, { input.GetDataType() }, "BatchNormalizationQueueDescriptor");
735
736 ValidateTensorQuantizationSpace(input, output, "BatchNormalizationQueueDescriptor", "input", "output");
737
telsoa014fcda012018-03-09 14:13:49 +0000738 ValidateTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
739 workloadInfo.m_OutputTensorInfos[0],
740 "BatchNormalizationQueueDescriptor",
741 "input",
742 "output");
Matteo Martincigh3122bd52019-06-03 16:54:25 +0100743
744 ValidatePointer(m_Mean, "BatchNormalizationQueueDescriptor", "mean");
telsoa014fcda012018-03-09 14:13:49 +0000745 ValidatePointer(m_Variance, "BatchNormalizationQueueDescriptor", "variance");
Matteo Martincigh3122bd52019-06-03 16:54:25 +0100746 ValidatePointer(m_Beta, "BatchNormalizationQueueDescriptor", "beta");
747 ValidatePointer(m_Gamma, "BatchNormalizationQueueDescriptor", "gamma");
telsoa014fcda012018-03-09 14:13:49 +0000748
Matteo Martincigh3122bd52019-06-03 16:54:25 +0100749 const TensorInfo& mean = m_Mean->GetTensorInfo();
750 const TensorInfo& variance = m_Variance->GetTensorInfo();
751 const TensorInfo& beta = m_Beta->GetTensorInfo();
752 const TensorInfo& gamma = m_Gamma->GetTensorInfo();
telsoa014fcda012018-03-09 14:13:49 +0000753
Matteo Martincigh3122bd52019-06-03 16:54:25 +0100754 ValidateTensorNumDimensions(mean, "BatchNormalizationQueueDescriptor", 1, "mean");
755 ValidateTensorNumDimensions(variance, "BatchNormalizationQueueDescriptor", 1, "variance");
756 ValidateTensorNumDimensions(beta, "BatchNormalizationQueueDescriptor", 1, "beta");
757 ValidateTensorNumDimensions(gamma, "BatchNormalizationQueueDescriptor", 1, "gamma");
telsoa014fcda012018-03-09 14:13:49 +0000758
Matteo Martincigh3122bd52019-06-03 16:54:25 +0100759 ValidateTensorShapesMatch(mean, variance, "BatchNormalizationQueueDescriptor", "mean", "variance");
760 ValidateTensorShapesMatch(mean, beta, "BatchNormalizationQueueDescriptor", "mean", "beta");
761 ValidateTensorShapesMatch(mean, gamma, "BatchNormalizationQueueDescriptor", "mean", "gamma");
telsoa014fcda012018-03-09 14:13:49 +0000762}
763
764void Convolution2dQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
765{
Sadik Armaganeff363d2019-04-05 15:25:46 +0100766 ValidateNumInputs(workloadInfo, "Convolution2dQueueDescriptor", 1);
767 ValidateNumOutputs(workloadInfo, "Convolution2dQueueDescriptor", 1);
telsoa014fcda012018-03-09 14:13:49 +0000768
769 ValidateTensorNumDimensions(workloadInfo.m_InputTensorInfos[0], "Convolution2dQueueDescriptor", 4, "input");
770 ValidateTensorNumDimensions(workloadInfo.m_OutputTensorInfos[0], "Convolution2dQueueDescriptor", 4, "output");
771
772 ValidatePointer(m_Weight, "Convolution2dQueueDescriptor", "weight");
773 ValidateTensorNumDimensions(m_Weight->GetTensorInfo(), "Convolution2dQueueDescriptor", 4, "weight");
774 ValidateTensorDataType(m_Weight->GetTensorInfo(), workloadInfo.m_InputTensorInfos[0].GetDataType(),
775 "Convolution2dQueueDescriptor", "weight");
776 if (m_Parameters.m_BiasEnabled)
777 {
778 ValidateTensorNumDimensions(m_Bias->GetTensorInfo(), "Convolution2dQueueDescriptor", 1, "bias");
779 ValidateTensorDataType(m_Bias->GetTensorInfo(),
780 GetBiasDataType(workloadInfo.m_InputTensorInfos[0].GetDataType()),
781 "Convolution2dQueueDescriptor", "bias");
782 ValidateBiasTensorQuantization(m_Bias->GetTensorInfo(),
783 workloadInfo.m_InputTensorInfos[0], m_Weight->GetTensorInfo(), "Convolution2dQueueDescriptor");
784 }
785
786 ValidateTensorQuantizationMultiplier(workloadInfo.m_InputTensorInfos[0], m_Weight->GetTensorInfo(),
787 workloadInfo.m_OutputTensorInfos[0], "Convolution2dQueueDescriptor", "input", "weights", "output");
788}
789
790void DepthwiseConvolution2dQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
791{
Sadik Armaganeff363d2019-04-05 15:25:46 +0100792 ValidateNumInputs(workloadInfo, "DepthwiseConvolution2dQueueDescriptor", 1);
793 ValidateNumOutputs(workloadInfo, "DepthwiseConvolution2dQueueDescriptor", 1);
telsoa014fcda012018-03-09 14:13:49 +0000794
795 ValidateTensorNumDimensions(
796 workloadInfo.m_InputTensorInfos[0], "DepthwiseConvolution2dQueueDescriptor", 4, "input");
797 ValidateTensorNumDimensions(
798 workloadInfo.m_OutputTensorInfos[0], "DepthwiseConvolution2dQueueDescriptor", 4, "output");
799
800 ValidatePointer(m_Weight, "DepthwiseConvolution2dQueueDescriptor", "weight");
801 ValidateTensorNumDimensions(m_Weight->GetTensorInfo(), "DepthwiseConvolution2dQueueDescriptor", 4, "weight");
802
Bruno Goncalves22972f02019-04-26 21:03:24 -0300803 if (m_Parameters.m_DilationX < 1 || m_Parameters.m_DilationY < 1 )
804 {
805 throw InvalidArgumentException(
806 boost::str(boost::format("DepthwiseConvolution2dQueueDescriptor: dilationX (provided %1%) "
807 "and dilationY (provided %2%) cannot be smaller than 1.")
808 % m_Parameters.m_DilationX % m_Parameters.m_DilationX));
809 }
810
Nikhil Rajcec6b652018-10-12 13:51:57 +0100811 const unsigned int channelIndex = (m_Parameters.m_DataLayout == DataLayout::NCHW) ? 1 : 3;
812
Matteo Martincigh747ef822018-12-18 09:26:39 +0000813 // Expected weight shape: [ M, I, H, W ] - This shape does NOT depend on the data layout
814 // inputChannels * channelMultiplier should be equal to outputChannels.
telsoa014fcda012018-03-09 14:13:49 +0000815 const unsigned int numWeightChannelMultiplier = m_Weight->GetTensorInfo().GetShape()[0];
Matteo Martincigh747ef822018-12-18 09:26:39 +0000816 const unsigned int numWeightInputChannels = m_Weight->GetTensorInfo().GetShape()[1];
Nikhil Rajcec6b652018-10-12 13:51:57 +0100817 const unsigned int numWeightOutputChannels = workloadInfo.m_OutputTensorInfos[0].GetShape()[channelIndex];
telsoa014fcda012018-03-09 14:13:49 +0000818 if (numWeightChannelMultiplier * numWeightInputChannels != numWeightOutputChannels)
819 {
820 throw InvalidArgumentException(
821 boost::str(boost::format("DepthwiseConvolution2dQueueDescriptor: output_channels (provided %1%) should be "
822 "equal to input_channels (provided %2%) multiplied by channel_multiplier "
823 "(provided %3%).")
824 % numWeightOutputChannels % numWeightInputChannels % numWeightChannelMultiplier));
825 }
826
827 if (m_Parameters.m_BiasEnabled)
828 {
829 ValidatePointer(m_Bias, "DepthwiseConvolution2dQueueDescriptor", "bias");
830 ValidateTensorNumDimensions(m_Bias->GetTensorInfo(), "DepthwiseConvolution2dQueueDescriptor", 1, "bias");
831 ValidateBiasTensorQuantization(m_Bias->GetTensorInfo(),
832 workloadInfo.m_InputTensorInfos[0], m_Weight->GetTensorInfo(), "DepthwiseConvolution2dQueueDescriptor");
833
834 ValidateTensorDataType(m_Bias->GetTensorInfo(),
835 GetBiasDataType(workloadInfo.m_InputTensorInfos[0].GetDataType()),
836 "DepthwiseConvolution2dQueueDescriptor", "bias");
837 }
838
839 ValidateTensorQuantizationMultiplier(workloadInfo.m_InputTensorInfos[0], m_Weight->GetTensorInfo(),
840 workloadInfo.m_OutputTensorInfos[0], "DepthwiseConvolution2dQueueDescriptor", "input", "weights", "output");
Ruomei Yan88d44b82019-05-23 14:29:06 +0100841
842 // Check the supported data types
843 std::vector<DataType> supportedTypes = {
844 DataType::Float32,
845 DataType::QuantisedAsymm8,
846 DataType::QuantisedSymm16,
847 DataType::Float16
848 };
849
850 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
851 supportedTypes,
852 "DepthwiseConvolution2dQueueDescriptor");
853
854 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
855 {workloadInfo.m_InputTensorInfos[0].GetDataType()},
856 "DepthwiseConvolution2dQueueDescriptor");
telsoa014fcda012018-03-09 14:13:49 +0000857}
858
859void PermuteQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
860{
Sadik Armaganeff363d2019-04-05 15:25:46 +0100861 ValidateNumInputs(workloadInfo, "PermuteQueueDescriptor", 1);
862 ValidateNumOutputs(workloadInfo, "PermuteQueueDescriptor", 1);
telsoa014fcda012018-03-09 14:13:49 +0000863
864 const PermutationVector& mapping = m_Parameters.m_DimMappings;
865
866 const TensorInfo& input = workloadInfo.m_InputTensorInfos[0];
867 const TensorInfo& output = workloadInfo.m_OutputTensorInfos[0];
868
869 ValidateTensorNumDimensions(input, "PermuteQueueDescriptor", mapping.GetSize(), "input");
870 ValidateTensorNumDimensions(output, "PermuteQueueDescriptor", mapping.GetSize(), "output");
871
872 for (unsigned int i = 0; i < mapping.GetSize(); ++i)
873 {
874 if (input.GetShape()[i] != output.GetShape()[mapping[i]])
875 {
876 throw InvalidArgumentException("PermuteQueueDescriptor: src dimension " + to_string(i) +
877 " (=" + to_string(input.GetShape()[i]) + ") " +
878 "must match dst dimension " + to_string(mapping[i]) +
879 " (=" + to_string(output.GetShape()[mapping[i]]) + ")");
880 }
881 }
882}
883
884void Pooling2dQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
885{
Sadik Armaganeff363d2019-04-05 15:25:46 +0100886 ValidateNumInputs(workloadInfo, "Pooling2dQueueDescriptor", 1);
887 ValidateNumOutputs(workloadInfo, "Pooling2dQueueDescriptor", 1);
telsoa014fcda012018-03-09 14:13:49 +0000888
889 ValidateTensorNumDimensions(workloadInfo.m_InputTensorInfos[0], "Pooling2dQueueDescriptor", 4, "input");
890 ValidateTensorNumDimensions(workloadInfo.m_OutputTensorInfos[0], "Pooling2dQueueDescriptor", 4, "output");
Teresa Charlina3b20472019-06-06 11:12:32 +0100891
892 std::vector<DataType> supportedTypes =
893 {
894 DataType::Float32,
895 DataType::Float16,
Teresa Charlin0434df62019-06-06 13:40:35 +0100896 DataType::QuantisedAsymm8,
897 DataType::QuantisedSymm16
Teresa Charlina3b20472019-06-06 11:12:32 +0100898 };
899
900 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
901 supportedTypes,
902 "Pooling2dQueueDescriptor");
903
904 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
905 {workloadInfo.m_InputTensorInfos[0].GetDataType()},
906 "Pooling2dQueueDescriptor");
telsoa014fcda012018-03-09 14:13:49 +0000907}
908
909void ResizeBilinearQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
910{
Sadik Armaganeff363d2019-04-05 15:25:46 +0100911 ValidateNumInputs(workloadInfo, "ResizeBilinearQueueDescriptor", 1);
912 ValidateNumOutputs(workloadInfo, "ResizeBilinearQueueDescriptor", 1);
telsoa014fcda012018-03-09 14:13:49 +0000913
914 ValidateTensorNumDimensions(workloadInfo.m_InputTensorInfos[0], "ResizeBilinearQueueDescriptor", 4, "input");
915 ValidateTensorNumDimensions(workloadInfo.m_OutputTensorInfos[0], "ResizeBilinearQueueDescriptor", 4, "output");
916
Ellen Norris-Thompson3cb85f32019-06-17 11:32:49 +0100917 std::vector<DataType> supportedTypes =
918 {
919 DataType::Float16,
920 DataType::Float32,
921 DataType::QuantisedAsymm8,
922 DataType::QuantisedSymm16
923 };
924
925 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
926 supportedTypes,
927 "ResizeBilinearQueueDescriptor");
928
929 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
930 {workloadInfo.m_InputTensorInfos[0].GetDataType()},
931 "ResizeBilinearQueueDescriptor");
932
telsoa01c577f2c2018-08-31 09:22:23 +0100933 // Resizes bilinear only changes width and height: batch and channel count must match.
telsoa014fcda012018-03-09 14:13:49 +0000934 {
935 const unsigned int inputBatchSize = workloadInfo.m_InputTensorInfos[0].GetShape()[0];
936 const unsigned int outputBatchSize = workloadInfo.m_OutputTensorInfos[0].GetShape()[0];
937 if (inputBatchSize != outputBatchSize)
938 {
939 throw InvalidArgumentException(
940 boost::str(boost::format("ResizeBilinearQueueDescriptor: Input batch size (%1%) "
941 "does not match output batch size (%2%)") % inputBatchSize % outputBatchSize));
942 }
943 }
944
945 {
Matthew Bentham8800c002018-11-19 13:19:28 +0000946 DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
James Conroy59540822018-10-11 12:39:05 +0100947 const unsigned int inputChannelCount =
Matthew Bentham8800c002018-11-19 13:19:28 +0000948 workloadInfo.m_InputTensorInfos[0].GetShape()[dimensionIndices.GetChannelsIndex()];
James Conroy59540822018-10-11 12:39:05 +0100949 const unsigned int outputChannelCount =
Matthew Bentham8800c002018-11-19 13:19:28 +0000950 workloadInfo.m_OutputTensorInfos[0].GetShape()[dimensionIndices.GetChannelsIndex()];
telsoa014fcda012018-03-09 14:13:49 +0000951 if (inputChannelCount != outputChannelCount)
952 {
953 throw InvalidArgumentException(
954 boost::str(boost::format("ResizeBilinearQueueDescriptor: Input channel count (%1%) "
955 "does not match output channel count (%2%)") % inputChannelCount % outputChannelCount));
956 }
957 }
958}
959
960void FakeQuantizationQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
961{
Sadik Armaganeff363d2019-04-05 15:25:46 +0100962 ValidateNumInputs(workloadInfo, "FakeQuantizationQueueDescriptor", 1);
963 ValidateNumOutputs(workloadInfo, "FakeQuantizationQueueDescriptor", 1);
telsoa014fcda012018-03-09 14:13:49 +0000964
965 ValidateTensorNumDimensions(workloadInfo.m_InputTensorInfos[0], "FakeQuantizationQueueDescriptor", 2, "input");
966 ValidateTensorNumDimensions(workloadInfo.m_OutputTensorInfos[0], "FakeQuantizationQueueDescriptor", 2, "output");
967 ValidateTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
968 workloadInfo.m_OutputTensorInfos[0],
969 "FakeQuantizationQueueDescriptor",
970 "input",
971 "output");
972 if (m_Parameters.m_Min > m_Parameters.m_Max)
973 {
974 throw InvalidArgumentException("FakeQuantizationQueueDescriptor: min cannot be greater than max");
975 }
976
977}
978
979void L2NormalizationQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
980{
Ferran Balaguerd73d14f2019-06-10 10:29:54 +0100981 const std::string& descriptorName = "L2NormalizationQueueDescriptor";
telsoa014fcda012018-03-09 14:13:49 +0000982
Ferran Balaguerd73d14f2019-06-10 10:29:54 +0100983 ValidateNumInputs(workloadInfo, descriptorName, 1);
984 ValidateNumOutputs(workloadInfo, descriptorName, 1);
985
986 ValidateTensorNumDimensions(workloadInfo.m_InputTensorInfos[0], descriptorName, 4, "input");
987 ValidateTensorNumDimensions(workloadInfo.m_OutputTensorInfos[0], descriptorName, 4, "output");
telsoa014fcda012018-03-09 14:13:49 +0000988 ValidateTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
989 workloadInfo.m_OutputTensorInfos[0],
Ferran Balaguerd73d14f2019-06-10 10:29:54 +0100990 descriptorName,
telsoa014fcda012018-03-09 14:13:49 +0000991 "input",
992 "output");
Ferran Balaguerd73d14f2019-06-10 10:29:54 +0100993
994 // Check the supported data types
995 std::vector<DataType> supportedTypes =
996 {
997 DataType::Float32,
998 DataType::Float16,
999 DataType::QuantisedAsymm8,
1000 DataType::QuantisedSymm16
1001 };
1002
1003 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0], supportedTypes, descriptorName);
1004 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0], supportedTypes, descriptorName);
1005 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
1006 {workloadInfo.m_InputTensorInfos[0].GetDataType()}, descriptorName);
telsoa014fcda012018-03-09 14:13:49 +00001007}
1008
1009void ConstantQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1010{
Sadik Armaganeff363d2019-04-05 15:25:46 +01001011 ValidateNumInputs(workloadInfo, "ConstantQueueDescriptor", 0);
1012 ValidateNumOutputs(workloadInfo, "ConstantQueueDescriptor", 1);
telsoa014fcda012018-03-09 14:13:49 +00001013
1014 if (!m_LayerOutput)
1015 {
1016 throw InvalidArgumentException("ConstantQueueDescriptor: No const input specified");
1017 }
1018
1019 ValidateTensorShapesMatch(m_LayerOutput->GetTensorInfo(),
1020 workloadInfo.m_OutputTensorInfos[0],
1021 "ConstantQueueDescriptor",
1022 "constant",
1023 "output");
Nina Drozd58ef2c62019-05-16 12:09:18 +01001024
1025 // Check the supported data types
1026 std::vector<DataType> supportedTypes =
Nina Drozd2f2778f2019-05-27 10:37:05 +01001027 {
1028 DataType::Float32,
1029 DataType::Float16,
1030 DataType::Signed32,
1031 DataType::QuantisedAsymm8,
1032 DataType::QuantisedSymm16
1033 };
Nina Drozd58ef2c62019-05-16 12:09:18 +01001034
1035 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0], supportedTypes, "ConstantQueueDescriptor");
telsoa014fcda012018-03-09 14:13:49 +00001036}
1037
1038void ReshapeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1039{
Sadik Armaganeff363d2019-04-05 15:25:46 +01001040 ValidateNumInputs(workloadInfo, "ReshapeQueueDescriptor", 1);
1041 ValidateNumOutputs(workloadInfo, "ReshapeQueueDescriptor", 1);
telsoa014fcda012018-03-09 14:13:49 +00001042
1043 if (workloadInfo.m_InputTensorInfos[0].GetNumElements() != workloadInfo.m_OutputTensorInfos[0].GetNumElements())
1044 {
1045 throw InvalidArgumentException("ReshapeQueueDescriptor: Input tensor has " +
1046 to_string(workloadInfo.m_InputTensorInfos[0].GetNumElements()) + " but output tensor has " +
1047 to_string(workloadInfo.m_OutputTensorInfos[0].GetNumElements()) + " elements.");
1048 }
Nina Drozd2f2778f2019-05-27 10:37:05 +01001049
1050 // Check the supported data types
1051 std::vector<DataType> supportedTypes =
1052 {
1053 DataType::Float32,
1054 DataType::Float16,
Nina Drozd8ed4b8c2019-05-29 10:41:04 +01001055 DataType::QuantisedAsymm8,
1056 DataType::QuantisedSymm16
Nina Drozd2f2778f2019-05-27 10:37:05 +01001057 };
1058
1059 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0], supportedTypes, "ReshapeQueueDescriptor");
1060 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0], supportedTypes, "ReshapeQueueDescriptor");
telsoa014fcda012018-03-09 14:13:49 +00001061}
1062
Nattapat Chaimanowong207ef9a2018-11-02 10:57:25 +00001063void SpaceToBatchNdQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1064{
Sadik Armaganeff363d2019-04-05 15:25:46 +01001065 ValidateNumInputs(workloadInfo, "SpaceToBatchNdQueueDescriptor", 1);
1066 ValidateNumOutputs(workloadInfo, "SpaceToBatchNdQueueDescriptor", 1);
Nattapat Chaimanowong207ef9a2018-11-02 10:57:25 +00001067
1068 ValidateTensorNumDimensions(workloadInfo.m_InputTensorInfos[0], "SpaceToBatchNdQueueDescriptor", 4, "input");
1069 ValidateTensorNumDimensions(workloadInfo.m_OutputTensorInfos[0], "SpaceToBatchNdQueueDescriptor", 4, "output");
1070
Nattapat Chaimanowong207ef9a2018-11-02 10:57:25 +00001071 if (m_Parameters.m_BlockShape.size() != 2)
1072 {
Nattapat Chaimanowong3ea76d52018-11-09 14:10:38 +00001073 throw InvalidArgumentException("Block Shape must contain 2 spatial dimensions");
Nattapat Chaimanowong207ef9a2018-11-02 10:57:25 +00001074 }
1075
1076 if (m_Parameters.m_BlockShape.size() != m_Parameters.m_PadList.size())
1077 {
Nattapat Chaimanowong3ea76d52018-11-09 14:10:38 +00001078 throw InvalidArgumentException("Pad List must contain the same number of dimensions as Block Shape.");
Nattapat Chaimanowong207ef9a2018-11-02 10:57:25 +00001079 }
1080
1081 const TensorShape inputShape = workloadInfo.m_InputTensorInfos[0].GetShape();
1082
1083 std::pair<unsigned int, unsigned int> heightPad = m_Parameters.m_PadList[0];
1084 std::pair<unsigned int, unsigned int> widthPad = m_Parameters.m_PadList[1];
1085
Matthew Bentham8800c002018-11-19 13:19:28 +00001086 DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
1087 unsigned int inputHeight = inputShape[dimensionIndices.GetHeightIndex()]
Nattapat Chaimanowong3ea76d52018-11-09 14:10:38 +00001088 + heightPad.first + heightPad.second;
1089
Matthew Bentham8800c002018-11-19 13:19:28 +00001090 unsigned int inputWidth = inputShape[dimensionIndices.GetWidthIndex()]
Nattapat Chaimanowong3ea76d52018-11-09 14:10:38 +00001091 + widthPad.first + widthPad.second;
1092
1093 unsigned int numInputElements = inputShape[0] * inputHeight * inputWidth
Matthew Bentham8800c002018-11-19 13:19:28 +00001094 * inputShape[dimensionIndices.GetChannelsIndex()];
Nattapat Chaimanowong3ea76d52018-11-09 14:10:38 +00001095
1096 if (workloadInfo.m_OutputTensorInfos[0].GetNumElements() != numInputElements)
1097 {
1098 throw InvalidArgumentException("SpaceToBatchNdQueueDescriptor: Input tensor has " +
1099 to_string(numInputElements) + " after padding but output tensor has " +
1100 to_string(workloadInfo.m_OutputTensorInfos[0].GetNumElements()) + " elements.");
1101 }
1102
1103 if (inputHeight % m_Parameters.m_BlockShape[0] != 0 || inputWidth % m_Parameters.m_BlockShape[1] != 0)
Nattapat Chaimanowong207ef9a2018-11-02 10:57:25 +00001104 {
1105 throw InvalidArgumentException(
1106 "Input shape after padding must be divisible by Block Shape in all spatial dimensions");
1107 }
nikraj01120522a2019-05-31 11:33:07 +01001108
1109 std::vector<DataType> supportedTypes =
1110 {
1111 DataType::Float16,
1112 DataType::Float32,
1113 DataType::QuantisedAsymm8,
1114 DataType::QuantisedSymm16
1115 };
1116
1117 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
1118 supportedTypes,
1119 "SpaceToBatchNdQueueDescriptor");
1120
1121 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
1122 {workloadInfo.m_InputTensorInfos[0].GetDataType()},
1123 "SpaceToBatchNdQueueDescriptor");
Nattapat Chaimanowong207ef9a2018-11-02 10:57:25 +00001124}
1125
Keith Davisa57eccb2019-06-14 17:33:22 +01001126void SpaceToDepthQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1127{
1128 ValidateNumInputs(workloadInfo, "SpaceToDepthQueueDescriptor", 1);
1129 ValidateNumOutputs(workloadInfo, "SpaceToDepthQueueDescriptor", 1);
1130
1131 ValidateTensorNumDimensions(workloadInfo.m_InputTensorInfos[0],
1132 "SpaceToDepthQueueDescriptor", 4, "input");
1133 ValidateTensorNumDimensions(workloadInfo.m_OutputTensorInfos[0],
1134 "SpaceToDepthQueueDescriptor", 4, "output");
1135
1136 DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout);
1137
1138 std::vector<DataType> supportedTypes =
1139 {
1140 DataType::Float32,
1141 DataType::Float16,
1142 DataType::QuantisedAsymm8
1143 };
1144
1145 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
1146 supportedTypes,
1147 "SpaceToDepthQueueDescriptor");
1148 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
1149 supportedTypes,
1150 "SpaceToDepthQueueDescriptor");
1151
1152 const TensorShape inputShape = workloadInfo.m_InputTensorInfos[0].GetShape();
1153
1154 unsigned int numInputElements = inputShape[0]
1155 * inputShape[dimensionIndices.GetWidthIndex()]
1156 * inputShape[dimensionIndices.GetHeightIndex()]
1157 * inputShape[dimensionIndices.GetChannelsIndex()];
1158
1159 if (workloadInfo.m_OutputTensorInfos[0].GetNumElements() != numInputElements)
1160 {
1161 throw InvalidArgumentException("SpaceToDepthQueueDescriptor: Input tensor has " +
1162 to_string(numInputElements) + " but output tensor has " +
1163 to_string(workloadInfo.m_OutputTensorInfos[0].GetNumElements()) + " elements.");
1164 }
1165
1166 if (inputShape[dimensionIndices.GetHeightIndex()] % m_Parameters.m_BlockSize != 0 ||
1167 inputShape[dimensionIndices.GetWidthIndex()] % m_Parameters.m_BlockSize != 0)
1168 {
1169 throw InvalidArgumentException(
1170 "Input shape must be divisible by block size in all spatial dimensions");
1171 }
1172}
1173
telsoa014fcda012018-03-09 14:13:49 +00001174void FloorQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1175{
James Conroy83735b12019-05-30 16:36:59 +01001176 const std::string floorQueueDescString = "FloorQueueDescriptor";
1177
1178 ValidateNumInputs(workloadInfo, floorQueueDescString, 1);
1179 ValidateNumOutputs(workloadInfo, floorQueueDescString, 1);
1180
1181 std::vector<DataType> supportedTypes =
1182 {
James Conroyb40d7102019-06-04 12:32:09 +01001183 DataType::Float32,
1184 DataType::QuantisedSymm16
James Conroy83735b12019-05-30 16:36:59 +01001185 };
1186
1187 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0], supportedTypes, floorQueueDescString);
1188 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0], supportedTypes, floorQueueDescString);
telsoa014fcda012018-03-09 14:13:49 +00001189
1190 if (workloadInfo.m_InputTensorInfos[0] != workloadInfo.m_OutputTensorInfos[0])
1191 {
James Conroy83735b12019-05-30 16:36:59 +01001192 throw InvalidArgumentException(floorQueueDescString + ": Input and output tensor infos do not match.");
telsoa014fcda012018-03-09 14:13:49 +00001193 }
1194}
1195
telsoa01c577f2c2018-08-31 09:22:23 +01001196void LstmQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1197{
1198 ValidateTensorNumDimensions(workloadInfo.m_InputTensorInfos[0], "LstmQueueDescriptor", 2, "input");
1199 ValidateTensorNumDimensions(workloadInfo.m_OutputTensorInfos[0], "LstmQueueDescriptor", 2, "output");
Nattapat Chaimanowongeb2b3292019-05-07 12:02:30 +01001200
1201 std::vector<DataType> supportedTypes = {
Conor Kennedyb9971c92019-05-07 07:14:23 +01001202 DataType::Float16,
Nattapat Chaimanowongeb2b3292019-05-07 12:02:30 +01001203 DataType::Float32,
Conor Kennedyb9971c92019-05-07 07:14:23 +01001204 DataType::QuantisedSymm16
Nattapat Chaimanowongeb2b3292019-05-07 12:02:30 +01001205 };
1206
1207 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
1208 supportedTypes,
1209 "LstmQueueDescriptor");
1210
1211 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
1212 supportedTypes,
1213 "LstmQueueDescriptor");
telsoa01c577f2c2018-08-31 09:22:23 +01001214}
1215
1216void ConvertFp32ToFp16QueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1217{
Sadik Armaganeff363d2019-04-05 15:25:46 +01001218 ValidateNumInputs(workloadInfo, "ConvertFp32ToFp16QueueDescriptor", 1);
1219 ValidateNumOutputs(workloadInfo, "ConvertFp32ToFp16QueueDescriptor", 1);
telsoa01c577f2c2018-08-31 09:22:23 +01001220
1221 if (workloadInfo.m_InputTensorInfos[0].GetDataType() != DataType::Float32)
1222 {
1223 throw InvalidArgumentException("ConvertFp32ToFp16QueueDescriptor: Input tensor type must be Float32.");
1224 }
1225
1226 if (workloadInfo.m_OutputTensorInfos[0].GetDataType() != DataType::Float16)
1227 {
1228 throw InvalidArgumentException("ConvertFp32ToFp16QueueDescriptor: Output tensor type must be Float16.");
1229 }
1230
1231 ValidateTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
1232 workloadInfo.m_OutputTensorInfos[0],
1233 "ConvertFp32ToFp16QueueDescriptor",
1234 "input",
1235 "output");
1236}
1237
1238void ConvertFp16ToFp32QueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1239{
Sadik Armaganeff363d2019-04-05 15:25:46 +01001240 ValidateNumInputs(workloadInfo, "ConvertFp16ToFp32QueueDescriptor", 1);
1241 ValidateNumOutputs(workloadInfo, "ConvertFp16ToFp32QueueDescriptor", 1);
telsoa01c577f2c2018-08-31 09:22:23 +01001242
1243 if (workloadInfo.m_InputTensorInfos[0].GetDataType() != DataType::Float16)
1244 {
1245 throw InvalidArgumentException("ConvertFp16ToFp32QueueDescriptor: Input tensor type must be Float16.");
1246 }
1247 if (workloadInfo.m_OutputTensorInfos[0].GetDataType() != DataType::Float32)
1248 {
1249 throw InvalidArgumentException("ConvertFp16ToFp32QueueDescriptor: Output tensor type must be Float32.");
1250 }
1251
1252 ValidateTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
1253 workloadInfo.m_OutputTensorInfos[0],
1254 "ConvertFp16ToFp32QueueDescriptor",
1255 "input",
1256 "output");
1257}
1258
Francis Murtaghe7a86a42018-08-29 12:42:10 +01001259void DivisionQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1260{
Sadik Armaganeff363d2019-04-05 15:25:46 +01001261 ValidateNumInputs(workloadInfo, "DivisionQueueDescriptor", 2);
1262 ValidateNumOutputs(workloadInfo, "DivisionQueueDescriptor", 1);
Francis Murtaghe7a86a42018-08-29 12:42:10 +01001263
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01001264 std::vector<DataType> supportedTypes = {
1265 DataType::Float32,
Sadik Armagan2999a022019-04-09 14:20:12 +01001266 DataType::QuantisedAsymm8,
Jim Flynn82fbe7c2019-04-02 15:19:08 +01001267 DataType::QuantisedSymm16,
1268 DataType::Float16
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01001269 };
1270
1271 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
1272 supportedTypes,
1273 "DivisionQueueDescriptor");
1274
1275 ValidateDataTypes(workloadInfo.m_InputTensorInfos[1],
1276 supportedTypes,
1277 "DivisionQueueDescriptor");
1278
1279 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
1280 supportedTypes,
1281 "DivisionQueueDescriptor");
1282
Francis Murtaghe7a86a42018-08-29 12:42:10 +01001283 ValidateBroadcastTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
1284 workloadInfo.m_InputTensorInfos[1],
1285 workloadInfo.m_OutputTensorInfos[0],
1286 "DivisionQueueDescriptor",
1287 "first input",
1288 "second input");
1289}
1290
David Beckc2044fe2018-09-05 15:00:38 +01001291void SubtractionQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1292{
Sadik Armaganeff363d2019-04-05 15:25:46 +01001293 ValidateNumInputs(workloadInfo, "SubtractionQueueDescriptor", 2);
1294 ValidateNumOutputs(workloadInfo, "SubtractionQueueDescriptor", 1);
David Beckc2044fe2018-09-05 15:00:38 +01001295
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01001296 std::vector<DataType> supportedTypes = {
1297 DataType::Float32,
Sadik Armagan2999a022019-04-09 14:20:12 +01001298 DataType::QuantisedAsymm8,
Jim Flynn82fbe7c2019-04-02 15:19:08 +01001299 DataType::QuantisedSymm16,
1300 DataType::Float16
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01001301 };
1302
1303 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
1304 supportedTypes,
1305 "SubtractionQueueDescriptor");
1306
1307 ValidateDataTypes(workloadInfo.m_InputTensorInfos[1],
1308 supportedTypes,
1309 "SubtractionQueueDescriptor");
1310
1311 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
1312 supportedTypes,
1313 "SubtractionQueueDescriptor");
1314
David Beckc2044fe2018-09-05 15:00:38 +01001315 ValidateBroadcastTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
1316 workloadInfo.m_InputTensorInfos[1],
1317 workloadInfo.m_OutputTensorInfos[0],
1318 "SubtractionQueueDescriptor",
1319 "first input",
1320 "second input");
1321}
1322
Nattapat Chaimanowong5a4304a2018-11-28 10:44:37 +00001323void MaximumQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1324{
Sadik Armaganeff363d2019-04-05 15:25:46 +01001325 ValidateNumInputs(workloadInfo, "MaximumQueueDescriptor", 2);
1326 ValidateNumOutputs(workloadInfo, "MaximumQueueDescriptor", 1);
Nattapat Chaimanowong5a4304a2018-11-28 10:44:37 +00001327
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01001328 std::vector<DataType> supportedTypes = {
1329 DataType::Float32,
Sadik Armagan2999a022019-04-09 14:20:12 +01001330 DataType::QuantisedAsymm8,
1331 DataType::QuantisedSymm16
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01001332 };
1333
1334 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
1335 supportedTypes,
1336 "MaximumQueueDescriptor");
1337
1338 ValidateDataTypes(workloadInfo.m_InputTensorInfos[1],
1339 supportedTypes,
1340 "MaximumQueueDescriptor");
1341
1342 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
1343 supportedTypes,
1344 "MaximumQueueDescriptor");
1345
Nattapat Chaimanowong5a4304a2018-11-28 10:44:37 +00001346 ValidateBroadcastTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
1347 workloadInfo.m_InputTensorInfos[1],
1348 workloadInfo.m_OutputTensorInfos[0],
1349 "MaximumQueueDescriptor",
1350 "first input",
1351 "second input");
1352}
1353
narpra01a6bf9122018-09-10 09:50:09 +01001354void MeanQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1355{
James Conroy4d1ff582019-06-10 17:06:39 +01001356 const std::string meanQueueDescString = "MeanQueueDescriptor";
1357
1358 ValidateNumInputs(workloadInfo, meanQueueDescString, 1);
1359 ValidateNumOutputs(workloadInfo, meanQueueDescString, 1);
1360
1361 std::vector<DataType> supportedTypes =
1362 {
1363 DataType::Float32,
1364 DataType::Float16,
1365 DataType::QuantisedAsymm8,
1366 DataType::QuantisedSymm16
1367 };
narpra01eb061912018-09-10 17:35:27 +01001368
1369 const TensorInfo& input = workloadInfo.m_InputTensorInfos[0];
1370 const TensorInfo& output = workloadInfo.m_OutputTensorInfos[0];
1371
James Conroy4d1ff582019-06-10 17:06:39 +01001372 // First check if input tensor data type is supported, then
1373 // check if this data type matches the output tensor data type
1374 ValidateDataTypes(input, supportedTypes, meanQueueDescString);
1375 ValidateTensorDataTypesMatch(input, output, meanQueueDescString, "input", "output");
1376
narpra0132b90462018-09-13 11:07:48 +01001377 if (m_Parameters.m_KeepDims)
narpra01eb061912018-09-10 17:35:27 +01001378 {
James Conroy4d1ff582019-06-10 17:06:39 +01001379 ValidateTensorNumDimensions(output, meanQueueDescString, input.GetNumDimensions(), "output");
narpra01eb061912018-09-10 17:35:27 +01001380 }
narpra0132b90462018-09-13 11:07:48 +01001381 else if (m_Parameters.m_Axis.empty())
narpra01eb061912018-09-10 17:35:27 +01001382 {
James Conroy4d1ff582019-06-10 17:06:39 +01001383 ValidateTensorNumDimensions(output, meanQueueDescString, 1, "output");
narpra01eb061912018-09-10 17:35:27 +01001384 }
1385 else
1386 {
narpra0132b90462018-09-13 11:07:48 +01001387 auto outputDim = input.GetNumDimensions() - boost::numeric_cast<unsigned int>(m_Parameters.m_Axis.size());
narpra01eb061912018-09-10 17:35:27 +01001388 ValidateTensorNumDimensions(output,
James Conroy4d1ff582019-06-10 17:06:39 +01001389 meanQueueDescString,
narpra01eb061912018-09-10 17:35:27 +01001390 outputDim > 0 ? outputDim : 1,
1391 "output");
1392 }
narpra01a6bf9122018-09-10 09:50:09 +01001393}
1394
jimfly012c9322a2018-09-19 10:59:49 +01001395void PadQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1396{
Sadik Armaganeff363d2019-04-05 15:25:46 +01001397 ValidateNumInputs(workloadInfo, "PadQueueDescriptor", 1);
1398 ValidateNumOutputs(workloadInfo, "PadQueueDescriptor", 1);
jimfly012c9322a2018-09-19 10:59:49 +01001399
1400 const TensorInfo& input = workloadInfo.m_InputTensorInfos[0];
Nina Drozd661dfa72018-10-02 11:14:17 +01001401 const TensorInfo& output = workloadInfo.m_OutputTensorInfos[0];
1402
jimfly012c9322a2018-09-19 10:59:49 +01001403 // input and output should have the same number of dimensions
1404 ValidateTensorNumDimensions(output, "PadQueueDescriptor", input.GetNumDimensions(), "output");
1405 // there should be entry in the pad list for each dimension in the input tensor
1406 if (m_Parameters.m_PadList.size() != input.GetNumDimensions()) {
1407 throw InvalidArgumentException("Pad List should contain the same number of entries as there"
1408 " are dimensions in the input tensor that is " +
1409 to_string(input.GetNumDimensions()) + " entries " +
1410 " not " + to_string(m_Parameters.m_PadList.size()) + " entries.");
1411 }
1412}
1413
Derek Lambertia9cca6a2019-03-25 15:41:58 +00001414void QuantizeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1415{
Sadik Armaganeff363d2019-04-05 15:25:46 +01001416 ValidateNumInputs(workloadInfo, "QuantizeQueueDescriptor", 1);
1417 ValidateNumOutputs(workloadInfo, "QuantizeQueueDescriptor", 1);
Derek Lambertia9cca6a2019-03-25 15:41:58 +00001418
1419
1420 if (workloadInfo.m_InputTensorInfos[0].GetDataType() != DataType::Float32)
1421 {
1422 throw InvalidArgumentException("Quantize only accepts Float32 inputs.");
1423 }
1424
1425 if (workloadInfo.m_OutputTensorInfos[0].GetDataType() != DataType::QuantisedAsymm8 &&
1426 workloadInfo.m_OutputTensorInfos[0].GetDataType() != DataType::QuantisedSymm16)
1427 {
1428 throw InvalidArgumentException("Output of quantized layer must be quantized type.");
1429 }
1430}
1431
Éanna Ó Catháin4e1e1362018-11-12 11:36:34 +00001432void BatchToSpaceNdQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1433{
Sadik Armaganeff363d2019-04-05 15:25:46 +01001434 ValidateNumInputs(workloadInfo, "BatchToSpaceNdQueueDescriptor", 1);
1435 ValidateNumOutputs(workloadInfo, "BatchToSpaceNdQueueDescriptor", 1);
Éanna Ó Catháin4e1e1362018-11-12 11:36:34 +00001436}
1437
Conor Kennedy430b5d82018-11-14 15:28:28 +00001438void StridedSliceQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1439{
Sadik Armaganeff363d2019-04-05 15:25:46 +01001440 ValidateNumInputs(workloadInfo, "StridedSliceQueueDescriptor", 1);
1441 ValidateNumOutputs(workloadInfo, "StridedSliceQueueDescriptor", 1);
Conor Kennedy430b5d82018-11-14 15:28:28 +00001442
1443 const TensorInfo& input = workloadInfo.m_InputTensorInfos[0];
Matteo Martincighe851b3d2019-05-28 14:31:20 +01001444 const TensorInfo& output = workloadInfo.m_OutputTensorInfos[0];
1445
1446 std::vector<DataType> supportedTypes =
1447 {
1448 DataType::Float16,
1449 DataType::Float32,
Matteo Martincigh42666a12019-05-29 08:53:41 +01001450 DataType::QuantisedAsymm8,
1451 DataType::QuantisedSymm16
Matteo Martincighe851b3d2019-05-28 14:31:20 +01001452 };
1453
1454 ValidateDataTypes(input, supportedTypes, "StridedSliceQueueDescriptor");
1455 ValidateDataTypes(output, supportedTypes, "StridedSliceQueueDescriptor");
1456
1457 ValidateDataTypes(output, { input.GetDataType() }, "StridedSliceQueueDescriptor");
1458
1459 ValidateTensorQuantizationSpace(input, output, "StridedSliceQueueDescriptor", "input", "output");
1460
Conor Kennedy430b5d82018-11-14 15:28:28 +00001461 const uint32_t rank = input.GetNumDimensions();
1462
Nattapat Chaimanowonga0d28442018-11-21 16:48:17 +00001463 if (rank > 4)
1464 {
1465 throw InvalidArgumentException(
1466 "StridedSliceLayer: Input tensors with rank greater than 4 are not supported");
1467 }
1468
Conor Kennedy430b5d82018-11-14 15:28:28 +00001469 // Begin, End & Stride length must be of rank(input0)
1470 if (m_Parameters.m_Begin.size() != rank)
1471 {
1472 throw InvalidArgumentException("StridedSliceLayer: Begin length must be of rank input0("
1473 + to_string(rank) + ")");
1474 }
1475
1476 if (m_Parameters.m_End.size() != rank)
1477 {
1478 throw InvalidArgumentException("StridedSliceLayer: End length must be of rank input0("
1479 + to_string(rank) + ")");
1480 }
1481
1482 if (m_Parameters.m_Stride.size() != rank)
1483 {
1484 throw InvalidArgumentException("StridedSliceLayer: Stride length must be of rank input0("
1485 + to_string(rank) + ")");
1486 }
1487
1488 // Stride entries must be non-zero
1489 for (auto& stride : m_Parameters.m_Stride)
1490 {
1491 if (stride == 0)
1492 {
1493 throw InvalidArgumentException("StridedSliceLayer: Stride entries must be non-zero");
1494 }
1495 }
1496}
1497
kevmay0190539692018-11-29 08:40:19 +00001498void MinimumQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1499{
Sadik Armaganeff363d2019-04-05 15:25:46 +01001500 ValidateNumInputs(workloadInfo, "MinimumQueueDescriptor", 2);
1501 ValidateNumOutputs(workloadInfo, "MinimumQueueDescriptor", 1);
kevmay0190539692018-11-29 08:40:19 +00001502
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01001503 std::vector<DataType> supportedTypes = {
1504 DataType::Float32,
Sadik Armagan2999a022019-04-09 14:20:12 +01001505 DataType::QuantisedAsymm8,
1506 DataType::QuantisedSymm16
Sadik Armagan2e6dc3a2019-04-03 17:48:18 +01001507 };
1508
1509 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
1510 supportedTypes,
1511 "MinimumQueueDescriptor");
1512
1513 ValidateDataTypes(workloadInfo.m_InputTensorInfos[1],
1514 supportedTypes,
1515 "MinimumQueueDescriptor");
1516
1517 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
1518 supportedTypes,
1519 "MinimumQueueDescriptor");
1520
kevmay0190539692018-11-29 08:40:19 +00001521 ValidateBroadcastTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
1522 workloadInfo.m_InputTensorInfos[1],
1523 workloadInfo.m_OutputTensorInfos[0],
1524 "MinimumQueueDescriptor",
1525 "first input",
1526 "second input");
1527}
1528
Nattapat Chaimanowonga9a1cf12018-12-03 16:06:49 +00001529void DebugQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1530{
Sadik Armaganeff363d2019-04-05 15:25:46 +01001531 ValidateNumInputs(workloadInfo, "DebugQueueDescriptor", 1);
1532 ValidateNumOutputs(workloadInfo, "DebugQueueDescriptor", 1);
Nattapat Chaimanowonga9a1cf12018-12-03 16:06:49 +00001533}
1534
FrancisMurtagh30cdfca2018-12-18 12:57:35 +00001535void EqualQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1536{
Sadik Armaganeff363d2019-04-05 15:25:46 +01001537 ValidateNumInputs(workloadInfo, "EqualQueueDescriptor", 2);
1538 ValidateNumOutputs(workloadInfo, "EqualQueueDescriptor", 1);
FrancisMurtagh30cdfca2018-12-18 12:57:35 +00001539
1540 ValidateBroadcastTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
1541 workloadInfo.m_InputTensorInfos[1],
1542 workloadInfo.m_OutputTensorInfos[0],
1543 "EqualQueueDescriptor",
1544 "first input",
1545 "second input");
kevmay012b4d88e2019-01-24 14:05:09 +00001546
1547 if (workloadInfo.m_OutputTensorInfos[0].GetDataType() != DataType::Boolean)
1548 {
1549 throw InvalidArgumentException("EqualQueueDescriptor: Output tensor type must be Boolean.");
1550 }
FrancisMurtagh30cdfca2018-12-18 12:57:35 +00001551}
1552
FrancisMurtagh878f0232018-12-19 10:56:15 +00001553void GreaterQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1554{
Sadik Armaganeff363d2019-04-05 15:25:46 +01001555 ValidateNumInputs(workloadInfo, "GreaterQueueDescriptor", 2);
1556 ValidateNumOutputs(workloadInfo, "GreaterQueueDescriptor", 1);
FrancisMurtagh878f0232018-12-19 10:56:15 +00001557
1558 ValidateBroadcastTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
1559 workloadInfo.m_InputTensorInfos[1],
1560 workloadInfo.m_OutputTensorInfos[0],
1561 "GreaterQueueDescriptor",
1562 "first input",
1563 "second input");
kevmay012b4d88e2019-01-24 14:05:09 +00001564
1565 if (workloadInfo.m_OutputTensorInfos[0].GetDataType() != DataType::Boolean)
1566 {
1567 throw InvalidArgumentException("GreaterQueueDescriptor: Output tensor type must be Boolean.");
1568 }
FrancisMurtagh878f0232018-12-19 10:56:15 +00001569}
1570
Mohamed Nour Abouelseouda1d3c6a2018-12-27 12:39:16 +00001571void RsqrtQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1572{
Sadik Armaganeff363d2019-04-05 15:25:46 +01001573 ValidateNumInputs(workloadInfo, "RsqrtQueueDescriptor", 1);
1574 ValidateNumOutputs(workloadInfo, "RsqrtQueueDescriptor", 1);
Mohamed Nour Abouelseouda1d3c6a2018-12-27 12:39:16 +00001575 ValidateTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
1576 workloadInfo.m_OutputTensorInfos[0],
1577 "RsqrtQueueDescriptor",
1578 "input",
1579 "output");
nikraj010421e7f2019-06-14 09:40:34 +01001580
1581 std::vector<DataType> supportedTypes =
1582 {
1583 DataType::Float16,
1584 DataType::Float32,
nikraj0124d73212019-06-14 14:20:40 +01001585 DataType::QuantisedAsymm8,
1586 DataType::QuantisedSymm16
nikraj010421e7f2019-06-14 09:40:34 +01001587 };
1588
1589 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
1590 supportedTypes,
1591 "RsqrtQueueDescriptor");
1592
1593 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
1594 {workloadInfo.m_InputTensorInfos[0].GetDataType()},
1595 "RsqrtQueueDescriptor");
Mohamed Nour Abouelseouda1d3c6a2018-12-27 12:39:16 +00001596}
1597
narpra01b89b05f2019-01-16 09:53:09 +00001598void GatherQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1599{
Sadik Armaganeff363d2019-04-05 15:25:46 +01001600 ValidateNumInputs(workloadInfo, "GatherQueueDescriptor", 2);
1601 ValidateNumOutputs(workloadInfo, "GatherQueueDescriptor", 1);
narpra014951d842019-01-18 16:53:53 +00001602
1603 const TensorInfo& indices = workloadInfo.m_InputTensorInfos[1];
1604
1605 if (indices.GetDataType() != DataType::Signed32)
1606 {
1607 throw InvalidArgumentException("GatherQueueDescriptor: Indices tensor type must be int32.");
1608 }
1609
1610 const TensorInfo& params = workloadInfo.m_InputTensorInfos[0];
1611 const TensorInfo& output = workloadInfo.m_OutputTensorInfos[0];
1612 unsigned int paramsDim = params.GetNumDimensions();
1613 unsigned int indicesDim = indices.GetNumDimensions();
1614 unsigned int outputDim = paramsDim - 1 + indicesDim;
1615
1616 ValidateTensorNumDimensions(output, "GatherQueueDescriptor", outputDim, "output");
narpra01b89b05f2019-01-16 09:53:09 +00001617}
1618
Narumol Prangnawaratbc67cef2019-01-31 15:31:54 +00001619void DetectionPostProcessQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1620{
Aron Virginas-Tar6331f912019-06-03 17:10:02 +01001621 const std::string& descriptorName = " DetectionPostProcessQueueDescriptor";
1622 ValidateNumInputs(workloadInfo, descriptorName, 2);
Narumol Prangnawaratbc67cef2019-01-31 15:31:54 +00001623
1624 if (workloadInfo.m_OutputTensorInfos.size() != 4)
1625 {
Aron Virginas-Tar6331f912019-06-03 17:10:02 +01001626 throw InvalidArgumentException(descriptorName + ": Requires exactly four outputs. " +
Narumol Prangnawaratbc67cef2019-01-31 15:31:54 +00001627 to_string(workloadInfo.m_OutputTensorInfos.size()) + " has been provided.");
1628 }
1629
1630 if (m_Anchors == nullptr)
1631 {
Aron Virginas-Tar6331f912019-06-03 17:10:02 +01001632 throw InvalidArgumentException(descriptorName + ": Anchors tensor descriptor is missing.");
Narumol Prangnawaratbc67cef2019-01-31 15:31:54 +00001633 }
1634
1635 const TensorInfo& boxEncodingsInfo = workloadInfo.m_InputTensorInfos[0];
Aron Virginas-Tar6331f912019-06-03 17:10:02 +01001636 const TensorInfo& scoresInfo = workloadInfo.m_InputTensorInfos[1];
1637 const TensorInfo& anchorsInfo = m_Anchors->GetTensorInfo();
1638
1639 const TensorInfo& detectionBoxesInfo = workloadInfo.m_OutputTensorInfos[0];
Narumol Prangnawarat6d302bf2019-02-04 11:46:26 +00001640 const TensorInfo& detectionClassesInfo = workloadInfo.m_OutputTensorInfos[1];
Aron Virginas-Tar6331f912019-06-03 17:10:02 +01001641 const TensorInfo& detectionScoresInfo = workloadInfo.m_OutputTensorInfos[2];
1642 const TensorInfo& numDetectionsInfo = workloadInfo.m_OutputTensorInfos[3];
Narumol Prangnawaratbc67cef2019-01-31 15:31:54 +00001643
Aron Virginas-Tar6331f912019-06-03 17:10:02 +01001644 ValidateTensorNumDimensions(boxEncodingsInfo, descriptorName, 3, "box encodings");
1645 ValidateTensorNumDimensions(scoresInfo, descriptorName, 3, "scores");
1646 ValidateTensorNumDimensions(anchorsInfo, descriptorName, 2, "anchors");
Narumol Prangnawaratbc67cef2019-01-31 15:31:54 +00001647
Aron Virginas-Tar6331f912019-06-03 17:10:02 +01001648 const std::vector<DataType> supportedInputTypes =
1649 {
1650 DataType::Float32,
1651 DataType::QuantisedAsymm8,
1652 DataType::QuantisedSymm16
1653 };
Narumol Prangnawaratbc67cef2019-01-31 15:31:54 +00001654
Aron Virginas-Tar6331f912019-06-03 17:10:02 +01001655 ValidateDataTypes(boxEncodingsInfo, supportedInputTypes, descriptorName);
1656 ValidateDataTypes(scoresInfo, supportedInputTypes, descriptorName);
1657 ValidateDataTypes(anchorsInfo, supportedInputTypes, descriptorName);
1658
1659 ValidateTensorNumDimensions(detectionBoxesInfo, descriptorName, 3, "detection boxes");
1660 ValidateTensorNumDimensions(detectionScoresInfo, descriptorName, 2, "detection scores");
1661 ValidateTensorNumDimensions(detectionClassesInfo, descriptorName, 2, "detection classes");
1662 ValidateTensorNumDimensions(numDetectionsInfo, descriptorName, 1, "num detections");
1663
1664 // NOTE: Output is always Float32 regardless of input type
1665 ValidateTensorDataType(detectionBoxesInfo, DataType::Float32, descriptorName, "detection boxes");
1666 ValidateTensorDataType(detectionScoresInfo, DataType::Float32, descriptorName, "detection scores");
1667 ValidateTensorDataType(detectionClassesInfo, DataType::Float32, descriptorName, "detection classes");
1668 ValidateTensorDataType(numDetectionsInfo, DataType::Float32, descriptorName, "num detections");
Narumol Prangnawaratbc67cef2019-01-31 15:31:54 +00001669
1670 if (m_Parameters.m_NmsIouThreshold <= 0.0f || m_Parameters.m_NmsIouThreshold > 1.0f)
1671 {
Aron Virginas-Tar6331f912019-06-03 17:10:02 +01001672 throw InvalidArgumentException(descriptorName + ": Intersection over union threshold "
Narumol Prangnawaratbc67cef2019-01-31 15:31:54 +00001673 "must be positive and less than or equal to 1.");
1674 }
1675 if (scoresInfo.GetShape()[2] != m_Parameters.m_NumClasses + 1)
1676 {
Aron Virginas-Tar6331f912019-06-03 17:10:02 +01001677 throw InvalidArgumentException(descriptorName + ": Number of classes with background "
Narumol Prangnawaratbc67cef2019-01-31 15:31:54 +00001678 "should be equal to number of classes + 1.");
1679 }
1680}
1681
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +00001682void DequantizeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1683{
Sadik Armaganeff363d2019-04-05 15:25:46 +01001684 ValidateNumInputs(workloadInfo, "DequantizeQueueDescriptor", 1);
1685 ValidateNumOutputs(workloadInfo, "DequantizeQueueDescriptor", 1);
Nattapat Chaimanowonge4294fd2019-03-28 09:56:53 +00001686
1687 if (workloadInfo.m_InputTensorInfos[0].GetDataType() != DataType::QuantisedAsymm8 &&
1688 workloadInfo.m_InputTensorInfos[0].GetDataType() != DataType::QuantisedSymm16)
1689 {
1690 throw InvalidArgumentException("Input to dequantize layer must be quantized type.");
1691 }
1692
1693 if (workloadInfo.m_OutputTensorInfos[0].GetDataType() != DataType::Float32)
1694 {
1695 throw InvalidArgumentException("Output of dequantize layer must be Float32 type.");
1696 }
1697}
1698
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +01001699void MergeQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1700{
Sadik Armaganeff363d2019-04-05 15:25:46 +01001701 ValidateNumInputs(workloadInfo, "MergeQueueDescriptor", 2);
1702 ValidateNumOutputs(workloadInfo, "MergeQueueDescriptor", 1);
Nattapat Chaimanowong1f886302019-04-05 13:37:19 +01001703
1704 ValidateTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
1705 workloadInfo.m_InputTensorInfos[1],
1706 "MergeQueueDescriptor",
1707 "input0",
1708 "input1");
1709
1710 ValidateTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
1711 workloadInfo.m_OutputTensorInfos[0],
1712 "MergeQueueDescriptor",
1713 "input0",
1714 "output");
1715
1716 const DataType dataType = workloadInfo.m_InputTensorInfos[0].GetDataType();
1717 ValidateTensorDataType(workloadInfo.m_InputTensorInfos[1], dataType, "MergeQueueDescriptor", "input1");
1718 ValidateTensorDataType(workloadInfo.m_OutputTensorInfos[0], dataType, "MergeQueueDescriptor", "output");
1719}
1720
Sadik Armaganeff363d2019-04-05 15:25:46 +01001721void SwitchQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1722{
1723 ValidateNumInputs(workloadInfo, "SwitchQueueDescriptor", 2);
1724 ValidateNumOutputs(workloadInfo, "SwitchQueueDescriptor", 2);
1725
1726 std::vector<DataType> supportedTypes = {
1727 DataType::Float32,
1728 DataType::QuantisedAsymm8,
1729 DataType::QuantisedSymm16
1730 };
1731
1732 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
1733 supportedTypes,
1734 "SwitchQueueDescriptor");
1735
1736 ValidateDataTypes(workloadInfo.m_InputTensorInfos[1],
1737 supportedTypes,
1738 "SwitchQueueDescriptor");
1739
1740 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
1741 supportedTypes,
1742 "SwitchQueueDescriptor");
1743
1744 ValidateTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
1745 workloadInfo.m_OutputTensorInfos[0],
1746 "SwitchQueueDescriptor",
1747 "input0",
1748 "output0");
1749
1750 ValidateTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
1751 workloadInfo.m_OutputTensorInfos[1],
1752 "SwitchQueueDescriptor",
1753 "input0",
1754 "output1");
1755}
1756
Matteo Martincigh49124022019-01-11 13:25:59 +00001757void PreCompiledQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1758{
1759 // This is internally generated so it should not need validation.
1760}
1761
Matteo Martincigh0e406ee2019-06-12 15:42:18 +01001762void PreluQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1763{
1764 ValidateNumInputs(workloadInfo, "PreluQueueDescriptor", 2);
1765 ValidateNumOutputs(workloadInfo, "PreluQueueDescriptor", 1);
1766
1767 std::vector<DataType> supportedTypes
1768 {
1769 DataType::Float16,
1770 DataType::Float32,
Matteo Martincighab9e5252019-06-13 17:27:46 +01001771 DataType::QuantisedAsymm8,
1772 DataType::QuantisedSymm16
Matteo Martincigh0e406ee2019-06-12 15:42:18 +01001773 };
1774
1775 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
1776 supportedTypes,
1777 "PreluQueueDescriptor");
1778
1779 ValidateDataTypes(workloadInfo.m_InputTensorInfos[1],
1780 supportedTypes,
1781 "PreluQueueDescriptor");
1782
1783 ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0],
1784 supportedTypes,
1785 "PreluQueueDescriptor");
1786
1787 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
1788 { workloadInfo.m_InputTensorInfos[1].GetDataType() },
1789 "PreluQueueDescriptor");
1790
1791 ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
1792 { workloadInfo.m_OutputTensorInfos[0].GetDataType() },
1793 "PreluQueueDescriptor");
1794
1795 ValidateBroadcastTensorShapesMatch(workloadInfo.m_InputTensorInfos[0],
1796 workloadInfo.m_InputTensorInfos[1],
1797 workloadInfo.m_OutputTensorInfos[0],
1798 "PreluQueueDescriptor",
1799 "input",
1800 "alpha");
1801}
1802
Aron Virginas-Tar639fb042019-06-20 14:28:19 +01001803void TransposeConvolution2dQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
1804{
1805 const std::string descriptorName{"TransposeConvolution2dQueueDescriptor"};
1806
1807 ValidateNumInputs(workloadInfo, descriptorName, 1);
1808 ValidateNumOutputs(workloadInfo, descriptorName, 1);
1809
1810 ValidateTensorNumDimensions(workloadInfo.m_InputTensorInfos[0], descriptorName, 4, "input");
1811 ValidateTensorNumDimensions(workloadInfo.m_OutputTensorInfos[0], descriptorName, 4, "output");
1812
1813 ValidatePointer(m_Weight, descriptorName, "weight");
1814 ValidateTensorNumDimensions(m_Weight->GetTensorInfo(), descriptorName, 4, "weight");
1815
1816 ValidateTensorDataType(m_Weight->GetTensorInfo(),
1817 workloadInfo.m_InputTensorInfos[0].GetDataType(),
1818 descriptorName,
1819 "weight");
1820
1821 if (m_Parameters.m_BiasEnabled)
1822 {
1823 ValidateTensorNumDimensions(m_Bias->GetTensorInfo(), descriptorName, 1, "bias");
1824
1825 ValidateTensorDataType(m_Bias->GetTensorInfo(),
1826 GetBiasDataType(workloadInfo.m_InputTensorInfos[0].GetDataType()),
1827 descriptorName, "bias");
1828
1829 ValidateBiasTensorQuantization(m_Bias->GetTensorInfo(),
1830 workloadInfo.m_InputTensorInfos[0],
1831 m_Weight->GetTensorInfo(),
1832 descriptorName);
1833 }
1834
1835 ValidateTensorQuantizationMultiplier(workloadInfo.m_InputTensorInfos[0],
1836 m_Weight->GetTensorInfo(),
1837 workloadInfo.m_OutputTensorInfos[0],
1838 descriptorName,
1839 "input",
1840 "weights",
1841 "output");
1842}
1843
Nattapat Chaimanowonga0d28442018-11-21 16:48:17 +00001844} //namespace armnn