aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTeresa Charlin <teresa.charlinreyes@arm.com>2022-12-06 20:43:06 +0000
committerTeresa Charlin <teresa.charlinreyes@arm.com>2022-12-07 15:40:28 +0000
commit6bc85258b0a87cde2e1e644d930ea546b6c3a1cc (patch)
tree463e31a280a8a57b4d43acd9adb1e05de000b4c0
parent4002a609b1e5a75d7527cd8b7cb05ed444d27caa (diff)
downloadarmnn-6bc85258b0a87cde2e1e644d930ea546b6c3a1cc.tar.gz
IVGCVSW-6853 Rewrite BuildArmComputePermutationVector()
* Some pemutation vectors were not converted correctly. * Add Transpose end to end test. * Comments added with an example to clarify the differences betweeen Transpose and Permute Signed-off-by: Teresa Charlin <teresa.charlinreyes@arm.com> Change-Id: I6c0954ca6ce00ef5f2a6f3625abe6f4fd27b5cdf
-rw-r--r--include/armnn/Descriptors.hpp20
-rw-r--r--src/armnn/layers/PermuteLayer.hpp4
-rw-r--r--src/armnn/layers/TransposeLayer.hpp3
-rw-r--r--src/backends/aclCommon/ArmComputeTensorUtils.cpp51
-rw-r--r--src/backends/aclCommon/ArmComputeTensorUtils.hpp10
-rw-r--r--src/backends/backendsCommon/test/CMakeLists.txt3
-rw-r--r--src/backends/backendsCommon/test/TransposeEndToEndTestImpl.hpp69
-rw-r--r--src/backends/cl/test/ClEndToEndTests.cpp9
-rw-r--r--src/backends/neon/test/NeonEndToEndTests.cpp9
-rw-r--r--src/backends/reference/test/RefEndToEndTests.cpp9
10 files changed, 155 insertions, 32 deletions
diff --git a/include/armnn/Descriptors.hpp b/include/armnn/Descriptors.hpp
index 2540073090..1cc403cf99 100644
--- a/include/armnn/Descriptors.hpp
+++ b/include/armnn/Descriptors.hpp
@@ -1,5 +1,5 @@
//
-// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2017,2022 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
#pragma once
@@ -142,7 +142,14 @@ struct PermuteDescriptor : BaseDescriptor
}
/// @brief Indicates how to translate tensor elements from a given source into the target destination, when
- /// source and target potentially have different memory layouts e.g. {0U, 3U, 1U, 2U}.
+ /// source and target potentially have different memory layouts e.g.
+ /// Input Shape {1, 1, 4, 4}
+ /// Permutation Vector {0, 2, 3, 1}
+ /// Output Shape {1, 4, 1, 4}
+ /// dim "0" goes into index 0 ([ 1, X, X, X ])
+ /// dim "1" goes into index 2 ([ 1, X, 1, X ])
+ /// dim "2" goes into index 3 ([ 1, X, 1, 4 ])
+ /// dim "3" goes into index 1 ([ 1, 4, 1, 4 ])
PermutationVector m_DimMappings;
};
@@ -1443,7 +1450,14 @@ struct TransposeDescriptor : BaseDescriptor
}
/// @brief Indicates how to translate tensor elements from a given source into the target destination, when
- /// source and target potentially have different memory layouts e.g. {0U, 3U, 1U, 2U}.
+ /// source and target potentially have different memory layouts e.g.
+ /// Input Shape {1, 1, 4, 4}
+ /// Permutation Vector {0, 2, 3, 1}
+ /// Output Shape {1, 4, 4, 1}
+ /// dim "0" of input goes into index 0 ([ 1, X, X, X])
+ /// dim "2" of input goes into index 1 ([ 1, 4, X, X ])
+ /// dim "3" of input goes into index 2 ([ 1, 4, 4, X ])
+ /// dim "1" of input goes into index 3 ([ 1, 4, 4, 1 ])
PermutationVector m_DimMappings;
};
diff --git a/src/armnn/layers/PermuteLayer.hpp b/src/armnn/layers/PermuteLayer.hpp
index 37ae444199..530042515a 100644
--- a/src/armnn/layers/PermuteLayer.hpp
+++ b/src/armnn/layers/PermuteLayer.hpp
@@ -1,5 +1,5 @@
//
-// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2017,2022 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
#pragma once
@@ -16,7 +16,6 @@ class PermuteLayer : public LayerWithParameters<PermuteDescriptor>
{
public:
/// Makes a workload for the Permute type.
- /// @param [in] graph The graph where this layer can be found.
/// @param [in] factory The workload factory which will create the workload.
/// @return A pointer to the created workload, or nullptr if not created.
virtual std::unique_ptr<IWorkload> CreateWorkload(const IWorkloadFactory& factory) const override;
@@ -27,7 +26,6 @@ public:
/// Check if the input tensor shape(s)
/// will lead to a valid configuration of @ref PermuteLayer.
- /// @param [in] shapeInferenceMethod Indicates if output shape shall be overwritten or just validated.
void ValidateTensorShapesFromInputs() override;
/// By default returns inputShapes if the number of inputs are equal to number of outputs,
diff --git a/src/armnn/layers/TransposeLayer.hpp b/src/armnn/layers/TransposeLayer.hpp
index 08268f2a54..cd54df5fe1 100644
--- a/src/armnn/layers/TransposeLayer.hpp
+++ b/src/armnn/layers/TransposeLayer.hpp
@@ -1,5 +1,5 @@
//
-// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2020,2022 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
#pragma once
@@ -26,7 +26,6 @@ public:
/// Check if the input tensor shape(s)
/// will lead to a valid configuration of @ref TransposeLayer.
- /// @param [in] shapeInferenceMethod Indicates if output shape shall be overwritten or just validated.
void ValidateTensorShapesFromInputs() override;
/// Infers the output shapes from given input shapes and the permutation vector.
diff --git a/src/backends/aclCommon/ArmComputeTensorUtils.cpp b/src/backends/aclCommon/ArmComputeTensorUtils.cpp
index 517b11ced8..38c7f70da5 100644
--- a/src/backends/aclCommon/ArmComputeTensorUtils.cpp
+++ b/src/backends/aclCommon/ArmComputeTensorUtils.cpp
@@ -1,11 +1,12 @@
//
-// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2017,2022 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
#include <aclCommon/ArmComputeTensorUtils.hpp>
#include <aclCommon/ArmComputeUtils.hpp>
#include "armnn/Exceptions.hpp"
+#include "ArmComputeUtils.hpp"
#include <armnn/Descriptors.hpp>
#include <fmt/format.h>
@@ -293,28 +294,44 @@ arm_compute::PermutationVector BuildArmComputePermutationVector(const armnn::Per
arm_compute::PermutationVector BuildArmComputeTransposeVector(const armnn::PermutationVector& perm)
{
- arm_compute::PermutationVector aclPerm;
- std::map<unsigned int, unsigned int> permuteMappings;
- for (unsigned int i = 0; i < perm.GetSize(); ++i)
- {
- permuteMappings[perm[i]] = i;
- }
+ // As ArmNN indexes are left to right and ACL indexes are right to left,
+ // the permutation vector has to be reversed and then translated into ACL axis.
+ // i.e. {1, 0, 2, 3} --> {3, 2, 0, 1} --> {0, 1, 3, 2}
+
+ // Below an example of how the ArmNN and ACL index format work:
+ // ArmNN Format:
+ // Input Shape {1, 10, 20, 30}
+ // Permutation Vector {1, 0, 2, 3}
+ // Output Shape {10, 1, 20, 30}
+ // dim "1" of input goes into index 0 of the output ([ 10, X, X, X])
+ // dim "0" of input goes into index 1 of the output ([ 10, 1, X, X ])
+ // dim "2" of input goes into index 2 of the output ([ 10, 1, 20, X ])
+ // dim "3" of input goes into index 3 of the output ([ 10, 1, 20, 30 ])
+ // ACL Format:
+ // Input Shape {30, 20, 10, 1}
+ // Permutation Vector {0, 1, 3, 2}
+ // Output Shape {30, 20, 1, 10}
+ // dim "0" of input goes into index 0 of the output ([ 30, X, X, X])
+ // dim "1" of input goes into index 1 of the output ([ 30, 20, X, X ])
+ // dim "3" of input goes into index 2 of the output ([ 30, 20, 1, X ])
+ // dim "2" of input goes into index 3 of the output ([ 30, 20, 1, 10 ])
- std::vector<unsigned int> permuteVector;
- for (unsigned int i = 0; i < perm.GetSize(); ++i)
- {
- permuteVector.push_back(permuteMappings.at(i));
- }
+ arm_compute::PermutationVector aclPerm;
+ auto rank = perm.GetSize();
- unsigned int start = 0;
- while ((start < perm.GetSize()) && (start == permuteVector[start]))
+ // Reverse the order. i.e. {1, 0, 2, 3} --> {3, 2, 0, 1}
+ std::vector<unsigned int> reversedPerm;
+ reversedPerm.reserve(rank);
+ for (unsigned int i = rank; i > 0; --i)
{
- ++start;
+ reversedPerm.push_back(perm[i-1]);
}
- for (unsigned int i = start; i < perm.GetSize(); ++i)
+ // Translate from Arm NN axis to ACL axis. i.e. {3, 2, 0, 1} --> {0, 1, 3, 2}
+ for (unsigned int i = 0; i < rank; ++i)
{
- aclPerm.set(i - start, permuteVector[i] - start);
+ auto aclAxis = rank - 1 - reversedPerm[i];
+ aclPerm.set(i, aclAxis);
}
return aclPerm;
}
diff --git a/src/backends/aclCommon/ArmComputeTensorUtils.hpp b/src/backends/aclCommon/ArmComputeTensorUtils.hpp
index fdcd867bba..6ddecf2aaa 100644
--- a/src/backends/aclCommon/ArmComputeTensorUtils.hpp
+++ b/src/backends/aclCommon/ArmComputeTensorUtils.hpp
@@ -1,5 +1,5 @@
//
-// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2017,2022 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
#pragma once
@@ -66,10 +66,14 @@ arm_compute::Pooling3dLayerInfo BuildArmComputePooling3dLayerInfo(const Pooling3
arm_compute::NormalizationLayerInfo BuildArmComputeNormalizationLayerInfo(const NormalizationDescriptor& desc);
/// Utility function used to setup an arm_compute::PermutationVector object from an armnn::PermutationVector.
-arm_compute::PermutationVector BuildArmComputePermutationVector(const armnn::PermutationVector& vector);
+/// \param perm PermutationVector used in Arm NN Permute layer
+/// \return PermutationVector used in ACL Transpose layer
+arm_compute::PermutationVector BuildArmComputePermutationVector(const armnn::PermutationVector& perm);
/// Utility function used to setup an arm_compute::PermutationVector object from an armnn::PermutationVector.
-arm_compute::PermutationVector BuildArmComputeTransposeVector(const armnn::PermutationVector& vector);
+/// \param perm PermutationVector used in Arm NN Transpose layer
+/// \return PermutationVector used in ACL Transpose layer
+arm_compute::PermutationVector BuildArmComputeTransposeVector(const armnn::PermutationVector& perm);
/// Utility function used to setup an arm_compute::Size2D object from width and height values.
arm_compute::Size2D BuildArmComputeSize2D(const unsigned int width, const unsigned int height);
diff --git a/src/backends/backendsCommon/test/CMakeLists.txt b/src/backends/backendsCommon/test/CMakeLists.txt
index 232226b5df..c9668a22f2 100644
--- a/src/backends/backendsCommon/test/CMakeLists.txt
+++ b/src/backends/backendsCommon/test/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
+# Copyright © 2017,2022 Arm Ltd and Contributors. All rights reserved.
# SPDX-License-Identifier: MIT
#
@@ -54,6 +54,7 @@ list(APPEND armnnBackendsCommonUnitTests_sources
SpaceToDepthEndToEndTestImpl.hpp
SplitterEndToEndTestImpl.hpp
StridedSliceAsyncEndToEndTest.hpp
+ TransposeEndToEndTestImpl.hpp
TensorCopyUtils.hpp
WorkloadFactoryHelper.hpp
layerTests/AbsTestImpl.cpp
diff --git a/src/backends/backendsCommon/test/TransposeEndToEndTestImpl.hpp b/src/backends/backendsCommon/test/TransposeEndToEndTestImpl.hpp
new file mode 100644
index 0000000000..32e1b0edaf
--- /dev/null
+++ b/src/backends/backendsCommon/test/TransposeEndToEndTestImpl.hpp
@@ -0,0 +1,69 @@
+//
+// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include <CommonTestUtils.hpp>
+
+#include <armnn/INetwork.hpp>
+#include <armnn/TypesUtils.hpp>
+
+#include <ResolveType.hpp>
+
+#include <doctest/doctest.h>
+
+namespace
+{
+
+armnn::INetworkPtr CreateTransposeNetwork(const armnn::TensorInfo& inputTensorInfo,
+ const armnn::TensorInfo& outputTensorInfo,
+ const armnn::PermutationVector& mappings)
+{
+ armnn::INetworkPtr network(armnn::INetwork::Create());
+
+ const armnn::TransposeDescriptor transposeDescriptor(mappings);
+
+ armnn::IConnectableLayer* inputLayer = network->AddInputLayer(0, "Input");
+ armnn::IConnectableLayer* transposeLayer = network->AddTransposeLayer(transposeDescriptor, "Transpose");
+ armnn::IConnectableLayer* outputLayer = network->AddOutputLayer(0, "Output");
+
+ Connect(inputLayer, transposeLayer, inputTensorInfo, 0, 0);
+ Connect(transposeLayer, outputLayer, outputTensorInfo, 0, 0);
+
+ return network;
+}
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+void TransposeEndToEnd(const std::vector<armnn::BackendId>& backends)
+{
+ using namespace armnn;
+
+ std::vector<float> floatInputData{
+ 1, 2, 3, 4, 5,
+ 11, 12, 13, 14, 15,
+ 21, 22, 23, 24, 25
+ };
+ std::vector<T> inputData = armnnUtils::QuantizedVector<T>(floatInputData);
+ std::vector<T> expectedOutputData = armnnUtils::QuantizedVector<T>(floatInputData);
+
+ const armnn::PermutationVector mappings{0, 2, 1 ,3};
+
+ TensorInfo inputInfo ({ 1, 1, 5, 3 }, ArmnnType, 0.0f, 0, true);
+ TensorInfo outputInfo({ 1, 5, 1, 3 }, ArmnnType, 0.0f, 0, true);
+
+ armnn::INetworkPtr network = CreateTransposeNetwork(inputInfo, outputInfo, mappings);
+
+ CHECK(network);
+
+ std::map<int, std::vector<T>> inputTensorData = {{ 0, inputData }};
+ std::map<int, std::vector<T>> expectedOutputTensorData = {{ 0, expectedOutputData }};
+
+ EndToEndLayerTestImpl<ArmnnType, DataType::Signed32>(std::move(network),
+ inputTensorData,
+ expectedOutputTensorData,
+ backends);
+}
+
+} // anonymous namespace \ No newline at end of file
diff --git a/src/backends/cl/test/ClEndToEndTests.cpp b/src/backends/cl/test/ClEndToEndTests.cpp
index 74307e4b6e..b354481967 100644
--- a/src/backends/cl/test/ClEndToEndTests.cpp
+++ b/src/backends/cl/test/ClEndToEndTests.cpp
@@ -1,5 +1,5 @@
//
-// Copyright © 2022 Arm Ltd. All rights reserved.
+// Copyright © 2017,2022 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//
@@ -21,6 +21,7 @@
#include <backendsCommon/test/SpaceToDepthEndToEndTestImpl.hpp>
#include <backendsCommon/test/SplitterEndToEndTestImpl.hpp>
#include <backendsCommon/test/TransposeConvolution2dEndToEndTestImpl.hpp>
+#include <backendsCommon/test/TransposeEndToEndTestImpl.hpp>
#include <doctest/doctest.h>
@@ -415,6 +416,12 @@ TEST_CASE("ClTransposeConvolution2dEndToEndUint8NhwcTest")
clDefaultBackends, armnn::DataLayout::NHWC);
}
+// Transpose
+TEST_CASE("ClTransposeEndToEndTest")
+{
+TransposeEndToEnd<armnn::DataType::Float32>(clDefaultBackends);
+}
+
TEST_CASE("ClQuantizedLstmEndToEndTest")
{
QuantizedLstmEndToEnd(clDefaultBackends);
diff --git a/src/backends/neon/test/NeonEndToEndTests.cpp b/src/backends/neon/test/NeonEndToEndTests.cpp
index faeb4dac6c..a64e42688e 100644
--- a/src/backends/neon/test/NeonEndToEndTests.cpp
+++ b/src/backends/neon/test/NeonEndToEndTests.cpp
@@ -1,5 +1,5 @@
//
-// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2017,2022 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
@@ -23,6 +23,7 @@
#include <backendsCommon/test/SpaceToDepthEndToEndTestImpl.hpp>
#include <backendsCommon/test/SplitterEndToEndTestImpl.hpp>
#include <backendsCommon/test/TransposeConvolution2dEndToEndTestImpl.hpp>
+#include <backendsCommon/test/TransposeEndToEndTestImpl.hpp>
#include <doctest/doctest.h>
@@ -417,6 +418,12 @@ TEST_CASE("NeonTransposeConvolution2dEndToEndUint8NhwcTest")
neonDefaultBackends, armnn::DataLayout::NHWC);
}
+// Transpose
+TEST_CASE("NeonTransposeEndToEndTest")
+{
+ TransposeEndToEnd<armnn::DataType::Float32>(neonDefaultBackends);
+}
+
TEST_CASE("NeonImportNonAlignedInputPointerTest")
{
ImportNonAlignedInputPointerTest(neonDefaultBackends);
diff --git a/src/backends/reference/test/RefEndToEndTests.cpp b/src/backends/reference/test/RefEndToEndTests.cpp
index a8c0634186..218f6dd695 100644
--- a/src/backends/reference/test/RefEndToEndTests.cpp
+++ b/src/backends/reference/test/RefEndToEndTests.cpp
@@ -1,5 +1,5 @@
//
-// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2017,2022 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
@@ -32,6 +32,7 @@
#include <backendsCommon/test/SplitterEndToEndTestImpl.hpp>
#include <backendsCommon/test/StridedSliceAsyncEndToEndTest.hpp>
#include <backendsCommon/test/TransposeConvolution2dEndToEndTestImpl.hpp>
+#include <backendsCommon/test/TransposeEndToEndTestImpl.hpp>
#include <doctest/doctest.h>
@@ -1194,6 +1195,12 @@ TEST_CASE("RefTransposeConvolution2dEndToEndInt16NhwcTest")
defaultBackends, armnn::DataLayout::NHWC);
}
+// Transpose
+TEST_CASE("RefTransposeEndToEndTest")
+{
+ TransposeEndToEnd<armnn::DataType::Float32>(defaultBackends);
+}
+
// Resize Bilinear
TEST_CASE("RefResizeBilinearEndToEndFloatNchwTest")
{