aboutsummaryrefslogtreecommitdiff
path: root/src/armnn/optimizations
diff options
context:
space:
mode:
authorCathal Corbett <cathal.corbett@arm.com>2022-04-14 17:55:11 +0100
committerCathal Corbett <cathal.corbett@arm.com>2022-05-05 16:10:06 +0000
commit0690265d83e5aa79bd174544a7b35330781619dd (patch)
tree2cb825017ee202ebcfa9c8428271a4dccaed72a4 /src/armnn/optimizations
parent3a3a6bfaedc64fac3644c8fe88dbfc3947e2b3ab (diff)
downloadarmnn-0690265d83e5aa79bd174544a7b35330781619dd.tar.gz
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 <cathal.corbett@arm.com> Change-Id: Ib18b6c10a093042e165e25237dc04a4c67ba82da
Diffstat (limited to 'src/armnn/optimizations')
-rw-r--r--src/armnn/optimizations/FoldPadIntoLayer2d.hpp23
-rw-r--r--src/armnn/optimizations/FuseBatchNorm.hpp84
-rw-r--r--src/armnn/optimizations/RedirectMembersToConstantInputs.hpp3
3 files changed, 91 insertions, 19 deletions
diff --git a/src/armnn/optimizations/FoldPadIntoLayer2d.hpp b/src/armnn/optimizations/FoldPadIntoLayer2d.hpp
index 87117debe9..bbaabb815e 100644
--- a/src/armnn/optimizations/FoldPadIntoLayer2d.hpp
+++ b/src/armnn/optimizations/FoldPadIntoLayer2d.hpp
@@ -191,21 +191,26 @@ class FoldPadIntoDepthwiseConvolution2dImpl
public:
void Run(Graph& graph, InputSlot& connection) const
{
- const auto newConv2dLayer = FoldPadIntoLayer2dImpl<DepthwiseConvolution2dLayer>(graph, connection);
+ const auto newLayer2d = FoldPadIntoLayer2dImpl<DepthwiseConvolution2dLayer>(graph, connection);
- if (newConv2dLayer != nullptr)
+ if (newLayer2d != nullptr)
{
- const auto conv2dLayer = PolymorphicDowncast<DepthwiseConvolution2dLayer*>(&connection.GetOwningLayer());
- // Copy weights and bias to the new convolution layer
- ARMNN_ASSERT_MSG(conv2dLayer->m_Weight != nullptr,
+ const auto layer2d = PolymorphicDowncast<DepthwiseConvolution2dLayer*>(&connection.GetOwningLayer());
+
+ // Move weights and bias layer connections to the new convolution layer
+ ARMNN_ASSERT_MSG(layer2d->GetInputSlot(1).GetConnection() != nullptr,
"FoldPadIntoDepthwiseConvolution2d: Weights data should not be null.");
- newConv2dLayer->m_Weight = std::move(conv2dLayer->m_Weight);
+ Layer& weightLayer = layer2d->GetInputSlot(1).GetConnectedOutputSlot()->GetOwningLayer();
+ weightLayer.GetOutputSlot(0).Disconnect(layer2d->GetInputSlot(1));
+ weightLayer.GetOutputSlot(0).Connect(newLayer2d->GetInputSlot(1));
- if (conv2dLayer->GetParameters().m_BiasEnabled)
+ if (layer2d->GetParameters().m_BiasEnabled)
{
- ARMNN_ASSERT_MSG(conv2dLayer->m_Bias != nullptr,
+ ARMNN_ASSERT_MSG(layer2d->GetInputSlot(2).GetConnection() != nullptr,
"FoldPadIntoDepthwiseConvolution2d: Bias data should not be null if bias is enabled.");
- newConv2dLayer->m_Bias = std::move(conv2dLayer->m_Bias);
+ Layer& biasLayer = layer2d->GetInputSlot(2).GetConnectedOutputSlot()->GetOwningLayer();
+ biasLayer.GetOutputSlot(0).Disconnect(layer2d->GetInputSlot(2));
+ biasLayer.GetOutputSlot(0).Connect(newLayer2d->GetInputSlot(2));
}
}
}
diff --git a/src/armnn/optimizations/FuseBatchNorm.hpp b/src/armnn/optimizations/FuseBatchNorm.hpp
index 66f722a8ef..6a50fc4a0c 100644
--- a/src/armnn/optimizations/FuseBatchNorm.hpp
+++ b/src/armnn/optimizations/FuseBatchNorm.hpp
@@ -50,12 +50,28 @@ public:
ConstTensor meanTensor(batchNormLayer->m_Mean->GetTensorInfo(), batchNormLayer->m_Mean->Map(true));
ConstTensor varTensor(batchNormLayer->m_Variance->GetTensorInfo(), batchNormLayer->m_Variance->Map(true));
- auto convDescriptor = convLayer->GetParameters();
- auto weightsInfo(convLayer->m_Weight->GetTensorInfo());
- ConstTensor weightsTensor(weightsInfo, convLayer->m_Weight->Map(true));
+ auto convDescriptor = convLayer->GetParameters();
+ ConstTensor weightsTensor;
+ if (convLayer->GetNumInputSlots() > 1)
+ {
+ ARMNN_ASSERT_MSG(convLayer->GetInputSlots()[1].GetConnection() != nullptr,
+ "FuseBatchNorm: Weight data should not be null.");
+ InputSlot & oldSlotWeights = const_cast<InputSlot&>(convLayer->GetInputSlots()[1]);
+ OutputSlot & constantSlotWeights = const_cast<OutputSlot&>(*oldSlotWeights.GetConnectedOutputSlot());
+ ConstantLayer* weightLayer = PolymorphicDowncast<ConstantLayer*>(
+ &constantSlotWeights.GetOwningLayer());
+ weightsTensor = ConstTensor(weightLayer->m_LayerOutput->GetTensorInfo(),
+ weightLayer->m_LayerOutput->Map(true));
+ }
+ else
+ {
+ ARMNN_ASSERT_MSG(convLayer->m_Weight != nullptr,
+ "FuseBatchNorm: Bias data should not be null if bias is enabled.");
+ weightsTensor = ConstTensor(convLayer->m_Weight->GetTensorInfo(), convLayer->m_Weight->Map(true));
+ }
armnnUtils::DataLayoutIndexed dataLayout(convDescriptor.m_DataLayout);
- auto weightsShape = weightsInfo.GetShape();
+ auto weightsShape = weightsTensor.GetInfo().GetShape();
const unsigned int inputChannels = parentOut->GetTensorInfo().GetShape()[dataLayout.GetChannelsIndex()];
const unsigned int depthMultiplier = depthwise ? weightsShape[3] / inputChannels : 1;
const unsigned int outputChannels = depthwise ? weightsShape[3] : weightsShape[0];
@@ -116,16 +132,32 @@ public:
}
}
}
- ConstTensor fusedWeightsTensor(weightsInfo, fusedWeightsVector);
+ ConstTensor fusedWeightsTensor(weightsTensor.GetInfo(), fusedWeightsVector);
// fusedBias = (gamma * (bias - mean)) / (variance - epsilon) + beta;
std::vector<T> fusedBiasVector(outputChannels);
- if (convDescriptor.m_BiasEnabled)
+ bool biasWasEnabledBeforeOpt = convDescriptor.m_BiasEnabled;
+ if (biasWasEnabledBeforeOpt)
{
- ARMNN_ASSERT_MSG(convLayer->m_Bias != nullptr,
- "FuseBatchNorm: Bias data should not be null if bias is enabled.");
+ ConstTensor biasTensor;
+ if (convLayer->GetNumInputSlots() > 1)
+ {
+ ARMNN_ASSERT_MSG(convLayer->GetInputSlots()[2].GetConnection() != nullptr,
+ "FuseBatchNorm: Bias data should not be null if bias is enabled.");
+ InputSlot & oldSlotBias = const_cast<InputSlot&>(convLayer->GetInputSlots()[2]);
+ OutputSlot & constantSlotBias = const_cast<OutputSlot&>(*oldSlotBias.GetConnectedOutputSlot());
+ ConstantLayer* biasLayer = PolymorphicDowncast<ConstantLayer*>(
+ &constantSlotBias.GetOwningLayer());
+ biasTensor = ConstTensor(biasLayer->m_LayerOutput->GetTensorInfo(),
+ biasLayer->m_LayerOutput->Map(true));
+ }
+ else
+ {
+ ARMNN_ASSERT_MSG(convLayer->m_Bias != nullptr,
+ "FuseBatchNorm: Bias data should not be null if bias is enabled.");
+ biasTensor = ConstTensor(convLayer->m_Bias->GetTensorInfo(), convLayer->m_Bias->Map(true));
+ }
- ConstTensor biasTensor(convLayer->m_Bias->GetTensorInfo(), convLayer->m_Bias->Map(true));
const auto* biasBuffer = static_cast<const T*>(biasTensor.GetMemoryArea());
std::vector<T> biasVector(biasBuffer, biasBuffer + biasTensor.GetNumElements());
@@ -156,6 +188,40 @@ public:
newConv2dLayer.m_Weight = std::make_unique<ScopedTensorHandle>(fusedWeightsTensor);
newConv2dLayer.m_Bias = std::make_unique<ScopedTensorHandle>(ConstTensor(fusedBiasTensor));
+ // Connect weights and bias from old to new Conv2d layer
+ // This optimization will always have 3 input slots on the Conv2d base layer
+ if (newConv2dLayer.GetNumInputSlots() > 1)
+ {
+ ConstantLayer* weightLayer = PolymorphicDowncast<ConstantLayer*>(
+ &base.GetInputSlot(1).GetConnectedOutputSlot()->GetOwningLayer());
+ // Remove old connection and connect to new layer2d
+ weightLayer->GetOutputSlot(0).Disconnect(base.GetInputSlot(1));
+ weightLayer->GetOutputSlot(0).Connect(newConv2dLayer.GetInputSlot(1));
+ weightLayer->m_LayerOutput = newConv2dLayer.m_Weight;
+
+ // Move bias const layers as normal if it was enabled before the optimisation
+ ConstantLayer* biasLayer;
+ if (biasWasEnabledBeforeOpt)
+ {
+ biasLayer = PolymorphicDowncast<ConstantLayer*>(
+ &base.GetInputSlot(2).GetConnectedOutputSlot()->GetOwningLayer());
+ // Remove old connection and connect to new layer2d
+ biasLayer->GetOutputSlot(0).Disconnect(base.GetInputSlot(2));
+ biasLayer->GetOutputSlot(0).Connect(newConv2dLayer.GetInputSlot(2));
+
+ }
+ // Otherwise create a new bias layer and add to the new convolution2d
+ else
+ {
+ // Add in bias constant layer
+ biasLayer = graph.AddLayer<ConstantLayer>("Bias");
+ biasLayer->GetOutputSlot(0).SetTensorInfo(fusedBiasTensor.GetInfo());
+ biasLayer->GetOutputSlot(0).Connect(newConv2dLayer.GetInputSlot(2));
+ }
+ biasLayer->m_LayerOutput = newConv2dLayer.m_Bias;
+ }
+
+
// Reconnects with original parent.
newConv2dLayer.GetOutputSlot().MoveAllConnections(*parentOut);
// Parent is now the new convolution2d layer.
diff --git a/src/armnn/optimizations/RedirectMembersToConstantInputs.hpp b/src/armnn/optimizations/RedirectMembersToConstantInputs.hpp
index 85d715c6b1..cb97a0fe32 100644
--- a/src/armnn/optimizations/RedirectMembersToConstantInputs.hpp
+++ b/src/armnn/optimizations/RedirectMembersToConstantInputs.hpp
@@ -31,6 +31,7 @@ public:
case LayerType::Convolution2d:
break;
case LayerType::DepthwiseConvolution2d:
+ RedirectWeightsAndBiases<DepthwiseConvolution2dLayer>(&layer);
break;
case LayerType::DetectionPostProcess:
break;
@@ -80,7 +81,7 @@ private:
}
};
-using RedirectMembersToConstantInputs = OptimizeForType<FullyConnectedLayer, RedirectMembersToConstantInputsImpl>;
+using RedirectMembersToConstantInputs = OptimizeForType<Layer, RedirectMembersToConstantInputsImpl>;
} // namespace optimizations
} // namespace armnn