From 2ea403d130db0d2853d5c43c29b5112893efc2bf Mon Sep 17 00:00:00 2001 From: Teresa Charlin Date: Mon, 19 Jun 2023 12:06:19 +0100 Subject: IVGCVSW-7785 3D tensors in BATCH_TO_SPACE and SPACE_TO_BATCH in CpuAcc & GpuAcc * Add Reshape layers before and after to extend support for 3D tensors, as ACL only supports 4D tensors for those layers * Add Unit Tests Signed-off-by: Teresa Charlin Change-Id: I4431185ce3a3b2f595d2a79bdda7095212d1c52d --- src/backends/cl/test/ClLayerTests.cpp | 9 + .../cl/workloads/ClBatchToSpaceNdWorkload.cpp | 153 +++++++++++++--- .../cl/workloads/ClBatchToSpaceNdWorkload.hpp | 12 +- .../cl/workloads/ClSpaceToBatchNdWorkload.cpp | 195 +++++++++++++++------ .../cl/workloads/ClSpaceToBatchNdWorkload.hpp | 15 +- 5 files changed, 298 insertions(+), 86 deletions(-) (limited to 'src/backends/cl') diff --git a/src/backends/cl/test/ClLayerTests.cpp b/src/backends/cl/test/ClLayerTests.cpp index 03a4d6fc49..93ad653441 100644 --- a/src/backends/cl/test/ClLayerTests.cpp +++ b/src/backends/cl/test/ClLayerTests.cpp @@ -145,6 +145,9 @@ ARMNN_AUTO_TEST_FIXTURE_WITH_THF(BatchToSpaceNdNhwcFloat326, ARMNN_AUTO_TEST_FIXTURE_WITH_THF(BatchToSpaceNdNhwcFloat327, ClContextControlFixture, BatchToSpaceNdNhwcTest7) +ARMNN_AUTO_TEST_FIXTURE_WITH_THF(BatchToSpaceNdNhwcFloat32_3D, + ClContextControlFixture, + BatchToSpaceNdNhwcTest8) ARMNN_AUTO_TEST_FIXTURE_WITH_THF(BatchToSpaceNdNchwFloat321, ClContextControlFixture, @@ -189,6 +192,9 @@ ARMNN_AUTO_TEST_FIXTURE_WITH_THF(BatchToSpaceNdNhwcInt6, ARMNN_AUTO_TEST_FIXTURE_WITH_THF(BatchToSpaceNdNhwcInt7, ClContextControlFixture, BatchToSpaceNdNhwcTest7) +ARMNN_AUTO_TEST_FIXTURE_WITH_THF(BatchToSpaceNdNhwcInt_3D, + ClContextControlFixture, + BatchToSpaceNdNhwcTest8) ARMNN_AUTO_TEST_FIXTURE_WITH_THF(BatchToSpaceNdNchwInt1, ClContextControlFixture, @@ -233,6 +239,9 @@ ARMNN_AUTO_TEST_FIXTURE_WITH_THF(BatchToSpaceNdNhwcUint6, ARMNN_AUTO_TEST_FIXTURE_WITH_THF(BatchToSpaceNdNhwcUint7, ClContextControlFixture, BatchToSpaceNdNhwcTest7) +ARMNN_AUTO_TEST_FIXTURE_WITH_THF(BatchToSpaceNdNhwcUint_3D, + ClContextControlFixture, + BatchToSpaceNdNhwcTest8) ARMNN_AUTO_TEST_FIXTURE_WITH_THF(BatchToSpaceNdNchwUint1, ClContextControlFixture, diff --git a/src/backends/cl/workloads/ClBatchToSpaceNdWorkload.cpp b/src/backends/cl/workloads/ClBatchToSpaceNdWorkload.cpp index ad3a602f48..f6d96041cc 100644 --- a/src/backends/cl/workloads/ClBatchToSpaceNdWorkload.cpp +++ b/src/backends/cl/workloads/ClBatchToSpaceNdWorkload.cpp @@ -1,43 +1,88 @@ // -// Copyright © 2017, 2023 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2017, 2019-2023 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // #include "ClBatchToSpaceNdWorkload.hpp" -#include -#include -#include - -#include +#include -#include "ClWorkloadUtils.hpp" +#include namespace armnn { + using namespace armcomputetensorutils; arm_compute::Status ClBatchToSpaceNdWorkloadValidate(const TensorInfo& input, const TensorInfo& output, const BatchToSpaceNdDescriptor& descriptor) { - DataLayout dataLayout = descriptor.m_DataLayout; - const arm_compute::TensorInfo aclInputInfo = BuildArmComputeTensorInfo(input, dataLayout); + arm_compute::TensorInfo aclInputInfo = BuildArmComputeTensorInfo(input, descriptor.m_DataLayout); + arm_compute::TensorInfo aclOutputInfo = BuildArmComputeTensorInfo(output, descriptor.m_DataLayout); - // ArmNN blockShape is [H, W] Cl asks for W, H + arm_compute::Status statusBatchToSpace = arm_compute::Status(arm_compute::ErrorCode::OK); + arm_compute::Status statusReshapeInput = arm_compute::Status(arm_compute::ErrorCode::OK); + arm_compute::Status statusReshapeOutput = arm_compute::Status(arm_compute::ErrorCode::OK); + + arm_compute::TensorInfo aclReshapeInputInfo = aclInputInfo; + arm_compute::TensorInfo aclReshapeOutputInfo = aclOutputInfo; + + // When a spacial dimension is missing (rank=3) set W to 1 + const unsigned int rank = input.GetNumDimensions(); + if (rank == 3) + { + const arm_compute::TensorShape inputShape = aclInputInfo.tensor_shape(); + const arm_compute::TensorShape outputShape = aclOutputInfo.tensor_shape(); + + if (descriptor.m_DataLayout == armnn::DataLayout::NHWC) + { + // In ACL dimensions are right to left: C, W, H, N + aclInputInfo.set_tensor_shape({inputShape.x(), 1, inputShape.y(), inputShape.z()}); + aclOutputInfo.set_tensor_shape({outputShape.x(), 1, outputShape.y(), outputShape.z()}); + } + else if (descriptor.m_DataLayout == armnn::DataLayout::NCHW) + { + // In ACL dimensions are right to left: W, H, C, N + aclInputInfo.set_tensor_shape({1, inputShape.x(), inputShape.y(), inputShape.z()}); + aclOutputInfo.set_tensor_shape({1, outputShape.x(), outputShape.y(), outputShape.z()}); + } + else + { + throw InvalidArgumentException("Unsupported or unknown DataLayout", CHECK_LOCATION()); + } + + statusReshapeInput = arm_compute::CLReshapeLayer::validate(&aclInputInfo, &aclReshapeInputInfo); + statusReshapeOutput = arm_compute::CLReshapeLayer::validate(&aclReshapeOutputInfo, &aclOutputInfo); + } + + // ArmNN blockShape is [H, W] ACl asks for W, H int32_t blockHeight = armnn::numeric_cast(descriptor.m_BlockShape[0]); - int32_t blockWidth = armnn::numeric_cast(descriptor.m_BlockShape[1]); + int32_t blockWidth = (rank == 3) ? 1 : armnn::numeric_cast(descriptor.m_BlockShape[1]); - const arm_compute::TensorInfo aclOutputInfo = BuildArmComputeTensorInfo(output, dataLayout); + const arm_compute::CropInfo cropInfo = BuildArmComputeCropInfo(descriptor, rank); - const arm_compute::CropInfo cropInfo = BuildArmComputeCropInfo(descriptor); + statusBatchToSpace = arm_compute::CLBatchToSpaceLayer::validate(rank == 3 ? &aclReshapeInputInfo : &aclInputInfo, + blockWidth, + blockHeight, + rank == 3 ? &aclReshapeOutputInfo : &aclOutputInfo, + cropInfo); - const arm_compute::Status aclStatus = arm_compute::CLBatchToSpaceLayer::validate(&aclInputInfo, - blockWidth, - blockHeight, - &aclOutputInfo, - cropInfo); - return aclStatus; + if (statusReshapeInput.error_code() == arm_compute::ErrorCode::OK && + statusReshapeOutput.error_code() == arm_compute::ErrorCode::OK && + statusBatchToSpace.error_code() == arm_compute::ErrorCode::OK) + { + return arm_compute::Status(arm_compute::ErrorCode::OK, + "All BatchToSpace layers validate status OK."); + } + else + { + return arm_compute::Status(arm_compute::ErrorCode::RUNTIME_ERROR, + "BatchToSpace layer validate status failed." + + statusBatchToSpace.error_description() + + statusReshapeInput.error_description() + + statusReshapeOutput.error_description()); + } } ClBatchToSpaceNdWorkload::ClBatchToSpaceNdWorkload(const BatchToSpaceNdQueueDescriptor& descriptor, @@ -53,30 +98,84 @@ ClBatchToSpaceNdWorkload::ClBatchToSpaceNdWorkload(const BatchToSpaceNdQueueDesc m_Data.ValidateInputsOutputs("ClBatchToSpaceNdWorkload", 1, 1); - arm_compute::DataLayout aclDataLayout = ConvertDataLayout(m_Data.m_Parameters.m_DataLayout); - arm_compute::ICLTensor& input = static_cast(m_Data.m_Inputs[0])->GetTensor(); + arm_compute::ICLTensor& output = static_cast(m_Data.m_Outputs[0])->GetTensor(); + + arm_compute::DataLayout aclDataLayout = ConvertDataLayout(m_Data.m_Parameters.m_DataLayout); input.info()->set_data_layout(aclDataLayout); + output.info()->set_data_layout(aclDataLayout); - // ArmNN blockShape is [H, W] Cl asks for W, H - int32_t blockHeight = armnn::numeric_cast(descriptor.m_Parameters.m_BlockShape[0]); - int32_t blockWidth = armnn::numeric_cast(descriptor.m_Parameters.m_BlockShape[1]); + arm_compute::TensorInfo aclReshapeInputInfo = BuildArmComputeTensorInfo(info.m_InputTensorInfos[0], + m_Data.m_Parameters.m_DataLayout); + arm_compute::TensorInfo aclReshapeOutputInfo = BuildArmComputeTensorInfo(info.m_OutputTensorInfos[0], + m_Data.m_Parameters.m_DataLayout); - arm_compute::ICLTensor& output = static_cast(m_Data.m_Outputs[0])->GetTensor(); - output.info()->set_data_layout(aclDataLayout); + const unsigned int rank = info.m_InputTensorInfos[0].GetNumDimensions(); + if (rank == 3) + { + const arm_compute::TensorShape inputShape = input.info()->tensor_shape(); + const arm_compute::TensorShape outputShape = output.info()->tensor_shape(); + + // When a spacial dimension is missing set W to 1 + if (m_Data.m_Parameters.m_DataLayout == armnn::DataLayout::NHWC) + { + // In ACL dimensions are right to left: C, W, H, N + aclReshapeInputInfo.set_tensor_shape({inputShape.x(), 1, inputShape.y(), inputShape.z()}); + aclReshapeOutputInfo.set_tensor_shape({outputShape.x(), 1, outputShape.y(), outputShape.z()}); + } + else if (m_Data.m_Parameters.m_DataLayout == armnn::DataLayout::NCHW) + { + // In ACL dimensions are right to left: W, H, C, N + aclReshapeInputInfo.set_tensor_shape({1, inputShape.x(), inputShape.y(), inputShape.z()}); + aclReshapeOutputInfo.set_tensor_shape({1, outputShape.x(), outputShape.y(), outputShape.z()}); + } + else + { + throw InvalidArgumentException("Unsupported or unknown DataLayout", CHECK_LOCATION()); + } + + m_ReshapeInputTensor.allocator()->init(aclReshapeInputInfo); + m_ReshapeOutputTensor.allocator()->init(aclReshapeOutputInfo); + + InitialiseArmComputeTensorEmpty(m_ReshapeInputTensor); + InitialiseArmComputeTensorEmpty(m_ReshapeOutputTensor); + + m_LayerReshapeInput.reset(new arm_compute::CLReshapeLayer()); + m_LayerReshapeOutput.reset(new arm_compute::CLReshapeLayer()); + + m_LayerReshapeInput->configure(clCompileContext, &input, &m_ReshapeInputTensor); + m_LayerReshapeOutput->configure(clCompileContext, &m_ReshapeOutputTensor, &output); + } + + // ArmNN blockShape is [H, W] ACl asks for W, H + int32_t blockHeight = armnn::numeric_cast(descriptor.m_Parameters.m_BlockShape[0]); + int32_t blockWidth = (rank == 3) ? 1 : armnn::numeric_cast(descriptor.m_Parameters.m_BlockShape[1]); const arm_compute::CropInfo cropInfo = BuildArmComputeCropInfo(descriptor.m_Parameters); { ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "ClBatchToSpaceNdWorkload_configure"); - m_Layer.configure(clCompileContext, &input, blockWidth, blockHeight, &output, cropInfo); + m_Layer.configure(clCompileContext, + (rank == 3) ? &m_ReshapeInputTensor : &input, + blockWidth, + blockHeight, + (rank == 3) ? &m_ReshapeOutputTensor : &output, + cropInfo); } } void ClBatchToSpaceNdWorkload::Execute() const { ARMNN_SCOPED_PROFILING_EVENT_CL_GUID("ClBatchToSpaceNdWorkload_Execute", this->GetGuid()); + if (m_LayerReshapeInput) + { + m_LayerReshapeInput->run(); + } RunClFunction(m_Layer, CHECK_LOCATION()); + if (m_LayerReshapeOutput) + { + m_LayerReshapeOutput->run(); + } } } //namespace armnn diff --git a/src/backends/cl/workloads/ClBatchToSpaceNdWorkload.hpp b/src/backends/cl/workloads/ClBatchToSpaceNdWorkload.hpp index 5026dc3aaf..b23c416c4f 100644 --- a/src/backends/cl/workloads/ClBatchToSpaceNdWorkload.hpp +++ b/src/backends/cl/workloads/ClBatchToSpaceNdWorkload.hpp @@ -1,12 +1,15 @@ // -// Copyright © 2017 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2017-2018,2020-2023 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // #pragma once #include "ClBaseWorkload.hpp" +#include "ClWorkloadUtils.hpp" + #include +#include namespace armnn { @@ -22,11 +25,14 @@ public: const WorkloadInfo& info, const arm_compute::CLCompileContext& clCompileContext); - void Execute() const override; + virtual void Execute() const override; private: - mutable arm_compute::CLBatchToSpaceLayer m_Layer; + mutable std::unique_ptr m_LayerReshapeInput; + mutable std::unique_ptr m_LayerReshapeOutput; + arm_compute::CLTensor m_ReshapeInputTensor; + arm_compute::CLTensor m_ReshapeOutputTensor; }; } //namespace armnn diff --git a/src/backends/cl/workloads/ClSpaceToBatchNdWorkload.cpp b/src/backends/cl/workloads/ClSpaceToBatchNdWorkload.cpp index 220d2d1908..fd90adb2ff 100644 --- a/src/backends/cl/workloads/ClSpaceToBatchNdWorkload.cpp +++ b/src/backends/cl/workloads/ClSpaceToBatchNdWorkload.cpp @@ -1,20 +1,13 @@ // -// Copyright © 2017 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2017-2023 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // #include "ClSpaceToBatchNdWorkload.hpp" -#include "ClWorkloadUtils.hpp" - -#include -#include -#include #include -#include -#include + #include -#include namespace armnn { @@ -24,30 +17,82 @@ arm_compute::Status ClSpaceToBatchNdWorkloadValidate(const TensorInfo& input, const TensorInfo& output, const SpaceToBatchNdDescriptor& descriptor) { - const arm_compute::TensorInfo aclInputInfo = BuildArmComputeTensorInfo(input, descriptor.m_DataLayout); - const arm_compute::TensorInfo aclOutputInfo = BuildArmComputeTensorInfo(output, descriptor.m_DataLayout); + arm_compute::TensorInfo aclInputInfo = BuildArmComputeTensorInfo(input, descriptor.m_DataLayout); + arm_compute::TensorInfo aclOutputInfo = BuildArmComputeTensorInfo(output, descriptor.m_DataLayout); + + arm_compute::Status statusSpaceToBatch = arm_compute::Status(arm_compute::ErrorCode::OK); + arm_compute::Status statusReshapeInput = arm_compute::Status(arm_compute::ErrorCode::OK); + arm_compute::Status statusReshapeOutput = arm_compute::Status(arm_compute::ErrorCode::OK); + + arm_compute::TensorInfo aclReshapeInputInfo = aclInputInfo; + arm_compute::TensorInfo aclReshapeOutputInfo = aclOutputInfo; + + // When a spacial dimension is missing (rank=3) set W to 1 + const unsigned int rank = input.GetNumDimensions(); + if (rank == 3) + { + const arm_compute::TensorShape inputShape = aclInputInfo.tensor_shape(); + const arm_compute::TensorShape outputShape = aclOutputInfo.tensor_shape(); + + if (descriptor.m_DataLayout == armnn::DataLayout::NHWC) + { + // In ACL dimensions are right to left: C, W, H, N + aclInputInfo.set_tensor_shape({inputShape.x(), 1, inputShape.y(), inputShape.z()}); + aclOutputInfo.set_tensor_shape({outputShape.x(), 1, outputShape.y(), outputShape.z()}); + } + else if (descriptor.m_DataLayout == armnn::DataLayout::NCHW) + { + // In ACL dimensions are right to left: W, H, C, N + aclInputInfo.set_tensor_shape({1, inputShape.x(), inputShape.y(), inputShape.z()}); + aclOutputInfo.set_tensor_shape({1, outputShape.x(), outputShape.y(), outputShape.z()}); + } + else + { + throw InvalidArgumentException("Unsupported or unknown DataLayout", CHECK_LOCATION()); + } + + statusReshapeInput = arm_compute::CLReshapeLayer::validate(&aclInputInfo, &aclReshapeInputInfo); + statusReshapeOutput = arm_compute::CLReshapeLayer::validate(&aclReshapeOutputInfo, &aclOutputInfo); + } - // ArmNN blockShape is [H, W] Cl asks for W, H + // ArmNN blockShape is [H, W] ACl asks for W, H int32_t blockHeight = armnn::numeric_cast(descriptor.m_BlockShape[0]); - int32_t blockWidth = armnn::numeric_cast(descriptor.m_BlockShape[1]); - - arm_compute::Size2D paddingLeftTop = BuildArmComputeSize2D( - descriptor.m_PadList[1].first, descriptor.m_PadList[0].first); - arm_compute::Size2D paddingRightBottom = BuildArmComputeSize2D( - descriptor.m_PadList[1].second, descriptor.m_PadList[0].second); - - return arm_compute::CLSpaceToBatchLayer::validate(&aclInputInfo, - blockWidth, - blockHeight, - paddingLeftTop, - paddingRightBottom, - &aclOutputInfo); + int32_t blockWidth = (rank == 3) ? 1 : armnn::numeric_cast(descriptor.m_BlockShape[1]); + + unsigned int padLeft = (rank == 3) ? 0 : descriptor.m_PadList[1].first; + unsigned int padRight = (rank == 3) ? 0 : descriptor.m_PadList[1].second; + arm_compute::Size2D paddingLeftTop = BuildArmComputeSize2D(padLeft, + descriptor.m_PadList[0].first); + arm_compute::Size2D paddingRightBottom = BuildArmComputeSize2D(padRight, + descriptor.m_PadList[0].second); + + const arm_compute::Status aclStatus = arm_compute::CLSpaceToBatchLayer::validate(&aclInputInfo, + blockWidth, + blockHeight, + paddingLeftTop, + paddingRightBottom, + &aclOutputInfo); + + if (statusReshapeInput.error_code() == arm_compute::ErrorCode::OK && + statusReshapeOutput.error_code() == arm_compute::ErrorCode::OK && + statusSpaceToBatch.error_code() == arm_compute::ErrorCode::OK) + { + return arm_compute::Status(arm_compute::ErrorCode::OK, + "All SpaceToBatch layers validate status OK."); + } + else + { + return arm_compute::Status(arm_compute::ErrorCode::RUNTIME_ERROR, + "SpaceToBatch layer validate status failed." + + statusSpaceToBatch.error_description() + + statusReshapeInput.error_description() + + statusReshapeOutput.error_description()); + } } -ClSpaceToBatchNdWorkload::ClSpaceToBatchNdWorkload( - const SpaceToBatchNdQueueDescriptor& descriptor, - const WorkloadInfo& info, - const arm_compute::CLCompileContext& clCompileContext) +ClSpaceToBatchNdWorkload::ClSpaceToBatchNdWorkload(const SpaceToBatchNdQueueDescriptor& descriptor, + const WorkloadInfo& info, + const arm_compute::CLCompileContext& clCompileContext) : ClBaseWorkload(descriptor, info) { // Report Profiling Details @@ -58,40 +103,90 @@ ClSpaceToBatchNdWorkload::ClSpaceToBatchNdWorkload( m_Data.ValidateInputsOutputs("ClSpaceToBatchNdWorkload", 1, 1); - arm_compute::ICLTensor& input = - armnn::PolymorphicPointerDowncast(m_Data.m_Inputs[0])->GetTensor(); - arm_compute::ICLTensor& output = - armnn::PolymorphicPointerDowncast(m_Data.m_Outputs[0])->GetTensor(); - - // ArmNN blockShape is [H, W] Cl asks for W, H - int32_t blockHeight = armnn::numeric_cast(m_Data.m_Parameters.m_BlockShape[0]); - int32_t blockWidth = armnn::numeric_cast(m_Data.m_Parameters.m_BlockShape[1]); - - arm_compute::Size2D paddingLeftTop = BuildArmComputeSize2D( - m_Data.m_Parameters.m_PadList[1].first, m_Data.m_Parameters.m_PadList[0].first); - arm_compute::Size2D paddingRightBottom = BuildArmComputeSize2D( - m_Data.m_Parameters.m_PadList[1].second, m_Data.m_Parameters.m_PadList[0].second); + arm_compute::ICLTensor& input = PolymorphicPointerDowncast(m_Data.m_Inputs[0])->GetTensor(); + arm_compute::ICLTensor& output = PolymorphicPointerDowncast(m_Data.m_Outputs[0])->GetTensor(); arm_compute::DataLayout aclDataLayout = ConvertDataLayout(m_Data.m_Parameters.m_DataLayout); input.info()->set_data_layout(aclDataLayout); output.info()->set_data_layout(aclDataLayout); + arm_compute::TensorInfo aclReshapeInputInfo = BuildArmComputeTensorInfo(info.m_InputTensorInfos[0], + m_Data.m_Parameters.m_DataLayout); + arm_compute::TensorInfo aclReshapeOutputInfo = BuildArmComputeTensorInfo(info.m_OutputTensorInfos[0], + m_Data.m_Parameters.m_DataLayout); + + const unsigned int rank = info.m_InputTensorInfos[0].GetNumDimensions(); + if (rank == 3) + { + const arm_compute::TensorShape inputShape = input.info()->tensor_shape(); + const arm_compute::TensorShape outputShape = output.info()->tensor_shape(); + + // When a spacial dimension is missing set W to 1 + if (m_Data.m_Parameters.m_DataLayout == armnn::DataLayout::NHWC) + { + // In ACL dimensions are right to left: C, W, H, N + aclReshapeInputInfo.set_tensor_shape({inputShape.x(), 1, inputShape.y(), inputShape.z()}); + aclReshapeOutputInfo.set_tensor_shape({outputShape.x(), 1, outputShape.y(), outputShape.z()}); + } + else if (m_Data.m_Parameters.m_DataLayout == armnn::DataLayout::NCHW) + { + // In ACL dimensions are right to left: W, H, C, N + aclReshapeInputInfo.set_tensor_shape({1, inputShape.x(), inputShape.y(), inputShape.z()}); + aclReshapeOutputInfo.set_tensor_shape({1, outputShape.x(), outputShape.y(), outputShape.z()}); + } + else + { + throw InvalidArgumentException("Unsupported or unknown DataLayout", CHECK_LOCATION()); + } + + m_ReshapeInputTensor.allocator()->init(aclReshapeInputInfo); + m_ReshapeOutputTensor.allocator()->init(aclReshapeOutputInfo); + + InitialiseArmComputeTensorEmpty(m_ReshapeInputTensor); + InitialiseArmComputeTensorEmpty(m_ReshapeOutputTensor); + + m_LayerReshapeInput.reset(new arm_compute::CLReshapeLayer()); + m_LayerReshapeOutput.reset(new arm_compute::CLReshapeLayer()); + + m_LayerReshapeInput->configure(clCompileContext, &input, &m_ReshapeInputTensor); + m_LayerReshapeOutput->configure(clCompileContext, &m_ReshapeOutputTensor, &output); + } + + // ArmNN blockShape is [H, W] ACl asks for W, H + int32_t blockHeight = armnn::numeric_cast(m_Data.m_Parameters.m_BlockShape[0]); + int32_t blockWidth = (rank == 3) ? 1: armnn::numeric_cast(descriptor.m_Parameters.m_BlockShape[1]); + + unsigned int padLeft = (rank == 3) ? 0 : descriptor.m_Parameters.m_PadList[1].first; + unsigned int padRight = (rank == 3) ? 0 : descriptor.m_Parameters.m_PadList[1].second; + arm_compute::Size2D paddingLeftTop = BuildArmComputeSize2D(padLeft, + descriptor.m_Parameters.m_PadList[0].first); + arm_compute::Size2D paddingRightBottom = BuildArmComputeSize2D(padRight, + descriptor.m_Parameters.m_PadList[0].second); + { ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "ClSpaceToBatchNdWorkload_configure"); - m_SpaceToBatchLayer.configure(clCompileContext, - &input, - blockWidth, - blockHeight, - paddingLeftTop, - paddingRightBottom, - &output); + m_Layer.configure(clCompileContext, + rank == 3 ? &m_ReshapeInputTensor : &input, + blockWidth, + blockHeight, + paddingLeftTop, + paddingRightBottom, + rank == 3 ? &m_ReshapeOutputTensor : &output); } } void ClSpaceToBatchNdWorkload::Execute() const { ARMNN_SCOPED_PROFILING_EVENT_CL_GUID("ClSpaceToBatchNdWorkload_Execute", this->GetGuid()); - RunClFunction(m_SpaceToBatchLayer, CHECK_LOCATION()); + if (m_LayerReshapeInput) + { + m_LayerReshapeInput->run(); + } + RunClFunction(m_Layer, CHECK_LOCATION()); + if (m_LayerReshapeOutput) + { + m_LayerReshapeOutput->run(); + } } } //namespace armnn diff --git a/src/backends/cl/workloads/ClSpaceToBatchNdWorkload.hpp b/src/backends/cl/workloads/ClSpaceToBatchNdWorkload.hpp index 948d13b934..a577c06fea 100644 --- a/src/backends/cl/workloads/ClSpaceToBatchNdWorkload.hpp +++ b/src/backends/cl/workloads/ClSpaceToBatchNdWorkload.hpp @@ -1,16 +1,15 @@ // -// Copyright © 2017 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2017, 2020-2023 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // #pragma once -#include -#include - #include "ClBaseWorkload.hpp" +#include "ClWorkloadUtils.hpp" #include +#include namespace armnn { @@ -25,10 +24,14 @@ public: ClSpaceToBatchNdWorkload(const SpaceToBatchNdQueueDescriptor& descriptor, const WorkloadInfo& info, const arm_compute::CLCompileContext& clCompileContext); - void Execute() const override; + virtual void Execute() const override; private: - mutable arm_compute::CLSpaceToBatchLayer m_SpaceToBatchLayer; + mutable arm_compute::CLSpaceToBatchLayer m_Layer; + mutable std::unique_ptr m_LayerReshapeInput; + mutable std::unique_ptr m_LayerReshapeOutput; + arm_compute::CLTensor m_ReshapeInputTensor; + arm_compute::CLTensor m_ReshapeOutputTensor; }; } //namespace armnn -- cgit v1.2.1