ArmNN
 23.02
SubgraphView.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017, 2019-2023 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
7 
8 #include <Graph.hpp>
9 
13 
14 #include <fmt/format.h>
15 #include <utility>
16 
17 namespace armnn
18 {
19 
20 namespace
21 {
22 
23 template <class C>
24 void AssertIfNullsOrDuplicates(const C& container, const std::string& errorMessage)
25 {
26  using T = typename C::value_type;
27  std::unordered_set<T> duplicateSet;
28  std::for_each(container.begin(), container.end(), [&duplicateSet, &errorMessage](const T& i)
29  {
30  // Ignore unused for release builds
31  IgnoreUnused(errorMessage);
32 
33  // Check if the item is valid
34  ARMNN_ASSERT_MSG(i, errorMessage.c_str());
35 
36  // Check if a duplicate has been found
37  ARMNN_ASSERT_MSG(duplicateSet.find(i) == duplicateSet.end(), errorMessage.c_str());
38 
39  duplicateSet.insert(i);
40  });
41 }
42 
43 } // anonymous namespace
44 
46  : enable_shared_from_this()
47  , m_InputSlots{}
48  , m_OutputSlots{}
49  , m_Layers(graph.begin(), graph.end())
50  , m_IConnectableLayers(graph.begin(), graph.end())
51 {
52  ArrangeBySortOrder();
53  CheckSubgraph();
54 }
55 
56 /// IConnectable Duplication to maintain backwards compatibility
57 SubgraphView::SubgraphView(InputSlots&& inputs, OutputSlots&& outputs, Layers&& layers)
58  : enable_shared_from_this()
59  , m_InputSlots{InputSlots{inputs.begin(), inputs.end()}}
60  , m_IInputSlots{IInputSlots{inputs.begin(), inputs.end()}}
61  , m_OutputSlots{OutputSlots{outputs.begin(), outputs.end()}}
62  , m_IOutputSlots{IOutputSlots{outputs.begin(), outputs.end()}}
63  , m_Layers(layers)
64  , m_IConnectableLayers(IConnectableLayers{layers.begin(), layers.end()})
65 {
66  ArrangeBySortOrder();
67  CheckSubgraph();
68 }
69 
70 /// IConnectable Duplication to maintain backwards compatibility
74  : enable_shared_from_this()
75  , m_IInputSlots{inputs}
76  , m_IOutputSlots{outputs}
77  , m_IConnectableLayers(IConnectableLayers{layers.begin(), layers.end()})
78 {
79  // Cast from IConnectableLayer to Layer for backward compatibility
80  auto f = [](IConnectableLayer* value)
81  {
82  return PolymorphicDowncast<Layer*>(value);
83  };
84  std::transform(layers.begin(), layers.end(), std::back_inserter(m_Layers), f);
85 
86  m_InputSlots.resize(inputs.size());
87  m_IInputSlots.resize(inputs.size());
88  for (unsigned int i = 0; i < inputs.size(); i++)
89  {
90  m_InputSlots.at(i) = PolymorphicDowncast<InputSlot*>(inputs[i]);
91  m_IInputSlots.at(i) = inputs[i];
92  }
93 
94  m_OutputSlots.resize(outputs.size());
95  m_IOutputSlots.resize(outputs.size());
96  for (unsigned int i = 0; i < outputs.size(); i++)
97  {
98  m_OutputSlots.at(i) = PolymorphicDowncast<OutputSlot*>(outputs[i]);
99  m_IOutputSlots.at(i) = outputs[i];
100  }
101 
102  ArrangeBySortOrder();
103  CheckSubgraph();
104 }
105 
106 /// IConnectable Duplication to maintain backwards compatibility
108  SubgraphView::IInputSlots&& inputs,
109  SubgraphView::IOutputSlots&& outputs,
110  std::shared_ptr<SubgraphViewWorkingCopy> ptr)
111  : enable_shared_from_this()
112  , m_IInputSlots{inputs}
113  , m_IOutputSlots{outputs}
114  , m_IConnectableLayers(IConnectableLayers{layers.begin(), layers.end()})
115  , p_WorkingCopyImpl(std::move(ptr))
116 {
117  // Cast from IConnectableLayer to Layer for backward compatibility
118  auto f = [](IConnectableLayer* value)
119  {
120  return PolymorphicDowncast<Layer*>(value);
121  };
122  std::transform(layers.begin(), layers.end(), std::back_inserter(m_Layers), f);
123 
124  m_InputSlots.resize(inputs.size());
125  m_IInputSlots.resize(inputs.size());
126  for (unsigned int i = 0; i < inputs.size(); i++)
127  {
128  m_InputSlots.at(i) = PolymorphicDowncast<InputSlot*>(inputs[i]);
129  m_IInputSlots.at(i) = inputs[i];
130  }
131 
132  m_OutputSlots.resize(outputs.size());
133  m_IOutputSlots.resize(outputs.size());
134  for (unsigned int i = 0; i < outputs.size(); i++)
135  {
136  m_OutputSlots.at(i) = PolymorphicDowncast<OutputSlot*>(outputs[i]);
137  m_IOutputSlots.at(i) = outputs[i];
138  }
139 
140  ArrangeBySortOrder();
141  CheckSubgraph();
142 }
143 
145  : enable_shared_from_this()
146  , m_InputSlots(subgraph.m_InputSlots.begin(), subgraph.m_InputSlots.end())
147  , m_IInputSlots(subgraph.m_IInputSlots.begin(), subgraph.m_IInputSlots.end())
148  , m_OutputSlots(subgraph.m_OutputSlots.begin(), subgraph.m_OutputSlots.end())
149  , m_IOutputSlots(subgraph.m_IOutputSlots.begin(), subgraph.m_IOutputSlots.end())
150  , m_Layers(subgraph.m_Layers.begin(), subgraph.m_Layers.end())
151  , m_IConnectableLayers(IConnectableLayers{subgraph.m_IConnectableLayers.begin(),
152  subgraph.m_IConnectableLayers.end()})
153 {
154  ArrangeBySortOrder();
155  CheckSubgraph();
156 }
157 
159  : enable_shared_from_this()
160  , m_InputSlots(std::move(subgraph.m_InputSlots))
161  , m_IInputSlots(std::move(subgraph.m_IInputSlots))
162  , m_OutputSlots(std::move(subgraph.m_OutputSlots))
163  , m_IOutputSlots(std::move(subgraph.m_IOutputSlots))
164  , m_Layers(std::move(subgraph.m_Layers))
165  , m_IConnectableLayers(std::move(subgraph.m_IConnectableLayers))
166 {
167  ArrangeBySortOrder();
168  CheckSubgraph();
169 }
170 
172  : enable_shared_from_this()
173  , m_Layers{PolymorphicDowncast<Layer*>(layer)}
174  , m_IConnectableLayers{layer}
175 {
176  unsigned int numInputSlots = layer->GetNumInputSlots();
177  m_InputSlots.resize(numInputSlots);
178  m_IInputSlots.resize(numInputSlots);
179  for (unsigned int i = 0; i < numInputSlots; i++)
180  {
181  m_InputSlots.at(i) = PolymorphicDowncast<InputSlot*>(&(layer->GetInputSlot(i)));
182  m_IInputSlots.at(i) = &(layer->GetInputSlot(i));
183  }
184 
185  unsigned int numOutputSlots = layer->GetNumOutputSlots();
186  m_OutputSlots.resize(numOutputSlots);
187  m_IOutputSlots.resize(numOutputSlots);
188  for (unsigned int i = 0; i < numOutputSlots; i++)
189  {
190  m_OutputSlots.at(i) = PolymorphicDowncast<OutputSlot*>(&(layer->GetOutputSlot(i)));
191  m_IOutputSlots.at(i) = &(layer->GetOutputSlot(i));
192  }
193 
194  CheckSubgraph();
195 }
196 
198 {
199  m_InputSlots = std::move(other.m_InputSlots);
200  m_IInputSlots = std::move(other.m_IInputSlots);
201  m_OutputSlots = std::move(other.m_OutputSlots);
202  m_IOutputSlots = std::move(other.m_IOutputSlots);
203  m_Layers = std::move(other.m_Layers);
204  m_IConnectableLayers = std::move(other.m_IConnectableLayers);
205 
206  CheckSubgraph();
207 
208  return *this;
209 }
210 
211 void SubgraphView::CheckSubgraph()
212 {
213  // Check for invalid or duplicate input slots
214  AssertIfNullsOrDuplicates(m_InputSlots, "Sub-graphs cannot contain null or duplicate input slots");
215 
216  // Check for invalid or duplicate output slots
217  AssertIfNullsOrDuplicates(m_OutputSlots, "Sub-graphs cannot contain null or duplicate output slots");
218 
219  // Check for invalid or duplicate layers
220  AssertIfNullsOrDuplicates(m_Layers, "Sub-graphs cannot contain null or duplicate layers");
221 
222  // Check for invalid or duplicate input slots
223  AssertIfNullsOrDuplicates(m_IInputSlots, "Sub-graphs cannot contain null or duplicate IInputSlots");
224 
225  // Check for invalid or duplicate output slots
226  AssertIfNullsOrDuplicates(m_IOutputSlots, "Sub-graphs cannot contain null or duplicate IOutputSlots");
227 
228  // Check for invalid or duplicate layers
229  AssertIfNullsOrDuplicates(m_IConnectableLayers,
230  "Sub-graphs cannot contain null or duplicate IConnectableLayers");
231 }
232 
233 const SubgraphView::InputSlots& SubgraphView::GetInputSlots() const
234 {
235  return m_InputSlots;
236 }
237 
239 {
240  return m_IInputSlots;
241 }
242 
243 const SubgraphView::OutputSlots& SubgraphView::GetOutputSlots() const
244 {
245  return m_OutputSlots;
246 }
247 
249 {
250  return m_IOutputSlots;
251 }
252 
253 const InputSlot* SubgraphView::GetInputSlot(unsigned int index) const
254 {
255  return m_InputSlots.at(index);
256 }
257 
258 const IInputSlot* SubgraphView::GetIInputSlot(unsigned int index) const
259 {
260  return m_IInputSlots.at(index);
261 }
262 
263 InputSlot* SubgraphView::GetInputSlot(unsigned int index)
264 {
265  return m_InputSlots.at(index);
266 }
267 
269 {
270  return m_IInputSlots.at(index);
271 }
272 
273 const OutputSlot* SubgraphView::GetOutputSlot(unsigned int index) const
274 {
275  return m_OutputSlots.at(index);
276 }
277 
278 const IOutputSlot* SubgraphView::GetIOutputSlot(unsigned int index) const
279 {
280  return m_IOutputSlots.at(index);
281 }
282 
283 OutputSlot* SubgraphView::GetOutputSlot(unsigned int index)
284 {
285  return m_OutputSlots.at(index);
286 }
287 
289 {
290  return m_IOutputSlots.at(index);
291 }
292 
293 unsigned int SubgraphView::GetNumInputSlots() const
294 {
295  return armnn::numeric_cast<unsigned int>(m_IInputSlots.size());
296 }
297 
299 {
300  return armnn::numeric_cast<unsigned int>(m_IOutputSlots.size());
301 }
302 
303 const SubgraphView::Layers& SubgraphView::GetLayers() const
304 {
305  return m_Layers;
306 }
307 
309 {
310  return m_IConnectableLayers;
311 }
312 
313 SubgraphView::Iterator SubgraphView::begin()
314 {
315  return m_Layers.begin();
316 }
317 
318 SubgraphView::Iterator SubgraphView::end()
319 {
320  return m_Layers.end();
321 }
322 
323 // IConnectable Duplication to maintain backwards compatibility
325 {
326  return m_IConnectableLayers.begin();
327 }
328 
330 {
331  return m_IConnectableLayers.end();
332 }
333 
334 SubgraphView::ConstIterator SubgraphView::begin() const
335 {
336  return m_Layers.begin();
337 }
338 
339 SubgraphView::ConstIterator SubgraphView::end() const
340 {
341  return m_Layers.end();
342 }
343 
344 // IConnectable Duplication to maintain backwards compatibility
346 {
347  return m_IConnectableLayers.begin();
348 }
349 
351 {
352  return m_IConnectableLayers.end();
353 }
354 
355 SubgraphView::ConstIterator SubgraphView::cbegin() const
356 {
357  // Ignore deprecated call as this is internal to SubgraphView
359  return begin();
361 }
362 
363 SubgraphView::ConstIterator SubgraphView::cend() const
364 {
365  // Ignore deprecated call as this is internal to SubgraphView
367  return end();
369 }
370 
371 // IConnectable Duplication to maintain backwards compatibility
373 {
374  return beginIConnectable();
375 }
376 
378 {
379  return endIConnectable();
380 }
381 
383 {
384  m_InputSlots.clear();
385  m_OutputSlots.clear();
386  m_Layers.clear();
387 
388  m_IInputSlots.clear();
389  m_IOutputSlots.clear();
390  m_IConnectableLayers.clear();
391 }
392 
393 void SubgraphView::ArrangeBySortOrder()
394 {
395  using LayerList = std::list<Layer*>;
396  auto compareLayerPriority = [](const LayerList::value_type& layerA, const LayerList::value_type& layerB)
397  {
398  return layerA->GetPriority() < layerB->GetPriority();
399  };
400 
401  m_Layers.sort(compareLayerPriority);
402 
403  using IConnectableLayersList = std::list<IConnectableLayer*>;
404  auto compareIConnectableLayerPriority = [](const IConnectableLayersList::value_type& layerA,
405  const IConnectableLayersList::value_type& layerB)
406  {
407  return PolymorphicDowncast<Layer*>(layerA)->GetPriority() <
408  PolymorphicDowncast<Layer*>(layerB)->GetPriority();
409  };
410 
411  m_IConnectableLayers.sort(compareIConnectableLayerPriority);
412 }
413 
414 struct SubgraphView::SubgraphViewWorkingCopy
415 {
416 public:
417 
418  SubgraphViewWorkingCopy() = default;
419  SubgraphViewWorkingCopy(Graph graph, std::shared_ptr<const SubgraphView> originalSubgraphView)
420  : m_Graph(graph)
421  , m_OriginalSubgraphView(originalSubgraphView)
422  {};
423 
424  Graph m_Graph;
425  std::shared_ptr<const SubgraphView> m_OriginalSubgraphView;
426 
427 };
428 
430 {
431  if (p_WorkingCopyImpl)
432  {
433  throw Exception("The SubgraphView calling GetWorkingCopy() is already a working copy. This function "
434  "should be called on original SubgraphView obtained from OptimizeSubgraphView()");
435  }
436 
437  // Create a cut down SubgraphView with underlying graph containing only the relevant layers.
438  // It needs its own underlying layers so that they can be replaced safely.
439  auto ptr = std::make_shared<SubgraphViewWorkingCopy>(Graph(), shared_from_this());
440 
441  std::unordered_map<const IConnectableLayer*, IConnectableLayer*> originalToClonedLayerMap;
442  std::list<armnn::IConnectableLayer*> originalSubgraphLayers = GetIConnectableLayers();
443 
444  for (auto&& originalLayer : originalSubgraphLayers)
445  {
446  Layer* const layer = PolymorphicDowncast<const Layer*>(originalLayer)->Clone(ptr->m_Graph);
447  originalToClonedLayerMap.emplace(originalLayer, layer);
448  }
449 
450  SubgraphView::IInputSlots workingCopyInputs;
451  // Add IInputSlots to workingCopy
452  for (auto originalSubgraphInputSlot : GetIInputSlots())
453  {
454  const IConnectableLayer& originalSubgraphLayer =
455  PolymorphicDowncast<InputSlot*>(originalSubgraphInputSlot)->GetOwningLayer();
456 
457  auto* clonedLayer = originalToClonedLayerMap[&originalSubgraphLayer];
458 
459  workingCopyInputs.push_back(&clonedLayer->GetInputSlot(originalSubgraphInputSlot->GetSlotIndex()));
460  }
461 
462  for (auto originalSubgraphLayer : originalSubgraphLayers)
463  {
464  IConnectableLayer* const clonedLayer = originalToClonedLayerMap[originalSubgraphLayer];
465 
466  // OutputLayers have no OutputSlots to be connected
467  if (clonedLayer->GetType() != LayerType::Output)
468  {
469  // connect all cloned layers as per original subgraph
470  for (unsigned int i = 0; i < clonedLayer->GetNumOutputSlots(); i++)
471  {
472  auto& originalOutputSlot = originalSubgraphLayer->GetOutputSlot(i);
473  auto& clonedOutputSlot = clonedLayer->GetOutputSlot(i);
474  for (unsigned int j = 0; j < originalOutputSlot.GetNumConnections(); j++)
475  {
476  // nextLayer is the layer with IInputSlot connected to IOutputSlot we are working on
477  const IConnectableLayer& nextLayerOnOriginalSubgraph =
478  originalOutputSlot.GetConnection(j)->GetOwningIConnectableLayer();
479 
480  // Check the layer is in our map and so has a clonedLayer
481  if (originalToClonedLayerMap.find(&nextLayerOnOriginalSubgraph) != originalToClonedLayerMap.end())
482  {
483  auto* nextLayerOnClonedSubgraph = originalToClonedLayerMap[&nextLayerOnOriginalSubgraph];
484 
485  auto index = PolymorphicDowncast<OutputSlot*>(
486  &originalOutputSlot)->GetConnection(j)->GetSlotIndex();
487 
488  IInputSlot& inputSlot = nextLayerOnClonedSubgraph->GetInputSlot(index);
489 
490  // Then make the connection
491  clonedOutputSlot.Connect(inputSlot);
492  }
493  }
494  // Copy the tensorInfo to the clonedOutputSlot
495  clonedOutputSlot.SetTensorInfo(originalOutputSlot.GetTensorInfo());
496  }
497  }
498  }
499 
500  SubgraphView::IOutputSlots workingCopyOutputs;
501 
502  // Add IOutputSlots to workingCopy
503  for (auto outputSlot : GetIOutputSlots())
504  {
505  auto outputSlotIndex = outputSlot->CalculateIndexOnOwner();
506  const IConnectableLayer& originalSubgraphLayer = outputSlot->GetOwningIConnectableLayer();
507 
508  // OutputLayers have no OutputSlots to be connected
509  if (originalSubgraphLayer.GetType() != LayerType::Output)
510  {
511  IConnectableLayer* clonedLayer = originalToClonedLayerMap[&originalSubgraphLayer];
512 
513  // Add the OutputSlot of clonedLayer to WorkingCopy OutputSlots
514  workingCopyOutputs.push_back(&clonedLayer->GetOutputSlot(outputSlotIndex));
515  }
516  }
517 
518  SubgraphView::IConnectableLayers workingCopyLayers;
519  for (auto& pair : originalToClonedLayerMap)
520  {
521  workingCopyLayers.push_back(pair.second);
522  }
523 
524  return {std::move(workingCopyLayers),
525  std::move(workingCopyInputs),
526  std::move(workingCopyOutputs),
527  ptr};
528 }
529 
531 {
532  ARMNN_ASSERT(substituteLayer != nullptr);
533  SubgraphView substituteSubgraph(substituteLayer);
534 
535  SubstituteSubgraph(subgraph, substituteSubgraph);
536 }
537 
538 void SubgraphView::UpdateSubgraphViewSlotPointers(SubgraphView& patternSubgraph,
539  const SubgraphView& substituteSubgraph)
540 {
541  std::vector<IInputSlot*>::iterator inputSlotPosition;
542  // search for and erase any InputSlots that appear in the WorkingCopy that match those in the PatternSubgraph
543  for (unsigned long idx = 0; idx < patternSubgraph.GetIInputSlots().size(); idx++)
544  {
545  IInputSlot *slot = patternSubgraph.GetIInputSlots()[idx];
546  inputSlotPosition = std::find(m_IInputSlots.begin(), m_IInputSlots.end(), slot);
547  if (inputSlotPosition != m_IInputSlots.end())
548  {
549  m_IInputSlots.erase(inputSlotPosition);
550 
551  // while here, with correct position, add in replacement InputSlot from the substituteSubgraph
552  m_IInputSlots.insert(inputSlotPosition, substituteSubgraph.GetIInputSlots()[idx]);
553  }
554  }
555 
556  std::vector<IOutputSlot*>::iterator outputSlotPosition;
557  // search for and erase any OutputSlots that appear in the WorkingCopy that match those in the PatternSubgraph
558  for (unsigned long idx = 0; idx < patternSubgraph.GetIOutputSlots().size(); idx++)
559  {
560  IOutputSlot *slot = patternSubgraph.GetIOutputSlots()[idx];
561  outputSlotPosition = std::find(m_IOutputSlots.begin(), m_IOutputSlots.end(), slot);
562  if (outputSlotPosition != m_IOutputSlots.end())
563  {
564  m_IOutputSlots.erase(outputSlotPosition);
565 
566  // while here, with correct position, add in replacement OutputSlot from the substituteSubgraph
567  m_IOutputSlots.insert(outputSlotPosition, substituteSubgraph.GetIOutputSlots()[idx]);
568  }
569  }
570 }
571 
572 void SubgraphView::SubstituteSubgraph(SubgraphView& patternSubgraph, const SubgraphView& substituteSubgraph)
573 {
574  if (!p_WorkingCopyImpl)
575  {
576  throw NullPointerException("The SubgraphView calling SubstituteSubgraphView is not a working copy. "
577  "Call this function on SubgraphView returned from SubgraphView::GetWorkingCopy()");
578  }
579 
580  auto numPatternInputs = patternSubgraph.GetIInputSlots().size();
581  auto numSubInputs = substituteSubgraph.GetIInputSlots().size();
582  if (numPatternInputs != numSubInputs)
583  {
585  fmt::format("Number of InputSlots on substitute SubgraphView ({}) must equal the number of"
586  " InputSlots on pattern SubgraphView ({})",
587  numSubInputs,
588  numPatternInputs));
589  }
590 
591  auto numPatternOutputs = patternSubgraph.GetIOutputSlots().size();
592  auto numSubOutputs = substituteSubgraph.GetIOutputSlots().size();
593  if (numPatternOutputs != numSubOutputs)
594  {
596  fmt::format("Number of OutputSlots on substitute SubgraphView ({}) must equal the number of"
597  " OutputSlots on pattern SubgraphView ({})",
598  numSubOutputs,
599  numPatternOutputs));
600  }
601 
602  // Add substitute layer to the Main graph i.e. graph in p_WorkingCopyImpl
603  auto workingCopyGraph = &p_WorkingCopyImpl->m_Graph;
604  substituteSubgraph.ForEachIConnectableLayer([workingCopyGraph](IConnectableLayer* iConnectableLayer)
605  {
606  // Search WorkingCopy Graph for substituteLayer and add if missing
607  if (std::find(std::begin(workingCopyGraph->m_Layers),
608  std::end(workingCopyGraph->m_Layers),
609  iConnectableLayer) ==
610  std::end(workingCopyGraph->m_Layers))
611  {
612  auto layer = PolymorphicDowncast<Layer*>(iConnectableLayer);
613 
614  layer->Reparent(*workingCopyGraph,
615  (workingCopyGraph->m_Layers).end());
616 
617  workingCopyGraph->m_LayersInOrder = false;
618  }
619  });
620 
621  // Replace the old connections with connections to new layer
622  workingCopyGraph->ReplaceSubgraphConnections(patternSubgraph, substituteSubgraph);
623 
624  // Update input/outputSlot pointers
625  UpdateSubgraphViewSlotPointers(patternSubgraph, substituteSubgraph);
626 
627  // Delete the old layers.
628  workingCopyGraph->EraseSubgraphLayers(patternSubgraph);
629 
630  // Sort
631  workingCopyGraph->TopologicalSort();
632 
633  // Update SubgraphView layer pointers to match those of the internal WorkingCopy layer pointers
634  m_IConnectableLayers = IConnectableLayers{ workingCopyGraph->m_Layers.begin(),
635  workingCopyGraph->m_Layers.end() };
636 }
637 
639 {
640  if (!p_WorkingCopyImpl)
641  {
642  throw NullPointerException("The SubgraphView calling GetOriginalInputSlots is not a working copy. "
643  "Call this function on SubgraphView returned from SubgraphView::GetWorkingCopy()");
644  }
645  if (!p_WorkingCopyImpl->m_OriginalSubgraphView)
646  {
647  throw NullPointerException("The working copy SubgraphView pointer to its original SubgraphView is null.");
648  }
649  return p_WorkingCopyImpl->m_OriginalSubgraphView->GetIInputSlots();
650 }
652 {
653  if (!p_WorkingCopyImpl)
654  {
655  throw NullPointerException("The SubgraphView calling GetOriginalOutputSlots is not a working copy. "
656  "Call this function on SubgraphView returned from SubgraphView::GetWorkingCopy()");
657  }
658  if (!p_WorkingCopyImpl->m_OriginalSubgraphView)
659  {
660  throw NullPointerException("The working copy SubgraphView pointer to its original SubgraphView is null.");
661  }
662  return p_WorkingCopyImpl->m_OriginalSubgraphView->GetIOutputSlots();
663 }
664 
665 
666 } // namespace armnn
armnn::SubgraphView::OutputSlots
std::vector< OutputSlot * > OutputSlots
Definition: SubgraphView.hpp:59
armnn::OutputSlot
Definition: Layer.hpp:87
armnn::SubgraphView::GetNumOutputSlots
unsigned int GetNumOutputSlots() const
Definition: SubgraphView.cpp:298
armnn::SubgraphView::GetOriginalOutputSlots
const IOutputSlots & GetOriginalOutputSlots() const
Definition: SubgraphView.cpp:651
SubgraphView.hpp
armnn::SubgraphView::GetOriginalInputSlots
const IInputSlots & GetOriginalInputSlots() const
These methods should be called on a working copy subgraph created from GetWorkingCopy.
Definition: SubgraphView.cpp:638
armnn::Exception
Base class for all ArmNN exceptions so that users can filter to just those.
Definition: Exceptions.hpp:46
armnn::InputSlot
Definition: Layer.hpp:42
armnn::SubgraphView::GetNumInputSlots
unsigned int GetNumInputSlots() const
Definition: SubgraphView.cpp:293
armnn::IConnectableLayer
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:68
armnn::SubgraphView::beginIConnectable
IConnectableLayerIterator beginIConnectable()
Definition: SubgraphView.cpp:324
armnn::SubgraphView::cbeginIConnectable
ConstIConnectableIterator cbeginIConnectable() const
Definition: SubgraphView.cpp:372
armnn::SubgraphView::Iterator
Layers::iterator Iterator
Definition: SubgraphView.hpp:63
armnn::SubgraphView::IConnectableLayerIterator
IConnectableLayers::iterator IConnectableLayerIterator
Definition: SubgraphView.hpp:64
PolymorphicDowncast.hpp
armnn::Layer
Definition: Layer.hpp:217
armnn::SubgraphView::SubstituteSubgraph
void SubstituteSubgraph(SubgraphView &, IConnectableLayer *)
These methods should be called on a working copy subgraph created from GetWorkingCopy.
Definition: SubgraphView.cpp:530
armnn::SubgraphView::IConnectableLayers
std::list< IConnectableLayer * > IConnectableLayers
Definition: SubgraphView.hpp:62
armnn::IConnectableLayer::GetOutputSlot
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
armnn::SubgraphView::GetIConnectableLayers
const IConnectableLayers & GetIConnectableLayers() const
Definition: SubgraphView.cpp:308
armnn
Copyright (c) 2021 ARM Limited and Contributors.
Definition: 01_00_quick_start.dox:6
armnn::SubgraphView::IInputSlots
std::vector< IInputSlot * > IInputSlots
Definition: SubgraphView.hpp:58
armnn::IInputSlot
An input connection slot for a layer.
Definition: INetwork.hpp:25
armnn::SubgraphView::endIConnectable
IConnectableLayerIterator endIConnectable()
Definition: SubgraphView.cpp:329
armnn::NullPointerException
Definition: Exceptions.hpp:146
armnn::SubgraphView::operator=
SubgraphView & operator=(SubgraphView &&other)
Move-assignment operator.
Definition: SubgraphView.cpp:197
armnn::SubgraphView::ForEachIConnectableLayer
void ForEachIConnectableLayer(Func func) const
Definition: SubgraphView.hpp:46
armnn::SubgraphView::SubgraphView
SubgraphView(Graph &graph)
Constructs a sub-graph from the entire given graph.
Definition: SubgraphView.cpp:45
armnn::Layer::Clone
virtual Layer * Clone(Graph &graph) const =0
Creates a dynamically-allocated copy of this layer.
armnn::IConnectableLayer::GetNumOutputSlots
virtual unsigned int GetNumOutputSlots() const =0
Returns the number of connectable output slots.
armnn::SubgraphView::GetIOutputSlot
const IOutputSlot * GetIOutputSlot(unsigned int index) const
Definition: SubgraphView.cpp:278
armnn::SubgraphView::GetWorkingCopy
SubgraphView GetWorkingCopy() const
This method returns a copy of the original SubgraphView provided by OptimizeSubgraphView with a separ...
Definition: SubgraphView.cpp:429
armnn::SubgraphView
The SubgraphView class represents a subgraph of a Graph.
Definition: SubgraphView.hpp:31
armnn::IOutputSlot
An output connection slot for a layer.
Definition: INetwork.hpp:41
armnn::SubgraphView::cendIConnectable
ConstIConnectableIterator cendIConnectable() const
Definition: SubgraphView.cpp:377
armnn::SubgraphView::ConstIConnectableIterator
IConnectableLayers::const_iterator ConstIConnectableIterator
Definition: SubgraphView.hpp:66
armnn::SubgraphView::IOutputSlots
std::vector< IOutputSlot * > IOutputSlots
Definition: SubgraphView.hpp:60
ARMNN_NO_DEPRECATE_WARN_BEGIN
#define ARMNN_NO_DEPRECATE_WARN_BEGIN
Definition: Deprecated.hpp:33
armnn::Graph
Definition: Graph.hpp:30
armnn::SubgraphView::Layers
std::list< Layer * > Layers
Definition: SubgraphView.hpp:61
ARMNN_ASSERT
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
armnn::SubgraphView::Clear
void Clear()
Definition: SubgraphView.cpp:382
armnn::SubgraphView::ConstIterator
Layers::const_iterator ConstIterator
Definition: SubgraphView.hpp:65
armnn::SubgraphView::GetIInputSlot
const IInputSlot * GetIInputSlot(unsigned int index) const
Definition: SubgraphView.cpp:258
NumericCast.hpp
armnn::SubgraphView::InputSlots
std::vector< InputSlot * > InputSlots
Definition: SubgraphView.hpp:57
armnn::IConnectableLayer::GetType
virtual LayerType GetType() const =0
Returns the armnn::LayerType of this layer.
armnn::SubgraphView::GetIInputSlots
const IInputSlots & GetIInputSlots() const
Definition: SubgraphView.cpp:238
IgnoreUnused.hpp
std
Definition: BackendId.hpp:149
armnn::LayerType::Output
@ Output
armnn::SubgraphView::GetIOutputSlots
const IOutputSlots & GetIOutputSlots() const
Definition: SubgraphView.cpp:248
armnn::InvalidArgumentException
Definition: Exceptions.hpp:80
Graph.hpp
ARMNN_NO_DEPRECATE_WARN_END
#define ARMNN_NO_DEPRECATE_WARN_END
Definition: Deprecated.hpp:34