aboutsummaryrefslogtreecommitdiff
path: root/src/backends/backendsCommon
diff options
context:
space:
mode:
Diffstat (limited to 'src/backends/backendsCommon')
-rw-r--r--src/backends/backendsCommon/WorkloadData.cpp15
-rw-r--r--src/backends/backendsCommon/WorkloadFactory.cpp12
-rw-r--r--src/backends/backendsCommon/test/DynamicBackendTests.hpp2
-rw-r--r--src/backends/backendsCommon/test/FullyConnectedEndToEndTestImpl.hpp39
-rw-r--r--src/backends/backendsCommon/test/LayerReleaseConstantDataTest.cpp99
-rw-r--r--src/backends/backendsCommon/test/OptimizationViewsTests.cpp45
-rw-r--r--src/backends/backendsCommon/test/OptimizeSubgraphViewTests.cpp505
-rw-r--r--src/backends/backendsCommon/test/OptimizedNetworkTests.cpp3
-rw-r--r--src/backends/backendsCommon/test/WorkloadDataValidation.cpp93
-rw-r--r--src/backends/backendsCommon/test/layerTests/Conv2dTestImpl.cpp114
10 files changed, 703 insertions, 224 deletions
diff --git a/src/backends/backendsCommon/WorkloadData.cpp b/src/backends/backendsCommon/WorkloadData.cpp
index 289f780fba..37fda3e210 100644
--- a/src/backends/backendsCommon/WorkloadData.cpp
+++ b/src/backends/backendsCommon/WorkloadData.cpp
@@ -1246,7 +1246,13 @@ void Convolution2dQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) co
{
const std::string descriptorName{"Convolution2dQueueDescriptor"};
- 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];
@@ -1255,9 +1261,8 @@ void Convolution2dQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) co
ValidateTensorNumDimensions(inputTensorInfo, descriptorName, 4, "input");
ValidateTensorNumDimensions(outputTensorInfo, descriptorName, 4, "output");
- ValidatePointer(m_Weight, descriptorName, "weight");
+ const TensorInfo& weightTensorInfo = workloadInfo.m_InputTensorInfos[1];
- const TensorInfo& weightTensorInfo = m_Weight->GetTensorInfo();
ValidateTensorNumDimensions(weightTensorInfo, descriptorName, 4, "weight");
ValidateWeightDataType(inputTensorInfo, weightTensorInfo, descriptorName);
@@ -1265,9 +1270,7 @@ void Convolution2dQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) co
Optional<TensorInfo> optionalBiasTensorInfo;
if (m_Parameters.m_BiasEnabled)
{
- ValidatePointer(m_Bias, descriptorName, "bias");
-
- optionalBiasTensorInfo = MakeOptional<TensorInfo>(m_Bias->GetTensorInfo());
+ optionalBiasTensorInfo = MakeOptional<TensorInfo>(workloadInfo.m_InputTensorInfos[2]);
const TensorInfo& biasTensorInfo = optionalBiasTensorInfo.value();
ValidateTensorDataType(biasTensorInfo, GetBiasDataType(inputTensorInfo.GetDataType()), descriptorName, "bias");
diff --git a/src/backends/backendsCommon/WorkloadFactory.cpp b/src/backends/backendsCommon/WorkloadFactory.cpp
index f624ee6021..3660e6e721 100644
--- a/src/backends/backendsCommon/WorkloadFactory.cpp
+++ b/src/backends/backendsCommon/WorkloadFactory.cpp
@@ -246,7 +246,10 @@ bool IWorkloadFactory::IsLayerConfigurationSupported(const BackendId& backendId,
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);
+ ARMNN_ASSERT_MSG(layer.GetInputSlot(1).GetConnection(),
+ "Convolution2dLayer: Weights should be connected as a Constant Layer.");
+ const TensorInfo weights = OverrideDataType(layer.GetInputSlot(1).GetConnection()->GetTensorInfo(),
+ dataType);
const Convolution2dDescriptor& descriptor = cLayer->GetParameters();
@@ -254,14 +257,17 @@ bool IWorkloadFactory::IsLayerConfigurationSupported(const BackendId& backendId,
Optional<TensorInfo> biases;
if (descriptor.m_BiasEnabled)
{
- biases = OverrideDataType(cLayer->m_Bias->GetTensorInfo(), GetBiasTypeFromWeightsType(dataType));
+ ARMNN_ASSERT_MSG(layer.GetInputSlot(2).GetConnection(),
+ "Convolution2dLayer: Bias should be connected as a Constant Layer.");
+ biases = OverrideDataType(layer.GetInputSlot(2).GetConnection()->GetTensorInfo(),
+ GetBiasTypeFromWeightsType(dataType));
}
result = layerSupportObject.IsConvolution2dSupported(
input,
output,
descriptor,
- OverrideDataType(cLayer->m_Weight->GetTensorInfo(), dataType),
+ weights,
biases,
reason);
break;
diff --git a/src/backends/backendsCommon/test/DynamicBackendTests.hpp b/src/backends/backendsCommon/test/DynamicBackendTests.hpp
index f53bd83100..0d98804954 100644
--- a/src/backends/backendsCommon/test/DynamicBackendTests.hpp
+++ b/src/backends/backendsCommon/test/DynamicBackendTests.hpp
@@ -1465,7 +1465,7 @@ void CreateReferenceDynamicBackendTestImpl()
Convolution2dQueueDescriptor convolution2dQueueDescriptor;
WorkloadInfo workloadInfo
{
- { inputInfo },
+ { inputInfo, weightInfo },
{ outputInfo }
};
convolution2dQueueDescriptor.m_Inputs.push_back(nullptr);
diff --git a/src/backends/backendsCommon/test/FullyConnectedEndToEndTestImpl.hpp b/src/backends/backendsCommon/test/FullyConnectedEndToEndTestImpl.hpp
index 1076aa6669..0d2d2cb2de 100644
--- a/src/backends/backendsCommon/test/FullyConnectedEndToEndTestImpl.hpp
+++ b/src/backends/backendsCommon/test/FullyConnectedEndToEndTestImpl.hpp
@@ -110,8 +110,11 @@ armnn::INetworkPtr CreateFullyConnectedNetworkNoConnectedWeightsExplicit(const a
{
armnn::INetworkPtr network(armnn::INetwork::Create());
+
+ ConstTensor biases;
+
armnn::IConnectableLayer* inputLayer = network->AddInputLayer(0, "Input");
- armnn::IConnectableLayer* biasLayer = network->AddInputLayer(2, "Bias_Input");
+ armnn::IConnectableLayer* biasLayer = network->AddConstantLayer(biases, "Bias_Input");
armnn::IConnectableLayer* fullyConnectedLayer = network->AddFullyConnectedLayer(descriptor, "Fully_Connected");
armnn::IConnectableLayer* outputLayer = network->AddOutputLayer(0, "Output");
@@ -402,16 +405,7 @@ void FullyConnectedErrorChecking(const std::vector<armnn::BackendId>& backends,
IRuntime::CreationOptions options;
IRuntimePtr runtime(IRuntime::Create(options));
- try
- {
- Optimize(*network, backends, runtime->GetDeviceSpec());
- FAIL("LayerValidationException should have been thrown");
- }
- catch (const LayerValidationException& exc)
- {
- CHECK(strcmp(exc.what(), "Fully_Connected layer weights not set: Input slot(s) 1 not connected "
- "to an output slot on FullyConnected layer \"Fully_Connected\"") == 0);
- }
+ CHECK_THROWS_AS(Optimize(*network, backends, runtime->GetDeviceSpec()), LayerValidationException);
}
else if (!connectedBias)
{
@@ -429,16 +423,7 @@ void FullyConnectedErrorChecking(const std::vector<armnn::BackendId>& backends,
IRuntime::CreationOptions options;
IRuntimePtr runtime(IRuntime::Create(options));
- try
- {
- Optimize(*network, backends, runtime->GetDeviceSpec());
- FAIL("LayerValidationException should have been thrown");
- }
- catch (const LayerValidationException& exc)
- {
- CHECK(strcmp(exc.what(), "Fully_Connected layer bias not set: Input slot(s) 2 not connected "
- "to an output slot on FullyConnected layer \"Fully_Connected\"") == 0);
- }
+ CHECK_THROWS_AS(Optimize(*network, backends, runtime->GetDeviceSpec()), LayerValidationException);
}
}
else if(!connectedWeights && !connectedBias)
@@ -452,17 +437,7 @@ void FullyConnectedErrorChecking(const std::vector<armnn::BackendId>& backends,
IRuntime::CreationOptions options;
IRuntimePtr runtime(IRuntime::Create(options));
- try
- {
- Optimize(*network, backends, runtime->GetDeviceSpec());
- FAIL("LayerValidationException should have been thrown");
- }
- catch (const LayerValidationException& exc)
- {
- CHECK(strcmp(exc.what(), "Fully_Connected layer weights and bias not set: Input slot(s) 1 & 2 not "
- "connected to an output slot on FullyConnected layer \"Fully_Connected\"") == 0);
- }
-
+ CHECK_THROWS_AS(Optimize(*network, backends, runtime->GetDeviceSpec()), LayerValidationException);
}
else if(!tensorInfoSet)
{
diff --git a/src/backends/backendsCommon/test/LayerReleaseConstantDataTest.cpp b/src/backends/backendsCommon/test/LayerReleaseConstantDataTest.cpp
index 56f15a51e5..5ceb8ae4b4 100644
--- a/src/backends/backendsCommon/test/LayerReleaseConstantDataTest.cpp
+++ b/src/backends/backendsCommon/test/LayerReleaseConstantDataTest.cpp
@@ -70,49 +70,68 @@ TEST_CASE("ReleaseBatchNormalizationLayerConstantDataTest")
}
+TEST_CASE("ReleaseConvolution2dLayerConstantDataTest")
+{
+ Graph graph;
+
+ // create the layer we're testing
+ Convolution2dDescriptor layerDesc;
+ layerDesc.m_PadLeft = 3;
+ layerDesc.m_PadRight = 3;
+ layerDesc.m_PadTop = 1;
+ layerDesc.m_PadBottom = 1;
+ layerDesc.m_StrideX = 2;
+ layerDesc.m_StrideY = 4;
+ layerDesc.m_BiasEnabled = true;
+
+ Convolution2dLayer* const layer = graph.AddLayer<Convolution2dLayer>(layerDesc, "layer");
- TEST_CASE("ReleaseConvolution2dLayerConstantDataTest")
- {
- Graph graph;
+ layer->m_Weight = std::make_unique<ScopedTensorHandle>(TensorInfo({ 2, 3, 5, 3 },
+ armnn::DataType::Float32));
+ layer->m_Bias = std::make_unique<ScopedTensorHandle>
+ (TensorInfo({ 2 }, GetBiasDataType(armnn::DataType::Float32)));
- // create the layer we're testing
- Convolution2dDescriptor layerDesc;
- layerDesc.m_PadLeft = 3;
- layerDesc.m_PadRight = 3;
- layerDesc.m_PadTop = 1;
- layerDesc.m_PadBottom = 1;
- layerDesc.m_StrideX = 2;
- layerDesc.m_StrideY = 4;
- layerDesc.m_BiasEnabled = true;
+ layer->m_Weight->Allocate();
+ layer->m_Bias->Allocate();
- Convolution2dLayer* const layer = graph.AddLayer<Convolution2dLayer>(layerDesc, "layer");
+ ConstantLayer* weightsLayer = graph.AddLayer<ConstantLayer>("Weights");
+ ConstantLayer* biasLayer = graph.AddLayer<ConstantLayer>("Bias");
- layer->m_Weight = std::make_unique<ScopedTensorHandle>(TensorInfo({2, 3, 5, 3},
- armnn::DataType::Float32));
- layer->m_Bias = std::make_unique<ScopedTensorHandle>
- (TensorInfo({2}, GetBiasDataType(armnn::DataType::Float32)));
+ weightsLayer->m_LayerOutput = std::make_shared<ScopedTensorHandle>(TensorInfo({ 2, 3, 5, 3 },
+ armnn::DataType::Float32));
- layer->m_Weight->Allocate();
- layer->m_Bias->Allocate();
+ biasLayer->m_LayerOutput = std::make_shared<ScopedTensorHandle>(
+ TensorInfo({2}, GetBiasDataType(armnn::DataType::Float32)));
- // create extra layers
- Layer* const input = graph.AddLayer<InputLayer>(0, "input");
- Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
+ TensorInfo weightsInfo = weightsLayer->m_LayerOutput->GetTensorInfo();
+ weightsInfo.SetConstant();
+ TensorInfo biasInfo = biasLayer->m_LayerOutput->GetTensorInfo();
+ biasInfo.SetConstant();
- // connect up
- Connect(input, layer, TensorInfo({2, 3, 8, 16}, armnn::DataType::Float32));
- Connect(layer, output, TensorInfo({2, 2, 2, 10}, armnn::DataType::Float32));
- // check the constants that they are not NULL
- CHECK(layer->m_Weight != nullptr);
- CHECK(layer->m_Bias != nullptr);
+ weightsLayer->GetOutputSlot(0).SetTensorInfo(weightsInfo);
+ biasLayer->GetOutputSlot(0).SetTensorInfo(biasInfo);
- // free up the constants..
- layer->ReleaseConstantData();
+ // create extra layers
+ Layer* const input = graph.AddLayer<InputLayer>(0, "input");
+ Layer* const output = graph.AddLayer<OutputLayer>(0, "output");
- // check the constants that they are NULL now
- CHECK(layer->m_Weight == nullptr);
- CHECK(layer->m_Bias == nullptr);
+ // connect up
+ Connect(input, layer, TensorInfo({ 2, 3, 8, 16 }, armnn::DataType::Float32));
+ weightsLayer->GetOutputSlot().Connect(layer->GetInputSlot(1));
+ biasLayer->GetOutputSlot().Connect(layer->GetInputSlot(2));
+ Connect(layer, output, TensorInfo({ 2, 2, 2, 10 }, armnn::DataType::Float32));
+
+ // check the constants that they are not NULL
+ CHECK(layer->m_Weight != nullptr);
+ CHECK(layer->m_Bias != nullptr);
+
+ // free up the constants..
+ layer->ReleaseConstantData();
+
+ // check the constants that they are NULL now
+ CHECK(layer->m_Weight == nullptr);
+ CHECK(layer->m_Bias == nullptr);
}
TEST_CASE("ReleaseDepthwiseConvolution2dLayerConstantDataTest")
@@ -131,8 +150,10 @@ TEST_CASE("ReleaseDepthwiseConvolution2dLayerConstantDataTest")
DepthwiseConvolution2dLayer* const layer = graph.AddLayer<DepthwiseConvolution2dLayer>(layerDesc, "layer");
- layer->m_Weight = std::make_unique<ScopedTensorHandle>(TensorInfo({3, 3, 5, 3}, DataType::Float32));
- layer->m_Bias = std::make_unique<ScopedTensorHandle>(TensorInfo({9}, DataType::Float32));
+ layer->m_Weight = std::make_unique<ScopedTensorHandle>(
+ TensorInfo({3, 3, 5, 3}, DataType::Float32));
+ layer->m_Bias = std::make_unique<ScopedTensorHandle>(
+ TensorInfo({9}, DataType::Float32));
layer->m_Weight->Allocate();
layer->m_Bias->Allocate();
@@ -170,10 +191,10 @@ TEST_CASE("ReleaseFullyConnectedLayerConstantDataTest")
float inputsQScale = 1.0f;
float outputQScale = 2.0f;
- layer->m_Weight = std::make_unique<ScopedTensorHandle>(TensorInfo({7, 20},
- DataType::QAsymmU8, inputsQScale, 0));
- layer->m_Bias = std::make_unique<ScopedTensorHandle>(TensorInfo({7},
- GetBiasDataType(DataType::QAsymmU8), inputsQScale));
+ layer->m_Weight = std::make_unique<ScopedTensorHandle>(
+ TensorInfo({7, 20}, DataType::QAsymmU8, inputsQScale, 0));
+ layer->m_Bias = std::make_unique<ScopedTensorHandle>(
+ TensorInfo({7}, GetBiasDataType(DataType::QAsymmU8), inputsQScale));
layer->m_Weight->Allocate();
layer->m_Bias->Allocate();
diff --git a/src/backends/backendsCommon/test/OptimizationViewsTests.cpp b/src/backends/backendsCommon/test/OptimizationViewsTests.cpp
index 1219ac5a33..9b86784dce 100644
--- a/src/backends/backendsCommon/test/OptimizationViewsTests.cpp
+++ b/src/backends/backendsCommon/test/OptimizationViewsTests.cpp
@@ -61,31 +61,35 @@ TEST_CASE("OptimizedViewsSubgraphLayerCount")
Layer* const inputLayer = baseGraph.AddLayer<InputLayer>(0, "input");
Convolution2dDescriptor convDescriptor;
- PreCompiledDescriptor substitutionLayerDescriptor(1, 1);
+ PreCompiledDescriptor substitutionLayerDescriptor(2, 1);
Layer* const convLayer1 = baseGraph.AddLayer<Convolution2dLayer>(convDescriptor, "conv1");
Layer* const convLayer2 = baseGraph.AddLayer<Convolution2dLayer>(convDescriptor, "conv2");
+ Layer* const weightsLayer1 = baseGraph.AddLayer<ConstantLayer>("weights1");
+ Layer* const weightsLayer2 = baseGraph.AddLayer<ConstantLayer>("weights2");
Layer* const substitutableCompiledLayer =
baseGraph.AddLayer<PreCompiledLayer>(substitutionLayerDescriptor, "pre-compiled");
Layer* const outputLayer = baseGraph.AddLayer<OutputLayer>(0, "output");
inputLayer->GetOutputSlot(0).Connect(convLayer1->GetInputSlot(0));
+ weightsLayer1->GetOutputSlot(0).Connect(convLayer1->GetInputSlot(1));
convLayer1->GetOutputSlot(0).Connect(convLayer2->GetInputSlot(0));
+ weightsLayer2->GetOutputSlot(0).Connect(convLayer2->GetInputSlot(1));
convLayer2->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
// Subgraph for a failed layer
SubgraphViewSelector::SubgraphViewPtr failedSubgraph =
- CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
+ CreateSubgraphViewFrom(CreateInputsFrom(convLayer1),
CreateOutputsFrom({convLayer1}),
{convLayer1});
// Subgraph for an untouched layer
SubgraphViewSelector::SubgraphViewPtr untouchedSubgraph =
- CreateSubgraphViewFrom(CreateInputsFrom({convLayer2}),
+ CreateSubgraphViewFrom(CreateInputsFrom(convLayer2),
CreateOutputsFrom({convLayer2}),
{convLayer2});
// Subgraph for a substitutable layer
SubgraphViewSelector::SubgraphViewPtr substitutableSubgraph =
- CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
+ CreateSubgraphViewFrom(CreateInputsFrom(convLayer1),
CreateOutputsFrom({convLayer2}),
{substitutableCompiledLayer});
// Create a Graph containing a layer to substitute in
@@ -95,7 +99,7 @@ TEST_CASE("OptimizedViewsSubgraphLayerCount")
// Subgraph for a substitution layer
SubgraphViewSelector::SubgraphViewPtr substitutionSubgraph =
- CreateSubgraphViewFrom(CreateInputsFrom({substitutionpreCompiledLayer}),
+ CreateSubgraphViewFrom(CreateInputsFrom(substitutionpreCompiledLayer),
CreateOutputsFrom({substitutionpreCompiledLayer}),
{substitutionpreCompiledLayer});
@@ -106,14 +110,14 @@ TEST_CASE("OptimizedViewsSubgraphLayerCount")
view.AddUntouchedSubgraph(SubgraphView(*untouchedSubgraph));
SubgraphViewSelector::SubgraphViewPtr baseSubgraph =
- CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
+ CreateSubgraphViewFrom(CreateInputsFrom(convLayer1),
CreateOutputsFrom({convLayer2}),
{substitutionpreCompiledLayer});
view.AddSubstitution({*baseSubgraph, *substitutionSubgraph});
// Construct original subgraph to compare against
SubgraphViewSelector::SubgraphViewPtr originalSubgraph =
- CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
+ CreateSubgraphViewFrom(CreateInputsFrom(convLayer1),
CreateOutputsFrom({convLayer2}),
{convLayer1, convLayer2, substitutionpreCompiledLayer});
@@ -147,11 +151,11 @@ TEST_CASE("OptimizedViewsSubgraphLayerCountUsingGetINetwork")
convLayer2->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
// Subgraph for a failed layer
- SubgraphViewSelector::SubgraphViewPtr failedSubgraph = CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
+ SubgraphViewSelector::SubgraphViewPtr failedSubgraph = CreateSubgraphViewFrom(CreateInputsFrom(convLayer1),
CreateOutputsFrom({convLayer1}),
{convLayer1});
// Subgraph for an untouched layer
- SubgraphViewSelector::SubgraphViewPtr untouchedSubgraph = CreateSubgraphViewFrom(CreateInputsFrom({convLayer2}),
+ SubgraphViewSelector::SubgraphViewPtr untouchedSubgraph = CreateSubgraphViewFrom(CreateInputsFrom(convLayer2),
CreateOutputsFrom({convLayer2}),
{convLayer2});
@@ -162,21 +166,21 @@ TEST_CASE("OptimizedViewsSubgraphLayerCountUsingGetINetwork")
// Subgraph for a substitution layer
SubgraphViewSelector::SubgraphViewPtr substitutionSubgraph =
- CreateSubgraphViewFrom(CreateInputsFrom({substitutionpreCompiledLayer}),
+ CreateSubgraphViewFrom(CreateInputsFrom(substitutionpreCompiledLayer),
CreateOutputsFrom({substitutionpreCompiledLayer}),
{substitutionpreCompiledLayer});
view.AddFailedSubgraph(SubgraphView(*failedSubgraph));
view.AddUntouchedSubgraph(SubgraphView(*untouchedSubgraph));
- SubgraphViewSelector::SubgraphViewPtr baseSubgraph = CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
+ SubgraphViewSelector::SubgraphViewPtr baseSubgraph = CreateSubgraphViewFrom(CreateInputsFrom(convLayer1),
CreateOutputsFrom({convLayer2}),
{substitutionpreCompiledLayer});
view.AddSubstitution({*baseSubgraph, *substitutionSubgraph});
// Construct original subgraph to compare against
SubgraphViewSelector::SubgraphViewPtr originalSubgraph =
- CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
+ CreateSubgraphViewFrom(CreateInputsFrom(convLayer1),
CreateOutputsFrom({convLayer2}),
{convLayer1, convLayer2, substitutionpreCompiledLayer});
@@ -192,26 +196,31 @@ TEST_CASE("OptimizedViewsSubgraphLayerCountFailValidate")
Layer* const inputLayer = baseGraph.AddLayer<InputLayer>(0, "input");
Convolution2dDescriptor convDescriptor;
- PreCompiledDescriptor substitutionLayerDescriptor(1, 1);
+ PreCompiledDescriptor substitutionLayerDescriptor(2, 1);
Layer* const convLayer1 = baseGraph.AddLayer<Convolution2dLayer>(convDescriptor, "conv1");
Layer* const convLayer2 = baseGraph.AddLayer<Convolution2dLayer>(convDescriptor, "conv2");
+ Layer* const weightsLayer1 = baseGraph.AddLayer<ConstantLayer>("weights1");
+ Layer* const weightsLayer2 = baseGraph.AddLayer<ConstantLayer>("weights2");
Layer* const substitutableCompiledLayer =
baseGraph.AddLayer<PreCompiledLayer>(substitutionLayerDescriptor, "pre-compiled");
Layer* const outputLayer = baseGraph.AddLayer<OutputLayer>(0, "output");
+
inputLayer->GetOutputSlot(0).Connect(convLayer1->GetInputSlot(0));
+ weightsLayer1->GetOutputSlot(0).Connect(convLayer1->GetInputSlot(1));
convLayer1->GetOutputSlot(0).Connect(convLayer2->GetInputSlot(0));
+ weightsLayer2->GetOutputSlot(0).Connect(convLayer2->GetInputSlot(1));
convLayer2->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
// Subgraph for an untouched layer
SubgraphViewSelector::SubgraphViewPtr untouchedSubgraph =
- CreateSubgraphViewFrom(CreateInputsFrom({convLayer2}),
+ CreateSubgraphViewFrom(CreateInputsFrom(convLayer2),
CreateOutputsFrom({convLayer2}),
{convLayer2});
// Subgraph for a substitutable layer
SubgraphViewSelector::SubgraphViewPtr substitutableSubgraph =
- CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
+ CreateSubgraphViewFrom(CreateInputsFrom(convLayer1),
CreateOutputsFrom({convLayer2}),
{substitutableCompiledLayer});
// Create a Graph containing a layer to substitute in
@@ -221,7 +230,7 @@ TEST_CASE("OptimizedViewsSubgraphLayerCountFailValidate")
// Subgraph for a substitution layer
SubgraphViewSelector::SubgraphViewPtr substitutionSubgraph =
- CreateSubgraphViewFrom(CreateInputsFrom({substitutionpreCompiledLayer}),
+ CreateSubgraphViewFrom(CreateInputsFrom(substitutionpreCompiledLayer),
CreateOutputsFrom({substitutionpreCompiledLayer}),
{substitutionpreCompiledLayer});
@@ -231,14 +240,14 @@ TEST_CASE("OptimizedViewsSubgraphLayerCountFailValidate")
view.AddUntouchedSubgraph(SubgraphView(*untouchedSubgraph));
SubgraphViewSelector::SubgraphViewPtr baseSubgraph =
- CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
+ CreateSubgraphViewFrom(CreateInputsFrom(convLayer1),
CreateOutputsFrom({convLayer2}),
{substitutionpreCompiledLayer});
view.AddSubstitution({*baseSubgraph, *substitutionSubgraph});
// Construct original subgraph to compare against
SubgraphViewSelector::SubgraphViewPtr originalSubgraph =
- CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
+ CreateSubgraphViewFrom(CreateInputsFrom(convLayer1),
CreateOutputsFrom({convLayer2}),
{convLayer1, convLayer2, substitutionpreCompiledLayer});
diff --git a/src/backends/backendsCommon/test/OptimizeSubgraphViewTests.cpp b/src/backends/backendsCommon/test/OptimizeSubgraphViewTests.cpp
index ad59704e2a..45fcf19f90 100644
--- a/src/backends/backendsCommon/test/OptimizeSubgraphViewTests.cpp
+++ b/src/backends/backendsCommon/test/OptimizeSubgraphViewTests.cpp
@@ -106,6 +106,21 @@ Convolution2dLayer* AddConvolutionLayer(Graph& graph,
return convLayer;
}
+// Convenience function to add a constant layer to a graph
+ConstantLayer* AddConstantLayer(Graph& graph,
+ LayerNameToLayerMap& layersInGraph,
+ const std::string& layerName,
+ const ConstTensor& constTensor,
+ const TensorInfo& outputInfo)
+{
+ ConstantLayer* const constantLayer = graph.AddLayer<ConstantLayer>(layerName.c_str());
+ CHECK(constantLayer);
+ constantLayer->m_LayerOutput = std::make_shared<ScopedTensorHandle>(constTensor);
+ constantLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
+ layersInGraph.insert(std::make_pair(constantLayer->GetName(), constantLayer));
+ return constantLayer;
+}
+
// Convenience function to add a pooling layer to a graph
Pooling2dLayer* AddPoolingLayer(Graph& graph,
LayerNameToLayerMap& layersInGraph,
@@ -246,7 +261,7 @@ SubgraphView::SubgraphViewPtr BuildFullyUnsupportedSubgraph1(Graph& graph, Layer
poolingLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
// Create the subgraph view for the whole network
- return CreateSubgraphViewFrom(CreateInputsFrom({poolingLayer}),
+ return CreateSubgraphViewFrom(CreateInputsFrom(poolingLayer),
CreateOutputsFrom({poolingLayer}),
{poolingLayer});
}
@@ -287,7 +302,7 @@ SubgraphView::SubgraphViewPtr BuildFullyUnsupportedSubgraph2(Graph& graph, Layer
pooling3Layer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
// Create the subgraph view for the whole network
- return CreateSubgraphViewFrom(CreateInputsFrom({pooling1Layer}),
+ return CreateSubgraphViewFrom(CreateInputsFrom(pooling1Layer),
CreateOutputsFrom({pooling3Layer}),
{pooling1Layer,
pooling2Layer,
@@ -299,8 +314,11 @@ SubgraphView::SubgraphViewPtr BuildFullyOptimizableSubgraph1(Graph& graph, Layer
{
const TensorInfo inputInfo ({ 1, 16, 16, 16 }, DataType::QAsymmU8, 1.0f, 0);
const TensorInfo outputInfo({ 1, 16, 16, 16 }, DataType::QAsymmU8, 1.0f, 0);
- const TensorInfo weightInfo({ 16, 1, 1, 16 }, DataType::QAsymmU8, 0.9f, 0);
- const TensorInfo biasInfo ({ 1, 1, 1, 16 }, DataType::Signed32, 0.9f, 0);
+ TensorInfo weightInfo({ 16, 1, 1, 16 }, DataType::QAsymmU8, 0.9f, 0);
+ TensorInfo biasInfo ({ 1, 1, 1, 16 }, DataType::Signed32, 0.9f, 0);
+
+ weightInfo.SetConstant(true);
+ biasInfo.SetConstant(true);
Convolution2dDescriptor convolutionDescriptor;
convolutionDescriptor.m_StrideX = 1;
@@ -308,20 +326,34 @@ SubgraphView::SubgraphViewPtr BuildFullyOptimizableSubgraph1(Graph& graph, Layer
convolutionDescriptor.m_BiasEnabled = true;
convolutionDescriptor.m_DataLayout = DataLayout::NHWC;
+ std::vector<float> weightsVector(64);
+ ConstTensor constWeightsTensor(weightInfo, weightsVector);
+
+ std::vector<float> biasVector(16);
+ ConstTensor constBiasTensor(biasInfo, biasVector);
+
// Construct the graph
Layer* const inputLayer = AddInputLayer(graph, "input layer", inputInfo);
Convolution2dLayer* const convLayer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
"conv layer", weightInfo, biasInfo, outputInfo);
+
+ ConstantLayer* const weightsLayer =
+ AddConstantLayer(graph, layersInGraph, "Weights Layer", constWeightsTensor, outputInfo);
+ ConstantLayer* const biasLayer = AddConstantLayer(graph, layersInGraph, "Bias Layer", constBiasTensor, outputInfo);
+
Layer* const outputLayer = AddOutputLayer(graph, "output layer");
// Connect the network
inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
+ weightsLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(1));
+ biasLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(2));
convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
+ std::vector<unsigned int> ignoreSlots = {1, 2};
// Create the subgraph view for the whole network
- return CreateSubgraphViewFrom(CreateInputsFrom({convLayer}),
+ return CreateSubgraphViewFrom(CreateInputsFrom(convLayer, ignoreSlots),
CreateOutputsFrom({convLayer}),
- {convLayer});
+ {convLayer, weightsLayer, biasLayer});
}
// Creates a subgraph with five convolutions layers, all supported by the mock backend
@@ -329,8 +361,18 @@ SubgraphView::SubgraphViewPtr BuildFullyOptimizableSubgraph2(Graph& graph, Layer
{
const TensorInfo inputInfo ({ 1, 16, 16, 16 }, DataType::QAsymmU8, 1.0f, 0);
const TensorInfo outputInfo({ 1, 16, 16, 16 }, DataType::QAsymmU8, 1.0f, 0);
- const TensorInfo weightInfo({ 16, 1, 1, 16 }, DataType::QAsymmU8, 0.9f, 0);
- const TensorInfo biasInfo ({ 1, 1, 1, 16 }, DataType::Signed32, 0.9f, 0);
+ TensorInfo weightInfo({ 16, 1, 1, 16 }, DataType::QAsymmU8, 0.9f, 0);
+ TensorInfo biasInfo ({ 1, 1, 1, 16 }, DataType::Signed32, 0.9f, 0);
+
+ weightInfo.SetConstant(true);
+ biasInfo.SetConstant(true);
+
+ std::vector<float> weightsVector(64);
+ ConstTensor constWeightsTensor(weightInfo, weightsVector);
+
+ std::vector<float> biasVector(16);
+ ConstTensor constBiasTensor(biasInfo, biasVector);
+
Convolution2dDescriptor convolutionDescriptor;
convolutionDescriptor.m_StrideX = 1;
@@ -342,32 +384,84 @@ SubgraphView::SubgraphViewPtr BuildFullyOptimizableSubgraph2(Graph& graph, Layer
Layer* const inputLayer = AddInputLayer(graph, "input layer", inputInfo);
Convolution2dLayer* const conv1Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
"conv1 layer", weightInfo, biasInfo, outputInfo);
+ ConstantLayer* const weightsLayer1 =
+ AddConstantLayer(graph, layersInGraph, "Weights Layer 1", constWeightsTensor, outputInfo);
+ ConstantLayer* const biasLayer1 =
+ AddConstantLayer(graph, layersInGraph, "Bias Layer 1", constBiasTensor, outputInfo);
+
Convolution2dLayer* const conv2Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
"conv2 layer", weightInfo, biasInfo, outputInfo);
+ ConstantLayer* const weightsLayer2 =
+ AddConstantLayer(graph, layersInGraph, "Weights Layer 2", constWeightsTensor, outputInfo);
+ ConstantLayer* const biasLayer2 =
+ AddConstantLayer(graph, layersInGraph, "Bias Layer 2", constBiasTensor, outputInfo);
+
+
Convolution2dLayer* const conv3Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
"conv3 layer", weightInfo, biasInfo, outputInfo);
+ ConstantLayer* const weightsLayer3 =
+ AddConstantLayer(graph, layersInGraph, "Weights Layer 3", constWeightsTensor, outputInfo);
+ ConstantLayer* const biasLayer3 =
+ AddConstantLayer(graph, layersInGraph, "Bias Layer 3", constBiasTensor, outputInfo);
+
Convolution2dLayer* const conv4Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
"conv4 layer", weightInfo, biasInfo, outputInfo);
+ ConstantLayer* const weightsLayer4 =
+ AddConstantLayer(graph, layersInGraph, "Weights Layer 4", constWeightsTensor, outputInfo);
+ ConstantLayer* const biasLayer4 =
+ AddConstantLayer(graph, layersInGraph, "Bias Layer 4", constBiasTensor, outputInfo);
+
Convolution2dLayer* const conv5Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
"conv5 layer", weightInfo, biasInfo, outputInfo);
+ ConstantLayer* const weightsLayer5 =
+ AddConstantLayer(graph, layersInGraph, "Weights Layer 5", constWeightsTensor, outputInfo);
+ ConstantLayer* const biasLayer5 =
+ AddConstantLayer(graph, layersInGraph, "Bias Layer 5", constBiasTensor, outputInfo);
+
+
Layer* const outputLayer = AddOutputLayer(graph, "output layer");
// Connect the network
inputLayer->GetOutputSlot(0).Connect(conv1Layer->GetInputSlot(0));
+ weightsLayer1->GetOutputSlot(0).Connect(conv1Layer->GetInputSlot(1));
+ biasLayer1->GetOutputSlot(0).Connect(conv1Layer->GetInputSlot(2));
+
conv1Layer->GetOutputSlot(0).Connect(conv2Layer->GetInputSlot(0));
+ weightsLayer2->GetOutputSlot(0).Connect(conv2Layer->GetInputSlot(1));
+ biasLayer2->GetOutputSlot(0).Connect(conv2Layer->GetInputSlot(2));
+
conv2Layer->GetOutputSlot(0).Connect(conv3Layer->GetInputSlot(0));
+ weightsLayer3->GetOutputSlot(0).Connect(conv3Layer->GetInputSlot(1));
+ biasLayer3->GetOutputSlot(0).Connect(conv3Layer->GetInputSlot(2));
+
conv3Layer->GetOutputSlot(0).Connect(conv4Layer->GetInputSlot(0));
+ weightsLayer4->GetOutputSlot(0).Connect(conv4Layer->GetInputSlot(1));
+ biasLayer4->GetOutputSlot(0).Connect(conv4Layer->GetInputSlot(2));
+
conv4Layer->GetOutputSlot(0).Connect(conv5Layer->GetInputSlot(0));
- conv5Layer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
+ weightsLayer5->GetOutputSlot(0).Connect(conv5Layer->GetInputSlot(1));
+ biasLayer5->GetOutputSlot(0).Connect(conv5Layer->GetInputSlot(2));
+ conv5Layer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
+ std::vector<unsigned int> ignoreSlots = {1, 2};
// Create the subgraph view for the whole network
- return CreateSubgraphViewFrom(CreateInputsFrom({conv1Layer}),
- CreateOutputsFrom({conv5Layer}),
- {conv1Layer,
- conv2Layer,
- conv3Layer,
- conv4Layer,
- conv5Layer});
+ return CreateSubgraphViewFrom(CreateInputsFrom(conv1Layer, ignoreSlots),
+ CreateOutputsFrom({ conv5Layer }),
+ { weightsLayer1,
+ biasLayer1,
+ conv1Layer,
+ weightsLayer2,
+ biasLayer2,
+ conv2Layer,
+ weightsLayer3,
+ biasLayer3,
+ conv3Layer,
+ weightsLayer4,
+ biasLayer4,
+ conv4Layer,
+ weightsLayer5,
+ biasLayer5,
+ conv5Layer });
}
// Creates a subgraph with both supported and unsupported layers
@@ -376,8 +470,17 @@ SubgraphView::SubgraphViewPtr BuildPartiallySupportedSubgraph(Graph& graph, Laye
{
const TensorInfo inputInfo ({ 1, 16, 16, 16 }, DataType::QAsymmU8, 1.0f, 0);
const TensorInfo outputInfo({ 1, 16, 16, 16 }, DataType::QAsymmU8, 1.0f, 0);
- const TensorInfo weightInfo({ 16, 1, 1, 16 }, DataType::QAsymmU8, 0.9f, 0);
- const TensorInfo biasInfo ({ 1, 1, 1, 16 }, DataType::Signed32, 0.9f, 0);
+ TensorInfo weightInfo({ 16, 1, 1, 16 }, DataType::QAsymmU8, 0.9f, 0);
+ TensorInfo biasInfo ({ 1, 1, 1, 16 }, DataType::Signed32, 0.9f, 0);
+
+ weightInfo.SetConstant(true);
+ biasInfo.SetConstant(true);
+
+ std::vector<float> weightsVector(64);
+ ConstTensor constWeightsTensor(weightInfo, weightsVector);
+
+ std::vector<float> biasVector(16);
+ ConstTensor constBiasTensor(biasInfo, biasVector);
Convolution2dDescriptor convolutionDescriptor;
convolutionDescriptor.m_StrideX = 1;
@@ -400,12 +503,25 @@ SubgraphView::SubgraphViewPtr BuildPartiallySupportedSubgraph(Graph& graph, Laye
// Construct the graph
Layer* const inputLayer = AddInputLayer(graph, "input layer", inputInfo);
+ ConstantLayer* const weightsLayer1 =
+ AddConstantLayer(graph, layersInGraph, "Weights Layer 1", constWeightsTensor, outputInfo);
+
+ ConstantLayer* const biasLayer1 =
+ AddConstantLayer(graph, layersInGraph, "Bias Layer 1", constBiasTensor, outputInfo);
+
Convolution2dLayer* const conv1Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
"conv1 layer", weightInfo, biasInfo, outputInfo);
Pooling2dLayer* const pooling1Layer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
"pooling1 layer", outputInfo);
Pooling2dLayer* const pooling2Layer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
"pooling2 layer", outputInfo);
+
+ ConstantLayer* const weightsLayer2 =
+ AddConstantLayer(graph, layersInGraph, "Weights Layer 2", constWeightsTensor, outputInfo);
+
+ ConstantLayer* const biasLayer2 =
+ AddConstantLayer(graph, layersInGraph, "Bias Layer 2", constBiasTensor, outputInfo);
+
Convolution2dLayer* const conv2Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
"conv2 layer", weightInfo, biasInfo, outputInfo);
Pooling2dLayer* const pooling3Layer = AddPoolingLayer(graph, layersInGraph, poolingDescriptor,
@@ -414,18 +530,27 @@ SubgraphView::SubgraphViewPtr BuildPartiallySupportedSubgraph(Graph& graph, Laye
// Connect the network
inputLayer->GetOutputSlot(0).Connect(conv1Layer->GetInputSlot(0));
+ weightsLayer1->GetOutputSlot(0).Connect(conv1Layer->GetInputSlot(1));
+ biasLayer1->GetOutputSlot(0).Connect(conv1Layer->GetInputSlot(2));
conv1Layer->GetOutputSlot(0).Connect(pooling1Layer->GetInputSlot(0));
pooling1Layer->GetOutputSlot(0).Connect(pooling2Layer->GetInputSlot(0));
pooling2Layer->GetOutputSlot(0).Connect(conv2Layer->GetInputSlot(0));
+ weightsLayer2->GetOutputSlot(0).Connect(conv2Layer->GetInputSlot(1));
+ biasLayer2->GetOutputSlot(0).Connect(conv2Layer->GetInputSlot(2));
conv2Layer->GetOutputSlot(0).Connect(pooling3Layer->GetInputSlot(0));
pooling3Layer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
+ std::vector<unsigned int> ignoreSlots = {1, 2};
// Create the subgraph view for the whole network
- return CreateSubgraphViewFrom(CreateInputsFrom({conv1Layer}),
+ return CreateSubgraphViewFrom(CreateInputsFrom(conv1Layer, ignoreSlots),
CreateOutputsFrom({pooling3Layer}),
- {conv1Layer,
+ {weightsLayer1,
+ biasLayer1,
+ conv1Layer,
pooling1Layer,
pooling2Layer,
+ weightsLayer2,
+ biasLayer2,
conv2Layer,
pooling3Layer});
}
@@ -435,9 +560,17 @@ SubgraphView::SubgraphViewPtr BuildFullyUnoptimizableSubgraph1(Graph& graph, Lay
{
const TensorInfo inputInfo ({ 1, 16, 16, 16 }, DataType::QAsymmU8, 1.0f, 0);
const TensorInfo outputInfo({ 1, 16, 16, 16 }, DataType::QAsymmU8, 1.0f, 0);
- const TensorInfo weightInfo({ 16, 1, 1, 16 }, DataType::QAsymmU8, 0.9f, 0);
- const TensorInfo biasInfo ({ 1, 1, 1, 16 }, DataType::Signed32, 0.9f, 0);
+ TensorInfo weightInfo({ 16, 1, 1, 16 }, DataType::QAsymmU8, 0.9f, 0);
+ TensorInfo biasInfo ({ 1, 1, 1, 16 }, DataType::Signed32, 0.9f, 0);
+ weightInfo.SetConstant(true);
+ biasInfo.SetConstant(true);
+
+ std::vector<float> weightsVector(64);
+ ConstTensor constWeightsTensor(weightInfo, weightsVector);
+
+ std::vector<float> biasVector(16);
+ ConstTensor constBiasTensor(biasInfo, biasVector);
Convolution2dDescriptor convolutionDescriptor;
convolutionDescriptor.m_StrideX = 1;
convolutionDescriptor.m_StrideY = 1;
@@ -446,6 +579,13 @@ SubgraphView::SubgraphViewPtr BuildFullyUnoptimizableSubgraph1(Graph& graph, Lay
// Construct the graph
Layer* const inputLayer = AddInputLayer(graph, "input layer", inputInfo);
+
+ ConstantLayer* const weightsLayer =
+ AddConstantLayer(graph, layersInGraph, "Weights Layer unoptimizable", constWeightsTensor, outputInfo);
+
+ ConstantLayer* const biasLayer =
+ AddConstantLayer(graph, layersInGraph, "Bias Layer unoptimizable", constBiasTensor, outputInfo);
+
Convolution2dLayer* const convLayer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
"conv layer unoptimizable", weightInfo, biasInfo,
outputInfo);
@@ -453,12 +593,15 @@ SubgraphView::SubgraphViewPtr BuildFullyUnoptimizableSubgraph1(Graph& graph, Lay
// Connect the network
inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
+ weightsLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(1));
+ biasLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(2));
convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
+ std::vector<unsigned int> ignoreSlots = {1, 2};
// Create the subgraph view for the whole network
- return CreateSubgraphViewFrom(CreateInputsFrom({convLayer}),
+ return CreateSubgraphViewFrom(CreateInputsFrom(convLayer, ignoreSlots),
CreateOutputsFrom({convLayer}),
- {convLayer});
+ {convLayer, weightsLayer, biasLayer});
}
// Creates a subgraph with some unoptimizable layers ("unoptimizable" is added to the layer's name)
@@ -466,8 +609,17 @@ SubgraphView::SubgraphViewPtr BuildPartiallyOptimizableSubgraph1(Graph& graph, L
{
const TensorInfo inputInfo ({ 1, 16, 16, 16 }, DataType::QAsymmU8, 1.0f, 0);
const TensorInfo outputInfo({ 1, 16, 16, 16 }, DataType::QAsymmU8, 1.0f, 0);
- const TensorInfo weightInfo({ 16, 1, 1, 16 }, DataType::QAsymmU8, 0.9f, 0);
- const TensorInfo biasInfo ({ 1, 1, 1, 16 }, DataType::Signed32, 0.9f, 0);
+ TensorInfo weightInfo({ 16, 1, 1, 16 }, DataType::QAsymmU8, 0.9f, 0);
+ TensorInfo biasInfo ({ 1, 1, 1, 16 }, DataType::Signed32, 0.9f, 0);
+
+ weightInfo.SetConstant(true);
+ biasInfo.SetConstant(true);
+
+ std::vector<float> weightsVector(64);
+ ConstTensor constWeightsTensor(weightInfo, weightsVector);
+
+ std::vector<float> biasVector(16);
+ ConstTensor constBiasTensor(biasInfo, biasVector);
Convolution2dDescriptor convolutionDescriptor;
convolutionDescriptor.m_StrideX = 1;
@@ -477,36 +629,93 @@ SubgraphView::SubgraphViewPtr BuildPartiallyOptimizableSubgraph1(Graph& graph, L
// Construct the graph
Layer* const inputLayer = AddInputLayer(graph, "input layer", inputInfo);
- Convolution2dLayer* const conv1Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
- "conv1 layer", weightInfo, biasInfo, outputInfo);
- Convolution2dLayer* const conv2Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
- "conv2 layer unoptimizable", weightInfo, biasInfo,
- outputInfo);
- Convolution2dLayer* const conv3Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
- "conv3 layer", weightInfo, biasInfo, outputInfo);
- Convolution2dLayer* const conv4Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
- "conv4 layer unoptimizable", weightInfo, biasInfo,
- outputInfo);
- Convolution2dLayer* const conv5Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
- "conv5 layer", weightInfo, biasInfo, outputInfo);
- Layer* const outputLayer = AddOutputLayer(graph, "output layer");
+
+ ConstantLayer* const weightsLayer1 =
+ AddConstantLayer(graph, layersInGraph, "Weights Layer 1", constWeightsTensor, outputInfo);
+ ConstantLayer* const biasLayer1 =
+ AddConstantLayer(graph, layersInGraph, "Bias Layer 1", constBiasTensor, outputInfo);
+ ConstantLayer* const weightsLayer2 =
+ AddConstantLayer(graph, layersInGraph, "Weights Layer 2 unoptimizable", constWeightsTensor, outputInfo);
+ ConstantLayer* const biasLayer2 =
+ AddConstantLayer(graph, layersInGraph, "Bias Layer 2 unoptimizable", constBiasTensor, outputInfo);
+ ConstantLayer* const weightsLayer3 =
+ AddConstantLayer(graph, layersInGraph, "Weights Layer 3", constWeightsTensor, outputInfo);
+ ConstantLayer* const biasLayer3 =
+ AddConstantLayer(graph, layersInGraph, "Bias Layer 3", constBiasTensor, outputInfo);
+ ConstantLayer* const weightsLayer4 =
+ AddConstantLayer(graph, layersInGraph, "Weights Layer 4 unoptimizable", constWeightsTensor, outputInfo);
+ ConstantLayer* const biasLayer4 =
+ AddConstantLayer(graph, layersInGraph, "Bias Layer 4 unoptimizable", constBiasTensor, outputInfo);
+ ConstantLayer* const weightsLayer5 =
+ AddConstantLayer(graph, layersInGraph, "Weights Layer 5", constWeightsTensor, outputInfo);
+ ConstantLayer* const biasLayer5 =
+ AddConstantLayer(graph, layersInGraph, "Bias Layer 5", constBiasTensor, outputInfo);
+
+ Convolution2dLayer* const conv1Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
+ "conv1 layer", weightInfo, biasInfo, outputInfo);
+ Convolution2dLayer* const conv2Layer = AddConvolutionLayer(graph,
+ layersInGraph,
+ convolutionDescriptor,
+ "conv2 layer unoptimizable",
+ weightInfo,
+ biasInfo,
+ outputInfo);
+ Convolution2dLayer* const conv3Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
+ "conv3 layer", weightInfo, biasInfo, outputInfo);
+ Convolution2dLayer* const conv4Layer = AddConvolutionLayer(graph,
+ layersInGraph,
+ convolutionDescriptor,
+ "conv4 layer unoptimizable",
+ weightInfo,
+ biasInfo,
+ outputInfo);
+ Convolution2dLayer* const conv5Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
+ "conv5 layer", weightInfo, biasInfo, outputInfo);
+
+ Layer* const outputLayer = AddOutputLayer(graph, "output layer");
// Connect the network
inputLayer->GetOutputSlot(0).Connect(conv1Layer->GetInputSlot(0));
+ weightsLayer1->GetOutputSlot(0).Connect(conv1Layer->GetInputSlot(1));
+ biasLayer1->GetOutputSlot(0).Connect(conv1Layer->GetInputSlot(2));
+
conv1Layer->GetOutputSlot(0).Connect(conv2Layer->GetInputSlot(0));
+ weightsLayer2->GetOutputSlot(0).Connect(conv2Layer->GetInputSlot(1));
+ biasLayer2->GetOutputSlot(0).Connect(conv2Layer->GetInputSlot(2));
+
conv2Layer->GetOutputSlot(0).Connect(conv3Layer->GetInputSlot(0));
+ weightsLayer3->GetOutputSlot(0).Connect(conv3Layer->GetInputSlot(1));
+ biasLayer3->GetOutputSlot(0).Connect(conv3Layer->GetInputSlot(2));
+
conv3Layer->GetOutputSlot(0).Connect(conv4Layer->GetInputSlot(0));
+ weightsLayer4->GetOutputSlot(0).Connect(conv4Layer->GetInputSlot(1));
+ biasLayer4->GetOutputSlot(0).Connect(conv4Layer->GetInputSlot(2));
+
conv4Layer->GetOutputSlot(0).Connect(conv5Layer->GetInputSlot(0));
+ weightsLayer5->GetOutputSlot(0).Connect(conv5Layer->GetInputSlot(1));
+ biasLayer5->GetOutputSlot(0).Connect(conv5Layer->GetInputSlot(2));
+
conv5Layer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
+ std::vector<unsigned int> ignoreSlots = {1, 2};
// Create the subgraph view for the whole network
- return CreateSubgraphViewFrom(CreateInputsFrom({conv1Layer}),
+ return CreateSubgraphViewFrom(CreateInputsFrom(conv1Layer, ignoreSlots),
CreateOutputsFrom({conv5Layer}),
- {conv1Layer,
- conv2Layer,
- conv3Layer,
- conv4Layer,
- conv5Layer});
+ {weightsLayer1,
+ biasLayer1,
+ conv1Layer,
+ weightsLayer2,
+ biasLayer2,
+ conv2Layer,
+ weightsLayer3,
+ biasLayer3,
+ conv3Layer,
+ weightsLayer4,
+ biasLayer4,
+ conv4Layer,
+ weightsLayer5,
+ biasLayer5,
+ conv5Layer});
}
// Creates a subgraph with some input unoptimizable layers ("unoptimizable" is added to the layer's name),
@@ -515,8 +724,17 @@ SubgraphView::SubgraphViewPtr BuildPartiallyOptimizableSubgraph2(Graph& graph, L
{
const TensorInfo inputInfo ({ 1, 16, 16, 16 }, DataType::QAsymmU8, 1.0f, 0);
const TensorInfo outputInfo({ 1, 16, 16, 16 }, DataType::QAsymmU8, 1.0f, 0);
- const TensorInfo weightInfo({ 16, 1, 1, 16 }, DataType::QAsymmU8, 0.9f, 0);
- const TensorInfo biasInfo ({ 1, 1, 1, 16 }, DataType::Signed32, 0.9f, 0);
+ TensorInfo weightInfo({ 16, 1, 1, 16 }, DataType::QAsymmU8, 0.9f, 0);
+ TensorInfo biasInfo ({ 1, 1, 1, 16 }, DataType::Signed32, 0.9f, 0);
+
+ weightInfo.SetConstant(true);
+ biasInfo.SetConstant(true);
+
+ std::vector<float> weightsVector(64);
+ ConstTensor constWeightsTensor(weightInfo, weightsVector);
+
+ std::vector<float> biasVector(16);
+ ConstTensor constBiasTensor(biasInfo, biasVector);
Convolution2dDescriptor convolutionDescriptor;
convolutionDescriptor.m_StrideX = 1;
@@ -527,6 +745,20 @@ SubgraphView::SubgraphViewPtr BuildPartiallyOptimizableSubgraph2(Graph& graph, L
// Construct the graph
Layer* const input1Layer = AddInputLayer(graph, "input1 layer", inputInfo, 0);
Layer* const input2Layer = AddInputLayer(graph, "input2 layer", inputInfo, 1);
+
+ ConstantLayer* const weightsLayer1 =
+ AddConstantLayer(graph, layersInGraph, "Weights Layer 1", constWeightsTensor, outputInfo);
+ ConstantLayer* const biasLayer1 =
+ AddConstantLayer(graph, layersInGraph, "Bias Layer 1", constBiasTensor, outputInfo);
+ ConstantLayer* const weightsLayer2 =
+ AddConstantLayer(graph, layersInGraph, "Weights Layer 2 unoptimizable", constWeightsTensor, outputInfo);
+ ConstantLayer* const biasLayer2 =
+ AddConstantLayer(graph, layersInGraph, "Bias Layer 2 unoptimizable", constBiasTensor, outputInfo);
+ ConstantLayer* const weightsLayer3 =
+ AddConstantLayer(graph, layersInGraph, "Weights Layer 3", constWeightsTensor, outputInfo);
+ ConstantLayer* const biasLayer3 =
+ AddConstantLayer(graph, layersInGraph, "Bias Layer 3", constBiasTensor, outputInfo);
+
Convolution2dLayer* const conv1Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
"conv1 layer", weightInfo, biasInfo, outputInfo);
Convolution2dLayer* const conv2Layer = AddConvolutionLayer(graph, layersInGraph, convolutionDescriptor,
@@ -539,20 +771,35 @@ SubgraphView::SubgraphViewPtr BuildPartiallyOptimizableSubgraph2(Graph& graph, L
// Connect the network
input1Layer->GetOutputSlot(0).Connect(conv1Layer->GetInputSlot(0));
- input2Layer->GetOutputSlot(0).Connect(conv2Layer->GetInputSlot(0));
+ weightsLayer1->GetOutputSlot(0).Connect(conv1Layer->GetInputSlot(1));
+ biasLayer1->GetOutputSlot(0).Connect(conv1Layer->GetInputSlot(2));
conv1Layer->GetOutputSlot(0).Connect(addLayer->GetInputSlot(0));
+
+ input2Layer->GetOutputSlot(0).Connect(conv2Layer->GetInputSlot(0));
+ weightsLayer2->GetOutputSlot(0).Connect(conv2Layer->GetInputSlot(1));
+ biasLayer2->GetOutputSlot(0).Connect(conv2Layer->GetInputSlot(2));
conv2Layer->GetOutputSlot(0).Connect(conv3Layer->GetInputSlot(0));
+ weightsLayer3->GetOutputSlot(0).Connect(conv3Layer->GetInputSlot(1));
+ biasLayer3->GetOutputSlot(0).Connect(conv3Layer->GetInputSlot(2));
conv3Layer->GetOutputSlot(0).Connect(addLayer->GetInputSlot(1));
+
addLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
// Create the subgraph view for the whole network
+ std::vector<unsigned int> ignoreSlots = {1, 2};
return CreateSubgraphViewFrom(CreateInputsFrom({conv1Layer,
- conv2Layer}),
+ conv2Layer}, ignoreSlots),
CreateOutputsFrom({addLayer}),
- {conv1Layer,
- conv2Layer,
- conv3Layer,
- addLayer});
+ { weightsLayer1,
+ biasLayer1,
+ weightsLayer2,
+ biasLayer2,
+ weightsLayer3,
+ biasLayer3,
+ conv1Layer,
+ conv2Layer,
+ conv3Layer,
+ addLayer });
}
// The input subgraph contains only a single unsupported layer (only convolutions are unsupported by the mock backend)
@@ -713,9 +960,11 @@ void FullyOptimizableSubgraphTestImpl1()
CHECK(subgraphInputSlots.size() == 1);
CHECK(subgraphOutputSlots.size() == 1);
- CHECK(subgraphLayers.size() == 1);
+ CHECK(subgraphLayers.size() == 3);
CHECK(Contains(layersInGraph, "conv layer"));
+ CHECK(Contains(layersInGraph, "Weights Layer"));
+ CHECK(Contains(layersInGraph, "Bias Layer"));
// Create a mock backend object
MockBackendInitialiser initialiser; // Register the Mock Backend
@@ -776,15 +1025,25 @@ void FullyOptimizableSubgraphTestImpl2()
const SubgraphView::IOutputSlots& subgraphOutputSlots = subgraphPtr->GetIOutputSlots();
const SubgraphView::IConnectableLayers& subgraphLayers = subgraphPtr->GetIConnectableLayers();
- CHECK(subgraphPtr->GetIInputSlots().size() == 1);
- CHECK(subgraphPtr->GetIOutputSlots().size() == 1);
- CHECK(subgraphPtr->GetIConnectableLayers().size() == 5);
+ CHECK(subgraphInputSlots.size() == 1);
+ CHECK(subgraphOutputSlots.size() == 1);
+ CHECK(subgraphPtr->GetIConnectableLayers().size() == 15);
CHECK(Contains(layersInGraph, "conv1 layer"));
CHECK(Contains(layersInGraph, "conv2 layer"));
CHECK(Contains(layersInGraph, "conv3 layer"));
CHECK(Contains(layersInGraph, "conv4 layer"));
CHECK(Contains(layersInGraph, "conv5 layer"));
+ CHECK(Contains(layersInGraph, "Weights Layer 1"));
+ CHECK(Contains(layersInGraph, "Weights Layer 2"));
+ CHECK(Contains(layersInGraph, "Weights Layer 3"));
+ CHECK(Contains(layersInGraph, "Weights Layer 4"));
+ CHECK(Contains(layersInGraph, "Weights Layer 5"));
+ CHECK(Contains(layersInGraph, "Bias Layer 1"));
+ CHECK(Contains(layersInGraph, "Bias Layer 2"));
+ CHECK(Contains(layersInGraph, "Bias Layer 3"));
+ CHECK(Contains(layersInGraph, "Bias Layer 4"));
+ CHECK(Contains(layersInGraph, "Bias Layer 5"));
// Create a mock backend object
MockBackendInitialiser initialiser; // Register the Mock Backend
@@ -811,20 +1070,31 @@ void FullyOptimizableSubgraphTestImpl2()
const OptimizationViews::Substitutions& substitutions = optimizationViews.GetSubstitutions();
CHECK(substitutions.size() == 1);
- std::list<IConnectableLayer*> expectedSubstitutableLayers{ layersInGraph.at("conv1 layer"),
+ std::list<IConnectableLayer*> expectedSubstitutableLayers{
+ layersInGraph.at("Weights Layer 1"),
+ layersInGraph.at("Weights Layer 2"),
+ layersInGraph.at("Weights Layer 3"),
+ layersInGraph.at("Weights Layer 4"),
+ layersInGraph.at("Weights Layer 5"),
+ layersInGraph.at("Bias Layer 1"),
+ layersInGraph.at("Bias Layer 2"),
+ layersInGraph.at("Bias Layer 3"),
+ layersInGraph.at("Bias Layer 4"),
+ layersInGraph.at("Bias Layer 5"),
+ layersInGraph.at("conv1 layer"),
layersInGraph.at("conv2 layer"),
layersInGraph.at("conv3 layer"),
layersInGraph.at("conv4 layer"),
- layersInGraph.at("conv5 layer") };
+ layersInGraph.at("conv5 layer")};
const OptimizationViews::SubstitutionPair& substitution = substitutions.at(0);
- CheckSubstitution(substitution,
- { subgraphInputSlots.size(), subgraphOutputSlots.size(), subgraphLayers.size() },
- { subgraphInputSlots.size(), subgraphOutputSlots.size(), 1 },
- subgraphInputSlots,
- subgraphOutputSlots,
- expectedSubstitutableLayers);
+ CheckSubstitution(
+ substitution,
+ {subgraphInputSlots.size(), subgraphOutputSlots.size(),
+ subgraphLayers.size()},
+ {subgraphInputSlots.size(), subgraphOutputSlots.size(), 1},
+ subgraphInputSlots, subgraphOutputSlots, expectedSubstitutableLayers);
const SubgraphView::IConnectableLayers& substitutableSubgraphLayers =
substitution.m_SubstitutableSubgraph.GetIConnectableLayers();
@@ -865,11 +1135,15 @@ void PartiallySupportedSubgraphTestImpl()
CHECK(subgraphInputSlots.size() == 1);
CHECK(subgraphOutputSlots.size() == 1);
- CHECK(subgraphLayers.size() == 5);
+ CHECK(subgraphLayers.size() == 9);
+ CHECK(Contains(layersInGraph, "Weights Layer 1"));
+ CHECK(Contains(layersInGraph, "Bias Layer 1"));
CHECK(Contains(layersInGraph, "conv1 layer"));
CHECK(Contains(layersInGraph, "pooling1 layer"));
CHECK(Contains(layersInGraph, "pooling2 layer"));
+ CHECK(Contains(layersInGraph, "Weights Layer 2"));
+ CHECK(Contains(layersInGraph, "Bias Layer 2"));
CHECK(Contains(layersInGraph, "conv2 layer"));
CHECK(Contains(layersInGraph, "pooling3 layer"));
@@ -903,16 +1177,16 @@ void PartiallySupportedSubgraphTestImpl()
s2.m_SubstitutableSubgraph.GetIConnectableLayers().front()->GetName()) < 0;
});
- std::vector<ExpectedSubgraphSize> expectedSubstitutableSubgraphSizes{ { 1, 1, 1 },
- { 1, 1, 1 } };
+ std::vector<ExpectedSubgraphSize> expectedSubstitutableSubgraphSizes{ { 1, 1, 3 },
+ { 1, 1, 3 } };
std::vector<ExpectedSubgraphSize> expectedReplacementSubgraphSizes{ { 1, 1, 1 },
{ 1, 1, 1 } };
std::vector<SubgraphView::IInputSlots> expectedSubstitutableInputSlots
{
ConvertSlotsToISlots<InputSlot, IInputSlot>(
- ConvertReferenceTypeToPointerType(layersInGraph.at("conv1 layer")->GetInputSlots())),
+ {ConvertReferenceTypeToPointerType(layersInGraph.at("conv1 layer")->GetInputSlot(0))}),
ConvertSlotsToISlots<InputSlot, IInputSlot>(
- ConvertReferenceTypeToPointerType(layersInGraph.at("conv2 layer")->GetInputSlots()))
+ {ConvertReferenceTypeToPointerType(layersInGraph.at("conv2 layer")->GetInputSlot(0))})
};
std::vector<SubgraphView::IOutputSlots> expectedSubstitutableOutputSlots
@@ -924,8 +1198,8 @@ void PartiallySupportedSubgraphTestImpl()
};
std::vector<SubgraphView::IConnectableLayers> expectedSubstitutableLayers
{
- { layersInGraph.at("conv1 layer") },
- { layersInGraph.at("conv2 layer") }
+ { layersInGraph.at("Weights Layer 1"), layersInGraph.at("Bias Layer 1"), layersInGraph.at("conv1 layer") },
+ { layersInGraph.at("Weights Layer 2"), layersInGraph.at("Bias Layer 2"), layersInGraph.at("conv2 layer") }
};
for (size_t substitutionIndex = 0; substitutionIndex < substitutions.size(); substitutionIndex++)
@@ -1005,7 +1279,7 @@ void FullyUnoptimizableSubgraphTestImpl1()
CHECK(subgraphInputSlots.size() == 1);
CHECK(subgraphOutputSlots.size() == 1);
- CHECK(subgraphLayers.size() == 1);
+ CHECK(subgraphLayers.size() == 3);
CHECK(Contains(layersInGraph, "conv layer unoptimizable"));
@@ -1047,9 +1321,9 @@ void FullyUnoptimizableSubgraphTestImpl1()
CHECK(untouchedSubgraphs.size() == 1);
CheckUntouchedSubgraph(untouchedSubgraphs.at(0),
- { subgraphInputSlots.size(), subgraphOutputSlots.size(), subgraphLayers.size() },
- subgraphInputSlots,
- subgraphOutputSlots,
+ {subgraphInputSlots.size(),
+ subgraphOutputSlots.size(), subgraphLayers.size()},
+ subgraphInputSlots, subgraphOutputSlots,
subgraphLayers);
}
@@ -1069,7 +1343,7 @@ void PartiallyOptimizableSubgraphTestImpl1()
CHECK(subgraphInputSlots.size() == 1);
CHECK(subgraphOutputSlots.size() == 1);
- CHECK(subgraphLayers.size() == 5);
+ CHECK(subgraphLayers.size() == 15);
CHECK(Contains(layersInGraph, "conv1 layer"));
CHECK(Contains(layersInGraph, "conv2 layer unoptimizable"));
@@ -1107,20 +1381,20 @@ void PartiallyOptimizableSubgraphTestImpl1()
{ return strcmp(s1.m_SubstitutableSubgraph.GetIConnectableLayers().front()->GetName(),
s2.m_SubstitutableSubgraph.GetIConnectableLayers().front()->GetName()) < 0; });
- std::vector<ExpectedSubgraphSize> expectedSubstitutableSubgraphSizes{ { 1, 1, 1 },
- { 1, 1, 1 },
- { 1, 1, 1 } };
+ std::vector<ExpectedSubgraphSize> expectedSubstitutableSubgraphSizes{ { 1, 1, 3 },
+ { 1, 1, 3 },
+ { 1, 1, 3 } };
std::vector<ExpectedSubgraphSize> expectedReplacementSubgraphSizes{ { 1, 1, 1 },
{ 1, 1, 1 },
{ 1, 1, 1 } };
std::vector<SubgraphView::IInputSlots> expectedSubstitutableInputSlots
{
ConvertSlotsToISlots<InputSlot, IInputSlot>(
- ConvertReferenceTypeToPointerType(layersInGraph.at("conv1 layer")->GetInputSlots())),
+ {ConvertReferenceTypeToPointerType(layersInGraph.at("conv1 layer")->GetInputSlot(0))}),
ConvertSlotsToISlots<InputSlot, IInputSlot>(
- ConvertReferenceTypeToPointerType(layersInGraph.at("conv3 layer")->GetInputSlots())),
+ {ConvertReferenceTypeToPointerType(layersInGraph.at("conv3 layer")->GetInputSlot(0))}),
ConvertSlotsToISlots<InputSlot, IInputSlot>(
- ConvertReferenceTypeToPointerType(layersInGraph.at("conv5 layer")->GetInputSlots()))
+ {ConvertReferenceTypeToPointerType(layersInGraph.at("conv5 layer")->GetInputSlot(0))})
};
std::vector<SubgraphView::IOutputSlots> expectedSubstitutableOutputSlots
{
@@ -1133,9 +1407,9 @@ void PartiallyOptimizableSubgraphTestImpl1()
};
std::vector<SubgraphView::IConnectableLayers> expectedSubstitutableLayers
{
- { layersInGraph.at("conv1 layer") },
- { layersInGraph.at("conv3 layer") },
- { layersInGraph.at("conv5 layer") }
+ { layersInGraph.at("Weights Layer 1"), layersInGraph.at("Bias Layer 1"), layersInGraph.at("conv1 layer") },
+ { layersInGraph.at("Weights Layer 3"), layersInGraph.at("Bias Layer 3"), layersInGraph.at("conv3 layer") },
+ { layersInGraph.at("Weights Layer 5"), layersInGraph.at("Bias Layer 5"), layersInGraph.at("conv5 layer") }
};
for (size_t substitutionIndex = 0; substitutionIndex < substitutions.size(); substitutionIndex++)
@@ -1166,27 +1440,33 @@ void PartiallyOptimizableSubgraphTestImpl1()
s2.GetIConnectableLayers().front()->GetName()) < 0;
});
- std::vector<ExpectedSubgraphSize> expectedUntouchedSubgraphSizes{ { 1, 1, 1 },
- { 1, 1, 1 } };
- std::vector<SubgraphView::IInputSlots> expectedUntouchedInputSlots
- {
- ConvertSlotsToISlots<InputSlot, IInputSlot>(
- ConvertReferenceTypeToPointerType(layersInGraph.at("conv2 layer unoptimizable")->GetInputSlots())),
- ConvertSlotsToISlots<InputSlot, IInputSlot>(
- ConvertReferenceTypeToPointerType(layersInGraph.at("conv4 layer unoptimizable")->GetInputSlots()))
- };
+ std::vector<ExpectedSubgraphSize> expectedUntouchedSubgraphSizes{ { 1, 1, 3 },
+ { 1, 1, 3 } };
+ std::vector<SubgraphView::IInputSlots> expectedUntouchedInputSlots{
+ ConvertSlotsToISlots<InputSlot,
+ IInputSlot>({ConvertReferenceTypeToPointerType(
+ layersInGraph.at("conv2 layer unoptimizable")->GetInputSlot(0))}),
+ ConvertSlotsToISlots<InputSlot,
+ IInputSlot>({ConvertReferenceTypeToPointerType(
+ layersInGraph.at("conv4 layer unoptimizable")->GetInputSlot(0))})};
+
std::vector<SubgraphView::IOutputSlots> expectedUntouchedOutputSlots
- {
+ {
ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
- ConvertReferenceTypeToPointerType(layersInGraph.at("conv2 layer unoptimizable")->GetOutputSlots())),
+ ConvertReferenceTypeToPointerType(layersInGraph.at("conv2 layer unoptimizable")->GetOutputSlots())),
ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
- ConvertReferenceTypeToPointerType(layersInGraph.at("conv4 layer unoptimizable")->GetOutputSlots()))
- };
+ ConvertReferenceTypeToPointerType(layersInGraph.at("conv4 layer unoptimizable")->GetOutputSlots()))
+ };
+
std::vector<SubgraphView::IConnectableLayers> expectedUntouchedLayers
- {
- { layersInGraph.at("conv2 layer unoptimizable") },
- { layersInGraph.at("conv4 layer unoptimizable") }
- };
+ {
+ { layersInGraph.at("Weights Layer 2 unoptimizable"),
+ layersInGraph.at("Bias Layer 2 unoptimizable"),
+ layersInGraph.at("conv2 layer unoptimizable") },
+ { layersInGraph.at("Weights Layer 4 unoptimizable"),
+ layersInGraph.at("Bias Layer 4 unoptimizable"),
+ layersInGraph.at("conv4 layer unoptimizable") }
+ };
for (size_t untouchedIndex = 0; untouchedIndex < untouchedSubgraphs.size(); untouchedIndex++)
{
@@ -1215,7 +1495,7 @@ void PartiallyOptimizableSubgraphTestImpl2()
CHECK(subgraphInputSlots.size() == 2);
CHECK(subgraphOutputSlots.size() == 1);
- CHECK(subgraphLayers.size() == 4);
+ CHECK(subgraphLayers.size() == 10);
CHECK(Contains(layersInGraph, "conv1 layer"));
CHECK(Contains(layersInGraph, "conv2 layer unoptimizable"));
@@ -1247,7 +1527,7 @@ void PartiallyOptimizableSubgraphTestImpl2()
const OptimizationViews::Substitutions& substitutions = optimizationViews.GetSubstitutions();
CHECK(substitutions.size() == 1);
- ExpectedSubgraphSize expectedSubstitutableSubgraphSizes{ 2, 1, 3 };
+ ExpectedSubgraphSize expectedSubstitutableSubgraphSizes{ 2, 1, 7 };
ExpectedSubgraphSize expectedReplacementSubgraphSizes{ 2, 1, 1 };
SubgraphView::IInputSlots expectedSubstitutableInputSlots
@@ -1266,6 +1546,10 @@ void PartiallyOptimizableSubgraphTestImpl2()
SubgraphView::IConnectableLayers expectedSubstitutableLayers
{
+ layersInGraph.at("Weights Layer 1"),
+ layersInGraph.at("Weights Layer 3"),
+ layersInGraph.at("Bias Layer 1"),
+ layersInGraph.at("Bias Layer 3"),
layersInGraph.at("conv1 layer"),
layersInGraph.at("conv3 layer"),
layersInGraph.at("add layer")
@@ -1291,12 +1575,12 @@ void PartiallyOptimizableSubgraphTestImpl2()
const OptimizationViews::Subgraphs& untouchedSubgraphs = optimizationViews.GetUntouchedSubgraphs();
CHECK(untouchedSubgraphs.size() == 1);
- std::vector<ExpectedSubgraphSize> expectedUntouchedSubgraphSizes{ { 1, 1, 1 } };
+ std::vector<ExpectedSubgraphSize> expectedUntouchedSubgraphSizes{ { 1, 1, 3 } };
std::vector<SubgraphView::IInputSlots> expectedUntouchedInputSlots
{
- ConvertSlotsToISlots<InputSlot, IInputSlot>(
- ConvertReferenceTypeToPointerType(layersInGraph.at("conv2 layer unoptimizable")->GetInputSlots()))
- };
+ ConvertSlotsToISlots<InputSlot,
+ IInputSlot>({ConvertReferenceTypeToPointerType(
+ layersInGraph.at("conv2 layer unoptimizable")->GetInputSlot(0))})};
std::vector<SubgraphView::IOutputSlots> expectedUntouchedOutputSlots
{
ConvertSlotsToISlots<OutputSlot, IOutputSlot>(
@@ -1304,7 +1588,8 @@ void PartiallyOptimizableSubgraphTestImpl2()
};
std::vector<SubgraphView::IConnectableLayers> expectedUntouchedLayers
{
- { layersInGraph.at("conv2 layer unoptimizable") }
+ { layersInGraph.at("conv2 layer unoptimizable"), layersInGraph.at("Weights Layer 2 unoptimizable"),
+ layersInGraph.at("Bias Layer 2 unoptimizable") }
};
for (size_t untouchedIndex = 0; untouchedIndex < untouchedSubgraphs.size(); untouchedIndex++)
diff --git a/src/backends/backendsCommon/test/OptimizedNetworkTests.cpp b/src/backends/backendsCommon/test/OptimizedNetworkTests.cpp
index cc7974130d..8e3b275649 100644
--- a/src/backends/backendsCommon/test/OptimizedNetworkTests.cpp
+++ b/src/backends/backendsCommon/test/OptimizedNetworkTests.cpp
@@ -401,11 +401,14 @@ TEST_CASE("OptimizeNetworkCopy")
armnn::INetworkPtr network = armnn::INetwork::Create();
armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
+
+ ARMNN_NO_DEPRECATE_WARN_BEGIN
armnn::IConnectableLayer* const convLayer =
network->AddConvolution2dLayer(descriptor,
weights,
armnn::Optional<armnn::ConstTensor>(biases),
layerName.c_str());
+ ARMNN_NO_DEPRECATE_WARN_END
armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
diff --git a/src/backends/backendsCommon/test/WorkloadDataValidation.cpp b/src/backends/backendsCommon/test/WorkloadDataValidation.cpp
index c715d28ebe..fed21eb911 100644
--- a/src/backends/backendsCommon/test/WorkloadDataValidation.cpp
+++ b/src/backends/backendsCommon/test/WorkloadDataValidation.cpp
@@ -642,7 +642,7 @@ TEST_CASE("LstmQueueDescriptor_Validate")
CHECK_NOTHROW(data.Validate(info));
}
-TEST_CASE("BiasPerAxisQuantization_Validate")
+TEST_CASE("BiasPerAxisQuantization_ValidateCorrectValues")
{
constexpr unsigned int nInput = 1u;
constexpr unsigned int cInput = 3u;
@@ -675,6 +675,7 @@ TEST_CASE("BiasPerAxisQuantization_Validate")
WorkloadInfo workloadInfo;
AddInputToWorkload(queueDescriptor, workloadInfo, inputInfo, nullptr);
+ AddInputToWorkload(queueDescriptor, workloadInfo, weightInfo, nullptr);
AddOutputToWorkload(queueDescriptor, workloadInfo, outputInfo, nullptr);
ScopedTensorHandle weightTensor(weightInfo);
@@ -687,17 +688,102 @@ TEST_CASE("BiasPerAxisQuantization_Validate")
ScopedTensorHandle biasHandle1(biasInfo1);
queueDescriptor.m_Bias = &biasHandle1;
+ AddInputToWorkload(queueDescriptor, workloadInfo, biasInfo1, nullptr);
+
CHECK_NOTHROW(queueDescriptor.Validate(workloadInfo));
+}
- // Test 2: wrong per-axis quantization values
+TEST_CASE("BiasPerAxisQuantization_ValidateIncorrectValues")
+{
+ constexpr unsigned int nInput = 1u;
+ constexpr unsigned int cInput = 3u;
+ constexpr unsigned int hInput = 3u;
+ constexpr unsigned int wInput = 3u;
+
+ constexpr unsigned int nOutput = nInput;
+ constexpr unsigned int cOutput = cInput;
+ constexpr unsigned int hOutput = 1u;
+ constexpr unsigned int wOutput = 1u;
+
+ const TensorShape inputShape { nInput, cInput, hInput, wInput };
+ const TensorShape outputShape{ nOutput, cOutput, hOutput, wOutput };
+ const TensorShape weightShape{ cOutput, cInput, hInput, wInput };
+ const TensorShape biasShape { cOutput };
+
+ constexpr DataType inputType = DataType::QAsymmU8;
+ constexpr DataType weightType = DataType::QSymmS8;
+ constexpr DataType biasType = DataType::Signed32;
+
+ constexpr float perTensorScale = 1.5f;
+ const TensorInfo inputInfo (inputShape, inputType, perTensorScale);
+ const TensorInfo outputInfo(outputShape, inputType, perTensorScale);
+
+ const std::vector<float> weightPerAxisScales = { 2.50f, 3.50f };
+ const TensorInfo weightInfo(weightShape, weightType, weightPerAxisScales, 0);
+
+ Convolution2dQueueDescriptor queueDescriptor;
+ queueDescriptor.m_Parameters.m_BiasEnabled = true;
+
+ WorkloadInfo workloadInfo;
+ AddInputToWorkload(queueDescriptor, workloadInfo, inputInfo, nullptr);
+ AddInputToWorkload(queueDescriptor, workloadInfo, weightInfo, nullptr);
+ AddOutputToWorkload(queueDescriptor, workloadInfo, outputInfo, nullptr);
+
+ ScopedTensorHandle weightTensor(weightInfo);
+ queueDescriptor.m_Weight = &weightTensor;
+
+ // Test 2: wrong per-axis quantization values
const std::vector<float> biasPerAxisScales2 = { 4.00f, 5.00f };
const TensorInfo biasInfo2(biasShape, biasType, biasPerAxisScales2, 0);
ScopedTensorHandle biasHandle2(biasInfo2);
queueDescriptor.m_Bias = &biasHandle2;
+ AddInputToWorkload(queueDescriptor, workloadInfo, biasInfo2, nullptr);
+
CHECK_NOTHROW(queueDescriptor.Validate(workloadInfo));
+}
+
+TEST_CASE("BiasPerAxisQuantization_ValidateInvalidArgumentException")
+{
+ constexpr unsigned int nInput = 1u;
+ constexpr unsigned int cInput = 3u;
+ constexpr unsigned int hInput = 3u;
+ constexpr unsigned int wInput = 3u;
+
+ constexpr unsigned int nOutput = nInput;
+ constexpr unsigned int cOutput = cInput;
+ constexpr unsigned int hOutput = 1u;
+ constexpr unsigned int wOutput = 1u;
+
+ const TensorShape inputShape { nInput, cInput, hInput, wInput };
+ const TensorShape outputShape{ nOutput, cOutput, hOutput, wOutput };
+ const TensorShape weightShape{ cOutput, cInput, hInput, wInput };
+ const TensorShape biasShape { cOutput };
+
+ constexpr DataType inputType = DataType::QAsymmU8;
+ constexpr DataType weightType = DataType::QSymmS8;
+ constexpr DataType biasType = DataType::Signed32;
+
+ constexpr float perTensorScale = 1.5f;
+ const TensorInfo inputInfo (inputShape, inputType, perTensorScale);
+ const TensorInfo outputInfo(outputShape, inputType, perTensorScale);
+
+ const std::vector<float> weightPerAxisScales = { 2.50f, 3.50f };
+ const TensorInfo weightInfo(weightShape, weightType, weightPerAxisScales, 0);
+
+ Convolution2dQueueDescriptor queueDescriptor;
+ queueDescriptor.m_Parameters.m_BiasEnabled = true;
+
+ WorkloadInfo workloadInfo;
+ AddInputToWorkload(queueDescriptor, workloadInfo, inputInfo, nullptr);
+ AddInputToWorkload(queueDescriptor, workloadInfo, weightInfo, nullptr);
+ AddOutputToWorkload(queueDescriptor, workloadInfo, outputInfo, nullptr);
+
+ ScopedTensorHandle weightTensor(weightInfo);
+ queueDescriptor.m_Weight = &weightTensor;
+
// Test 3: mismatched number of quantization scales
const std::vector<float> biasPerAxisScales3 = { 3.75f, 5.25f, 5.25f };
const TensorInfo biasInfo3(biasShape, biasType, biasPerAxisScales3, 0);
@@ -705,7 +791,10 @@ TEST_CASE("BiasPerAxisQuantization_Validate")
ScopedTensorHandle biasHandle3(biasInfo3);
queueDescriptor.m_Bias = &biasHandle3;
+ AddInputToWorkload(queueDescriptor, workloadInfo, biasInfo3, nullptr);
+
CHECK_THROWS_AS(queueDescriptor.Validate(workloadInfo), InvalidArgumentException);
}
+
}
diff --git a/src/backends/backendsCommon/test/layerTests/Conv2dTestImpl.cpp b/src/backends/backendsCommon/test/layerTests/Conv2dTestImpl.cpp
index 74c65e271c..1e0adc169a 100644
--- a/src/backends/backendsCommon/test/layerTests/Conv2dTestImpl.cpp
+++ b/src/backends/backendsCommon/test/layerTests/Conv2dTestImpl.cpp
@@ -309,6 +309,7 @@ LayerTestResult<T, 4> SimpleConvolution2dTestImpl(
std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
+ std::unique_ptr<armnn::ITensorHandle> weightsHandle = tensorHandleFactory.CreateTensorHandle(kernelDesc);
armnn::Convolution2dQueueDescriptor data;
armnn::WorkloadInfo info;
@@ -329,8 +330,15 @@ LayerTestResult<T, 4> SimpleConvolution2dTestImpl(
}
AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
+ AddInputToWorkload(data, info, kernelDesc, weightsHandle.get());
AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
+ std::unique_ptr<armnn::ITensorHandle> biasHandle = nullptr;
+ if (biasEnabled)
+ {
+ biasHandle = tensorHandleFactory.CreateTensorHandle(biasDesc);
+ 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.
data.m_Parameters.m_StrideX = strideX;
@@ -349,8 +357,16 @@ LayerTestResult<T, 4> SimpleConvolution2dTestImpl(
info);
inputHandle->Allocate();
outputHandle->Allocate();
+ weightsHandle->Allocate();
+
+ if (biasEnabled)
+ {
+ biasHandle->Allocate();
+ CopyDataToITensorHandle(biasHandle.get(), bias.data());
+ }
CopyDataToITensorHandle(inputHandle.get(), inputData.data());
+ CopyDataToITensorHandle(weightsHandle.get(), kernel.data());
ExecuteWorkload(*workload, memoryManager);
@@ -423,6 +439,8 @@ LayerTestResult<O, 4> SimpleConvolution2dNhwcTestImpl(
std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
+ std::unique_ptr<armnn::ITensorHandle> weightsHandle = tensorHandleFactory.CreateTensorHandle(kernelDesc);
+ std::unique_ptr<armnn::ITensorHandle> biasHandle = nullptr;
armnn::ScopedTensorHandle weightsTensor(kernelDesc);
AllocateAndCopyDataToITensorHandle(&weightsTensor, kernel.data());
@@ -444,15 +462,30 @@ LayerTestResult<O, 4> SimpleConvolution2dNhwcTestImpl(
armnn::WorkloadInfo info;
AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
+ AddInputToWorkload(data, info, kernelDesc, weightsHandle.get());
AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
+ if (biasEnabled)
+ {
+ biasHandle = tensorHandleFactory.CreateTensorHandle(biasDesc);
+ AddInputToWorkload(data, info, biasDesc, biasHandle.get());
+ }
+
std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateWorkload(armnn::LayerType::Convolution2d,
data,
info);
inputHandle->Allocate();
outputHandle->Allocate();
+ weightsHandle->Allocate();
+
+ if (biasEnabled)
+ {
+ biasHandle->Allocate();
+ CopyDataToITensorHandle(biasHandle.get(), bias.data());
+ }
CopyDataToITensorHandle(inputHandle.get(), inputData.data());
+ CopyDataToITensorHandle(weightsHandle.get(), kernel.data());
ExecuteWorkload(*workload, memoryManager);
@@ -552,35 +585,52 @@ LayerTestResult<T,4> Convolution1dTestImpl(
std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputInfo);
std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputInfo);
+ std::unique_ptr<armnn::ITensorHandle> weightsHandle = tensorHandleFactory.CreateTensorHandle(kernelInfo);
+ std::unique_ptr<armnn::ITensorHandle> biasHandle = nullptr;
armnn::Convolution2dQueueDescriptor data;
armnn::WorkloadInfo info;
- armnn::ScopedTensorHandle weightsTensor(kernelInfo);
- armnn::ScopedTensorHandle biasTensor(biasInfo);
+ armnn::ScopedTensorHandle weightsTensor(kernelInfo);
+ armnn::ScopedTensorHandle biasTensor(biasInfo);
AllocateAndCopyDataToITensorHandle(&weightsTensor, kernelData.data());
AllocateAndCopyDataToITensorHandle(&biasTensor, biasData.data());
AddInputToWorkload(data, info, inputInfo, inputHandle.get());
+ AddInputToWorkload(data, info, kernelInfo, weightsHandle.get());
AddOutputToWorkload(data, info, outputInfo, outputHandle.get());
- data.m_Weight = &weightsTensor;
- data.m_Bias = &biasTensor;
- data.m_Parameters.m_StrideX = 1;
- data.m_Parameters.m_StrideY = stride;
- data.m_Parameters.m_PadLeft = 0;
- data.m_Parameters.m_PadRight = 0;
- data.m_Parameters.m_PadTop = padSize;
- data.m_Parameters.m_PadBottom = padSize;
- data.m_Parameters.m_BiasEnabled = biasEnabled;
+ data.m_Weight = &weightsTensor;
+ data.m_Bias = &biasTensor;
+ data.m_Parameters.m_StrideX = 1;
+ data.m_Parameters.m_StrideY = stride;
+ data.m_Parameters.m_PadLeft = 0;
+ data.m_Parameters.m_PadRight = 0;
+ data.m_Parameters.m_PadTop = padSize;
+ data.m_Parameters.m_PadBottom = padSize;
+ data.m_Parameters.m_BiasEnabled = biasEnabled;
+
+ if (biasEnabled)
+ {
+ biasHandle = tensorHandleFactory.CreateTensorHandle(biasInfo);
+ AddInputToWorkload(data, info, biasInfo, biasHandle.get());
+ }
std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateWorkload(armnn::LayerType::Convolution2d,
data,
info);
inputHandle->Allocate();
outputHandle->Allocate();
+ weightsHandle->Allocate();
+
+ if (biasEnabled)
+ {
+ biasHandle->Allocate();
+ CopyDataToITensorHandle(biasHandle.get(), biasData.data());
+ }
CopyDataToITensorHandle(inputHandle.get(), inputData.data());
+ CopyDataToITensorHandle(weightsHandle.get(), kernelData.data());
ExecuteWorkload(*workload, memoryManager);
@@ -1364,18 +1414,30 @@ LayerTestResult<T,4> CompareConvolution2dTestImpl(
std::vector<T> expectedOutput(outputTensorInfo.GetNumElements());
std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
+ std::unique_ptr<armnn::ITensorHandle> biasHandle = tensorHandleFactory.CreateTensorHandle(biasDesc);
+ std::unique_ptr<armnn::ITensorHandle> weightsHandle = tensorHandleFactory.CreateTensorHandle(kernelDesc);
std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
armnn::Convolution2dQueueDescriptor 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;
@@ -1387,11 +1449,15 @@ LayerTestResult<T,4> CompareConvolution2dTestImpl(
data.m_Parameters.m_BiasEnabled = true;
std::unique_ptr<armnn::ITensorHandle> outputHandleRef = refTensorHandleFactory.CreateTensorHandle(outputTensorInfo);
+ std::unique_ptr<armnn::ITensorHandle> weightsHandleRef = refTensorHandleFactory.CreateTensorHandle(kernelDesc);
+ std::unique_ptr<armnn::ITensorHandle> biasHandleRef = refTensorHandleFactory.CreateTensorHandle(biasDesc);
std::unique_ptr<armnn::ITensorHandle> inputHandleRef = refTensorHandleFactory.CreateTensorHandle(inputTensorInfo);
armnn::Convolution2dQueueDescriptor 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<armnn::IWorkload> workload
@@ -1401,12 +1467,16 @@ LayerTestResult<T,4> CompareConvolution2dTestImpl(
outputHandleRef->Allocate();
inputHandleRef->Allocate();
+ weightsHandleRef->Allocate();
+ biasHandleRef->Allocate();
inputHandle->Allocate();
outputHandle->Allocate();
CopyDataToITensorHandle(inputHandle.get(), input.data());
CopyDataToITensorHandle(inputHandleRef.get(), input.data());
+ CopyDataToITensorHandle(weightsHandleRef.get(), kernel.data());
+ CopyDataToITensorHandle(biasHandleRef.get(), bias.data());
ExecuteWorkload(*workload, memoryManager);
@@ -3622,6 +3692,8 @@ LayerTestResult<uint8_t, 4> Convolution2dPerAxisQuantTest(
std::unique_ptr<ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputInfo);
std::unique_ptr<ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputInfo);
+ std::unique_ptr<armnn::ITensorHandle> weightsHandle = tensorHandleFactory.CreateTensorHandle(kernelInfo);
+ std::unique_ptr<armnn::ITensorHandle> biasHandle = nullptr;
WorkloadInfo workloadInfo;
ScopedTensorHandle weightTensor(kernelInfo);
@@ -3636,6 +3708,14 @@ LayerTestResult<uint8_t, 4> Convolution2dPerAxisQuantTest(
queueDescriptor.m_Bias = &biasTensor;
AddInputToWorkload(queueDescriptor, workloadInfo, inputInfo, inputHandle.get());
+ AddInputToWorkload(queueDescriptor, workloadInfo, kernelInfo, weightsHandle.get());
+
+ if (descriptor.m_BiasEnabled)
+ {
+ biasHandle = tensorHandleFactory.CreateTensorHandle(biasInfo);
+ AddInputToWorkload(queueDescriptor, workloadInfo, biasInfo, biasHandle.get());
+ }
+
AddOutputToWorkload(queueDescriptor, workloadInfo, outputInfo, outputHandle.get());
std::unique_ptr<IWorkload> workload= workloadFactory.CreateWorkload(armnn::LayerType::Convolution2d,
@@ -3643,8 +3723,16 @@ LayerTestResult<uint8_t, 4> Convolution2dPerAxisQuantTest(
workloadInfo);
inputHandle->Allocate();
outputHandle->Allocate();
+ weightsHandle->Allocate();
+ if (descriptor.m_BiasEnabled)
+ {
+ biasHandle->Allocate();
+ CopyDataToITensorHandle(biasHandle.get(), biasData.data());
+ }
CopyDataToITensorHandle(inputHandle.get(), inputData.data());
+ CopyDataToITensorHandle(weightsHandle.get(), kernelData.data());
+
ExecuteWorkload(*workload, memoryManager);