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;
35 return multiScales ? arm_compute::DataType::UNKNOWN : arm_compute::DataType::QASYMM8_SIGNED;
40 return multiScales ? arm_compute::DataType::UNKNOWN : arm_compute::DataType::QASYMM8;
45 return multiScales ? arm_compute::DataType::UNKNOWN : arm_compute::DataType::QSYMM16;
48 return arm_compute::DataType::S64;
51 return multiScales ? arm_compute::DataType::QSYMM8_PER_CHANNEL : arm_compute::DataType::QSYMM8;
54 return arm_compute::DataType::S32;
56 return arm_compute::DataType::UNKNOWN;
64 case arm_compute::DataType::BFLOAT16:
66 case arm_compute::DataType::U8:
68 case arm_compute::DataType::F16:
70 case arm_compute::DataType::F32:
72 case arm_compute::DataType::QASYMM8_SIGNED:
74 case arm_compute::DataType::QASYMM8:
76 case arm_compute::DataType::QSYMM16:
78 case arm_compute::DataType::S64:
80 case arm_compute::DataType::QSYMM8_PER_CHANNEL:
82 case arm_compute::DataType::QSYMM8:
84 case arm_compute::DataType::S32:
87 throw InvalidArgumentException(
"Unknown arm_compute::DataType data type");
92 unsigned int originalInputRank,
93 const std::vector<unsigned int>& armnnAxes)
97 if (armnnAxes.empty())
105 outAclCoords.set_num_dimensions(inputDimensions);
106 std::generate(outAclCoords.begin(), outAclCoords.end(), [d = inputDimensions - 1] ()
mutable { return d--; });
124 outAclCoords.set_num_dimensions(armnnAxes.size());
125 std::transform(armnnAxes.begin(), armnnAxes.end(),
126 outAclCoords.begin(),
127 [originalInputRank](
unsigned int i){ return originalInputRank - i - 1; });
133 arm_compute::TensorShape BuildArmComputeTensorShape(
const armnn::TensorShape& tensorShape)
135 arm_compute::TensorShape shape;
149 if (shape.num_dimensions() == 0)
151 shape.set_num_dimensions(1);
157 std::vector<unsigned int> ReduceDimsForACL(
const armnn::TensorShape tensorShape,
unsigned int dimensions)
159 std::vector<unsigned int> newShape;
161 unsigned int dimsToSkip = 0;
167 unsigned int dimsSkipped = 0;
168 bool insertRemainder =
false;
172 if (tensorShape[i] == 1 && dimsSkipped < dimsToSkip && !insertRemainder)
177 newShape.insert(newShape.begin(), tensorShape[i]);
179 insertRemainder =
true;
184 arm_compute::TensorShape BuildArmComputeTensorShape(
const armnn::TensorShape& tensorShape,
unsigned int dimensions)
186 arm_compute::TensorShape shape;
187 std::vector<unsigned int> strippedShape = ReduceDimsForACL(tensorShape, dimensions);
189 for (
unsigned int i = 0; i < strippedShape.size(); i++)
191 shape.set(i, strippedShape[i],
false);
195 if (shape.num_dimensions() == 0)
197 shape.set_num_dimensions(1);
208 arm_compute::TensorInfo BuildArmComputeTensorInfo(
const armnn::TensorInfo& tensorInfo)
211 const arm_compute::TensorShape aclTensorShape = BuildArmComputeTensorShape(tensorInfo.
GetShape());
214 const arm_compute::QuantizationInfo aclQuantizationInfo = multiScales ?
216 arm_compute::QuantizationInfo(tensorInfo.GetQuantizationScale(), tensorInfo.GetQuantizationOffset());
218 return arm_compute::TensorInfo(aclTensorShape, 1, aclDataType, aclQuantizationInfo);
221 arm_compute::TensorInfo BuildArmComputeTensorInfo(
const armnn::TensorInfo& tensorInfo,
224 arm_compute::TensorInfo aclTensorInfo = BuildArmComputeTensorInfo(tensorInfo);
225 aclTensorInfo.set_data_layout(ConvertDataLayout(dataLayout));
227 return aclTensorInfo;
230 arm_compute::TensorInfo BuildArmComputeTensorInfo(
const armnn::TensorInfo& tensorInfo,
unsigned int dimensions)
233 const arm_compute::TensorShape aclTensorShape = BuildArmComputeTensorShape(tensorInfo.
GetShape(), dimensions);
236 const arm_compute::QuantizationInfo aclQuantizationInfo = multiScales ?
238 arm_compute::QuantizationInfo(tensorInfo.GetQuantizationScale(), tensorInfo.GetQuantizationOffset());
240 return arm_compute::TensorInfo(aclTensorShape, 1, aclDataType, aclQuantizationInfo);
242 arm_compute::TensorInfo BuildArmComputeTensorInfo(
const armnn::TensorInfo& tensorInfo,
245 arm_compute::TensorInfo aclTensorInfo = BuildArmComputeTensorInfo(tensorInfo, dimensions);
246 aclTensorInfo.set_data_layout(ConvertDataLayout(dataLayout));
248 return aclTensorInfo;
264 default:
throw InvalidArgumentException(
"Unknown armnn::DataLayout: [" +
265 std::to_string(
static_cast<int>(dataLayout)) +
"]");
269 arm_compute::PoolingLayerInfo BuildArmComputePoolingLayerInfo(
const Pooling2dDescriptor& descriptor,
270 bool fpMixedPrecision)
277 bool isGlobalPooling = (descriptor.m_StrideX==0 && descriptor.m_StrideY==0);
281 return arm_compute::PoolingLayerInfo(poolingType, dataLayout);
285 descriptor.m_OutputShapeRounding);
286 const arm_compute::PadStrideInfo padStrideInfo(descriptor.m_StrideX,
287 descriptor.m_StrideY,
288 descriptor.m_PadLeft,
289 descriptor.m_PadRight,
291 descriptor.m_PadBottom,
296 const arm_compute::Size2D poolSize(descriptor.m_PoolWidth, descriptor.m_PoolHeight);
298 return arm_compute::PoolingLayerInfo(poolingType, poolSize, dataLayout, padStrideInfo, excludePadding,
302 arm_compute::Pooling3dLayerInfo BuildArmComputePooling3dLayerInfo(
const Pooling3dDescriptor& descriptor,
303 bool fpMixedPrecision)
307 bool isGlobalPooling = (descriptor.m_StrideX==0 && descriptor.m_StrideY==0 && descriptor.m_StrideZ==0);
311 return arm_compute::Pooling3dLayerInfo(poolingType);
314 const arm_compute::Size3D poolSize(descriptor.m_PoolWidth, descriptor.m_PoolHeight, descriptor.m_PoolDepth);
316 const arm_compute::Size3D stride(descriptor.m_StrideX,
317 descriptor.m_StrideY,
318 descriptor.m_StrideZ);
320 const arm_compute::Padding3D padding(descriptor.m_PadLeft,
321 descriptor.m_PadRight,
323 descriptor.m_PadBottom,
324 descriptor.m_PadFront,
325 descriptor.m_PadBack);
330 descriptor.m_OutputShapeRounding);
332 return arm_compute::Pooling3dLayerInfo(poolingType,
341 arm_compute::NormalizationLayerInfo BuildArmComputeNormalizationLayerInfo(
const NormalizationDescriptor& descriptor)
343 const arm_compute::NormType normType =
345 return arm_compute::NormalizationLayerInfo(normType,
346 descriptor.m_NormSize,
355 arm_compute::PermutationVector aclPerm;
357 unsigned int start = 0;
358 while ((start < perm.
GetSize()) && (start == perm[start]))
363 for (
unsigned int i = start; i < perm.
GetSize(); ++i)
365 aclPerm.set(i - start, perm[i] - start);
394 arm_compute::PermutationVector aclPerm;
398 std::vector<unsigned int> reversedPerm;
399 reversedPerm.reserve(rank);
400 for (
unsigned int i = rank; i > 0; --i)
402 reversedPerm.push_back(perm[i-1]);
406 for (
unsigned int i = 0; i < rank; ++i)
408 auto aclAxis = rank - 1 - reversedPerm[i];
409 aclPerm.set(i, aclAxis);
414 arm_compute::Size2D BuildArmComputeSize2D(
const unsigned int width,
const unsigned int height)
416 return arm_compute::Size2D(width, height);
419 arm_compute::PixelValue GetPixelValue(
const arm_compute::ITensorInfo* tensorInfo,
float value)
421 switch (tensorInfo->data_type())
423 case arm_compute::DataType::F16:
425 arm_compute::PixelValue pixelValue = arm_compute::PixelValue(
static_cast<Half>(value));
426 if (isinf(pixelValue.get<
Half>())) {
427 throw InvalidArgumentException(
"Under/Overflow converting float value [" + std::to_string(value) +
428 "] to fp16: [" + std::to_string(pixelValue.get<
Half>()) +
"]");
432 case arm_compute::DataType::F32:
433 return arm_compute::PixelValue(value);
434 case arm_compute::DataType::QASYMM8:
435 return arm_compute::PixelValue(
static_cast<uint8_t
>(value));
436 case arm_compute::DataType::QSYMM16:
437 return arm_compute::PixelValue(
static_cast<int16_t
>(value));
438 case arm_compute::DataType::QSYMM8:
439 case arm_compute::DataType::QASYMM8_SIGNED:
440 case arm_compute::DataType::QSYMM8_PER_CHANNEL:
441 return arm_compute::PixelValue(
static_cast<int8_t
>(value));
442 case arm_compute::DataType::S32:
443 return arm_compute::PixelValue(
static_cast<int32_t
>(value));
445 throw InvalidArgumentException(
"Unsupported DataType: [" +
446 std::to_string(
static_cast<int>(tensorInfo->data_type())) +
"]");
451 const arm_compute::TensorShape& weightsShape,
452 const arm_compute::TensorShape& inputShape)
454 unsigned int depthMultiplier;
457 depthMultiplier =
static_cast<uint32_t
>(weightsShape[0]) /
static_cast<uint32_t
>(inputShape[0]);
461 depthMultiplier =
static_cast<uint32_t
>(weightsShape[2]) /
static_cast<uint32_t
>(inputShape[2]);
465 throw InvalidArgumentException(fmt::format(
"Unknown data layout for tensor conversion: {}",
468 return depthMultiplier;
471 arm_compute::ScatterInfo BuildArmComputeScatterInfo(
const ScatterNdDescriptor& descriptor)
473 arm_compute::ScatterFunction scatterFunction;
474 switch(descriptor.m_Function)
477 scatterFunction = arm_compute::ScatterFunction::Update;
480 scatterFunction = arm_compute::ScatterFunction::Add;
483 scatterFunction = arm_compute::ScatterFunction::Sub;
486 scatterFunction = arm_compute::ScatterFunction::Max;
489 scatterFunction = arm_compute::ScatterFunction::Min;
491 default:
throw InvalidArgumentException(
"Unknown ArmNN::ScatterNd Function: [" +
492 std::to_string(
static_cast<int>(descriptor.m_Function)) +
"]");
495 return arm_compute::ScatterInfo(scatterFunction, !descriptor.m_InputEnabled);
const TensorShape & GetShape() const
std::vector< float > GetQuantizationScales() const
DataType GetDataType() const
bool HasMultipleQuantizationScales() const
unsigned int GetNumDimensions() const
Function that returns the tensor rank.
const armnnSerializer::Pooling3dDescriptor * Pooling3dDescriptor
const armnnSerializer::Pooling2dDescriptor * Pooling2dDescriptor
Copyright (c) 2021 ARM Limited and Contributors.
@ Exclude
The padding fields don't count and are ignored.
arm_compute::DimensionRoundingType ConvertOutputShapeRoundingToAclDimensionRoundingType(OutputShapeRounding rounding)
arm_compute::NormType ConvertNormalizationAlgorithmChannelToAclNormType(NormalizationAlgorithmChannel channelType)
std::array< unsigned int, MaxNumOfTensorDimensions > Coordinates
arm_compute::PoolingType ConvertPoolingAlgorithmToAclPoolingType(PoolingAlgorithm poolingAlgorithm)
constexpr const char * GetDataLayoutName(DataLayout dataLayout)