ArmNN
 21.08
OptimizerTests.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "TestUtils.hpp"
7 
8 #include <BackendSettings.hpp>
9 #include <Graph.hpp>
10 #include <Network.hpp>
11 #include <Optimizer.hpp>
12 
13 #include <armnn/BackendHelper.hpp>
15 #include <armnn/INetwork.hpp>
17 
18 #include <armnn/utility/Assert.hpp>
21 
25 
26 #include <doctest/doctest.h>
27 
28 using namespace armnn;
29 
30 namespace
31 {
32 
33 void CreateLSTMLayerHelper(Graph &graph, bool CifgEnabled)
34 {
35  LstmDescriptor layerDesc;
36  layerDesc.m_ActivationFunc = 4;
37  layerDesc.m_ClippingThresCell = 0.2f;
38  layerDesc.m_ClippingThresProj = 0.4f;
39  layerDesc.m_CifgEnabled = CifgEnabled;
40  layerDesc.m_PeepholeEnabled = false;
41  layerDesc.m_ProjectionEnabled = false;
42 
43  LstmLayer* const layer = graph.AddLayer<LstmLayer>(layerDesc, "layer");
44  unsigned int batchSize = 3;
45  unsigned int inputSize = 2;
46  unsigned int numUnits = 4;
47  unsigned int outputSize = 4;
48 
49  layer->m_BasicParameters.m_InputToForgetWeights = std::make_unique<ScopedTensorHandle>
50  (TensorInfo({ numUnits, inputSize }, DataType::Float32));
51  layer->m_BasicParameters.m_InputToCellWeights = std::make_unique<ScopedTensorHandle>
52  (TensorInfo({ numUnits, inputSize }, DataType::Float32));
53  layer->m_BasicParameters.m_InputToOutputWeights = std::make_unique<ScopedTensorHandle>
54  (TensorInfo({ numUnits, inputSize }, DataType::Float32));
55  layer->m_BasicParameters.m_RecurrentToForgetWeights = std::make_unique<ScopedTensorHandle>
56  (TensorInfo({ numUnits, outputSize }, DataType::Float32));
57  layer->m_BasicParameters.m_RecurrentToCellWeights = std::make_unique<ScopedTensorHandle>
58  (TensorInfo({ numUnits, outputSize }, DataType::Float32));
59  layer->m_BasicParameters.m_RecurrentToOutputWeights = std::make_unique<ScopedTensorHandle>
60  (TensorInfo({ numUnits, outputSize }, DataType::Float32));
61  layer->m_BasicParameters.m_ForgetGateBias = std::make_unique<ScopedTensorHandle>
62  (TensorInfo({ numUnits }, DataType::Float32));
63  layer->m_BasicParameters.m_CellBias = std::make_unique<ScopedTensorHandle>
64  (TensorInfo({ numUnits }, DataType::Float32));
65  layer->m_BasicParameters.m_OutputGateBias = std::make_unique<ScopedTensorHandle>
66  (TensorInfo({ numUnits }, DataType::Float32));
67 
68  layer->m_BasicParameters.m_InputToForgetWeights->Allocate();
69  layer->m_BasicParameters.m_InputToCellWeights->Allocate();
70  layer->m_BasicParameters.m_InputToOutputWeights->Allocate();
74  layer->m_BasicParameters.m_ForgetGateBias->Allocate();
75  layer->m_BasicParameters.m_CellBias->Allocate();
76  layer->m_BasicParameters.m_OutputGateBias->Allocate();
77 
78  if (!layerDesc.m_CifgEnabled)
79  {
80  layer->m_CifgParameters.m_InputToInputWeights = std::make_unique<ScopedTensorHandle>
81  (TensorInfo({ numUnits, inputSize }, DataType::Float32));
82  layer->m_CifgParameters.m_RecurrentToInputWeights = std::make_unique<ScopedTensorHandle>
83  (TensorInfo({ numUnits, outputSize }, DataType::Float32));
84  layer->m_CifgParameters.m_InputGateBias = std::make_unique<ScopedTensorHandle>
85  (TensorInfo({ numUnits }, DataType::Float32));
86  layer->m_CifgParameters.m_InputToInputWeights->Allocate();
88  layer->m_CifgParameters.m_InputGateBias->Allocate();
89  }
90 
91  if (layerDesc.m_ProjectionEnabled)
92  {
93  layer->m_ProjectionParameters.m_ProjectionWeights = std::make_unique<ScopedTensorHandle>
94  (TensorInfo({ outputSize, numUnits }, DataType::Float32));
95  layer->m_ProjectionParameters.m_ProjectionBias = std::make_unique<ScopedTensorHandle>
96  (TensorInfo({ outputSize }, DataType::Float32));
98  layer->m_ProjectionParameters.m_ProjectionBias->Allocate();
99  }
100 
101  if (layerDesc.m_PeepholeEnabled)
102  {
103  if (!layerDesc.m_CifgEnabled)
104  {
105  layer->m_PeepholeParameters.m_CellToInputWeights = std::make_unique<ScopedTensorHandle>
106  (TensorInfo({ numUnits }, DataType::Float32));
107  layer->m_PeepholeParameters.m_CellToInputWeights->Allocate();
108  }
109  layer->m_PeepholeParameters.m_CellToForgetWeights = std::make_unique<ScopedTensorHandle>
110  (TensorInfo({ numUnits }, DataType::Float32));
111  layer->m_PeepholeParameters.m_CellToOutputWeights = std::make_unique<ScopedTensorHandle>
112  (TensorInfo({ numUnits }, DataType::Float32));
113  layer->m_PeepholeParameters.m_CellToForgetWeights->Allocate();
114  layer->m_PeepholeParameters.m_CellToOutputWeights->Allocate();
115  }
116 
117  // create input and output layers
118  Layer* const input = graph.AddLayer<InputLayer>(0, "input");
119  Layer* const outputStateIn = graph.AddLayer<InputLayer>(1, "outputStateIn");
120  Layer* const cellStateIn = graph.AddLayer<InputLayer>(2, "cellStateIn");
121  Layer* const scratchBuffer = graph.AddLayer<OutputLayer>(0, "scratchBuffer");
122  Layer* const outputStateOut = graph.AddLayer<OutputLayer>(1, "outputStateOut");
123  Layer* const cellStateOut = graph.AddLayer<OutputLayer>(2, "cellStateOut");
124  Layer* const output = graph.AddLayer<OutputLayer>(3, "output");
125 
126  // connect up
127  armnn::TensorInfo lstmTensorInfo1({ batchSize, inputSize }, DataType::Float32);
128  armnn::TensorInfo lstmTensorInfo2({ batchSize, numUnits}, DataType::Float32);
129  armnn::TensorInfo lstmTensorInfo3({ batchSize, outputSize }, DataType::Float32);
130  armnn::TensorInfo lstmTensorInfoScratchBuff({ batchSize, numUnits * (layerDesc.m_CifgEnabled ? 3 : 4) },
132 
133  Connect(input, layer, lstmTensorInfo1, 0, 0);
134  Connect(cellStateIn, layer, lstmTensorInfo2, 0, 1);
135  Connect(outputStateIn, layer, lstmTensorInfo3, 0, 2);
136  Connect(layer, scratchBuffer, lstmTensorInfoScratchBuff, 0, 0);
137  Connect(layer, outputStateOut, lstmTensorInfo3, 1, 0);
138  Connect(layer, cellStateOut, lstmTensorInfo2, 2, 0);
139  Connect(layer, output, lstmTensorInfo3, 3, 0);
140 }
141 
142 
143 class MockLayerSupport : public LayerSupportBase
144 {
145 public:
146  bool IsInputSupported(const TensorInfo& /*input*/,
147  Optional<std::string&> /*reasonIfUnsupported = EmptyOptional()*/) const override
148  {
149  return true;
150  }
151 
152  bool IsOutputSupported(const TensorInfo& /*input*/,
153  Optional<std::string&> /*reasonIfUnsupported = EmptyOptional()*/) const override
154  {
155  return true;
156  }
157 
158  bool IsActivationSupported(const TensorInfo& /*input0*/,
159  const TensorInfo& /*output*/,
160  const ActivationDescriptor& /*descriptor*/,
161  Optional<std::string&> /*reasonIfUnsupported = EmptyOptional()*/) const override
162  {
163  return true;
164  }
165 };
166 
167 template <typename NamePolicy>
168 class MockBackend : public IBackendInternal
169 {
170 public:
171  MockBackend() :
172  m_BackendCapabilities(NamePolicy::GetIdStatic(), {{"NullCapability", false}}),
173  m_CustomAllocator(false) {};
174  MockBackend(const BackendCapabilities& capabilities) :
175  m_BackendCapabilities(capabilities),
176  m_CustomAllocator(false) {};
177  ~MockBackend() = default;
178 
179  static const BackendId& GetIdStatic()
180  {
181  return NamePolicy::GetIdStatic();
182  }
183  const BackendId& GetId() const override
184  {
185  return GetIdStatic();
186  }
187 
188  IBackendInternal::IMemoryManagerUniquePtr CreateMemoryManager() const override
189  {
190  return nullptr;
191  };
192 
194  CreateWorkloadFactory(const IBackendInternal::IMemoryManagerSharedPtr&) const override
195  {
196  return nullptr;
197  }
198 
199  IBackendInternal::IBackendContextPtr CreateBackendContext(const IRuntime::CreationOptions&) const override
200  {
201  return nullptr;
202  }
203 
204  IBackendInternal::Optimizations GetOptimizations() const override
205  {
206  return {};
207  }
208  IBackendInternal::ILayerSupportSharedPtr GetLayerSupport() const override
209  {
210  return std::make_shared<MockLayerSupport>();
211  }
212 
213  OptimizationViews OptimizeSubgraphView(const SubgraphView&) const override
214  {
215  return {};
216  };
217 
218  BackendCapabilities GetCapabilities() const override
219  {
220  return m_BackendCapabilities;
221  };
222 
223  virtual bool UseCustomMemoryAllocator(std::shared_ptr<ICustomAllocator> allocator,
224  armnn::Optional<std::string&> errMsg) override
225  {
226  IgnoreUnused(errMsg, allocator);
227  m_CustomAllocator = true;
228  return m_CustomAllocator;
229  }
230 
231  BackendCapabilities m_BackendCapabilities;
232  bool m_CustomAllocator;
233 };
234 
235 template <typename NamePolicy>
236 class NoProtectedModeMockBackend : public IBackendInternal
237 {
238 public:
239  NoProtectedModeMockBackend() : m_BackendCapabilities(NamePolicy::GetIdStatic(), {{"NullCapability", false}}) {};
240  NoProtectedModeMockBackend(const BackendCapabilities& capabilities) : m_BackendCapabilities(capabilities) {};
241  ~NoProtectedModeMockBackend() = default;
242 
243  static const BackendId& GetIdStatic()
244  {
245  return NamePolicy::GetIdStatic();
246  }
247  const BackendId& GetId() const override
248  {
249  return GetIdStatic();
250  }
251 
252  IBackendInternal::IMemoryManagerUniquePtr CreateMemoryManager() const override
253  {
254  return nullptr;
255  };
256 
258  CreateWorkloadFactory(const IBackendInternal::IMemoryManagerSharedPtr&) const override
259  {
260  return nullptr;
261  }
262 
263  IBackendInternal::IBackendContextPtr CreateBackendContext(const IRuntime::CreationOptions&) const override
264  {
265  return nullptr;
266  }
267 
268  IBackendInternal::Optimizations GetOptimizations() const override
269  {
270  return {};
271  }
272  IBackendInternal::ILayerSupportSharedPtr GetLayerSupport() const override
273  {
274  return std::make_shared<MockLayerSupport>();
275  }
276 
277  OptimizationViews OptimizeSubgraphView(const SubgraphView&) const override
278  {
279  return {};
280  };
281 
282  BackendCapabilities GetCapabilities() const override
283  {
284  return m_BackendCapabilities;
285  };
286 
287  BackendCapabilities m_BackendCapabilities;
288 };
289 
290 } // namespace
291 
292 TEST_SUITE("Optimizer")
293 {
294 using namespace armnn::optimizations;
295 
296 TEST_CASE("LSTMValidateTensorShapesFromInputsCIFGDisabledTest")
297 {
298  Graph graph;
299 
300  //Helper function creates graph containing LSTM layer with required input and output layers
301  CreateLSTMLayerHelper(graph, false);
302 
303  //This function used to call ValidateShapesFromInputs();
304  CHECK_NOTHROW(graph.InferTensorInfos());
305 }
306 
307 TEST_CASE("LSTMValidateTensorShapesFromInputsCIFGEnabledTest")
308 {
309  Graph graph;
310 
311  //Helper function creates graph containing LSTM layer with required input and output layers
312  CreateLSTMLayerHelper(graph, true);
313 
314  //This function used to call ValidateShapesFromInputs();
315  CHECK_NOTHROW(graph.InferTensorInfos());
316 }
317 
318 TEST_CASE("InsertConvertersTest")
319 {
320  const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float16);
321 
322  armnn::Graph graph;
323 
324  armnn::LayerBindingId inputId = 0;
325 
326  armnn::Layer* head = graph.AddLayer<armnn::OutputLayer>(0, "output");
327 
328  head = graph.InsertNewLayer<armnn::AdditionLayer>(head->GetInputSlot(0), "");
330 
331  graph.InsertNewLayer<armnn::InputLayer>(head->GetInputSlot(1), inputId++, "")
332  ->GetOutputHandler().SetTensorInfo(info);
333 
334  head = graph.InsertNewLayer<armnn::FloorLayer>(head->GetInputSlot(0), "");
336 
337  head = graph.InsertNewLayer<armnn::MemCopyLayer>(head->GetInputSlot(0), "");
339 
340  graph.InsertNewLayer<armnn::InputLayer>(head->GetInputSlot(0), inputId++, "")
341  ->GetOutputHandler().SetTensorInfo(info);
342 
343  // Check graph layer sequence before inserting convert layers
344  CHECK(CheckSequence(graph.cbegin(),
345  graph.cend(),
346  &IsLayerOfType<armnn::InputLayer>,
347  &IsLayerOfType<armnn::InputLayer>,
348  &IsLayerOfType<armnn::MemCopyLayer>,
349  &IsLayerOfType<armnn::FloorLayer>,
350  &IsLayerOfType<armnn::AdditionLayer>,
351  &IsLayerOfType<armnn::OutputLayer>));
352 
353  // Check layers have Float16 DataType
354  for (auto& layer : graph)
355  {
356  if(layer->GetType()==LayerType::Floor || layer->GetType() == LayerType::Addition)
357  {
360  }
361  }
362 
363  // Insert convert layers either side of unsupported layer
364  for (auto& layer : graph)
365  {
366  if(layer->GetType()==LayerType::Floor || layer->GetType() == LayerType::Addition)
367  {
369  InsertConvertFp32ToFp16LayersAfter(graph, *layer);
370  }
371  }
372 
373  // Check layers have correct DataType after inserting convert layers
374  for (auto& layer : graph)
375  {
376  if (layer->GetType()==LayerType::Floor || layer->GetType() == LayerType::Addition)
377  {
380  }
381  else if (layer->GetType() == LayerType::ConvertFp16ToFp32)
382  {
385  }
386  else if (layer->GetType() == LayerType::ConvertFp32ToFp16)
387  {
390  }
391  }
392 
393  // Check sequence of layers after inserting convert layers
394  CHECK(CheckSequence(graph.cbegin(),
395  graph.cend(),
396  &IsLayerOfType<armnn::InputLayer>,
397  &IsLayerOfType<armnn::InputLayer>,
398  &IsLayerOfType<armnn::ConvertFp16ToFp32Layer>,
399  &IsLayerOfType<armnn::MemCopyLayer>,
400  &IsLayerOfType<armnn::ConvertFp16ToFp32Layer>,
401  &IsLayerOfType<armnn::FloorLayer>,
402  &IsLayerOfType<armnn::ConvertFp32ToFp16Layer>,
403  &IsLayerOfType<armnn::ConvertFp16ToFp32Layer>,
404  &IsLayerOfType<armnn::AdditionLayer>,
405  &IsLayerOfType<armnn::ConvertFp32ToFp16Layer>,
406  &IsLayerOfType<armnn::OutputLayer>));
407 }
408 
409 void CreateConvolution2dGraph(Graph &graph, const unsigned int* inputShape,
410  const unsigned int* weightsShape, const unsigned int* outputShape,
411  DataLayout dataLayout = DataLayout::NCHW)
412 {
413  armnn::TensorInfo inputInfo(4, inputShape, DataType::Float32);
414  armnn::TensorInfo outputInfo(4, outputShape, DataType::Float32);
415 
416  std::vector<float> weightsVector(90);
417  armnn::ConstTensor weights(armnn::TensorInfo(4, weightsShape, armnn::DataType::Float32), weightsVector);
418 
420  desc.m_BiasEnabled = false;
421  desc.m_StrideX = 1;
422  desc.m_StrideY = 1;
423  desc.m_DataLayout = dataLayout;
424 
425  Layer* input = graph.AddLayer<InputLayer>(0, "input");
426  input->GetOutputSlot().SetTensorInfo(inputInfo);
427 
428  Convolution2dLayer* layer = graph.AddLayer<Convolution2dLayer>(desc, "conv2d");
429  layer->m_Weight = std::make_unique<armnn::ScopedTensorHandle>(weights);
430  layer->GetOutputSlot().SetTensorInfo(outputInfo);
431 
432  Layer* output = graph.AddLayer<OutputLayer>(0, "output");
433  input->GetOutputSlot().Connect(layer->GetInputSlot(0));
434  layer->GetOutputSlot().Connect(output->GetInputSlot(0));
435 }
436 
437 TEST_CASE("Conv2dValidateTensorShapesFromInputs")
438 {
439  Graph graph;
440  const unsigned int inputShape[] = { 1, 3, 8, 16 };
441  const unsigned int weightsShape[] = { 2, 3, 5, 3 };
442  const unsigned int outputShape[] = { 1, 2, 4, 14 };
443  CreateConvolution2dGraph(graph, inputShape, weightsShape, outputShape);
444 
445  CHECK_NOTHROW(graph.InferTensorInfos());
446 }
447 
448 TEST_CASE("Conv2dValidateTensorShapesFromInputsNhwc")
449 {
450  Graph graph;
451  const unsigned int inputShape[] = { 1, 8, 16, 3 };
452  const unsigned int weightsShape[] = { 2, 5, 3, 3 };
453  const unsigned int outputShape[] = { 1, 4, 14, 2 };
454  CreateConvolution2dGraph(graph, inputShape, weightsShape, outputShape, DataLayout::NHWC);
455 
456  CHECK_NOTHROW(graph.InferTensorInfos());
457 }
458 
459 void CreateDepthwiseConvolution2dGraph(Graph &graph, const unsigned int* inputShape,
460  const unsigned int* weightsShape, const unsigned int* outputShape,
461  DataLayout dataLayout = DataLayout::NCHW)
462 {
463  armnn::TensorInfo inputInfo(4, inputShape, DataType::Float32);
464  armnn::TensorInfo outputInfo(4, outputShape, DataType::Float32);
465 
466  std::vector<float> weightsVector(18);
467  armnn::ConstTensor weights(armnn::TensorInfo(4, weightsShape, armnn::DataType::Float32), weightsVector);
468 
470  desc.m_BiasEnabled = false;
471  desc.m_StrideX = 1;
472  desc.m_StrideY = 1;
473  desc.m_DataLayout = dataLayout;
474 
475  Layer* input = graph.AddLayer<InputLayer>(0, "input");
476  input->GetOutputSlot().SetTensorInfo(inputInfo);
477 
478  DepthwiseConvolution2dLayer* layer = graph.AddLayer<DepthwiseConvolution2dLayer>(desc, "depthwiseConv2d");
479  layer->m_Weight = std::make_unique<armnn::ScopedTensorHandle>(weights);
480  layer->GetOutputSlot().SetTensorInfo(outputInfo);
481 
482  Layer* output = graph.AddLayer<OutputLayer>(0, "output");
483  input->GetOutputSlot().Connect(layer->GetInputSlot(0));
484  layer->GetOutputSlot().Connect(output->GetInputSlot(0));
485 }
486 
487 TEST_CASE("DepthwiseConv2dValidateTensorShapesFromInputs")
488 {
489  Graph graph;
490  const unsigned int inputShape[] = { 1, 2, 3, 3 };
491  const unsigned int weightsShape[] = { 1, 3, 3, 2 };
492  const unsigned int outputShape[] = { 1, 2, 1, 1 };
493  CreateDepthwiseConvolution2dGraph(graph, inputShape, weightsShape, outputShape);
494 
495  CHECK_NOTHROW(graph.InferTensorInfos());
496 }
497 
498 TEST_CASE("DepthwiseConv2dValidateTensorShapesFromInputsNhwc")
499 {
500  Graph graph;
501  const unsigned int inputShape[] = { 1, 3, 3, 2 };
502  const unsigned int weightsShape[] = { 1, 3, 3, 2 };
503  const unsigned int outputShape[] = { 1, 1, 1, 2 };
504  CreateDepthwiseConvolution2dGraph(graph, inputShape, weightsShape, outputShape, DataLayout::NHWC);
505 
506  CHECK_NOTHROW(graph.InferTensorInfos());
507 }
508 
509 void CreatePooling2dGraph(Graph& graph, const unsigned int* inputShape, const unsigned int* outputShape,
510  DataLayout dataLayout = DataLayout::NCHW)
511 {
512  armnn::TensorInfo inputInfo(4, inputShape, DataType::Float32);
513  armnn::TensorInfo outputInfo(4, outputShape, DataType::Float32);
514 
515  Pooling2dDescriptor desc;
517  desc.m_PoolWidth = desc.m_PoolHeight = 100;
518  desc.m_StrideX = desc.m_StrideY = 5;
519  desc.m_PadLeft = 50;
520  desc.m_PadRight = 50;
521  desc.m_PadTop = 50;
522  desc.m_PadBottom = 50;
524  desc.m_DataLayout = dataLayout;
525 
526  Layer* input = graph.AddLayer<InputLayer>(0, "input");
527  input->GetOutputSlot().SetTensorInfo(inputInfo);
528 
529  Pooling2dLayer* layer = graph.AddLayer<Pooling2dLayer>(desc, "pooling2d");
530  layer->GetOutputSlot().SetTensorInfo(outputInfo);
531 
532  Layer* output = graph.AddLayer<OutputLayer>(0, "output");
533  input->GetOutputSlot().Connect(layer->GetInputSlot(0));
534  layer->GetOutputSlot().Connect(output->GetInputSlot(0));
535 }
536 
537 TEST_CASE("Pooling2dValidateTensorShapesFromInputs")
538 {
539  Graph graph;
540  const unsigned int inputShape[] = { 5, 3, 52, 60 };
541  const unsigned int outputShape[] = { 5, 3, 11, 13 };
542  CreatePooling2dGraph(graph, inputShape, outputShape, DataLayout::NCHW);
543 
544  CHECK_NOTHROW(graph.InferTensorInfos());
545 }
546 
547 TEST_CASE("Pooling2dValidateTensorShapesFromInputsNhwc")
548 {
549  Graph graph;
550  const unsigned int inputShape[] = { 5, 52, 60, 3 };
551  const unsigned int outputShape[] = { 5, 11, 13, 3 };
552  CreatePooling2dGraph(graph, inputShape, outputShape, DataLayout::NHWC);
553 
554  CHECK_NOTHROW(graph.InferTensorInfos());
555 }
556 
557 void CreateResizeBilinearGraph(Graph& graph,
558  const unsigned int* inputShape,
559  const unsigned int* outputShape,
560  DataLayout dataLayout = DataLayout::NCHW)
561 {
562  TensorInfo inputInfo(4, inputShape, DataType::Float32);
563  TensorInfo outputInfo(4, outputShape, DataType::Float32);
564 
565  ResizeDescriptor desc;
567  desc.m_TargetHeight = 3;
568  desc.m_TargetWidth = 4;
569  desc.m_DataLayout = dataLayout;
570 
571  Layer* input = graph.AddLayer<InputLayer>(0, "input");
572  input->GetOutputSlot().SetTensorInfo(inputInfo);
573 
574  ResizeLayer* layer = graph.AddLayer<ResizeLayer>(desc, "resizeBilinear");
575  layer->GetOutputSlot().SetTensorInfo(outputInfo);
576 
577  Layer* output = graph.AddLayer<OutputLayer>(0, "output");
578  input->GetOutputSlot().Connect(layer->GetInputSlot(0));
579  layer->GetOutputSlot().Connect(output->GetInputSlot(0));
580 }
581 
582 TEST_CASE("ResizeBilinearValidateTensorShapesFromInputs")
583 {
584  Graph graph;
585  const unsigned int inputShape[] = { 1, 2, 4, 5 };
586  const unsigned int outputShape[] = { 1, 2, 3, 4 };
587  CreateResizeBilinearGraph(graph, inputShape, outputShape);
588 
589  CHECK_NOTHROW(graph.InferTensorInfos());
590 }
591 
592 TEST_CASE("ResizeBilinearValidateTensorShapesFromInputsNhwc")
593 {
594  Graph graph;
595  const unsigned int inputShape[] = { 1, 4, 5, 2 };
596  const unsigned int outputShape[] = { 1, 3, 4, 2 };
597  CreateResizeBilinearGraph(graph, inputShape, outputShape, DataLayout::NHWC);
598 
599  CHECK_NOTHROW(graph.InferTensorInfos());
600 }
601 
602 void CreateGatherGraph(Graph& graph,
603  const armnn::TensorInfo& paramsInfo,
604  const armnn::TensorInfo& indicesInfo,
605  const armnn::TensorInfo& outputInfo)
606 {
607  Layer* input0 = graph.AddLayer<InputLayer>(0, "params");
608  input0->GetOutputSlot().SetTensorInfo(paramsInfo);
609 
610  Layer* input1 = graph.AddLayer<InputLayer>(1, "indices");
611  input1->GetOutputSlot().SetTensorInfo(indicesInfo);
612 
613  GatherDescriptor descriptor;
614  GatherLayer* layer = graph.AddLayer<GatherLayer>(descriptor, "gather");
615  layer->GetOutputSlot().SetTensorInfo(outputInfo);
616 
617  Layer* output = graph.AddLayer<OutputLayer>(0, "output");
618  input0->GetOutputSlot().Connect(layer->GetInputSlot(0));
619  input1->GetOutputSlot().Connect(layer->GetInputSlot(1));
620  layer->GetOutputSlot().Connect(output->GetInputSlot(0));
621 }
622 
623 TEST_CASE("GatherValidateTensorShapesFromInputs")
624 {
625  Graph graph;
626  armnn::TensorInfo paramsInfo({10, 5}, DataType::Float32);
627  armnn::TensorInfo indicesInfo({3}, DataType::Signed32);
628  armnn::TensorInfo outputInfo({3, 5}, DataType::Float32);
629 
630  CreateGatherGraph(graph, paramsInfo, indicesInfo, outputInfo);
631 
632  CHECK_NOTHROW(graph.InferTensorInfos());
633 }
634 
635 TEST_CASE("GatherValidateTensorShapesFromInputs1DParams")
636 {
637  Graph graph;
638  armnn::TensorInfo paramsInfo({8}, DataType::Float32);
639  armnn::TensorInfo indicesInfo({5}, DataType::Signed32);
640  armnn::TensorInfo outputInfo( {5}, DataType::Float32);
641 
642  CreateGatherGraph(graph, paramsInfo, indicesInfo, outputInfo);
643 
644  CHECK_NOTHROW(graph.InferTensorInfos());
645 }
646 
647 TEST_CASE("GatherValidateTensorShapesFromInputsMultiDimIndices")
648 {
649  Graph graph;
650  armnn::TensorInfo paramsInfo({3, 2, 5}, DataType::Float32);
651  armnn::TensorInfo indicesInfo({2, 2}, DataType::Signed32);
652  armnn::TensorInfo outputInfo({2, 2, 2, 5}, DataType::Float32);
653 
654  CreateGatherGraph(graph, paramsInfo, indicesInfo, outputInfo);
655 
656  CHECK_NOTHROW(graph.InferTensorInfos());
657 }
658 
659 TEST_CASE("DetectionPostProcessValidateTensorShapes")
660 {
661  Graph graph;
662  armnn::TensorInfo boxEncodingsInfo({1, 10, 4}, DataType::QAsymmU8);
663  armnn::TensorInfo scoresInfo({1, 10, 4}, DataType::QAsymmU8);
664  std::vector<uint8_t> anchorsVector(40);
665  armnn::ConstTensor anchors(armnn::TensorInfo({10, 4}, armnn::DataType::QAsymmU8), anchorsVector);
666 
667  armnn::TensorInfo detectionBoxesInfo({1, 3, 4}, DataType::QAsymmU8);
668  armnn::TensorInfo detectionScoresInfo({1, 3}, DataType::QAsymmU8);
669  armnn::TensorInfo detectionClassesInfo({1, 3}, DataType::QAsymmU8);
670  armnn::TensorInfo numDetectionInfo({1}, DataType::QAsymmU8);
671 
672  Layer* input0 = graph.AddLayer<InputLayer>(0, "boxEncodings");
673  input0->GetOutputSlot().SetTensorInfo(boxEncodingsInfo);
674 
675  Layer* input1 = graph.AddLayer<InputLayer>(1, "score");
676  input1->GetOutputSlot().SetTensorInfo(scoresInfo);
677 
679  descriptor.m_MaxDetections = 3;
680 
681  DetectionPostProcessLayer* layer = graph.AddLayer<DetectionPostProcessLayer>(descriptor, "detectionPostProcess");
682  layer->m_Anchors = std::make_unique<armnn::ScopedTensorHandle>(anchors);
683  layer->GetOutputSlot(0).SetTensorInfo(detectionBoxesInfo);
684  layer->GetOutputSlot(1).SetTensorInfo(detectionScoresInfo);
685  layer->GetOutputSlot(2).SetTensorInfo(detectionClassesInfo);
686  layer->GetOutputSlot(3).SetTensorInfo(numDetectionInfo);
687 
688  input0->GetOutputSlot().Connect(layer->GetInputSlot(0));
689  input1->GetOutputSlot().Connect(layer->GetInputSlot(1));
690 
691  CHECK_NOTHROW(graph.InferTensorInfos());
692 }
693 
694 TEST_CASE("BackendCapabilityTest")
695 {
696  BackendId backendId = "MockBackend";
697 
698  armnn::BackendOptions::BackendOption nonConstWeights{"NonConstWeights", true};
699 
700  // MockBackend does not support the NonConstWeights capability
701  CHECK(!armnn::HasCapability(nonConstWeights, backendId));
702  CHECK(!armnn::HasCapability("NonConstWeights", backendId));
703 
704  // MockBackend does not support the AsyncExecution capability
705  CHECK(!armnn::GetCapability("AsyncExecution", backendId).has_value());
706 }
707 
708 TEST_CASE("BackendHintTest")
709 {
710  class TestBackendAssignment : public LayerVisitorBase<VisitorNoThrowPolicy>
711  {
712  public:
713  void VisitInputLayer(const IConnectableLayer* layer, LayerBindingId id, const char* name = nullptr) override
714  {
715  IgnoreUnused(id, name);
716  auto inputLayer = PolymorphicDowncast<const InputLayer*>(layer);
717  CHECK((inputLayer->GetBackendId() == "MockBackend"));
718  }
719 
720  void VisitOutputLayer(const IConnectableLayer* layer, LayerBindingId id, const char* name = nullptr) override
721  {
722  IgnoreUnused(id, name);
723  auto outputLayer = PolymorphicDowncast<const OutputLayer*>(layer);
724  CHECK((outputLayer->GetBackendId() == "MockBackend"));
725  }
726 
727  void VisitActivationLayer(const IConnectableLayer* layer,
728  const ActivationDescriptor& activationDescriptor,
729  const char* name = nullptr) override
730  {
731  IgnoreUnused(activationDescriptor, name);
732  auto activation = PolymorphicDowncast<const ActivationLayer*>(layer);
733  CHECK((activation->GetBackendId() == "CustomBackend"));
734  }
735  };
736 
737  struct CustomPolicy
738  {
739  static const BackendId& GetIdStatic()
740  {
741  static BackendId id = "CustomBackend";
742  return id;
743  }
744  };
745 
746  struct MockPolicy
747  {
748  static const BackendId& GetIdStatic()
749  {
750  static BackendId id = "MockBackend";
751  return id;
752  }
753  };
754 
755  auto& backendRegistry = BackendRegistryInstance();
756 
757  backendRegistry.Register("MockBackend", []() { return std::make_unique<MockBackend<MockPolicy>>(); });
758 
759  backendRegistry.Register("CustomBackend", []() { return std::make_unique<MockBackend<CustomPolicy>>(); });
760 
761  // Define the network
762  auto network = INetwork::Create();
765 
766  std::unique_ptr<Graph> graph = std::make_unique<Graph>();
767  auto input = graph->AddLayer<InputLayer>(0, "input");
768  auto act = graph->AddLayer<ActivationLayer>(desc, "activation");
769  auto output = graph->AddLayer<OutputLayer>(0, "output");
770 
771  BackendId customBackendId("CustomBackend");
772  act->BackendSelectionHint(customBackendId);
773 
774  input->GetOutputSlot(0).Connect(act->GetInputSlot(0));
775  act->GetOutputSlot(0).Connect(output->GetInputSlot(0));
776 
777  OptimizedNetworkImpl optNet(std::move(graph));
778 
779  // Get the optimized graph
780  Graph& optGraph = optNet.GetGraph();
781 
782  std::vector<BackendId> prefs{ "MockBackend", "CustomBackend" };
783 
784  BackendIdSet availableBackends = { "CustomBackend", "MockBackend" };
785  DeviceSpec spec(availableBackends);
786 
787  BackendSettings backendSettings(prefs, spec);
788 
789  // Assign an available backend to each layer
790  Graph::Iterator firstLayer = optGraph.begin();
791  Graph::Iterator lastLayer = optGraph.end();
792 
793  OptimizedNetworkImpl* optNetObjPtr = &optNet;
794  OptimizationResult res = AssignBackends(optNetObjPtr,
795  backendSettings,
796  firstLayer,
797  lastLayer,
798  EmptyOptional());
799 
800  CHECK(res.IsOk());
801 
802  TestBackendAssignment visitor;
803  for (auto it = firstLayer; it != lastLayer; ++it)
804  {
805  (*it)->Accept(visitor);
806  }
807  // Clean up the registry for the next test.
808  backendRegistry.Deregister("MockBackend");
809  backendRegistry.Deregister("CustomBackend");
810 }
811 
812 // Tests that OptimizeForExclusiveConnections works, fusing when needed, using BatchNorm fusing as example
813 TEST_CASE("OptimizeForExclusiveConnectionsFuseTest")
814 {
815  using namespace armnn;
816  // Define layers information
817  Convolution2dDescriptor convolution2dDescriptor;
818  convolution2dDescriptor.m_BiasEnabled = false;
819  convolution2dDescriptor.m_DataLayout = DataLayout::NHWC;
820  BatchNormalizationDescriptor batchNormDescriptor;
821  batchNormDescriptor.m_DataLayout = DataLayout::NHWC;
822 
823  const unsigned int inputDimensionSizes[] = { 1, 4, 4, 3 }; // NHWCin
824  const unsigned int weightsDimensionSizes[] = { 1, 2, 2, 3 }; // CoutHWCin
825  const unsigned int outputDimensionSizes[] = { 1, 3, 3, 1 }; // NHWCout
826  const unsigned int outputChannelSize[] = { outputDimensionSizes[3] }; // Cout
827 
828  TensorInfo inputInfo(4, inputDimensionSizes, DataType::Float32);
829  TensorInfo outputInfo(4, outputDimensionSizes, DataType::Float32);
830 
831  std::vector<float> weightsVector = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
832  ConstTensor weights(TensorInfo(4, weightsDimensionSizes, DataType::Float32), weightsVector);
833 
834  std::vector<float> betaVector = { 0.1f };
835  std::vector<float> gammaVector = { 0.5f };
836  std::vector<float> meanVector = { 0 };
837  std::vector<float> varianceVector = { 1 };
838  ConstTensor beta(TensorInfo(1, outputChannelSize, DataType::Float32), betaVector);
839  ConstTensor gamma(TensorInfo(1, outputChannelSize, DataType::Float32), gammaVector);
840  ConstTensor mean(TensorInfo(1, outputChannelSize, DataType::Float32), meanVector);
841  ConstTensor variance(TensorInfo(1, outputChannelSize, DataType::Float32), varianceVector);
842 
843  // Define the network
844  Graph graph;
845  auto input = graph.AddLayer<InputLayer>(0, "input");
846  auto conv = graph.AddLayer<Convolution2dLayer>(convolution2dDescriptor, "convolution");
847  auto batchNorm = graph.AddLayer<BatchNormalizationLayer>(batchNormDescriptor, "batchNorm");
848  auto output = graph.AddLayer<OutputLayer>(0, "output");
849 
850  // Set layer information
851  input->GetOutputSlot().SetTensorInfo(inputInfo);
852  conv->GetOutputSlot().SetTensorInfo(outputInfo);
853  batchNorm->GetOutputSlot().SetTensorInfo(outputInfo);
854  conv->m_Weight = std::make_unique<ScopedTensorHandle>(weights);
855  batchNorm->m_Beta = std::make_unique<ScopedTensorHandle>(beta);
856  batchNorm->m_Gamma = std::make_unique<ScopedTensorHandle>(gamma);
857  batchNorm->m_Mean = std::make_unique<ScopedTensorHandle>(mean);
858  batchNorm->m_Variance = std::make_unique<ScopedTensorHandle>(variance);
859  if (convolution2dDescriptor.m_BiasEnabled)
860  {
861  std::vector<float> biasVector = { 11 };
862  ConstTensor bias(TensorInfo(1, outputChannelSize, DataType::Float32), biasVector);
863  conv->m_Bias = std::make_unique<ScopedTensorHandle>(bias);
864  }
865 
866  // Connect layers
867  input->GetOutputSlot(0).Connect(conv->GetInputSlot(0));
868  conv->GetOutputSlot(0).Connect(batchNorm->GetInputSlot(0));
869  batchNorm->GetOutputSlot(0).Connect(output->GetInputSlot(0));
870 
871  CHECK(4 == graph.GetNumLayers());
872  CHECK(CheckSequence(graph.cbegin(), graph.cend(),
873  &IsLayerOfType<InputLayer>,
874  &IsLayerOfType<Convolution2dLayer>,
875  &IsLayerOfType<BatchNormalizationLayer>,
876  &IsLayerOfType<OutputLayer>));
877 
878  // Optimize graph
880 
881  auto checkFusedConv2d = [](const armnn::Layer* const layer) -> bool {
882  return IsLayerOfType<armnn::Convolution2dLayer>(layer) &&
883  (layer->GetNameStr() == "fused-batchNorm-into-convolution");
884  };
885 
886  CHECK(3 == graph.GetNumLayers());
887  CHECK(CheckSequence(graph.cbegin(), graph.cend(),
888  &IsLayerOfType<InputLayer>,
889  checkFusedConv2d,
890  &IsLayerOfType<OutputLayer>));
891 }
892 
893 // Tests that OptimizeForExclusiveConnections works, not fusing when not needed, using BatchNorm fusing as example
894 TEST_CASE("OptimizeForExclusiveConnectionsWithoutFuseTest")
895 {
896  // Define the network
897  Graph graph;
898  Convolution2dDescriptor convolution2dDescriptor;
899  BatchNormalizationDescriptor batchNormDescriptor;
900 
901  auto input = graph.AddLayer<InputLayer>(0, "input");
902  auto conv = graph.AddLayer<Convolution2dLayer>(convolution2dDescriptor, "convolution");
903  auto batchNorm = graph.AddLayer<BatchNormalizationLayer>(batchNormDescriptor, "batchNorm");
904  auto output = graph.AddLayer<OutputLayer>(0, "output");
905  auto output2 = graph.AddLayer<OutputLayer>(1, "output2");
906 
907  // Connect layers
908  input->GetOutputSlot(0).Connect(conv->GetInputSlot(0));
909  conv->GetOutputSlot(0).Connect(batchNorm->GetInputSlot(0));
910  batchNorm->GetOutputSlot(0).Connect(output->GetInputSlot(0));
911  conv->GetOutputSlot(0).Connect(output2->GetInputSlot(0));
912 
913  CHECK(5 == graph.GetNumLayers());
914  CHECK(CheckSequence(graph.cbegin(), graph.cend(),
915  &IsLayerOfType<armnn::InputLayer>,
916  &IsLayerOfType<armnn::Convolution2dLayer>,
917  &IsLayerOfType<armnn::BatchNormalizationLayer>,
918  &IsLayerOfType<armnn::OutputLayer>,
919  &IsLayerOfType<armnn::OutputLayer>));
920  // Optimize graph
922 
923  CHECK(5 == graph.GetNumLayers());
924  CHECK(CheckSequence(graph.cbegin(), graph.cend(),
925  &IsLayerOfType<armnn::InputLayer>,
926  &IsLayerOfType<armnn::Convolution2dLayer>,
927  &IsLayerOfType<armnn::BatchNormalizationLayer>,
928  &IsLayerOfType<armnn::OutputLayer>,
929  &IsLayerOfType<armnn::OutputLayer>));
930 }
931 } // Optimizer TestSuite
TEST_SUITE("TestConstTensorLayerVisitor")
std::shared_ptr< ConstTensorHandle > m_ForgetGateBias
A unique pointer to represent 1D weights tensor with dimensions [num_units].
Iterator begin()
Returns iterator pointing to the beginning of the list. Lowercase for range-based for loops...
Definition: Graph.hpp:162
std::shared_ptr< ConstTensorHandle > m_OutputGateBias
A unique pointer to represent 1D weights tensor with dimensions [num_units].
bool m_BiasEnabled
Enable/disable bias.
bool m_ProjectionEnabled
Enable/disable the projection layer.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
OptimizationResult AssignBackends(OptimizedNetworkImpl *optNetObjPtr, BackendSettings &backendSettings, Graph::Iterator &firstLayer, Graph::Iterator &lastLayer, Optional< std::vector< std::string > &> errMessages)
Definition: Network.cpp:933
bool HasCapability(const std::string &name, const BackendCapabilities &capabilities)
Convenience function to check if a capability exists in a BackendCapabilites struct.
LstmBasicParameters m_BasicParameters
Definition: LstmLayer.hpp:20
This layer represents a batch normalization operation.
std::unique_ptr< IWorkloadFactory > IWorkloadFactoryPtr
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:61
uint32_t m_PadBottom
Padding bottom value in the height dimension.
std::vector< ConvertFp32ToFp16Layer * > InsertConvertFp32ToFp16LayersAfter(Graph &graph, Layer &layer)
bool m_BiasEnabled
Enable/disable bias.
std::shared_ptr< ConstTensorHandle > m_CellToForgetWeights
A unique pointer to represent 1D weights tensor with dimensions [num_units].
std::vector< OptimizationPtr > Optimizations
DataLayout
Definition: Types.hpp:53
std::vector< ConvertFp16ToFp32Layer * > InsertConvertFp16ToFp32LayersBefore(Graph &graph, Layer &layer, bool expectCorrectInputType)
uint32_t m_PadLeft
Padding left value in the width dimension.
Optimizer::Optimizations MakeOptimizations(Args &&... args)
Definition: Optimizer.hpp:43
bool IsOutputSupported(const TensorInfo &, Optional< std::string &>) const override
float m_ClippingThresProj
Clipping threshold value for the projection.
std::unordered_set< BackendId > BackendIdSet
Definition: BackendId.hpp:191
void BackendSelectionHint(Optional< BackendId > backend) final
Provide a hint for the optimizer as to which backend to prefer for this layer.
Definition: Layer.hpp:330
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Optional< const BackendOptions::BackendOption > GetCapability(const std::string &backendCapabilityName, const BackendCapabilities &capabilities)
Returns a BackendCapability if the backend lists the capability The BackendCapability must then be in...
This layer represents a depthwise convolution 2d operation.
LayerT * AddLayer(Args &&... args)
Adds a new layer, of type LayerType, to the graph constructed with the arguments passed.
Definition: Graph.hpp:402
uint32_t m_PoolWidth
Pooling width value.
ConstIterator cbegin() const
Returns const iterator pointing to the beginning of the list. Lowercase for range-based for loops...
Definition: Graph.hpp:172
A Convolution2dDescriptor for the Convolution2dLayer.
int Connect(InputSlot &destination)
Definition: Layer.cpp:83
ResizeMethod m_Method
The Interpolation method to use (Bilinear, NearestNeighbor).
bool IsActivationSupported(const TensorInfo &input, const TensorInfo &output, const ActivationDescriptor &descriptor, Optional< std::string &> reasonIfUnsupported=EmptyOptional()) const override
static void Pass(Graph &graph, const Optimizations &optimizations)
Definition: Optimizer.cpp:16
The padding fields don&#39;t count and are ignored.
bool IsInputSupported(const TensorInfo &, Optional< std::string &>) const override
PaddingMethod m_PaddingMethod
The padding method to be used. (Exclude, IgnoreValue).
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
OptimizeForExclusiveConnection< Convolution2dLayer, BatchNormalizationLayer, FuseBatchNorm< Convolution2dLayer, armnn::DataType::Float32 > > FuseBatchNormIntoConvolution2DFloat32
std::shared_ptr< ConstTensorHandle > m_Weight
A unique pointer to store Weight values.
This layer represents an activation operation with the specified activation function.
BackendRegistry & BackendRegistryInstance()
uint32_t m_PadTop
Padding top value in the height dimension.
std::shared_ptr< ConstTensorHandle > m_ProjectionWeights
A unique pointer to represent 2D weights tensor with dimensions [output_size, num_units].
This layer represents a detection postprocess operator.
Copyright (c) 2021 ARM Limited and Contributors.
std::shared_ptr< ConstTensorHandle > m_InputToCellWeights
A unique pointer to represent 2D weights tensor with dimensions [input_size, num_units].
std::unique_ptr< IMemoryManager > IMemoryManagerUniquePtr
This layer represents a LSTM operation.
Definition: LstmLayer.hpp:16
void IgnoreUnused(Ts &&...)
LayerList::const_iterator Iterator
Definition: Graph.hpp:50
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
int LayerBindingId
Type of identifiers for bindable layers (inputs, outputs).
Definition: Types.hpp:244
A ResizeDescriptor for the ResizeLayer.
std::shared_ptr< ConstTensorHandle > m_InputGateBias
A unique pointer to represent 1D weights tensor with dimensions [num_units].
std::shared_ptr< ConstTensorHandle > m_CellToOutputWeights
A unique pointer to represent 1D weights tensor with dimensions [num_units].
The SubgraphView class represents a subgraph of a Graph.
uint32_t m_PoolHeight
Pooling height value.
uint32_t m_MaxDetections
Maximum numbers of detections.
const InputSlot & GetInputSlot(unsigned int index) const override
Get a const input slot handle by slot index.
Definition: Layer.hpp:316
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
std::shared_ptr< ConstTensorHandle > m_RecurrentToCellWeights
A unique pointer to represent 2D weights tensor with dimensions [output_size, num_units].
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
A layer user-provided data can be bound to (e.g. inputs, outputs).
Definition: OutputLayer.hpp:13
std::shared_ptr< ConstTensorHandle > m_CellBias
A unique pointer to represent 1D weights tensor with dimensions [num_units].
This layer represents a Gather operator.
Definition: GatherLayer.hpp:14
An LstmDescriptor for the LstmLayer.
uint32_t m_PadRight
Padding right value in the width dimension.
std::shared_ptr< IMemoryManager > IMemoryManagerSharedPtr
DataType GetDataType() const
Definition: Tensor.hpp:198
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:327
const std::string & GetNameStr() const
Definition: Layer.hpp:220
LayerType GetType() const override
Returns the armnn::LayerType of this layer.
Definition: Layer.hpp:265
uint32_t m_TargetWidth
Target width value.
A GatherDescriptor for the GatherLayer.
std::shared_ptr< ConstTensorHandle > m_RecurrentToInputWeights
A unique pointer to represent 2D weights tensor with dimensions [input_size, num_units].
bool m_PeepholeEnabled
Enable/disable peephole.
This layer represents a memory copy operation.
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
std::shared_ptr< ConstTensorHandle > m_RecurrentToOutputWeights
A unique pointer to represent 2D weights tensor with dimensions [output_size, num_units].
std::shared_ptr< ConstTensorHandle > m_InputToInputWeights
A unique pointer to represent 2D weights tensor with dimensions [input_size, num_units].
An ActivationDescriptor for the ActivationLayer.
Definition: Descriptors.hpp:25
This layer represents a floor operation.
Definition: FloorLayer.hpp:13
std::shared_ptr< ConstTensorHandle > m_ProjectionBias
A unique pointer to represent 1D weights tensor with dimensions [output_size].
uint32_t m_TargetHeight
Target height value.
uint32_t m_ActivationFunc
The activation function to use.
Visitor base class with empty implementations.
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
This layer represents a pooling 2d operation.
float m_ClippingThresCell
Clipping threshold value for the cell state.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
This layer represents an addition operation.
LstmOptPeepholeParameters m_PeepholeParameters
Definition: LstmLayer.hpp:23
void SetTensorInfo(const TensorInfo &tensorInfo)
Sets the TensorInfo used by this output handler.
std::shared_ptr< ILayerSupport > ILayerSupportSharedPtr
Struct for the users to pass backend specific options.
LstmOptProjectionParameters m_ProjectionParameters
Definition: LstmLayer.hpp:22
bool m_CifgEnabled
Enable/disable cifg (coupled input & forget gate).
EmptyOptional is used to initialize the Optional class in case we want to have default value for an O...
Definition: Optional.hpp:32
std::shared_ptr< ConstTensorHandle > m_InputToForgetWeights
A unique pointer to represent 2D weights tensor with dimensions [input_size, num_units].
PoolingAlgorithm m_PoolType
The pooling algorithm to use (Max. Average, L2).
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
std::shared_ptr< ConstTensorHandle > m_RecurrentToForgetWeights
A unique pointer to represent 2D weights tensor with dimensions [output_size, num_units].
void InferTensorInfos()
Definition: Graph.cpp:529
std::shared_ptr< ConstTensorHandle > m_Weight
A unique pointer to store Weight values.
const OutputHandler & GetOutputHandler(unsigned int i=0) const
Definition: Layer.hpp:225
A layer user-provided data can be bound to (e.g. inputs, outputs).
Definition: InputLayer.hpp:13
Iterator end()
Returns iterator pointing to the end of the list. Lowercase for range-based for loops.
Definition: Graph.hpp:164
bool CheckSequence(const armnn::Graph::ConstIterator first, const armnn::Graph::ConstIterator last)
Definition: TestUtils.hpp:21
void SetTensorInfo(const TensorInfo &tensorInfo) override
Definition: Layer.cpp:58
DataType GetDataType() const
Definition: Layer.cpp:284
const OutputSlot & GetOutputSlot(unsigned int index=0) const override
Get the const output slot handle by slot index.
Definition: Layer.hpp:318
LstmOptCifgParameters m_CifgParameters
Definition: LstmLayer.hpp:21
ConstIterator cend() const
Returns const iterator pointing to the end of the list. Lowercase for range-based for loops...
Definition: Graph.hpp:174
This layer represents a convolution 2d operation.
void Connect(armnn::IConnectableLayer *from, armnn::IConnectableLayer *to, const armnn::TensorInfo &tensorInfo, unsigned int fromIndex, unsigned int toIndex)
Definition: TestUtils.cpp:12
A Pooling2dDescriptor for the Pooling2dLayer.
std::shared_ptr< ConstTensorHandle > m_CellToInputWeights
A unique pointer to represent 1D weights tensor with dimensions [num_units].
size_t GetNumLayers() const
Definition: Graph.hpp:191
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
std::shared_ptr< ConstTensorHandle > m_Anchors
A unique pointer to store Anchor values.
const TensorInfo & GetTensorInfo() const override
Definition: Layer.cpp:63
static INetworkPtr Create(NetworkOptions networkOptions={})
Definition: Network.cpp:530
ActivationFunction m_Function
The activation function to use (Sigmoid, TanH, Linear, ReLu, BoundedReLu, SoftReLu, LeakyReLu, Abs, Sqrt, Square, Elu).
Definition: Descriptors.hpp:48
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
A DepthwiseConvolution2dDescriptor for the DepthwiseConvolution2dLayer.
A BatchNormalizationDescriptor for the BatchNormalizationLayer.
This layer represents a resize operation.
Definition: ResizeLayer.hpp:13
std::shared_ptr< ConstTensorHandle > m_InputToOutputWeights
A unique pointer to represent 2D weights tensor with dimensions [input_size, num_units].
std::unique_ptr< IBackendContext > IBackendContextPtr