From 3883b2776cec33f16f0ea9a2d795de2b7c766df7 Mon Sep 17 00:00:00 2001 From: Cathal Corbett Date: Fri, 22 Jul 2022 16:03:36 +0100 Subject: GitHub #667: Neon fold padding into average pool 2D quantization bug fix. * Originated from a GitHub issue: https://github.com/ARM-software/armnn/issues/667 * Initially, Arm NN supports the pool 2D operation because there is no padding on the pool2d. Neon failure occurs when padding is followed by average pool 2D due to folding optimization. * Here we prevent the folding optimization from happening for the above special case and add it in as a backend specific optimization. Signed-off-by: Cathal Corbett Change-Id: Ia0fd90c3a6b4b9d29c81106f154617d2e893e26b --- src/backends/backendsCommon/SubgraphUtils.hpp | 99 +++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/backends/backendsCommon/SubgraphUtils.hpp (limited to 'src/backends/backendsCommon') diff --git a/src/backends/backendsCommon/SubgraphUtils.hpp b/src/backends/backendsCommon/SubgraphUtils.hpp new file mode 100644 index 0000000000..bd3d698a98 --- /dev/null +++ b/src/backends/backendsCommon/SubgraphUtils.hpp @@ -0,0 +1,99 @@ +// +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include + +namespace armnn +{ + +namespace +{ + +// +// this helper only works if all layers where the inputs connect to are not selected +// + +SubgraphView::IInputSlots CreateIInputsFrom(const std::vector& layers) +{ + SubgraphView::IInputSlots result; + for (auto&& layer : layers) + { + for (unsigned int i = 0 ; i < layer->GetNumInputSlots(); ++i) + { + result.push_back(&(layer->GetInputSlot(i))); + } + } + return result; +} + +// +// this helper only works if all layers where the outputs connect to are not selected +// + +SubgraphView::IOutputSlots CreateIOutputsFrom(const std::vector& layers) +{ + SubgraphView::IOutputSlots result; + for (auto &&layer: layers) + { + for (unsigned int i = 0; i < layer->GetNumOutputSlots(); ++i) + { + result.push_back(&(layer->GetOutputSlot(i))); + } + } + return result; +} + +} + +inline void ReportUntouchedLayers(OptimizationViews& optimizationViews, std::map untouched) +{ + std::vector untouchedVector; + for (const auto& pair : untouched) + { + Layer* layer = pair.second; + SubgraphView subgraphView({layer}, + CreateIInputsFrom({layer}), + CreateIOutputsFrom({layer})); + optimizationViews.AddUntouchedSubgraph(std::move(subgraphView)); + } +} + +template +LayerType* FoldPadLayer(OptimizationViews& optimizationViews, + LayerType* baseLayer, + LayerType* replacementLayer, + PadLayer* padLayer) +{ + SubgraphView substitutionSubgraph({padLayer, baseLayer}, + CreateIInputsFrom({padLayer}), + CreateIOutputsFrom({baseLayer})); + SubgraphView replacementSubgraph(replacementLayer); + + optimizationViews.AddSubstitution({substitutionSubgraph, replacementSubgraph}); + + return replacementLayer; +} + +template +LayerType* FoldPadIntoAveragePool2d(OptimizationViews& optimizationViews, + Pooling2dLayer* baseLayer, + Pooling2dDescriptor& poolDescriptor, + PadLayer* padLayer) +{ + IConnectableLayer* replacement = + optimizationViews.GetINetwork()->AddPooling2dLayer(poolDescriptor, "folded-pad-into-pool2d"); + LayerType* replacementLayer = PolymorphicDowncast(replacement); + + FoldPadLayer(optimizationViews, + baseLayer, + replacementLayer, + padLayer); + + return replacementLayer; +} + +} // namespace armnn -- cgit v1.2.1