11 #include <TestUtils.hpp> 13 #include <doctest/doctest.h> 15 using namespace armnn;
40 static std::vector<IConnectableLayer*> AddConstantLayers(
INetwork *network,
47 std::vector<IConnectableLayer*> layers = {weightsLayer};
53 layers.emplace_back(biasLayer);
60 class DepthwiseConv2dTest
78 static std::vector<IConnectableLayer*> AddConstantLayers(
INetwork *network,
85 std::vector<IConnectableLayer*> layers = {weightsLayer};
91 layers.emplace_back(biasLayer);
99 std::vector<T> GetVector(
unsigned int size,
float initial,
float increment)
101 std::vector<float> typeVector(size, initial);
102 std::vector<T> vector(size);
106 for (
unsigned int i = 0; i < size; ++i)
108 vector[i] = T(initial + (increment * static_cast<float>(i)));
116 template <
typename Conv2dTest,
118 typename ConvDescriptorType =
typename Conv2dTest::ConvDescriptorType,
120 INetworkPtr CreateNetwork(
bool depthwise,
bool preventFusing)
123 ConvDescriptorType convolution2dDescriptor;
124 convolution2dDescriptor.m_BiasEnabled =
false;
126 convolution2dDescriptor.m_StrideX = 1;
127 convolution2dDescriptor.m_StrideY = 1;
131 const unsigned int inputDimensionSizes[] = {1, 4, 4, 3};
132 unsigned int weightsDimensionSizes[] = {4, 2, 2, 3};
133 unsigned int outputDimensionSizes[] = {1, 3, 3, 4};
138 weightsDimensionSizes[0] = 1;
139 weightsDimensionSizes[1] = 2;
140 weightsDimensionSizes[2] = 2;
141 weightsDimensionSizes[3] = 12;
142 outputDimensionSizes[3] = weightsDimensionSizes[3];
144 const unsigned int outputChannelSize[] = {outputDimensionSizes[3]};
146 TensorInfo inputInfo(4, inputDimensionSizes, ArmnnType);
147 TensorInfo outputInfo(4, outputDimensionSizes, ArmnnType);
149 std::vector<int> weightsIntVector = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
150 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
151 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
152 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42};
153 std::vector<T> weightsVector(begin(weightsIntVector), end(weightsIntVector));
154 TensorInfo weightsInfo(4, weightsDimensionSizes, ArmnnType, 0.0f, 0,
true);
157 std::vector<T> betaVector = GetVector<T>(outputDimensionSizes[3], 0.0f, 0.2f);
158 std::vector<T> gammaVector = GetVector<T>(outputDimensionSizes[3], 0.5f, 0.1f);
159 std::vector<T> meanVector = GetVector<T>(outputDimensionSizes[3], 0.1f, 0.1f);
160 std::vector<T> varianceVector = GetVector<T>(outputDimensionSizes[3], 1.0f, 0.1f);
173 convolution2dDescriptor,
178 IConnectableLayer* batchNormLayer = network->AddBatchNormalizationLayer(batchNormDescriptor,
190 output2Layer = network->AddOutputLayer(1);
193 std::vector<IConnectableLayer*> constantLayers = Conv2dTest::AddConstantLayers(network.get(),
194 convolution2dDescriptor,
199 for (
unsigned int i = 0; i < constantLayers.size(); ++i)
201 constantLayers[i]->GetOutputSlot(0).Connect(convLayer->
GetInputSlot(i + 1));
222 template <
typename Conv2dTest,
224 typename ConvDescriptorType =
typename Conv2dTest::ConvDescriptorType,
225 typename ConvLayerType =
typename Conv2dTest::ConvLayerType,
227 void FuseBatchNormIntoConvTest(
bool depthwise,
float tolerance,
armnn::Compute backendId)
231 INetworkPtr networkFused = CreateNetwork<Conv2dTest, ArmnnType>(depthwise,
false);
241 auto checkFusedConv2d = [ ](
const armnn::Layer*
const layer) ->
bool 243 return IsLayerOfType<ConvLayerType>(layer) &&
244 (layer->GetNameStr() ==
"fused-batchNorm-into-convolution");
247 CHECK(5 == graphFused.GetNumLayers());
250 &IsLayerOfType<InputLayer>,
251 &IsLayerOfType<ConstantLayer>,
252 &IsLayerOfType<ConstantLayer>,
254 &IsLayerOfType<OutputLayer>));
258 CHECK(run->LoadNetwork(networkIdentifier, std::move(optNetFused)) ==
Status::Success);
261 std::vector<T> inputDataFused = GetVector<T>(48, 1.0f, 0.1f);
263 std::vector<T> outputDataFused(36);
267 outputDataFused.resize(108);
270 TensorInfo inputTensorInfo = run->GetInputTensorInfo(networkIdentifier, 0);
273 {0,
ConstTensor(inputTensorInfo, inputDataFused.data())}};
275 {0,
Tensor(run->GetOutputTensorInfo(networkIdentifier, 0), outputDataFused.data())}};
278 run->EnqueueWorkload(networkIdentifier, inputTensorsFused, outputTensorsFused);
282 INetworkPtr networkNotFused = CreateNetwork<Conv2dTest, ArmnnType>(depthwise,
true);
292 CHECK(6 == graphNotFused.GetNumLayers());
294 graphNotFused.cend(),
295 &IsLayerOfType<armnn::InputLayer>,
296 &IsLayerOfType<armnn::ConstantLayer>,
297 &IsLayerOfType<ConvLayerType>,
298 &IsLayerOfType<armnn::BatchNormalizationLayer>,
299 &IsLayerOfType<armnn::OutputLayer>,
300 &IsLayerOfType<armnn::OutputLayer>));
304 CHECK(runNotFused->LoadNetwork(networkIdentifierNotFused, std::move(optNetNotFused)) ==
Status::Success);
307 std::vector<T> inputDataNotFused = GetVector<T>(48, 1.0f, 0.1f);
309 std::vector<T> outputDataNotFused(36);
310 std::vector<T> outputData2NotFused(36);
314 outputDataNotFused.resize(108);
315 outputData2NotFused.resize(108);
318 TensorInfo inputTensorInfo2 = runNotFused->GetInputTensorInfo(networkIdentifierNotFused, 0);
321 { 0,
ConstTensor(inputTensorInfo2, inputDataNotFused.data()) } };
323 { 0,
Tensor(runNotFused->GetOutputTensorInfo(networkIdentifierNotFused, 0), outputDataNotFused.data()) },
324 { 1,
Tensor(runNotFused->GetOutputTensorInfo(networkIdentifierNotFused, 1), outputData2NotFused.data()) } };
327 runNotFused->EnqueueWorkload(networkIdentifierNotFused, inputTensorsNotFused, outputTensorsNotFused);
330 auto epsilon = T(tolerance);
331 for (
unsigned int n = 0; n < outputDataFused.size(); ++n)
333 CHECK_EQ(outputDataFused[n], doctest::Approx(outputDataNotFused[n]).epsilon(epsilon));
338 #if defined(ARMNNREF_ENABLED) 339 TEST_CASE(
"FuseBatchNormIntoConv2DFloat32Test")
344 TEST_CASE(
"FuseBatchNormIntoConv2DFloat16Test")
349 TEST_CASE(
"FuseBatchNormIntoDepthwiseConv2DFloat32Test")
354 TEST_CASE(
"FuseBatchNormIntoDepthwiseConv2DFloat16Test")
TEST_SUITE("TestConstTensorLayerVisitor")
bool m_BiasEnabled
Enable/disable bias.
static IRuntimePtr Create(const CreationOptions &options)
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
bool m_BiasEnabled
Enable/disable bias.
CPU Execution: Reference C++ kernels.
bool CheckSequence(const armnn::Graph::ConstIterator first, const armnn::Graph::ConstIterator last)
IConnectableLayer * AddConstantLayer(const ConstTensor &input, const char *name=nullptr)
Adds a layer with no inputs and a single output, which always corresponds to the passed in constant t...
IConnectableLayer * AddDepthwiseConvolution2dLayer(const DepthwiseConvolution2dDescriptor &convolution2dDescriptor, const char *name=nullptr)
Adds a 2D depthwise convolution layer to the network.
This layer represents a depthwise convolution 2d operation.
A Convolution2dDescriptor for the Convolution2dLayer.
std::unique_ptr< IRuntime, void(*)(IRuntime *runtime)> IRuntimePtr
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
typename ResolveTypeImpl< DT >::Type ResolveType
Main network class which provides the interface for building up a neural network. ...
std::vector< std::pair< LayerBindingId, class ConstTensor > > InputTensors
Copyright (c) 2021 ARM Limited and Contributors.
void IgnoreUnused(Ts &&...)
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
A tensor defined by a TensorInfo (shape and data type) and a mutable backing store.
Compute
The Compute enum is now deprecated and it is now being replaced by BackendId.
IOptimizedNetworkPtr Optimize(const INetwork &network, const std::vector< BackendId > &backendPreferences, const IDeviceSpec &deviceSpec, const OptimizerOptions &options=OptimizerOptions(), Optional< std::vector< std::string > &> messages=EmptyOptional())
Create an optimized version of the network.
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
std::vector< std::pair< LayerBindingId, class Tensor > > OutputTensors
std::unique_ptr< IOptimizedNetwork, void(*)(IOptimizedNetwork *network)> IOptimizedNetworkPtr
const TensorInfo & GetInfo() const
Graph & GetGraphForTesting(IOptimizedNetwork *optNet)
IConnectableLayer * AddConvolution2dLayer(const Convolution2dDescriptor &convolution2dDescriptor, const char *name=nullptr)
Adds a 2D convolution layer to the network.
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
void SetConstant(const bool IsConstant=true)
Marks the data corresponding to this tensor info as constant.
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
This layer represents a convolution 2d operation.
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
virtual int Connect(IInputSlot &destination)=0
static INetworkPtr Create(NetworkOptions networkOptions={})
A DepthwiseConvolution2dDescriptor for the DepthwiseConvolution2dLayer.
A BatchNormalizationDescriptor for the BatchNormalizationLayer.