diff options
author | Narumol Prangnawarat <narumol.prangnawarat@arm.com> | 2023-08-11 16:09:26 +0100 |
---|---|---|
committer | Narumol Prangnawarat <narumol.prangnawarat@arm.com> | 2023-08-21 13:34:54 +0100 |
commit | 5f94124ac11afbbf2d2a4cda539b316964802c76 (patch) | |
tree | 38d6f31517fe322cb0065a8c3e947801791a6405 /src/backends | |
parent | c4f42340bd3d6664098c69d2fb044089aa39aea0 (diff) | |
download | armnn-5f94124ac11afbbf2d2a4cda539b316964802c76.tar.gz |
IVGCVSW-7964 Fix UnidirectionalSequenceLstm
* Fix incorrect batch size and time size
* Fix incorrect time major when max time =1
* Fix incorrect permutation
* Fix incorrect scratch buffer
* Unit tests
Signed-off-by: Narumol Prangnawarat <narumol.prangnawarat@arm.com>
Change-Id: I510fae55528be412a58d020e82bd283852e7800b
Diffstat (limited to 'src/backends')
8 files changed, 66 insertions, 11 deletions
diff --git a/src/backends/backendsCommon/test/layerTests/UnidirectionalSequenceLstmTestImpl.cpp b/src/backends/backendsCommon/test/layerTests/UnidirectionalSequenceLstmTestImpl.cpp index 4a63d39800..5381df5276 100644 --- a/src/backends/backendsCommon/test/layerTests/UnidirectionalSequenceLstmTestImpl.cpp +++ b/src/backends/backendsCommon/test/layerTests/UnidirectionalSequenceLstmTestImpl.cpp @@ -224,7 +224,8 @@ LayerTestResult<T, 3> UnidirectionalSequenceLstmLayerFloat32TestImpl( const armnn::TensorShape& outputExpectedShape, float qScale = 1.0f, int32_t qOffset = 0, - armnn::DataType constantDataType = armnn::DataType::Float32) { + armnn::DataType constantDataType = armnn::DataType::Float32) +{ IgnoreUnused(memoryManager); unsigned int batchSize = armnn::numeric_cast<unsigned int>(inputShape[0]); unsigned int timeSize = armnn::numeric_cast<unsigned int>(inputShape[1]); @@ -413,7 +414,8 @@ UnidirectionalSequenceLstmLayerFloat32TimeMajorTestImpl( const armnn::TensorShape& outputExpectedShape, float qScale = 1.0f, int32_t qOffset = 0, - armnn::DataType constantDataType = armnn::DataType::Float32) { + armnn::DataType constantDataType = armnn::DataType::Float32) +{ IgnoreUnused(memoryManager); unsigned int batchSize = armnn::numeric_cast<unsigned int>(inputShape[1]); unsigned int timeSize = armnn::numeric_cast<unsigned int>(inputShape[0]); @@ -613,7 +615,8 @@ LayerTestResult<float, 3> UnidirectionalSequenceLstmLayerFloat32TimeMajorSingleB LayerTestResult<float, 3> UnidirectionalSequenceLstmLayerFloat32BatchMajorSingleBatchTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, - const armnn::ITensorHandleFactory& tensorHandleFactory) { + const armnn::ITensorHandleFactory& tensorHandleFactory) +{ armnn::TensorInfo inputInfo({3, 1, 3}, armnn::DataType::Float32); std::vector<float> input = { 1., 2., 3., 4., 5., 4., 3., 2., 1. }; @@ -626,10 +629,32 @@ LayerTestResult<float, 3> UnidirectionalSequenceLstmLayerFloat32BatchMajorSingle input, expectedOutput, inputInfo.GetShape(), outputInfo.GetShape()); } +LayerTestResult<float, 3> UnidirectionalSequenceLstmLayerFloat32TimeMajorSingleTimeTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const armnn::ITensorHandleFactory& tensorHandleFactory) +{ + armnn::TensorInfo inputInfo({ 1, 3, 3 }, armnn::DataType::Float32); + std::vector<float> input = { 1., 2., 3., + 4., 5., 6., + 7., 8., 9. }; + + armnn::TensorInfo outputInfo({ 1, 3, 4 }, armnn::DataType::Float32); + std::vector<float> expectedOutput = + { 0.13565768f, 0.12467254f, 0.02120903f, -0.05302038f, + 0.1053334f, 0.08508634f, 0.00667238f, -0.00356043f, + 0.05638668f, 0.02924093f, 0.00119751f, -0.00017249f }; + + return UnidirectionalSequenceLstmLayerFloat32TimeMajorTestImpl<armnn::DataType::Float32>( + workloadFactory, memoryManager, tensorHandleFactory, + input, expectedOutput, inputInfo.GetShape(), outputInfo.GetShape()); +} + LayerTestResult<float, 3> UnidirectionalSequenceLstmLayerFloat32Test( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, - const armnn::ITensorHandleFactory& tensorHandleFactory) { + const armnn::ITensorHandleFactory& tensorHandleFactory) +{ armnn::TensorInfo inputInfo({3, 2, 3}, armnn::DataType::Float32); std::vector<float> input = { 1., 2., 3., 4., 5., 4., 3., 2., 1., 2., 3., 4., @@ -650,7 +675,8 @@ LayerTestResult<float, 3> UnidirectionalSequenceLstmLayerFloat32Test( LayerTestResult<float, 3> UnidirectionalSequenceLstmLayerFloat32TimeMajorTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, - const armnn::ITensorHandleFactory& tensorHandleFactory) { + const armnn::ITensorHandleFactory& tensorHandleFactory) +{ armnn::TensorInfo inputInfo({2, 3, 3}, armnn::DataType::Float32); std::vector<float> input = { 1., 2., 3., 4., 5., 4., 3., 2., 1., 2., 3., 4., diff --git a/src/backends/backendsCommon/test/layerTests/UnidirectionalSequenceLstmTestImpl.hpp b/src/backends/backendsCommon/test/layerTests/UnidirectionalSequenceLstmTestImpl.hpp index f303b28c10..5e64dcd0ed 100644 --- a/src/backends/backendsCommon/test/layerTests/UnidirectionalSequenceLstmTestImpl.hpp +++ b/src/backends/backendsCommon/test/layerTests/UnidirectionalSequenceLstmTestImpl.hpp @@ -1,5 +1,5 @@ // -// Copyright © 2021 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2021, 2023 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // @@ -20,6 +20,11 @@ LayerTestResult<float, 3> UnidirectionalSequenceLstmLayerFloat32BatchMajorSingle const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, const armnn::ITensorHandleFactory& tensorHandleFactory); +LayerTestResult<float, 3> UnidirectionalSequenceLstmLayerFloat32TimeMajorSingleTimeTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const armnn::ITensorHandleFactory& tensorHandleFactory); + LayerTestResult<float, 3> UnidirectionalSequenceLstmLayerFloat32Test( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, diff --git a/src/backends/cl/test/ClLayerTests.cpp b/src/backends/cl/test/ClLayerTests.cpp index d8d451ead3..33e1b69ade 100644 --- a/src/backends/cl/test/ClLayerTests.cpp +++ b/src/backends/cl/test/ClLayerTests.cpp @@ -1346,6 +1346,8 @@ ARMNN_AUTO_TEST_CASE_WITH_THF(UnidirectionalSequenceLstmLayerFloat32TimeMajorSin UnidirectionalSequenceLstmLayerFloat32TimeMajorSingleBatchTest) ARMNN_AUTO_TEST_CASE_WITH_THF(UnidirectionalSequenceLstmLayerFloat32BatchMajorSingleBatch, UnidirectionalSequenceLstmLayerFloat32BatchMajorSingleBatchTest) +ARMNN_AUTO_TEST_CASE_WITH_THF(UnidirectionalSequenceLstmLayerFloat32TimeMajorSingleTime, + UnidirectionalSequenceLstmLayerFloat32TimeMajorSingleTimeTest) ARMNN_AUTO_TEST_CASE_WITH_THF(UnidirectionalSequenceLstmLayerFloat32, UnidirectionalSequenceLstmLayerFloat32Test) ARMNN_AUTO_TEST_CASE_WITH_THF(UnidirectionalSequenceLstmLayerFloat32TimeMajor, diff --git a/src/backends/neon/test/NeonLayerTests.cpp b/src/backends/neon/test/NeonLayerTests.cpp index ae8352d09e..588c90be6d 100644 --- a/src/backends/neon/test/NeonLayerTests.cpp +++ b/src/backends/neon/test/NeonLayerTests.cpp @@ -1092,6 +1092,8 @@ ARMNN_AUTO_TEST_CASE_WITH_THF(UnidirectionalSequenceLstmLayerFloat32TimeMajorSin UnidirectionalSequenceLstmLayerFloat32TimeMajorSingleBatchTest) ARMNN_AUTO_TEST_CASE_WITH_THF(UnidirectionalSequenceLstmLayerFloat32BatchMajorSingleBatch, UnidirectionalSequenceLstmLayerFloat32BatchMajorSingleBatchTest) +ARMNN_AUTO_TEST_CASE_WITH_THF(UnidirectionalSequenceLstmLayerFloat32TimeMajorSingleTime, + UnidirectionalSequenceLstmLayerFloat32TimeMajorSingleTimeTest) ARMNN_AUTO_TEST_CASE_WITH_THF(UnidirectionalSequenceLstmLayerFloat32, UnidirectionalSequenceLstmLayerFloat32Test) ARMNN_AUTO_TEST_CASE_WITH_THF(UnidirectionalSequenceLstmLayerFloat32TimeMajor, diff --git a/src/backends/neon/workloads/NeonUnidirectionalSequenceLstmFloatWorkload.cpp b/src/backends/neon/workloads/NeonUnidirectionalSequenceLstmFloatWorkload.cpp index e48425e3ee..bbdcd1f855 100644 --- a/src/backends/neon/workloads/NeonUnidirectionalSequenceLstmFloatWorkload.cpp +++ b/src/backends/neon/workloads/NeonUnidirectionalSequenceLstmFloatWorkload.cpp @@ -603,7 +603,8 @@ NeonUnidirectionalSequenceLstmFloatWorkloadValidate(const TensorInfo& input, statusSplit = arm_compute::NESplit::validate(&aclPermuteOutInfo, splitterOutputsTensorInfosPtr, aclAxisSplit); - } else + } + else { statusSplit = arm_compute::NESplit::validate(&aclInputInfo, splitterOutputsTensorInfosPtr, aclAxisSplit); } @@ -740,7 +741,7 @@ NeonUnidirectionalSequenceLstmFloatWorkloadValidate(const TensorInfo& input, // Set input of LSTM to be first input ITensor. // Set output of LSTM to be final output ITensor. // LSTM input/output cannot be > 2 dimensions so need to resize its TensorInfo. - if (maxTime == 1 && !descriptor.m_TimeMajor) + if (maxTime == 1 && descriptor.m_TimeMajor) { TensorShape inputShape = GetTensorShape(aclInputInfo.tensor_shape(), 1U); TensorShape outputShape = GetTensorShape(aclOutputInfo.tensor_shape(), 1U); diff --git a/src/backends/neon/workloads/NeonUnidirectionalSequenceLstmWorkload.cpp b/src/backends/neon/workloads/NeonUnidirectionalSequenceLstmWorkload.cpp index 8a1747edd1..984a5dc549 100644 --- a/src/backends/neon/workloads/NeonUnidirectionalSequenceLstmWorkload.cpp +++ b/src/backends/neon/workloads/NeonUnidirectionalSequenceLstmWorkload.cpp @@ -500,6 +500,12 @@ NeonUnidirectionalSequenceLstmWorkloadValidate(const TensorInfo& input, TensorShape inputLayerShape = input.GetShape(); TensorShape outputLayerShape = output.GetShape(); + if (inputLayerShape.GetNumDimensions() != 3) + { + return arm_compute::Status(arm_compute::ErrorCode::RUNTIME_ERROR, + "Unidirectional Sequence LSTM layer validate status failed."); + } + unsigned int maxTime = descriptor.m_TimeMajor ? inputLayerShape[0] : inputLayerShape[1]; unsigned int batchSize = descriptor.m_TimeMajor ? inputLayerShape[1] : inputLayerShape[0]; unsigned int inputSize = inputLayerShape[2]; @@ -525,7 +531,7 @@ NeonUnidirectionalSequenceLstmWorkloadValidate(const TensorInfo& input, // // Permute validate // - TensorInfo permuteOutInfo = TensorInfo(input); + TensorInfo permuteOutInfo = armnnUtils::Permuted(input, { 1U, 0U, 2U }); arm_compute::TensorInfo aclPermuteOutInfo = armcomputetensorutils::BuildArmComputeTensorInfo(permuteOutInfo); if (!descriptor.m_TimeMajor) { @@ -590,7 +596,17 @@ NeonUnidirectionalSequenceLstmWorkloadValidate(const TensorInfo& input, arm_compute::LSTMParams<arm_compute::ITensorInfo> lstm_params_info; - const TensorInfo& scratchBuffer = TensorInfo(cellStateIn.GetShape(), input.GetDataType()); + unsigned int numUnits = cellStateIn.GetShape()[1]; + unsigned int scratchBufferFactor = 4; + + if (descriptor.m_CifgEnabled) + { + // scratchBuffer = { batchSize, numUnits * 3 } with CIFG + scratchBufferFactor = 3; + } + + const TensorInfo& scratchBuffer = TensorInfo({ batchSize, numUnits * scratchBufferFactor }, input.GetDataType()); + lstm_params_info.set_cell_clip_params(descriptor.m_ClippingThresCell); lstm_params_info.set_projection_clip_params(descriptor.m_ClippingThresProj); @@ -707,7 +723,7 @@ NeonUnidirectionalSequenceLstmWorkloadValidate(const TensorInfo& input, // Set input of LSTM to be first input ITensor. // Set output of LSTM to be final output ITensor. // LSTM input/output cannot be > 2 dimensions so need to resize its TensorInfo. - if (maxTime == 1 && !descriptor.m_TimeMajor) + if (maxTime == 1 && descriptor.m_TimeMajor) { TensorShape inputShape = GetTensorShape(aclInputInfo.tensor_shape(), 1U); TensorShape outputShape = GetTensorShape(aclOutputInfo.tensor_shape(), 1U); diff --git a/src/backends/reference/test/RefLayerTests.cpp b/src/backends/reference/test/RefLayerTests.cpp index 1f42397458..a079bb712a 100644 --- a/src/backends/reference/test/RefLayerTests.cpp +++ b/src/backends/reference/test/RefLayerTests.cpp @@ -2800,6 +2800,8 @@ ARMNN_AUTO_TEST_CASE_WITH_THF(UnidirectionalSequenceLstmLayerFloat32TimeMajorSin UnidirectionalSequenceLstmLayerFloat32TimeMajorSingleBatchTest) ARMNN_AUTO_TEST_CASE_WITH_THF(UnidirectionalSequenceLstmLayerFloat32BatchMajorSingleBatch, UnidirectionalSequenceLstmLayerFloat32BatchMajorSingleBatchTest) +ARMNN_AUTO_TEST_CASE_WITH_THF(UnidirectionalSequenceLstmLayerFloat32TimeMajorSingleTime, + UnidirectionalSequenceLstmLayerFloat32TimeMajorSingleTimeTest) ARMNN_AUTO_TEST_CASE_WITH_THF(UnidirectionalSequenceLstmLayerFloat32, UnidirectionalSequenceLstmLayerFloat32Test) ARMNN_AUTO_TEST_CASE_WITH_THF(UnidirectionalSequenceLstmLayerFloat32TimeMajor, diff --git a/src/backends/reference/workloads/RefUnidirectionalSequenceLstmWorkload.cpp b/src/backends/reference/workloads/RefUnidirectionalSequenceLstmWorkload.cpp index c7a4b76964..4ca3e03c89 100644 --- a/src/backends/reference/workloads/RefUnidirectionalSequenceLstmWorkload.cpp +++ b/src/backends/reference/workloads/RefUnidirectionalSequenceLstmWorkload.cpp @@ -81,6 +81,7 @@ void RefUnidirectionalSequenceLstmWorkload::Execute(std::vector<ITensorHandle*> outputShape = armnnUtils::Permuted(outputInfo.GetShape(), mappings); outputInfo.SetShape(outputShape); } + // As it is permuted to time major, maxTime is inputShape[0]. unsigned int maxTime = inputShape[0]; unsigned int batchSize = inputShape[1]; unsigned int outputSize = outputShape[2]; |