From 0690265d83e5aa79bd174544a7b35330781619dd Mon Sep 17 00:00:00 2001 From: Cathal Corbett Date: Thu, 14 Apr 2022 17:55:11 +0100 Subject: IVGCVSW-6127 ConstTensorsAsInput: DepthwiseConvolution2d !android-nn-driver:7418 * Update Front-end and Tools. * Updated Serializer, Deserializer and unit tests to reflect this. * Updated TfLiteDelegate, TfLiteParser and OnnxParser. * Change NNDriver to new API. * Updated Ref. * Neon and Cl backend partially completed (Backend.cpp files). * Added dynamic or constant input EndToEnd tests. * Added ConstantTensorAsInputMemeberVariableRedirect Optimization. Signed-off-by: Cathal Corbett Change-Id: Ib18b6c10a093042e165e25237dc04a4c67ba82da --- src/backends/backendsCommon/WorkloadData.cpp | 16 +- src/backends/backendsCommon/WorkloadFactory.cpp | 28 ++-- src/backends/backendsCommon/test/CMakeLists.txt | 1 + .../test/DepthwiseConvolution2dEndToEndTests.hpp | 183 +++++++++++++++++++++ .../backendsCommon/test/OptimizationViewsTests.cpp | 6 +- .../test/layerTests/Conv2dTestImpl.cpp | 143 +++++++++++++--- 6 files changed, 327 insertions(+), 50 deletions(-) create mode 100644 src/backends/backendsCommon/test/DepthwiseConvolution2dEndToEndTests.hpp (limited to 'src/backends/backendsCommon') diff --git a/src/backends/backendsCommon/WorkloadData.cpp b/src/backends/backendsCommon/WorkloadData.cpp index d89b5899ba..7a46741964 100644 --- a/src/backends/backendsCommon/WorkloadData.cpp +++ b/src/backends/backendsCommon/WorkloadData.cpp @@ -1382,7 +1382,13 @@ void DepthwiseConvolution2dQueueDescriptor::Validate(const WorkloadInfo& workloa { const std::string descriptorName{"DepthwiseConvolution2dQueueDescriptor"}; - ValidateNumInputs(workloadInfo, descriptorName, 1); + uint32_t numInputs = 2; + if (m_Parameters.m_BiasEnabled) + { + numInputs = 3; + } + + ValidateNumInputs(workloadInfo, descriptorName, numInputs); ValidateNumOutputs(workloadInfo, descriptorName, 1); const TensorInfo& inputTensorInfo = workloadInfo.m_InputTensorInfos[0]; @@ -1391,9 +1397,7 @@ void DepthwiseConvolution2dQueueDescriptor::Validate(const WorkloadInfo& workloa ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input"); ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output"); - ValidatePointer(m_Weight, descriptorName, "weight"); - - const TensorInfo& weightTensorInfo = m_Weight->GetTensorInfo(); + const TensorInfo& weightTensorInfo = workloadInfo.m_InputTensorInfos[1]; ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 4, "weight"); if (m_Parameters.m_DilationX < 1 || m_Parameters.m_DilationY < 1 ) @@ -1447,9 +1451,7 @@ void DepthwiseConvolution2dQueueDescriptor::Validate(const WorkloadInfo& workloa Optional optionalBiasTensorInfo; if (m_Parameters.m_BiasEnabled) { - ValidatePointer(m_Bias, descriptorName, "bias"); - - optionalBiasTensorInfo = MakeOptional(m_Bias->GetTensorInfo()); + optionalBiasTensorInfo = MakeOptional(workloadInfo.m_InputTensorInfos[2]); const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value(); ValidateBiasTensorQuantization(biasTensorInfo, inputTensorInfo, weightTensorInfo, descriptorName); diff --git a/src/backends/backendsCommon/WorkloadFactory.cpp b/src/backends/backendsCommon/WorkloadFactory.cpp index 5847e8cc21..f624ee6021 100644 --- a/src/backends/backendsCommon/WorkloadFactory.cpp +++ b/src/backends/backendsCommon/WorkloadFactory.cpp @@ -324,10 +324,13 @@ bool IWorkloadFactory::IsLayerConfigurationSupported(const BackendId& backendId, case LayerType::DepthwiseConvolution2d: { auto cLayer = PolymorphicDowncast(&layer); - const TensorInfo& input = OverrideDataType(layer.GetInputSlot(0).GetConnection()->GetTensorInfo(), - dataType); - const TensorInfo& output = OverrideDataType(layer.GetOutputSlot(0).GetTensorInfo(), dataType); - ARMNN_ASSERT(cLayer->m_Weight.get() != nullptr); + const TensorInfo& input = OverrideDataType(layer.GetInputSlot(0).GetConnection()->GetTensorInfo(), + dataType); + const TensorInfo& output = OverrideDataType(layer.GetOutputSlot(0).GetTensorInfo(), dataType); + const TensorInfo& weights = OverrideDataType(layer.GetInputSlot(1).GetConnection()->GetTensorInfo(), + dataType); + + ARMNN_ASSERT(cLayer->GetInputSlot(1).GetConnection() != nullptr); const DepthwiseConvolution2dDescriptor& descriptor = cLayer->GetParameters(); @@ -335,17 +338,16 @@ bool IWorkloadFactory::IsLayerConfigurationSupported(const BackendId& backendId, Optional biases; if (descriptor.m_BiasEnabled) { - biases = - OverrideDataType(cLayer->m_Bias->GetTensorInfo(), GetBiasTypeFromWeightsType(dataType)); + biases = OverrideDataType(cLayer->GetInputSlot(2).GetConnection()->GetTensorInfo(), + GetBiasTypeFromWeightsType(dataType)); } - result = layerSupportObject.IsDepthwiseConvolutionSupported( - input, - output, - descriptor, - OverrideDataType(cLayer->m_Weight->GetTensorInfo(), dataType), - biases, - reason); + result = layerSupportObject.IsDepthwiseConvolutionSupported(input, + output, + descriptor, + weights, + biases, + reason); break; } case LayerType::Dequantize: diff --git a/src/backends/backendsCommon/test/CMakeLists.txt b/src/backends/backendsCommon/test/CMakeLists.txt index 06d230b006..991f37d17e 100644 --- a/src/backends/backendsCommon/test/CMakeLists.txt +++ b/src/backends/backendsCommon/test/CMakeLists.txt @@ -21,6 +21,7 @@ list(APPEND armnnBackendsCommonUnitTests_sources DataTypeUtils.hpp DefaultAsyncExecuteTest.cpp DepthToSpaceEndToEndTestImpl.hpp + DepthwiseConvolution2dEndToEndTests.hpp DequantizeEndToEndTestImpl.hpp DetectionPostProcessEndToEndTestImpl.hpp DynamicBackendTests.cpp diff --git a/src/backends/backendsCommon/test/DepthwiseConvolution2dEndToEndTests.hpp b/src/backends/backendsCommon/test/DepthwiseConvolution2dEndToEndTests.hpp new file mode 100644 index 0000000000..1f9b60a4f2 --- /dev/null +++ b/src/backends/backendsCommon/test/DepthwiseConvolution2dEndToEndTests.hpp @@ -0,0 +1,183 @@ +// +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// +#pragma once + +#include "EndToEndTestImpl.hpp" +#include + +#include + +#include +#include + +#include +#include + +namespace +{ + +armnn::INetworkPtr CreateDepthwiseConvolution2dNetwork(const armnn::DepthwiseConvolution2dDescriptor& descriptor, + const armnn::TensorInfo& inputInfo, + const armnn::TensorInfo& weightsInfo, + const armnn::TensorInfo& biasInfo, + const armnn::TensorInfo& outputInfo, + const armnn::ConstTensor& weights, + const armnn::ConstTensor& biases) +{ + using namespace armnn; + + INetworkPtr network(INetwork::Create()); + IConnectableLayer* input = network->AddInputLayer(0, "input"); + armnn::IConnectableLayer* weightsLayer = network->AddConstantLayer(weights, "Weights"); + armnn::IConnectableLayer* biasLayer = network->AddConstantLayer(biases, "Bias"); + IConnectableLayer* convolution2d = network->AddDepthwiseConvolution2dLayer(descriptor, "depthwiseConvolution2d"); + IConnectableLayer* output = network->AddOutputLayer(0, "output"); + + Connect(input, convolution2d, inputInfo, 0, 0); + Connect(weightsLayer, convolution2d, weightsInfo, 0, 1); + Connect(biasLayer, convolution2d, biasInfo, 0, 2); + Connect(convolution2d, output, outputInfo, 0, 0); + + return network; +} + +} // anonymous namespace + +template +void DepthwiseConvolution2dEndToEnd(const std::vector& backends, + armnn::DataLayout dataLayout) +{ + using namespace armnn; + using T = ResolveType; + using BT = ResolveType; + + const float qScale = IsQuantizedType() ? 0.25f : 1.0f; + const int32_t qOffset = IsQuantizedType() ? 50 : 0; + + unsigned int depthMultiplier = 2; + + unsigned int inputHeight = 8; + unsigned int inputWidth = 16; + unsigned int inputChannels = 2; + unsigned int inputBatchSize = 1; + + unsigned int kernelHeight = 5; + unsigned int kernelWidth = 3; + + unsigned int outputHeight = inputHeight - kernelHeight + 1 + 2; + unsigned int outputWidth = (inputWidth - kernelWidth + 1)/2; + unsigned int outputChannels = inputChannels * depthMultiplier; + unsigned int outputBatchSize = inputBatchSize; + + TensorInfo inputInfo({ inputBatchSize, inputChannels, inputHeight, inputWidth }, ArmnnType, qScale, qOffset, true); + TensorInfo outputInfo({ outputBatchSize, outputChannels, outputHeight, outputWidth }, ArmnnType, qScale, qOffset); + TensorInfo weightsInfo({1, kernelHeight, kernelWidth, outputChannels}, ArmnnType, qScale, qOffset, true); + TensorInfo biasesInfo({outputChannels}, ArmnnBType, qScale * qScale, 0, true); + + std::vector inputData = + { + 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f + }; + + std::vector weightsData = + { + 1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + + 2.0f, 2.0f, 2.0f, + 2.0f, 2.0f, 2.0f, + 2.0f, 2.0f, 2.0f, + 2.0f, 2.0f, 2.0f, + 2.0f, 2.0f, 2.0f, + + 0.0f, 0.0f, 0.0f, + 0.0f, -1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, + + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f + }; + + std::vector biasesData = { 0.0f, 2.0f, 1.0f, -1.0f }; + + std::vector expectedOutputData = + { + 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, + 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.5f, 5.5f, 5.5f, 5.5f, 5.5f, 5.5f, 5.5f, + 5.5f, 5.5f, 5.5f, 5.5f, 5.5f, 5.5f, 5.5f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, + 2.5f, 2.5f, 2.5f, 2.5f, 2.5f, 2.5f, 2.5f, 3.5f, 3.5f, 3.5f, 3.5f, 3.5f, 3.5f, 3.5f, + 4.5f, 4.5f, 4.5f, 4.5f, 4.5f, 4.5f, 4.5f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, + 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, + 1.0f, 3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, 4.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 2.0f, 4.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, 4.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 2.0f, 4.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, 4.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 2.0f, 4.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 3.0f, 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 3.0f, 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 3.0f, 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 3.0f, 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 3.0f, 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f + }; + + DepthwiseConvolution2dDescriptor descriptor; + descriptor.m_PadLeft = 0; + descriptor.m_PadRight = 0; + descriptor.m_PadTop = 1; + descriptor.m_PadBottom = 0; + descriptor.m_StrideX = 2; + descriptor.m_StrideY = 1; + descriptor.m_BiasEnabled = true; + descriptor.m_DataLayout = dataLayout; + + // Permute input and output if NCDHW. + if (dataLayout == DataLayout::NCHW) + { + PermuteTensorNhwcToNchw(inputInfo, inputData); + PermuteTensorNhwcToNchw(outputInfo, expectedOutputData); + } + + // Quantize data + std::vector qInputData = armnnUtils::QuantizedVector(inputData, qScale, qOffset); + std::vector qWeightsData = armnnUtils::QuantizedVector(weightsData, qScale, qOffset); + std::vector qExpectedOutputData = armnnUtils::QuantizedVector(expectedOutputData, qScale, qOffset); + + std::vector qBiasesData = armnnUtils::QuantizedVector(biasesData, qScale * qScale, 0); + + ConstTensor weights(weightsInfo, qWeightsData); + ConstTensor biases(biasesInfo, qBiasesData); + + INetworkPtr network = CreateDepthwiseConvolution2dNetwork(descriptor, + inputInfo, + weightsInfo, + biasesInfo, + outputInfo, + weights, + biases); + + EndToEndLayerTestImpl(std::move(network), + { { 0, qInputData } }, + { { 0, qExpectedOutputData } }, + backends); +} diff --git a/src/backends/backendsCommon/test/OptimizationViewsTests.cpp b/src/backends/backendsCommon/test/OptimizationViewsTests.cpp index f0f5b632de..1219ac5a33 100644 --- a/src/backends/backendsCommon/test/OptimizationViewsTests.cpp +++ b/src/backends/backendsCommon/test/OptimizationViewsTests.cpp @@ -128,20 +128,16 @@ TEST_CASE("OptimizedViewsSubgraphLayerCountUsingGetINetwork") IConnectableLayer* const inputLayer = view.GetINetwork()->AddInputLayer(0, "input"); DepthwiseConvolution2dDescriptor convDescriptor; - PreCompiledDescriptor substitutionLayerDescriptor(1, 1); + PreCompiledDescriptor substitutionLayerDescriptor(2, 1); CompiledBlobPtr blobPtr; BackendId backend = Compute::CpuRef; Layer* convLayer1 = PolymorphicDowncast( view.GetINetwork()->AddDepthwiseConvolution2dLayer(convDescriptor, - ConstTensor(), - Optional(), "conv1")); Layer* convLayer2 = PolymorphicDowncast( view.GetINetwork()->AddDepthwiseConvolution2dLayer(convDescriptor, - ConstTensor(), - Optional(), "conv2")); IConnectableLayer* const outputLayer = view.GetINetwork()->AddOutputLayer(0, "output"); diff --git a/src/backends/backendsCommon/test/layerTests/Conv2dTestImpl.cpp b/src/backends/backendsCommon/test/layerTests/Conv2dTestImpl.cpp index bd7cc40f27..4203fed23a 100644 --- a/src/backends/backendsCommon/test/layerTests/Conv2dTestImpl.cpp +++ b/src/backends/backendsCommon/test/layerTests/Conv2dTestImpl.cpp @@ -1736,19 +1736,38 @@ LayerTestResult DepthwiseConvolution2dAsymmetricTestImpl( } std::unique_ptr inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo); + std::unique_ptr weightsHandle = tensorHandleFactory.CreateTensorHandle(kernelDesc); + std::unique_ptr biasHandle = nullptr; std::unique_ptr outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo); + armnn::DepthwiseConvolution2dQueueDescriptor data; + armnn::WorkloadInfo info; + armnn::ScopedTensorHandle weightsTensor(kernelDesc); + // AllocateAndCopyDataToITensorHandle() is required twice for the weights AND biases: + // 1) ScopedTensorHandle (weightsTensor) required for QueueDescriptor (data.m_Weight). + // Needed in Neon and Cl Workload when permuting. Backend TensorHandle in (2) below will not work. + // 2) ITensorHandle (converts to Backend TensorHandle) required in RefWorkload for GetTensorInfo() method. + // Cannot PolymorphicDowncast from ScopedTensorHandle->RefTensorHandle. + // Need to PolymorphicDowncast from ITensorHandle->RefTensorHandle. AllocateAndCopyDataToITensorHandle(&weightsTensor, kernel.data()); + AllocateAndCopyDataToITensorHandle(weightsHandle.get(), kernel.data()); // required for ConstantTensor + + AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get()); + AddInputToWorkload(data, info, kernelDesc, weightsHandle.get()); + AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get()); armnn::ScopedTensorHandle biasTensor(biasDesc); if (biasEnabled) { AllocateAndCopyDataToITensorHandle(&biasTensor, bias.data()); + + biasHandle = tensorHandleFactory.CreateTensorHandle(biasDesc); + AllocateAndCopyDataToITensorHandle(biasHandle.get(), bias.data()); + AddInputToWorkload(data, info, biasDesc, biasHandle.get()); } - armnn::DepthwiseConvolution2dQueueDescriptor data; data.m_Weight = &weightsTensor; data.m_Bias = &biasTensor; // Still set this whether or not bias is enabled - it can be a source of bugs. data.m_Parameters.m_StrideX = strideX; @@ -1760,12 +1779,9 @@ LayerTestResult DepthwiseConvolution2dAsymmetricTestImpl( data.m_Parameters.m_BiasEnabled = biasEnabled; data.m_Parameters.m_DataLayout = layout; - armnn::WorkloadInfo info; - AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get()); - AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get()); - std::unique_ptr workload = workloadFactory.CreateWorkload(armnn::LayerType::DepthwiseConvolution2d, data, info); + inputHandle->Allocate(); outputHandle->Allocate(); @@ -1890,19 +1906,35 @@ LayerTestResult DepthwiseConvolution2dDepthMul1TestImpl( std::vector actualOutput(outputTensorInfo.GetNumElements()); std::unique_ptr inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo); + std::unique_ptr weightsHandle = tensorHandleFactory.CreateTensorHandle(kernelDesc); + std::unique_ptr biasHandle = nullptr; std::unique_ptr outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo); armnn::DepthwiseConvolution2dQueueDescriptor data; armnn::WorkloadInfo info; - armnn::ScopedTensorHandle weightsTensor(kernelDesc); - armnn::ScopedTensorHandle biasTensor(biasDesc); - AllocateAndCopyDataToITensorHandle(&weightsTensor, kernelData.data()); - AllocateAndCopyDataToITensorHandle(&biasTensor, biasV.data()); + armnn::ScopedTensorHandle weightsTensor(kernelDesc); + // AllocateAndCopyDataToITensorHandle() is required twice for the weights AND biases: + // See comment in DepthwiseConvolution2dAsymmetricTestImpl() for reasons. + // 1) ScopedTensorHandle (weightsTensor) required for QueueDescriptor (data.m_Weight). + // 2) ITensorHandle (converts to Backend TensorHandle) required in RefWorkload for GetTensorInfo() method. + AllocateAndCopyDataToITensorHandle(&weightsTensor, kernelData.data()); // required for QueueDescriptor + AllocateAndCopyDataToITensorHandle(weightsHandle.get(), kernelData.data()); // required for ConstantTensor AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get()); + AddInputToWorkload(data, info, kernelDesc, weightsHandle.get()); AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get()); + armnn::ScopedTensorHandle biasTensor(biasDesc); + if (biasEnabled) + { + AllocateAndCopyDataToITensorHandle(&biasTensor, biasV.data()); + + biasHandle = tensorHandleFactory.CreateTensorHandle(biasDesc); + AllocateAndCopyDataToITensorHandle(biasHandle.get(), biasV.data()); + AddInputToWorkload(data, info, biasDesc, biasHandle.get()); + } + data.m_Weight = &weightsTensor; data.m_Bias = &biasTensor; // Still set this whether or not bias is enabled. data.m_Parameters.m_StrideX = 1; @@ -1916,6 +1948,7 @@ LayerTestResult DepthwiseConvolution2dDepthMul1TestImpl( std::unique_ptr workload = workloadFactory.CreateWorkload(armnn::LayerType::DepthwiseConvolution2d, data, info); + inputHandle->Allocate(); outputHandle->Allocate(); @@ -2086,19 +2119,35 @@ LayerTestResult DepthwiseConvolution2dTestImpl( std::vector actualOutput(outputTensorInfo.GetNumElements()); std::unique_ptr inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo); + std::unique_ptr weightsHandle = tensorHandleFactory.CreateTensorHandle(kernelDesc); + std::unique_ptr biasHandle = nullptr; std::unique_ptr outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo); armnn::DepthwiseConvolution2dQueueDescriptor data; armnn::WorkloadInfo info; - armnn::ScopedTensorHandle weightsTensor(kernelDesc); - armnn::ScopedTensorHandle biasTensor(biasDesc); - AllocateAndCopyDataToITensorHandle(&weightsTensor, kernelData.data()); - AllocateAndCopyDataToITensorHandle(&biasTensor, biasV.data()); + armnn::ScopedTensorHandle weightsTensor(kernelDesc); + // AllocateAndCopyDataToITensorHandle() is required twice for the weights AND biases: + // See comment in DepthwiseConvolution2dAsymmetricTestImpl() for reasons. + // 1) ScopedTensorHandle (weightsTensor) required for QueueDescriptor (data.m_Weight). + // 2) ITensorHandle (converts to Backend TensorHandle) required in RefWorkload for GetTensorInfo() method. + AllocateAndCopyDataToITensorHandle(&weightsTensor, kernelData.data()); // required for QueueDescriptor + AllocateAndCopyDataToITensorHandle(weightsHandle.get(), kernelData.data()); // required for ConstantTensor AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get()); + AddInputToWorkload(data, info, kernelDesc, weightsHandle.get()); AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get()); + armnn::ScopedTensorHandle biasTensor(biasDesc); + if (biasEnabled) + { + AllocateAndCopyDataToITensorHandle(&biasTensor, biasV.data()); + + biasHandle = tensorHandleFactory.CreateTensorHandle(biasDesc); + AllocateAndCopyDataToITensorHandle(biasHandle.get(), biasV.data()); + AddInputToWorkload(data, info, biasDesc, biasHandle.get()); + } + data.m_Weight = &weightsTensor; data.m_Bias = &biasTensor; // Still set this whether or not bias is enabled. data.m_Parameters.m_StrideX = 2; @@ -2112,6 +2161,7 @@ LayerTestResult DepthwiseConvolution2dTestImpl( std::unique_ptr workload = workloadFactory.CreateWorkload(armnn::LayerType::DepthwiseConvolution2d, data, info); + inputHandle->Allocate(); outputHandle->Allocate(); @@ -2247,22 +2297,34 @@ LayerTestResult DepthwiseConvolution2dTestImpl( } std::unique_ptr inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo); + std::unique_ptr weightsHandle = tensorHandleFactory.CreateTensorHandle(kernelDesc); + std::unique_ptr biasHandle = nullptr; std::unique_ptr outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo); armnn::DepthwiseConvolution2dQueueDescriptor data; armnn::WorkloadInfo info; + armnn::ScopedTensorHandle weightsTensor(kernelDesc); - armnn::ScopedTensorHandle biasTensor(biasDesc); + // AllocateAndCopyDataToITensorHandle() is required twice for the weights AND biases: + // See comment in DepthwiseConvolution2dAsymmetricTestImpl() for reasons. + // 1) ScopedTensorHandle (weightsTensor) required for QueueDescriptor (data.m_Weight). + // 2) ITensorHandle (converts to Backend TensorHandle) required in RefWorkload for GetTensorInfo() method. + AllocateAndCopyDataToITensorHandle(&weightsTensor, originalKernel.data()); // required for QueueDescriptor + AllocateAndCopyDataToITensorHandle(weightsHandle.get(), originalKernel.data()); // required for ConstantTensor - AllocateAndCopyDataToITensorHandle(&weightsTensor, originalKernel.data()); + AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get()); + AddInputToWorkload(data, info, kernelDesc, weightsHandle.get()); + AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get()); - if(biasEnabled) + armnn::ScopedTensorHandle biasTensor(biasDesc); + if (biasEnabled) { AllocateAndCopyDataToITensorHandle(&biasTensor, bias.data()); - } - AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get()); - AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get()); + biasHandle = tensorHandleFactory.CreateTensorHandle(biasDesc); + AllocateAndCopyDataToITensorHandle(biasHandle.get(), bias.data()); + AddInputToWorkload(data, info, biasDesc, biasHandle.get()); + } data.m_Weight = &weightsTensor; data.m_Bias = &biasTensor; // Still set this whether or not bias is enabled - can be a source of bugs. @@ -2279,6 +2341,7 @@ LayerTestResult DepthwiseConvolution2dTestImpl( std::unique_ptr workload = workloadFactory.CreateWorkload(armnn::LayerType::DepthwiseConvolution2d, data, info); + inputHandle->Allocate(); outputHandle->Allocate(); @@ -2970,18 +3033,30 @@ LayerTestResult CompareDepthwiseConvolution2dTestImpl( std::vector expectedOutput(outputTensorInfo.GetNumElements()); std::unique_ptr inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo); + std::unique_ptr weightsHandle = tensorHandleFactory.CreateTensorHandle(kernelDesc); + std::unique_ptr biasHandle = tensorHandleFactory.CreateTensorHandle(biasDesc); std::unique_ptr outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo); armnn::DepthwiseConvolution2dQueueDescriptor data; armnn::WorkloadInfo info; + armnn::ScopedTensorHandle weightsTensor(kernelDesc); armnn::ScopedTensorHandle biasTensor(biasDesc); + AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get()); + AddInputToWorkload(data, info, kernelDesc, weightsHandle.get()); + AddInputToWorkload(data, info, biasDesc, biasHandle.get()); + AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get()); + + // AllocateAndCopyDataToITensorHandle() is required twice for the weights AND biases: + // See comment in DepthwiseConvolution2dAsymmetricTestImpl() for reasons. + // 1) ScopedTensorHandle (weightsTensor) required for QueueDescriptor (data.m_Weight). + // 2) ITensorHandle (converts to Backend TensorHandle) required in RefWorkload for GetTensorInfo() method. + AllocateAndCopyDataToITensorHandle(weightsHandle.get(), kernel.data()); AllocateAndCopyDataToITensorHandle(&weightsTensor, kernel.data()); + AllocateAndCopyDataToITensorHandle(biasHandle.get(), bias.data()); AllocateAndCopyDataToITensorHandle(&biasTensor, bias.data()); - AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get()); - AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get()); data.m_Weight = &weightsTensor; data.m_Bias = &biasTensor; data.m_Parameters.m_StrideX = strideX; @@ -2994,11 +3069,15 @@ LayerTestResult CompareDepthwiseConvolution2dTestImpl( data.m_Parameters.m_DataLayout = layout.GetDataLayout(); std::unique_ptr outputHandleRef = refTensorHandleFactory.CreateTensorHandle(outputTensorInfo); + std::unique_ptr weightsHandleRef = refTensorHandleFactory.CreateTensorHandle(kernelDesc); + std::unique_ptr biasHandleRef = refTensorHandleFactory.CreateTensorHandle(biasDesc); std::unique_ptr inputHandleRef = refTensorHandleFactory.CreateTensorHandle(inputTensorInfo); armnn::DepthwiseConvolution2dQueueDescriptor refData = data; armnn::WorkloadInfo refInfo = info; SetWorkloadInput(refData, refInfo, 0, inputTensorInfo, inputHandleRef.get()); + SetWorkloadInput(refData, refInfo, 1, kernelDesc, weightsHandleRef.get()); + SetWorkloadInput(refData, refInfo, 2, biasDesc, biasHandleRef.get()); SetWorkloadOutput(refData, refInfo, 0, outputTensorInfo, outputHandleRef.get()); std::unique_ptr workload @@ -3007,6 +3086,8 @@ LayerTestResult CompareDepthwiseConvolution2dTestImpl( = refWorkloadFactory.CreateWorkload(armnn::LayerType::DepthwiseConvolution2d, refData, refInfo); outputHandleRef->Allocate(); + weightsHandleRef->Allocate(); + biasHandleRef->Allocate(); inputHandleRef->Allocate(); inputHandle->Allocate(); @@ -3014,6 +3095,8 @@ LayerTestResult CompareDepthwiseConvolution2dTestImpl( CopyDataToITensorHandle(inputHandle.get(), input.data()); CopyDataToITensorHandle(inputHandleRef.get(), input.data()); + CopyDataToITensorHandle(weightsHandleRef.get(), kernel.data()); + CopyDataToITensorHandle(biasHandleRef.get(), bias.data()); ExecuteWorkload(*workload, memoryManager); @@ -3739,23 +3822,33 @@ LayerTestResult DepthwiseConvolution2dPerAxisQuantTest( descriptor.m_DataLayout = layout; std::unique_ptr inputHandle = tensorHandleFactory.CreateTensorHandle(inputInfo); + std::unique_ptr weightsHandle = tensorHandleFactory.CreateTensorHandle(kernelInfo); + std::unique_ptr biasHandle = tensorHandleFactory.CreateTensorHandle(biasInfo); std::unique_ptr outputHandle = tensorHandleFactory.CreateTensorHandle(outputInfo); + DepthwiseConvolution2dQueueDescriptor queueDescriptor; WorkloadInfo workloadInfo; ScopedTensorHandle weightTensor(kernelInfo); ScopedTensorHandle biasTensor(biasInfo); + AddInputToWorkload(queueDescriptor, workloadInfo, inputInfo, inputHandle.get()); + AddInputToWorkload(queueDescriptor, workloadInfo, kernelInfo, weightsHandle.get()); + AddOutputToWorkload(queueDescriptor, workloadInfo, outputInfo, outputHandle.get()); + AddInputToWorkload(queueDescriptor, workloadInfo, biasInfo, biasHandle.get()); + + // AllocateAndCopyDataToITensorHandle() is required twice for the weights AND biases: + // See comment in DepthwiseConvolution2dAsymmetricTestImpl() for reasons. + // 1) ScopedTensorHandle (weightsTensor) required for QueueDescriptor (data.m_Weight). + // 2) ITensorHandle (converts to Backend TensorHandle) required in RefWorkload for GetTensorInfo() method. + AllocateAndCopyDataToITensorHandle(weightsHandle.get(), kernelData.data()); AllocateAndCopyDataToITensorHandle(&weightTensor, kernelData.data()); + AllocateAndCopyDataToITensorHandle(biasHandle.get(), biasData.data()); AllocateAndCopyDataToITensorHandle(&biasTensor, biasData.data()); - DepthwiseConvolution2dQueueDescriptor queueDescriptor; queueDescriptor.m_Parameters = descriptor; queueDescriptor.m_Weight = &weightTensor; queueDescriptor.m_Bias = &biasTensor; - AddInputToWorkload(queueDescriptor, workloadInfo, inputInfo, inputHandle.get()); - AddOutputToWorkload(queueDescriptor, workloadInfo, outputInfo, outputHandle.get()); - std::unique_ptr workload = workloadFactory.CreateWorkload(armnn::LayerType::DepthwiseConvolution2d, queueDescriptor, workloadInfo); -- cgit v1.2.1