From 9145e38edf49fa4862008c163c34590141eecb14 Mon Sep 17 00:00:00 2001 From: Teresa Charlin Date: Thu, 17 Aug 2023 18:44:58 +0100 Subject: IVGCVSW-7505 Create FusedLayer and NeonFusedWorkload for AddMulAdd Neon kernel Signed-off-by: Teresa Charlin Change-Id: Ic778d35b001474b44fb1e433a6fe276e4ec9f565 --- .../test/layerTests/AddMulAddTestImpl.hpp | 182 +++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 src/backends/backendsCommon/test/layerTests/AddMulAddTestImpl.hpp (limited to 'src/backends/backendsCommon/test/layerTests') diff --git a/src/backends/backendsCommon/test/layerTests/AddMulAddTestImpl.hpp b/src/backends/backendsCommon/test/layerTests/AddMulAddTestImpl.hpp new file mode 100644 index 0000000000..9dece9be3b --- /dev/null +++ b/src/backends/backendsCommon/test/layerTests/AddMulAddTestImpl.hpp @@ -0,0 +1,182 @@ +// +// Copyright © 2023 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include + +template> +std::vector> AddMulAddTest(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const armnn::ITensorHandleFactory& tensorHandleFactory, + bool addOutput) +{ + using namespace armnn; + IgnoreUnused(memoryManager); + + TensorInfo input0TensorInfo({ 1, 2, 2, 3 }, ArmnnType); + TensorInfo input1TensorInfo({ 1, 2, 2, 3 }, ArmnnType); + TensorInfo mulInput1TensorInfo({ 3 }, ArmnnType); + TensorInfo addInput1TensorInfo({ 3 }, ArmnnType); + + TensorInfo output0TensorInfo({ 1, 2, 2, 3 }, ArmnnType); + TensorInfo output1TensorInfo({ 1, 2, 2, 3 }, ArmnnType); + + if (IsQuantizedType()) + { + input0TensorInfo.SetQuantizationScale(0.25f); + input0TensorInfo.SetQuantizationOffset(128); + input1TensorInfo.SetQuantizationScale(0.25f); + input1TensorInfo.SetQuantizationOffset(128); + mulInput1TensorInfo.SetQuantizationScale(0.25f); + mulInput1TensorInfo.SetQuantizationOffset(128); + addInput1TensorInfo.SetQuantizationScale(0.25f); + addInput1TensorInfo.SetQuantizationOffset(128); + + output0TensorInfo.SetQuantizationScale(0.5f); + output0TensorInfo.SetQuantizationOffset(120); + output1TensorInfo.SetQuantizationScale(0.5f); + output1TensorInfo.SetQuantizationOffset(120); + } + + std::vector input0Data + { + 0.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, + -2.0f, -2.0f, -2.0f + }; + std::vector input1Data + { + 0.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, + -2.0f, -2.0f, -2.0f + }; + std::vector mulInput1Data + { + 2.0f, 1.0f, 1.0f + }; + std::vector addInput1Data + { + 3.0f, 0.0f, 0.0f + }; + std::vector output0ExpectedData = + { + 0.0f, 0.0f, 0.0f, + 2.0f, 2.0f, 2.0f, + -2.0f, -2.0f, -2.0f, + -4.0f, -4.0f, -4.0f + }; + + std::vector output1ExpectedData = + { + 3.0f, 0.0f, 0.0f, + 7.0f, 2.0f, 2.0f, + -1.0f, -2.0f, -2.0f, + -5.0f, -4.0f, -4.0f + }; + + std::vector input0 = armnnUtils::QuantizedVector(input0Data, + input0TensorInfo.GetQuantizationScale(), + input0TensorInfo.GetQuantizationOffset()); + + std::vector input1 = armnnUtils::QuantizedVector(input1Data, + input1TensorInfo.GetQuantizationScale(), + input1TensorInfo.GetQuantizationOffset()); + + std::vector mulInput1 = armnnUtils::QuantizedVector(mulInput1Data, + mulInput1TensorInfo.GetQuantizationScale(), + mulInput1TensorInfo.GetQuantizationOffset()); + + std::vector addInput1 = armnnUtils::QuantizedVector(addInput1Data, + addInput1TensorInfo.GetQuantizationScale(), + addInput1TensorInfo.GetQuantizationOffset()); + + std::vector output0Expected = armnnUtils::QuantizedVector(output0ExpectedData, + output0TensorInfo.GetQuantizationScale(), + output0TensorInfo.GetQuantizationOffset()); + + std::vector output1Expected = armnnUtils::QuantizedVector(output1ExpectedData, + output1TensorInfo.GetQuantizationScale(), + output1TensorInfo.GetQuantizationOffset()); + + std::vector output0Actual(output0TensorInfo.GetNumElements()); + std::vector output1Actual(output1TensorInfo.GetNumElements()); + + std::unique_ptr input0Handle = tensorHandleFactory.CreateTensorHandle(input0TensorInfo); + std::unique_ptr input1Handle = tensorHandleFactory.CreateTensorHandle(input1TensorInfo); + std::unique_ptr mulInput1Handle = tensorHandleFactory.CreateTensorHandle(mulInput1TensorInfo); + std::unique_ptr addInput1Handle = tensorHandleFactory.CreateTensorHandle(addInput1TensorInfo); + std::unique_ptr output0Handle = tensorHandleFactory.CreateTensorHandle(output0TensorInfo); + std::unique_ptr output1Handle = tensorHandleFactory.CreateTensorHandle(output1TensorInfo); + + uint32_t numOutputs = addOutput ? 2 : 1; + FusedDescriptor descriptor(4, numOutputs, FusedKernelType::AddMulAdd); + FusedQueueDescriptor fusedQueueDescriptor; + fusedQueueDescriptor.m_Parameters = descriptor; + WorkloadInfo info; + AddInputToWorkload (fusedQueueDescriptor, info, input0TensorInfo, input0Handle.get()); + AddInputToWorkload (fusedQueueDescriptor, info, input1TensorInfo, input1Handle.get()); + AddInputToWorkload (fusedQueueDescriptor, info, mulInput1TensorInfo, mulInput1Handle.get()); + AddInputToWorkload (fusedQueueDescriptor, info, addInput1TensorInfo, addInput1Handle.get()); + if (addOutput) + { + AddOutputToWorkload(fusedQueueDescriptor, info, output0TensorInfo, output0Handle.get()); + } + AddOutputToWorkload(fusedQueueDescriptor, info, output1TensorInfo, output1Handle.get()); + + std::unique_ptr workload = workloadFactory.CreateWorkload(LayerType::Fused, + fusedQueueDescriptor, + info); + + input0Handle->Allocate(); + input1Handle->Allocate(); + mulInput1Handle->Allocate(); + addInput1Handle->Allocate(); + if (addOutput) + { + output0Handle->Allocate(); + } + output1Handle->Allocate(); + + CopyDataToITensorHandle(input0Handle.get(), input0.data()); + CopyDataToITensorHandle(input1Handle.get(), input1.data()); + CopyDataToITensorHandle(mulInput1Handle.get(), mulInput1.data()); + CopyDataToITensorHandle(addInput1Handle.get(), addInput1.data()); + + workload->Execute(); + + CopyDataFromITensorHandle(output1Actual.data(), output1Handle.get()); + LayerTestResult ret1(output1Actual, + output1Expected, + output1Handle->GetShape(), + output1TensorInfo.GetShape()); + + std::vector> ret = {ret1}; + + if (addOutput) + { + CopyDataFromITensorHandle(output0Actual.data(), output0Handle.get()); + LayerTestResult ret0(output0Actual, + output0Expected, + output0Handle->GetShape(), + output0TensorInfo.GetShape()); + ret = {ret0, ret1}; + } + return ret; +} -- cgit v1.2.1