13 #include <fmt/format.h>
17 namespace armcomputetensorutils
25 return arm_compute::DataType::BFLOAT16;
27 return arm_compute::DataType::U8;
29 return arm_compute::DataType::F16;
31 return arm_compute::DataType::F32;
33 return arm_compute::DataType::QASYMM8_SIGNED;
35 return arm_compute::DataType::QASYMM8;
37 return arm_compute::DataType::QSYMM16;
39 return arm_compute::DataType::S64;
42 return multiScales ? arm_compute::DataType::QSYMM8_PER_CHANNEL : arm_compute::DataType::QSYMM8;
45 return arm_compute::DataType::S32;
47 return arm_compute::DataType::UNKNOWN;
55 case arm_compute::DataType::BFLOAT16:
57 case arm_compute::DataType::U8:
59 case arm_compute::DataType::F16:
61 case arm_compute::DataType::F32:
63 case arm_compute::DataType::QASYMM8_SIGNED:
65 case arm_compute::DataType::QASYMM8:
67 case arm_compute::DataType::QSYMM16:
69 case arm_compute::DataType::S64:
71 case arm_compute::DataType::QSYMM8_PER_CHANNEL:
73 case arm_compute::DataType::QSYMM8:
75 case arm_compute::DataType::S32:
78 throw InvalidArgumentException(
"Unknown arm_compute::DataType data type");
83 unsigned int originalInputRank,
84 const std::vector<unsigned int>& armnnAxes)
88 if (armnnAxes.empty())
96 outAclCoords.set_num_dimensions(inputDimensions);
97 std::generate(outAclCoords.begin(), outAclCoords.end(), [d = inputDimensions - 1] ()
mutable { return d--; });
115 outAclCoords.set_num_dimensions(armnnAxes.size());
116 std::transform(armnnAxes.begin(), armnnAxes.end(),
117 outAclCoords.begin(),
118 [originalInputRank](
unsigned int i){ return originalInputRank - i - 1; });
124 arm_compute::TensorShape BuildArmComputeTensorShape(
const armnn::TensorShape& tensorShape)
126 arm_compute::TensorShape shape;
140 if (shape.num_dimensions() == 0)
142 shape.set_num_dimensions(1);
148 std::vector<unsigned int> ReduceDimsForACL(
const armnn::TensorShape tensorShape,
unsigned int dimensions)
150 std::vector<unsigned int> newShape;
152 unsigned int dimsToSkip = 0;
158 unsigned int dimsSkipped = 0;
159 bool insertRemainder =
false;
163 if (tensorShape[i] == 1 && dimsSkipped < dimsToSkip && !insertRemainder)
168 newShape.insert(newShape.begin(), tensorShape[i]);
170 insertRemainder =
true;
175 arm_compute::TensorShape BuildArmComputeTensorShape(
const armnn::TensorShape& tensorShape,
unsigned int dimensions)
177 arm_compute::TensorShape shape;
178 std::vector<unsigned int> strippedShape = ReduceDimsForACL(tensorShape, dimensions);
180 for (
unsigned int i = 0; i < strippedShape.size(); i++)
182 shape.set(i, strippedShape[i],
false);
186 if (shape.num_dimensions() == 0)
188 shape.set_num_dimensions(1);
199 arm_compute::TensorInfo BuildArmComputeTensorInfo(
const armnn::TensorInfo& tensorInfo)
202 const arm_compute::TensorShape aclTensorShape = BuildArmComputeTensorShape(tensorInfo.
GetShape());
205 const arm_compute::QuantizationInfo aclQuantizationInfo = multiScales ?
207 arm_compute::QuantizationInfo(tensorInfo.GetQuantizationScale(), tensorInfo.GetQuantizationOffset());
209 return arm_compute::TensorInfo(aclTensorShape, 1, aclDataType, aclQuantizationInfo);
212 arm_compute::TensorInfo BuildArmComputeTensorInfo(
const armnn::TensorInfo& tensorInfo,
215 arm_compute::TensorInfo aclTensorInfo = BuildArmComputeTensorInfo(tensorInfo);
216 aclTensorInfo.set_data_layout(ConvertDataLayout(dataLayout));
218 return aclTensorInfo;
221 arm_compute::TensorInfo BuildArmComputeTensorInfo(
const armnn::TensorInfo& tensorInfo,
unsigned int dimensions)
224 const arm_compute::TensorShape aclTensorShape = BuildArmComputeTensorShape(tensorInfo.
GetShape(), dimensions);
227 const arm_compute::QuantizationInfo aclQuantizationInfo = multiScales ?
229 arm_compute::QuantizationInfo(tensorInfo.GetQuantizationScale(), tensorInfo.GetQuantizationOffset());
231 return arm_compute::TensorInfo(aclTensorShape, 1, aclDataType, aclQuantizationInfo);
233 arm_compute::TensorInfo BuildArmComputeTensorInfo(
const armnn::TensorInfo& tensorInfo,
236 arm_compute::TensorInfo aclTensorInfo = BuildArmComputeTensorInfo(tensorInfo, dimensions);
237 aclTensorInfo.set_data_layout(ConvertDataLayout(dataLayout));
239 return aclTensorInfo;
255 default:
throw InvalidArgumentException(
"Unknown armnn::DataLayout: [" +
256 std::to_string(
static_cast<int>(dataLayout)) +
"]");
260 arm_compute::PoolingLayerInfo BuildArmComputePoolingLayerInfo(
const Pooling2dDescriptor& descriptor,
261 bool fpMixedPrecision)
268 bool isGlobalPooling = (descriptor.m_StrideX==0 && descriptor.m_StrideY==0);
272 return arm_compute::PoolingLayerInfo(poolingType, dataLayout);
276 descriptor.m_OutputShapeRounding);
277 const arm_compute::PadStrideInfo padStrideInfo(descriptor.m_StrideX,
278 descriptor.m_StrideY,
279 descriptor.m_PadLeft,
280 descriptor.m_PadRight,
282 descriptor.m_PadBottom,
287 const arm_compute::Size2D poolSize(descriptor.m_PoolWidth, descriptor.m_PoolHeight);
289 return arm_compute::PoolingLayerInfo(poolingType, poolSize, dataLayout, padStrideInfo, excludePadding,
293 arm_compute::Pooling3dLayerInfo BuildArmComputePooling3dLayerInfo(
const Pooling3dDescriptor& descriptor,
294 bool fpMixedPrecision)
298 bool isGlobalPooling = (descriptor.m_StrideX==0 && descriptor.m_StrideY==0 && descriptor.m_StrideZ==0);
302 return arm_compute::Pooling3dLayerInfo(poolingType);
305 const arm_compute::Size3D poolSize(descriptor.m_PoolWidth, descriptor.m_PoolHeight, descriptor.m_PoolDepth);
307 const arm_compute::Size3D stride(descriptor.m_StrideX,
308 descriptor.m_StrideY,
309 descriptor.m_StrideZ);
311 const arm_compute::Padding3D padding(descriptor.m_PadLeft,
312 descriptor.m_PadRight,
314 descriptor.m_PadBottom,
315 descriptor.m_PadFront,
316 descriptor.m_PadBack);
321 descriptor.m_OutputShapeRounding);
323 return arm_compute::Pooling3dLayerInfo(poolingType,
332 arm_compute::NormalizationLayerInfo BuildArmComputeNormalizationLayerInfo(
const NormalizationDescriptor& descriptor)
334 const arm_compute::NormType normType =
336 return arm_compute::NormalizationLayerInfo(normType,
337 descriptor.m_NormSize,
346 arm_compute::PermutationVector aclPerm;
348 unsigned int start = 0;
349 while ((start < perm.
GetSize()) && (start == perm[start]))
354 for (
unsigned int i = start; i < perm.
GetSize(); ++i)
356 aclPerm.set(i - start, perm[i] - start);
385 arm_compute::PermutationVector aclPerm;
389 std::vector<unsigned int> reversedPerm;
390 reversedPerm.reserve(rank);
391 for (
unsigned int i = rank; i > 0; --i)
393 reversedPerm.push_back(perm[i-1]);
397 for (
unsigned int i = 0; i < rank; ++i)
399 auto aclAxis = rank - 1 - reversedPerm[i];
400 aclPerm.set(i, aclAxis);
405 arm_compute::Size2D BuildArmComputeSize2D(
const unsigned int width,
const unsigned int height)
407 return arm_compute::Size2D(width, height);
410 arm_compute::PixelValue GetPixelValue(
const arm_compute::ITensorInfo* tensorInfo,
float value)
412 switch (tensorInfo->data_type())
414 case arm_compute::DataType::F16:
416 arm_compute::PixelValue pixelValue = arm_compute::PixelValue(
static_cast<Half>(value));
417 if (isinf(pixelValue.get<
Half>())) {
418 throw InvalidArgumentException(
"Under/Overflow converting float value [" + std::to_string(value) +
419 "] to fp16: [" + std::to_string(pixelValue.get<
Half>()) +
"]");
423 case arm_compute::DataType::F32:
424 return arm_compute::PixelValue(value);
425 case arm_compute::DataType::QASYMM8:
426 return arm_compute::PixelValue(
static_cast<uint8_t
>(value));
427 case arm_compute::DataType::QSYMM16:
428 return arm_compute::PixelValue(
static_cast<int16_t
>(value));
429 case arm_compute::DataType::QSYMM8:
430 case arm_compute::DataType::QASYMM8_SIGNED:
431 case arm_compute::DataType::QSYMM8_PER_CHANNEL:
432 return arm_compute::PixelValue(
static_cast<int8_t
>(value));
433 case arm_compute::DataType::S32:
434 return arm_compute::PixelValue(
static_cast<int32_t
>(value));
436 throw InvalidArgumentException(
"Unsupported DataType: [" +
437 std::to_string(
static_cast<int>(tensorInfo->data_type())) +
"]");
442 const arm_compute::TensorShape& weightsShape,
443 const arm_compute::TensorShape& inputShape)
445 unsigned int depthMultiplier;
448 depthMultiplier =
static_cast<uint32_t
>(weightsShape[0]) /
static_cast<uint32_t
>(inputShape[0]);
452 depthMultiplier =
static_cast<uint32_t
>(weightsShape[2]) /
static_cast<uint32_t
>(inputShape[2]);
456 throw InvalidArgumentException(fmt::format(
"Unknown data layout for tensor conversion: {}",
459 return depthMultiplier;
462 arm_compute::ScatterInfo BuildArmComputeScatterInfo(
const ScatterNdDescriptor& descriptor)
464 arm_compute::ScatterFunction scatterFunction;
465 switch(descriptor.m_Function)
468 scatterFunction = arm_compute::ScatterFunction::Update;
471 scatterFunction = arm_compute::ScatterFunction::Add;
474 scatterFunction = arm_compute::ScatterFunction::Sub;
477 scatterFunction = arm_compute::ScatterFunction::Max;
480 scatterFunction = arm_compute::ScatterFunction::Min;
482 default:
throw InvalidArgumentException(
"Unknown ArmNN::ScatterNd Function: [" +
483 std::to_string(
static_cast<int>(descriptor.m_Function)) +
"]");
486 return arm_compute::ScatterInfo(scatterFunction, !descriptor.m_InputEnabled);