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/armnn/test/optimizations/FoldPadTests.cpp | 19 +++- .../test/optimizations/FuseActivationTests.cpp | 37 +++--- .../test/optimizations/FuseBatchNormTests.cpp | 124 +++++++++++++++++---- 3 files changed, 135 insertions(+), 45 deletions(-) (limited to 'src/armnn/test/optimizations') diff --git a/src/armnn/test/optimizations/FoldPadTests.cpp b/src/armnn/test/optimizations/FoldPadTests.cpp index 2f9e1c6d31..9919c6d0e6 100644 --- a/src/armnn/test/optimizations/FoldPadTests.cpp +++ b/src/armnn/test/optimizations/FoldPadTests.cpp @@ -126,14 +126,18 @@ TEST_CASE("FoldPadLayerIntoDepthwiseConvolution2dLayer") auto* depthwiseConv2dLayer = graph.AddLayer(depthwiseConvolution2dDescriptor, "depthwiseConv2d"); - depthwiseConv2dLayer->m_Weight = std::make_unique(weights); + auto* weightsLayer = graph.AddLayer("weights"); + + weightsLayer->GetOutputSlot().SetTensorInfo(weights.GetInfo()); depthwiseConv2dLayer->GetOutputSlot().SetTensorInfo(outputInfo); + depthwiseConv2dLayer->m_Weight = std::make_shared(weights); Layer* output = graph.AddLayer(0, "output"); // Connect up layers - input -> pad -> depthwiseConv2d -> output input->GetOutputSlot().Connect(padLayer->GetInputSlot(0)); padLayer->GetOutputSlot().Connect(depthwiseConv2dLayer->GetInputSlot(0)); + weightsLayer->GetOutputSlot().Connect(depthwiseConv2dLayer->GetInputSlot(1)); depthwiseConv2dLayer->GetOutputSlot().Connect(output->GetInputSlot(0)); auto checkSimpleDepthwiseConv2d = [](const Layer* const layer)->bool { @@ -151,6 +155,7 @@ TEST_CASE("FoldPadLayerIntoDepthwiseConvolution2dLayer") &IsLayerOfType, &IsLayerOfType, checkSimpleDepthwiseConv2d, + &IsLayerOfType, &IsLayerOfType)); armnn::Optimizer::Pass(graph, MakeOptimizations(FoldPadIntoDepthwiseConvolution2d())); @@ -170,6 +175,7 @@ TEST_CASE("FoldPadLayerIntoDepthwiseConvolution2dLayer") CHECK(CheckSequence(graph.cbegin(), graph.cend(), &IsLayerOfType, checkPadFoldedIntoDepthwiseConv2d, + &IsLayerOfType, &IsLayerOfType)); } @@ -741,11 +747,8 @@ TEST_CASE("FoldPadLayerIntoDepthwiseConv2dLayer_ExecuteInferenceWithAndWithoutOp std::vector biasVector = {5, 6, 7, 8, 9, 10, 11, 12, 5, 6, 7, 8}; TensorInfo biasInfo({12}, DataType::Float32, 0.0f, 0, true); ConstTensor bias(biasInfo, biasVector); - Optional optionalBias = Optional(bias); IConnectableLayer* conv2dLayer = network->AddDepthwiseConvolution2dLayer(convDescriptor, - weights, - optionalBias, "DepthwiseConv2D"); TensorInfo outputInfo(4, outputShape, DataType::Float32); @@ -758,6 +761,14 @@ TEST_CASE("FoldPadLayerIntoDepthwiseConv2dLayer_ExecuteInferenceWithAndWithoutOp padLayer->GetOutputSlot(0).Connect(conv2dLayer->GetInputSlot(0)); conv2dLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + auto weightsLayer = network->AddConstantLayer(weights, "Weights"); + weightsLayer->GetOutputSlot(0).SetTensorInfo(weights.GetInfo()); + weightsLayer->GetOutputSlot(0).Connect(conv2dLayer->GetInputSlot(1)); + + auto biasLayer = network->AddConstantLayer(bias, "Bias"); + biasLayer->GetOutputSlot(0).SetTensorInfo(bias.GetInfo()); + biasLayer->GetOutputSlot(0).Connect(conv2dLayer->GetInputSlot(2)); + // Create ArmNN runtime IRuntimePtr run = IRuntime::Create(IRuntime::CreationOptions()); // default options // Optimise the network diff --git a/src/armnn/test/optimizations/FuseActivationTests.cpp b/src/armnn/test/optimizations/FuseActivationTests.cpp index ac327bb609..e5f54208f0 100644 --- a/src/armnn/test/optimizations/FuseActivationTests.cpp +++ b/src/armnn/test/optimizations/FuseActivationTests.cpp @@ -90,7 +90,7 @@ struct DWConvolution2dTest public: using LayerType = DepthwiseConvolution2dLayer; static const bool isElementWise = false; - static const bool isConstTensorAsInputSupported = false; + static const bool isConstTensorAsInputSupported = true; static TensorShape GetInputShape() { return TensorShape( {1, 4, 4, 3}); } // [N,H,W,Cin] static TensorShape GetOutputShape() { return TensorShape( {1, 3, 3, 12}); } // [N,H,W,Cout] @@ -104,32 +104,35 @@ public: float scale = 1.f, int32_t offset = 0) { + IgnoreUnused(scale); + IgnoreUnused(offset); + DepthwiseConvolution2dDescriptor descriptor; descriptor.m_BiasEnabled = false; descriptor.m_DataLayout = DataLayout::NHWC; descriptor.m_StrideX = 1; descriptor.m_StrideY = 1; - std::vector weightsData = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42}; - std::vector weightsVector = armnnUtils::QuantizedVector(weightsData, scale, offset); - TensorInfo weightsInfo(GetWeightsShape(), ArmnnType, scale, offset, true); - ConstTensor weights(weightsInfo, weightsVector); - Optional optionalBias; - - return network->AddDepthwiseConvolution2dLayer(descriptor, weights, optionalBias, name); + return network->AddDepthwiseConvolution2dLayer(descriptor, name); } static std::vector AddConstantLayers(INetwork* network, float scale = 1.f, int32_t offset = 0) { - IgnoreUnused(network); - IgnoreUnused(scale); - IgnoreUnused(offset); - return {}; + std::vector weightsData = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42}; + std::vector weightsVector = armnnUtils::QuantizedVector(weightsData, scale, offset); + TensorInfo weightsInfo(GetWeightsShape(), ArmnnType, scale, offset, true); + ConstTensor weights(weightsInfo, weightsVector); + + IConnectableLayer* weightsLayer = network->AddConstantLayer(weights, "Weights"); + weightsLayer->GetOutputSlot(0).SetTensorInfo(weightsInfo); + + std::vector layers = { weightsLayer }; + return layers; } }; @@ -390,10 +393,10 @@ INetworkPtr CreateNetwork(ActivationDescriptor activationDescriptor, bool preven "activation"); IConnectableLayer* outputLayer = network->AddOutputLayer(0); - IConnectableLayer* output2Layer = preventFusing?network->AddOutputLayer(1):nullptr; + IConnectableLayer* output2Layer = preventFusing ? network->AddOutputLayer(1) : nullptr; // If ConstTensorAsInputs is supported weights and bias are stored as constant layers. - if(LayerTest::isConstTensorAsInputSupported) + if (LayerTest::isConstTensorAsInputSupported) { std::vector constantLayers = LayerTest::AddConstantLayers(network.get(), scale, diff --git a/src/armnn/test/optimizations/FuseBatchNormTests.cpp b/src/armnn/test/optimizations/FuseBatchNormTests.cpp index 70cffea2b2..b28bb17773 100644 --- a/src/armnn/test/optimizations/FuseBatchNormTests.cpp +++ b/src/armnn/test/optimizations/FuseBatchNormTests.cpp @@ -24,6 +24,7 @@ class Conv2dTest public: using ConvDescriptorType = armnn::Convolution2dDescriptor; using ConvLayerType = armnn::Convolution2dLayer; + static const bool isConstTensorAsInputSupported = false; static IConnectableLayer *AddConvolution(INetwork *network, const Convolution2dDescriptor &descriptor, @@ -33,6 +34,19 @@ public: { return network->AddConvolution2dLayer(descriptor, weights, biases, name); } + + static std::vector AddConstantLayers(INetwork *network, + const Convolution2dDescriptor &descriptor, + const ConstTensor &weights, + const Optional &biases) + { + IgnoreUnused(network); + IgnoreUnused(descriptor); + IgnoreUnused(weights); + IgnoreUnused(biases); + + return {}; + } }; class DepthwiseConv2dTest @@ -40,6 +54,7 @@ class DepthwiseConv2dTest public: using ConvDescriptorType = armnn::DepthwiseConvolution2dDescriptor; using ConvLayerType = armnn::DepthwiseConvolution2dLayer; + static const bool isConstTensorAsInputSupported = true; static IConnectableLayer *AddConvolution(INetwork *network, const DepthwiseConvolution2dDescriptor &descriptor, @@ -47,7 +62,29 @@ public: const Optional &biases, const char *name) { - return network->AddDepthwiseConvolution2dLayer(descriptor, weights, biases, name); + IgnoreUnused(weights); + IgnoreUnused(biases); + + return network->AddDepthwiseConvolution2dLayer(descriptor, name); + } + + static std::vector AddConstantLayers(INetwork *network, + const DepthwiseConvolution2dDescriptor &descriptor, + const ConstTensor &weights, + const Optional &biases) + { + auto weightsLayer = network->AddConstantLayer(weights, "Weights"); + weightsLayer->GetOutputSlot(0).SetTensorInfo(weights.GetInfo()); + std::vector layers = {weightsLayer}; + + if (descriptor.m_BiasEnabled) + { + auto biasLayer = network->AddConstantLayer(biases.value(), "Bias"); + biasLayer->GetOutputSlot(0).SetTensorInfo(biases.value().GetInfo()); + layers.emplace_back(biasLayer); + } + + return layers; } }; @@ -73,7 +110,7 @@ template > -INetworkPtr CreatNetwork(bool depthwise, bool preventFusing) +INetworkPtr CreateNetwork(bool depthwise, bool preventFusing) { // Define layers information ConvDescriptorType convolution2dDescriptor; @@ -110,11 +147,6 @@ INetworkPtr CreatNetwork(bool depthwise, bool preventFusing) TensorInfo weightsInfo(4, weightsDimensionSizes, ArmnnType, 0.0f, 0, true); ConstTensor weights(weightsInfo, weightsVector); - std::vector biasVector = GetVector(outputDimensionSizes[3], 3.3f, 0.1f); - TensorInfo biasInfo(1, outputChannelSize, ArmnnType, 0.0f, 0, true); - ConstTensor bias(biasInfo, biasVector); - Optional optionalBias = Optional(bias); - std::vector betaVector = GetVector(outputDimensionSizes[3], 0.0f, 0.2f); std::vector gammaVector = GetVector(outputDimensionSizes[3], 0.5f, 0.1f); std::vector meanVector = GetVector(outputDimensionSizes[3], 0.1f, 0.1f); @@ -133,7 +165,7 @@ INetworkPtr CreatNetwork(bool depthwise, bool preventFusing) IConnectableLayer* convLayer = Conv2dTest::AddConvolution(network.get(), convolution2dDescriptor, weights, - optionalBias, + Optional(), "convolution"); IConnectableLayer* batchNormLayer = network->AddBatchNormalizationLayer(batchNormDescriptor, @@ -151,6 +183,21 @@ INetworkPtr CreatNetwork(bool depthwise, bool preventFusing) output2Layer = network->AddOutputLayer(1); } + // If ConstTensorAsInputs is supported weights and bias are stored as constant layers. + if (Conv2dTest::isConstTensorAsInputSupported) + { + std::vector constantLayers = Conv2dTest::AddConstantLayers(network.get(), + convolution2dDescriptor, + weights, + Optional()); + + // Connect constant layers to receiverLayer. + for (unsigned int i = 0; i < constantLayers.size(); ++i) + { + constantLayers[i]->GetOutputSlot(0).Connect(convLayer->GetInputSlot(i + 1)); + } + } + // Set layer information inputLayer ->GetOutputSlot(0).SetTensorInfo(inputInfo); convLayer ->GetOutputSlot(0).SetTensorInfo(outputInfo); @@ -178,7 +225,7 @@ void FuseBatchNormIntoConvTest(bool depthwise, float tolerance, armnn::Compute b { // FIRST NETWORK: Fused // Construct ArmNN network - INetworkPtr networkFused = CreatNetwork(depthwise, false); + INetworkPtr networkFused = CreateNetwork(depthwise, false); // Create ArmNN runtime IRuntimePtr run = IRuntime::Create(IRuntime::CreationOptions()); // default options @@ -194,12 +241,26 @@ void FuseBatchNormIntoConvTest(bool depthwise, float tolerance, armnn::Compute b (layer->GetNameStr() == "fused-batchNorm-into-convolution"); }; - CHECK(3 == graphFused.GetNumLayers()); - CHECK(CheckSequence(graphFused.cbegin(), - graphFused.cend(), - &IsLayerOfType, - checkFusedConv2d, - &IsLayerOfType)); + if (Conv2dTest::isConstTensorAsInputSupported) + { + CHECK(5 == graphFused.GetNumLayers()); + CHECK(CheckSequence(graphFused.cbegin(), + graphFused.cend(), + &IsLayerOfType, + &IsLayerOfType, + &IsLayerOfType, + checkFusedConv2d, + &IsLayerOfType)); + } + else + { + CHECK(3 == graphFused.GetNumLayers()); + CHECK(CheckSequence(graphFused.cbegin(), + graphFused.cend(), + &IsLayerOfType, + checkFusedConv2d, + &IsLayerOfType)); + } // Load network into runtime NetworkId networkIdentifier; @@ -227,7 +288,7 @@ void FuseBatchNormIntoConvTest(bool depthwise, float tolerance, armnn::Compute b // SECOND NETWORK: NotFused // Construct ArmNN network - INetworkPtr networkNotFused = CreatNetwork(depthwise, true); + INetworkPtr networkNotFused = CreateNetwork(depthwise, true); // Create ArmNN runtime IRuntimePtr runNotFused = IRuntime::Create(IRuntime::CreationOptions()); // default options @@ -237,14 +298,29 @@ void FuseBatchNormIntoConvTest(bool depthwise, float tolerance, armnn::Compute b Graph& graphNotFused = GetGraphForTesting(optNetNotFused.get()); - CHECK(5 == graphNotFused.GetNumLayers()); - CHECK(CheckSequence(graphNotFused.cbegin(), - graphNotFused.cend(), - &IsLayerOfType, - &IsLayerOfType, - &IsLayerOfType, - &IsLayerOfType, - &IsLayerOfType)); + if (Conv2dTest::isConstTensorAsInputSupported) + { + CHECK(6 == graphNotFused.GetNumLayers()); + CHECK(CheckSequence(graphNotFused.cbegin(), + graphNotFused.cend(), + &IsLayerOfType, + &IsLayerOfType, + &IsLayerOfType, + &IsLayerOfType, + &IsLayerOfType, + &IsLayerOfType)); + } + else + { + CHECK(5 == graphNotFused.GetNumLayers()); + CHECK(CheckSequence(graphNotFused.cbegin(), + graphNotFused.cend(), + &IsLayerOfType, + &IsLayerOfType, + &IsLayerOfType, + &IsLayerOfType, + &IsLayerOfType)); + } // Load network into runtime NetworkId networkIdentifierNotFused; -- cgit v1.2.1