diff options
author | Mike Kelly <mike.kelly@arm.com> | 2023-01-23 19:32:06 +0000 |
---|---|---|
committer | TeresaARM <teresa.charlinreyes@arm.com> | 2023-01-24 17:01:30 +0000 |
commit | 0e3fe10bfe1b4f006f6e0c5c2fae8fb5515c7544 (patch) | |
tree | 222ff6eb1c034efa05bc5dcf4b255f80993987bf /src/backends/aclCommon | |
parent | d134c13ec9a0585bb7656654e0e65c57958d8833 (diff) | |
download | armnn-0e3fe10bfe1b4f006f6e0c5c2fae8fb5515c7544.tar.gz |
IVGCVSW-7455 Workaround to allow CLBatchMatMul to parse some 4D models
* Added ability to reduce dimension sizes when calling BuildArmComputeTensorInfo or
BuildArmComputeTensorShapes, this will attempt to remove leading 1s in order to
squeeze the number of dimensions but retain the size.
* Changed ClBatchMatMulWorkload to attempt to squeeze the number of dimensions to 3
as the CL Gemm Kernel can only support up to 3 dimensions.
Signed-off-by: Mike Kelly <mike.kelly@arm.com>
Change-Id: I6b3d0886c5b97fdb686838fc3dc292833ddc4643
Diffstat (limited to 'src/backends/aclCommon')
-rw-r--r-- | src/backends/aclCommon/ArmComputeTensorUtils.cpp | 69 | ||||
-rw-r--r-- | src/backends/aclCommon/ArmComputeTensorUtils.hpp | 24 |
2 files changed, 91 insertions, 2 deletions
diff --git a/src/backends/aclCommon/ArmComputeTensorUtils.cpp b/src/backends/aclCommon/ArmComputeTensorUtils.cpp index 38c7f70da5..e6c5a9b41c 100644 --- a/src/backends/aclCommon/ArmComputeTensorUtils.cpp +++ b/src/backends/aclCommon/ArmComputeTensorUtils.cpp @@ -1,5 +1,5 @@ // -// Copyright © 2017,2022 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2017-2023 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // #include <aclCommon/ArmComputeTensorUtils.hpp> @@ -146,6 +146,51 @@ arm_compute::TensorShape BuildArmComputeTensorShape(const armnn::TensorShape& te return shape; } +std::vector<unsigned int> ReduceDimsForACL(const armnn::TensorShape tensorShape, unsigned int dimensions) +{ + std::vector<unsigned int> newShape; + + unsigned int dimsToSkip = 0; + + if (tensorShape.GetNumDimensions() > dimensions) + { + dimsToSkip = tensorShape.GetNumDimensions() - dimensions; + } + unsigned int dimsSkipped = 0; + bool insertRemainder = false; + + for (unsigned int i = 0; i < tensorShape.GetNumDimensions(); ++i) + { + if (tensorShape[i] == 1 && dimsSkipped < dimsToSkip && !insertRemainder) + { + ++dimsSkipped; + continue; + } + newShape.insert(newShape.begin(), tensorShape[i]); + // Once we insert the first dimension we can't skip any more + insertRemainder = true; + } + return newShape; +} + +arm_compute::TensorShape BuildArmComputeTensorShape(const armnn::TensorShape& tensorShape, unsigned int dimensions) +{ + arm_compute::TensorShape shape; + std::vector<unsigned int> strippedShape = ReduceDimsForACL(tensorShape, dimensions); + + for (unsigned int i = 0; i < strippedShape.size(); i++) + { + shape.set(i, strippedShape[i], false); + } + + // prevent arm_compute issue where tensor is flattened to nothing + if (shape.num_dimensions() == 0) + { + shape.set_num_dimensions(1); + } + return shape; +} + // Utility function used to build a TensorInfo object, that can be used to initialise // ARM Compute Tensor and CLTensor allocators. // Note: this utility ignores the value of armnn::TensorInfo.IsConstant(). ACL tensors @@ -174,6 +219,28 @@ arm_compute::TensorInfo BuildArmComputeTensorInfo(const armnn::TensorInfo& tenso return aclTensorInfo; } +arm_compute::TensorInfo BuildArmComputeTensorInfo(const armnn::TensorInfo& tensorInfo, unsigned int dimensions) +{ + bool multiScales = tensorInfo.HasMultipleQuantizationScales(); + const arm_compute::TensorShape aclTensorShape = BuildArmComputeTensorShape(tensorInfo.GetShape(), dimensions); + const arm_compute::DataType aclDataType = GetArmComputeDataType(tensorInfo.GetDataType(), multiScales); + + const arm_compute::QuantizationInfo aclQuantizationInfo = multiScales ? + arm_compute::QuantizationInfo(tensorInfo.GetQuantizationScales()) : + arm_compute::QuantizationInfo(tensorInfo.GetQuantizationScale(), tensorInfo.GetQuantizationOffset()); + + return arm_compute::TensorInfo(aclTensorShape, 1, aclDataType, aclQuantizationInfo); +} +arm_compute::TensorInfo BuildArmComputeTensorInfo(const armnn::TensorInfo& tensorInfo, + armnn::DataLayout dataLayout, unsigned int dimensions) +{ + arm_compute::TensorInfo aclTensorInfo = BuildArmComputeTensorInfo(tensorInfo, dimensions); + aclTensorInfo.set_data_layout(ConvertDataLayout(dataLayout)); + + return aclTensorInfo; +} + + arm_compute::DataLayout ConvertDataLayout(armnn::DataLayout dataLayout) { switch(dataLayout) diff --git a/src/backends/aclCommon/ArmComputeTensorUtils.hpp b/src/backends/aclCommon/ArmComputeTensorUtils.hpp index 6ddecf2aaa..1f07fa949c 100644 --- a/src/backends/aclCommon/ArmComputeTensorUtils.hpp +++ b/src/backends/aclCommon/ArmComputeTensorUtils.hpp @@ -1,5 +1,5 @@ // -// Copyright © 2017,2022 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2017-2023 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // #pragma once @@ -36,16 +36,38 @@ arm_compute::Coordinates BuildArmComputeReductionCoordinates(size_t inputDimensi /// Utility function used to setup an arm_compute::TensorShape object from an armnn::TensorShape. arm_compute::TensorShape BuildArmComputeTensorShape(const armnn::TensorShape& tensorShape); +/// Utility function used to setup an arm_compute::TensorShape object from an armnn::TensorShape. This will +/// attempt to reduce the number of leading 1s until the dimension length is equal to the dimensions passed in. +arm_compute::TensorShape BuildArmComputeTensorShape(const armnn::TensorShape& tensorShape, unsigned int dimensions); + /// Utility function used to setup an arm_compute::ITensorInfo object whose dimensions are based on the given /// armnn::ITensorInfo. arm_compute::TensorInfo BuildArmComputeTensorInfo(const armnn::TensorInfo& tensorInfo); /// Utility function used to setup an arm_compute::ITensorInfo object whose dimensions are based on the given +/// armnn::ITensorInfo. This will attempt to reduce the number of leading 1s until the dimension length is equal +/// to the dimensions passed in. +arm_compute::TensorInfo BuildArmComputeTensorInfo(const armnn::TensorInfo& tensorInfo, unsigned int dimensions); + +/// Utility function used to setup an arm_compute::ITensorInfo object whose dimensions are based on the given +/// armnn::ITensorInfo. This will attempt to reduce the number of leading 1s until the dimension length is equal +/// to the dimensions passed in. +arm_compute::TensorInfo BuildArmComputeTensorInfo(const armnn::TensorInfo& tensorInfo, + armnn::DataLayout dataLayout, + unsigned int dimensions); + +/// Utility function used to setup an arm_compute::ITensorInfo object whose dimensions are based on the given /// armnn::ITensorInfo. /// armnn::DataLayout. arm_compute::TensorInfo BuildArmComputeTensorInfo(const armnn::TensorInfo& tensorInfo, armnn::DataLayout dataLayout); +/// Utility function used to setup an arm_compute::ITensorInfo object whose dimensions are based on the given +/// armnn::ITensorInfo. This will attempt to reduce the number of leading 1s until the dimension length is equal +/// to the dimensions passed in. +arm_compute::TensorInfo BuildArmComputeTensorInfo(const armnn::TensorInfo& tensorInfo, + armnn::DataLayout dataLayout, unsigned int dimensions); + /// Utility function used to convert armnn::DataLayout to arm_compute::DataLayout /// armnn::DataLayout. arm_compute::DataLayout ConvertDataLayout(armnn::DataLayout dataLayout); |