| 504 | } |
| 505 | |
| 506 | void Graph::ReplaceSubgraphConnections(const SubgraphView& subgraph, const SubgraphView& substituteSubgraph) |
| 507 | { |
| 508 | if (substituteSubgraph.GetIConnectableLayers().empty()) |
| 509 | { |
| 510 | throw armnn::Exception("New sub-graph used for substitution must not be empty"); |
| 511 | } |
| 512 | |
| 513 | const SubgraphView::IConnectableLayers& substituteSubgraphLayers = substituteSubgraph.GetIConnectableLayers(); |
| 514 | std::for_each(substituteSubgraphLayers.begin(), substituteSubgraphLayers.end(), [&](IConnectableLayer* layer) |
| 515 | { |
| 516 | layer = PolymorphicDowncast<Layer*>(layer); |
| 517 | if (std::find(m_Layers.begin(), m_Layers.end(), layer) == m_Layers.end()) |
| 518 | { |
| 519 | throw armnn::Exception("Substitute layer is not a member of graph"); |
| 520 | } |
| 521 | }); |
| 522 | |
| 523 | const SubgraphView::IInputSlots& subgraphInputSlots = subgraph.GetIInputSlots(); |
| 524 | const SubgraphView::IOutputSlots& subgraphOutputSlots = subgraph.GetIOutputSlots(); |
| 525 | |
| 526 | unsigned int subgraphNumInputSlots = armnn::numeric_cast<unsigned int>(subgraphInputSlots.size()); |
| 527 | unsigned int subgraphNumOutputSlots = armnn::numeric_cast<unsigned int>(subgraphOutputSlots.size()); |
| 528 | |
| 529 | const SubgraphView::IInputSlots& substituteSubgraphInputSlots = substituteSubgraph.GetIInputSlots(); |
| 530 | const SubgraphView::IOutputSlots& substituteSubgraphOutputSlots = substituteSubgraph.GetIOutputSlots(); |
| 531 | |
| 532 | if (subgraphNumInputSlots != substituteSubgraphInputSlots.size()) |
| 533 | { |
| 534 | throw armnn::Exception("subgraph and substitute subgraph input slot sizes must be the same."); |
| 535 | } |
| 536 | |
| 537 | if (subgraphNumOutputSlots != substituteSubgraphOutputSlots.size()) |
| 538 | { |
| 539 | throw armnn::Exception("subgraph and substitute subgraph output slot sizes must be the same."); |
| 540 | } |
| 541 | |
| 542 | // Disconnect the sub-graph and replace it with the substitute sub-graph |
| 543 | |
| 544 | // Step 1: process input slots |
| 545 | for (unsigned int inputSlotIdx = 0; inputSlotIdx < subgraphNumInputSlots; ++inputSlotIdx) |
| 546 | { |
| 547 | IInputSlot* subgraphInputSlot = subgraphInputSlots.at(inputSlotIdx); |
| 548 | if (!subgraphInputSlot) |
| 549 | { |
| 550 | throw armnn::NullPointerException("subgraphInputSlot must not be null."); |
| 551 | } |
| 552 | |
| 553 | // Only disconnect if the InputSlot has a connection, this might not be the case when |
| 554 | // dealing with working copies of SubgraphViews |
| 555 | // Note: we don't need this check for OutputSlot as it iterates over a vector of valid connections |
| 556 | if (subgraphInputSlot->GetConnection()) |
| 557 | { |
| 558 | IOutputSlot* connectedOutputSlot = subgraphInputSlot->GetConnection(); |
| 559 | InputSlot* inputSlot = PolymorphicDowncast<InputSlot*>(subgraphInputSlot); |
| 560 | bool isOverridden = inputSlot->IsTensorInfoOverridden(); |
| 561 | |
| 562 | if (!connectedOutputSlot) |
| 563 | { |
no test coverage detected