23 void AssertIfNullsOrDuplicates(
const C& container,
const std::string& errorMessage)
25 using T =
typename C::value_type;
26 std::unordered_set<T> duplicateSet;
27 std::for_each(container.begin(), container.end(), [&duplicateSet, &errorMessage](
const T& i)
36 ARMNN_ASSERT_MSG(duplicateSet.find(i) == duplicateSet.end(), errorMessage.c_str());
38 duplicateSet.insert(i);
47 , m_Layers(graph.begin(), graph.end())
48 , m_IConnectableLayers(graph.begin(), graph.end())
56 : m_InputSlots{
InputSlots{inputs.begin(), inputs.end()}}
57 , m_IInputSlots{
IInputSlots{inputs.begin(), inputs.end()}}
71 : m_IInputSlots{inputs}
78 return PolymorphicDowncast<Layer*>(value);
80 std::transform(
layers.begin(),
layers.end(), std::back_inserter(m_Layers), f);
82 m_InputSlots.resize(inputs.size());
83 m_IInputSlots.resize(inputs.size());
84 for (
unsigned int i = 0; i < inputs.size(); i++)
86 m_InputSlots.at(i) = PolymorphicDowncast<InputSlot*>(inputs[i]);
87 m_IInputSlots.at(i) = inputs[i];
90 m_OutputSlots.resize(
outputs.size());
91 m_IOutputSlots.resize(
outputs.size());
92 for (
unsigned int i = 0; i <
outputs.size(); i++)
94 m_OutputSlots.at(i) = PolymorphicDowncast<OutputSlot*>(
outputs[i]);
95 m_IOutputSlots.at(i) =
outputs[i];
106 std::shared_ptr<SubgraphViewWorkingCopy> ptr)
107 : m_IInputSlots{inputs}
110 , p_WorkingCopyImpl(std::move(ptr))
115 return PolymorphicDowncast<Layer*>(value);
117 std::transform(
layers.begin(),
layers.end(), std::back_inserter(m_Layers), f);
119 m_InputSlots.resize(inputs.size());
120 m_IInputSlots.resize(inputs.size());
121 for (
unsigned int i = 0; i < inputs.size(); i++)
123 m_InputSlots.at(i) = PolymorphicDowncast<InputSlot*>(inputs[i]);
124 m_IInputSlots.at(i) = inputs[i];
127 m_OutputSlots.resize(
outputs.size());
128 m_IOutputSlots.resize(
outputs.size());
129 for (
unsigned int i = 0; i <
outputs.size(); i++)
131 m_OutputSlots.at(i) = PolymorphicDowncast<OutputSlot*>(
outputs[i]);
132 m_IOutputSlots.at(i) =
outputs[i];
135 ArrangeBySortOrder();
140 : m_InputSlots(subgraph.m_InputSlots.begin(), subgraph.m_InputSlots.end())
141 , m_IInputSlots(subgraph.m_IInputSlots.begin(), subgraph.m_IInputSlots.end())
142 , m_OutputSlots(subgraph.m_OutputSlots.begin(), subgraph.m_OutputSlots.end())
143 , m_IOutputSlots(subgraph.m_IOutputSlots.begin(), subgraph.m_IOutputSlots.end())
144 , m_Layers(subgraph.m_Layers.begin(), subgraph.m_Layers.end())
146 subgraph.m_IConnectableLayers.end()})
148 ArrangeBySortOrder();
153 : m_InputSlots(
std::move(subgraph.m_InputSlots))
154 , m_IInputSlots(
std::move(subgraph.m_IInputSlots))
155 , m_OutputSlots(
std::move(subgraph.m_OutputSlots))
156 , m_IOutputSlots(
std::move(subgraph.m_IOutputSlots))
157 , m_Layers(
std::move(subgraph.m_Layers))
158 , m_IConnectableLayers(
std::move(subgraph.m_IConnectableLayers))
160 ArrangeBySortOrder();
165 : m_Layers{PolymorphicDowncast<Layer*>(layer)}
166 , m_IConnectableLayers{layer}
168 unsigned int numInputSlots = layer->GetNumInputSlots();
169 m_InputSlots.resize(numInputSlots);
170 m_IInputSlots.resize(numInputSlots);
171 for (
unsigned int i = 0; i < numInputSlots; i++)
173 m_InputSlots.at(i) = PolymorphicDowncast<InputSlot*>(&(layer->GetInputSlot(i)));
174 m_IInputSlots.at(i) = &(layer->GetInputSlot(i));
177 unsigned int numOutputSlots = layer->GetNumOutputSlots();
178 m_OutputSlots.resize(numOutputSlots);
179 m_IOutputSlots.resize(numOutputSlots);
180 for (
unsigned int i = 0; i < numOutputSlots; i++)
182 m_OutputSlots.at(i) = PolymorphicDowncast<OutputSlot*>(&(layer->GetOutputSlot(i)));
183 m_IOutputSlots.at(i) = &(layer->GetOutputSlot(i));
191 m_InputSlots = std::move(other.m_InputSlots);
192 m_IInputSlots = std::move(other.m_IInputSlots);
193 m_OutputSlots = std::move(other.m_OutputSlots);
194 m_IOutputSlots = std::move(other.m_IOutputSlots);
195 m_Layers = std::move(other.m_Layers);
196 m_IConnectableLayers = std::move(other.m_IConnectableLayers);
203 void SubgraphView::CheckSubgraph()
206 AssertIfNullsOrDuplicates(m_InputSlots,
"Sub-graphs cannot contain null or duplicate input slots");
209 AssertIfNullsOrDuplicates(m_OutputSlots,
"Sub-graphs cannot contain null or duplicate output slots");
212 AssertIfNullsOrDuplicates(m_Layers,
"Sub-graphs cannot contain null or duplicate layers");
215 AssertIfNullsOrDuplicates(m_IInputSlots,
"Sub-graphs cannot contain null or duplicate IInputSlots");
218 AssertIfNullsOrDuplicates(m_IOutputSlots,
"Sub-graphs cannot contain null or duplicate IOutputSlots");
221 AssertIfNullsOrDuplicates(m_IConnectableLayers,
222 "Sub-graphs cannot contain null or duplicate IConnectableLayers");
232 return m_IInputSlots;
237 return m_OutputSlots;
242 return m_IOutputSlots;
245 const InputSlot* SubgraphView::GetInputSlot(
unsigned int index)
const 247 return m_InputSlots.at(index);
252 return m_IInputSlots.at(index);
255 InputSlot* SubgraphView::GetInputSlot(
unsigned int index)
257 return m_InputSlots.at(index);
262 return m_IInputSlots.at(index);
265 const OutputSlot* SubgraphView::GetOutputSlot(
unsigned int index)
const 267 return m_OutputSlots.at(index);
272 return m_IOutputSlots.at(index);
275 OutputSlot* SubgraphView::GetOutputSlot(
unsigned int index)
277 return m_OutputSlots.at(index);
282 return m_IOutputSlots.at(index);
302 return m_IConnectableLayers;
307 return m_Layers.begin();
312 return m_Layers.end();
318 return m_IConnectableLayers.begin();
323 return m_IConnectableLayers.end();
328 return m_Layers.begin();
333 return m_Layers.end();
339 return m_IConnectableLayers.begin();
344 return m_IConnectableLayers.end();
376 m_InputSlots.clear();
377 m_OutputSlots.clear();
380 m_IInputSlots.clear();
381 m_IOutputSlots.clear();
382 m_IConnectableLayers.clear();
385 void SubgraphView::ArrangeBySortOrder()
387 using LayerList = std::list<Layer*>;
388 auto compareLayerPriority = [](
const LayerList::value_type& layerA,
const LayerList::value_type& layerB)
390 return layerA->GetPriority() < layerB->GetPriority();
393 m_Layers.sort(compareLayerPriority);
395 using IConnectableLayersList = std::list<IConnectableLayer*>;
396 auto compareIConnectableLayerPriority = [](
const IConnectableLayersList::value_type& layerA,
397 const IConnectableLayersList::value_type& layerB)
399 return PolymorphicDowncast<Layer*>(layerA)->GetPriority() <
400 PolymorphicDowncast<Layer*>(layerB)->GetPriority();
403 m_IConnectableLayers.sort(compareIConnectableLayerPriority);
406 struct SubgraphView::SubgraphViewWorkingCopy
410 SubgraphViewWorkingCopy() =
default;
411 SubgraphViewWorkingCopy(
Graph graph)
421 if (p_WorkingCopyImpl)
423 throw Exception(
"The SubgraphView calling GetWorkingCopy() is already a working copy. This function " 424 "should be called on original SubgraphView obtained from OptimizeSubgraphView()");
430 std::unordered_map<const IConnectableLayer*, IConnectableLayer*> originalToClonedLayerMap;
433 auto ptr = std::make_shared<SubgraphViewWorkingCopy>(std::move(newGraph));
436 for (
auto&& originalLayer : originalSubgraphLayers)
438 Layer*
const layer = PolymorphicDowncast<const Layer*>(originalLayer)->Clone(ptr->m_Graph);
439 originalToClonedLayerMap.emplace(originalLayer, layer);
443 std::vector<const IConnectableLayer*> processed;
447 PolymorphicDowncast<InputSlot*>(originalSubgraphInputSlot)->GetOwningLayer();
450 if (std::find(processed.begin(), processed.end(), &originalSubgraphLayer) == processed.end())
452 IConnectableLayer* clonedLayer = originalToClonedLayerMap[&originalSubgraphLayer];
457 workingCopyInputs.push_back(&clonedLayer->
GetInputSlot(i));
459 processed.push_back(&originalSubgraphLayer);
465 for (
auto originalSubgraphLayer : originalSubgraphLayers)
467 IConnectableLayer*
const clonedLayer = originalToClonedLayerMap[originalSubgraphLayer];
476 for (
unsigned int k = 0; k < originalSubgraphLayer->GetNumOutputSlots(); k++)
478 auto& originalOutputSlot = originalSubgraphLayer->GetOutputSlot(k);
479 for (
unsigned int j = 0; j < originalOutputSlot.GetNumConnections(); j++)
483 originalOutputSlot.GetConnection(j)->GetOwningIConnectableLayer();
486 if (originalToClonedLayerMap.find(&nextLayer) != originalToClonedLayerMap.end())
492 PolymorphicDowncast<OutputSlot*>(
493 &originalOutputSlot)->GetConnection(j)->GetSlotIndex());
496 outputSlot.Connect(inputSlot);
500 outputSlot.SetTensorInfo(originalOutputSlot.GetTensorInfo());
512 const IConnectableLayer& originalSubgraphLayer = outputSlot->GetOwningIConnectableLayer();
517 std::find(processed.begin(), processed.end(), &originalSubgraphLayer) == processed.end())
519 IConnectableLayer* clonedLayer = originalToClonedLayerMap[&originalSubgraphLayer];
524 workingCopyOutputs.push_back(&clonedLayer->
GetOutputSlot(i));
526 processed.push_back(&originalSubgraphLayer);
532 for (
auto& pair : originalToClonedLayerMap)
534 workingCopyLayers.push_back(pair.second);
537 return {std::move(workingCopyLayers),
538 std::move(workingCopyInputs),
539 std::move(workingCopyOutputs),
553 if (!p_WorkingCopyImpl)
555 throw NullPointerException(
"The SubgraphView calling SubstituteSubgraphView is not a working copy. " 556 "Call this function on SubgraphView returned from SubgraphView::GetWorkingCopy()");
560 auto workingCopyGraph = &p_WorkingCopyImpl->m_Graph;
564 if (std::find(std::begin(workingCopyGraph->m_Layers),
565 std::end(workingCopyGraph->m_Layers),
566 iConnectableLayer) ==
567 std::end(workingCopyGraph->m_Layers))
569 auto layer = PolymorphicDowncast<Layer*>(iConnectableLayer);
571 layer->Reparent(*workingCopyGraph,
572 (workingCopyGraph->m_Layers).end());
574 workingCopyGraph->m_LayersInOrder = false;
579 workingCopyGraph->ReplaceSubgraphConnections(patternSubgraph, substituteSubgraph);
582 m_IInputSlots = std::move(substituteSubgraph.m_IInputSlots);
583 m_IOutputSlots = std::move(substituteSubgraph.m_IOutputSlots);
586 workingCopyGraph->EraseSubgraphLayers(patternSubgraph);
589 workingCopyGraph->TopologicalSort();
593 workingCopyGraph->m_Layers.end() };
IConnectableLayers::iterator IConnectableLayerIterator
IConnectableLayerIterator endIConnectable()
virtual unsigned int GetNumOutputSlots() const =0
Returns the number of connectable output slots.
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Layers::iterator Iterator
const IOutputSlots & GetIOutputSlots() const
virtual unsigned int GetNumInputSlots() const =0
Returns the number of connectable input slots.
const IConnectableLayers & GetIConnectableLayers() const
const IInputSlots & GetIInputSlots() const
#define ARMNN_NO_DEPRECATE_WARN_BEGIN
SubgraphView & operator=(SubgraphView &&other)
Move-assignment operator.
std::vector< OutputSlot * > OutputSlots
unsigned int GetNumInputSlots() const
IConnectableLayerIterator beginIConnectable()
Copyright (c) 2021 ARM Limited and Contributors.
void IgnoreUnused(Ts &&...)
ConstIConnectableIterator cendIConnectable() const
void SubstituteSubgraph(SubgraphView &, IConnectableLayer *)
These methods should be called on a working copy subgraph created from GetWorkingCopy.
const IOutputSlot * GetIOutputSlot(unsigned int index) const
The SubgraphView class represents a subgraph of a Graph.
OutputSlots Layers && layers
std::list< IConnectableLayer * > IConnectableLayers
#define ARMNN_NO_DEPRECATE_WARN_END
#define ARMNN_ASSERT_MSG(COND, MSG)
An output connection slot for a layer.
std::vector< IOutputSlot * > IOutputSlots
void ForEachIConnectableLayer(Func func) const
std::vector< IInputSlot * > IInputSlots
#define ARMNN_ASSERT(COND)
virtual LayerType GetType() const =0
Returns the armnn::LayerType of this layer.
std::vector< InputSlot * > InputSlots
SubgraphView(Graph &graph)
Constructs a sub-graph from the entire given graph.
IConnectableLayers::const_iterator ConstIConnectableIterator
Base class for all ArmNN exceptions so that users can filter to just those.
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
std::enable_if_t< std::is_unsigned< Source >::value &&std::is_unsigned< Dest >::value, Dest > numeric_cast(Source source)
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
std::list< Layer * > Layers
SubgraphView GetWorkingCopy()
This method returns a copy of the original SubgraphView provided by OptimizeSubgraphView with a separ...
Layers::const_iterator ConstIterator
const IInputSlot * GetIInputSlot(unsigned int index) const
unsigned int GetNumOutputSlots() const
ConstIConnectableIterator cbeginIConnectable() const