Skip to content

Commit 6b5603b

Browse files
authored
[Transformations] Transformations utils: added extract_subgraph helper (openvinotoolkit#35426)
### Details: Adds a new transformations utility helper to extract a bounded subgraph from an existing `ov::Model` into an independent `ov::Model`, primarily to support debugging/isolated repro workflows. ### Tickets: - *N\A* ### AI Assistance: - *AI assistance used: yes* - *AI was used to create a feature based on the PoC branch. The tests are also written by the LLM* ### Prerequisites: - openvinotoolkit#35363
1 parent 836a3e1 commit 6b5603b

7 files changed

Lines changed: 446 additions & 0 deletions

File tree

src/common/transformations/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ file(GLOB_RECURSE PUBLIC_HEADERS ${PUBLIC_HEADERS_DIR}/*.hpp)
1515
source_group("src" FILES ${LIBRARY_SRC})
1616
source_group("include" FILES ${PUBLIC_HEADERS})
1717

18+
# Debug capabilities sources - only compiled when ENABLE_DEBUG_CAPS is ON
19+
if(NOT ENABLE_DEBUG_CAPS)
20+
list(REMOVE_ITEM LIBRARY_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/transformations/utils/extract_subgraph.cpp")
21+
list(REMOVE_ITEM PUBLIC_HEADERS "${PUBLIC_HEADERS_DIR}/transformations/utils/extract_subgraph.hpp")
22+
endif()
23+
1824
# Create library
1925
add_library(${TARGET_NAME}_obj OBJECT ${LIBRARY_SRC} ${PUBLIC_HEADERS})
2026
target_compile_definitions(${TARGET_NAME}_obj PRIVATE IMPLEMENT_OPENVINO_API)

src/common/transformations/docs/debug_capabilities/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ They can be activated at runtime and are useful for analyzing transformation beh
2020
When to use: need to inspect model IR (.xml/.bin) after specific passes — useful for diffing model state before and after a transformation.
2121
Example: `OV_ENABLE_SERIALIZE_TRACING=true` or `OV_ENABLE_SERIALIZE_TRACING="Pass1,Pass2"`
2222

23+
* [Subgraph extraction](extract_subgraph.md)
24+
When to use: working with a large model where full compilation or inference is slow, or where the serialized IR is too large to read or render in graph visualization tools — extract only the relevant subgraph as a standalone `ov::Model`, serialize to IR, and continue investigation on the smaller model independently.
25+
Example: `extract_subgraph(model, {{"MatMul_0", 0}}, {{"Softmax_0", 0}})`
26+
2327
## See also
2428

2529
* [debug-matcher-pass skill](../../../../.claude/skills/debug-matcher-pass/SKILL.md) — automated diagnosis workflow for MatcherPass transformations that are not firing. Collects matcher logs, identifies root cause, and generates a reproducer test.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Subgraph extraction
2+
3+
Extracts a subgraph from an `ov::Model` as a standalone `ov::Model`, without modifying the original model.
4+
5+
Useful for inspecting, serializing, or testing a specific portion of a larger model during development or debugging. This is especially valuable when working with large models where full compilation or inference takes a significant amount of time, or where the serialized IR is too large to read or render in graph visualization tools — extracting only the relevant subgraph lets you iterate on it in isolation instead of processing the entire model on each run.
6+
7+
Once extracted, the subgraph can be serialized to IR via `ov::pass::Serialize` and reloaded independently, so subsequent investigation or reproduction work can be done on the smaller model without access to the original.
8+
9+
## Example
10+
11+
```cpp
12+
#include "transformations/utils/extract_subgraph.hpp"
13+
14+
// Extract the subgraph between two named nodes
15+
const std::multimap<std::string, size_t> inputs = {{"MatMul_0", 0}};
16+
const std::multimap<std::string, size_t> outputs = {{"Softmax_0", 0}};
17+
18+
auto subgraph = ov::op::util::extract_subgraph(model, inputs, outputs);
19+
20+
// The original model is unchanged; subgraph is an independent ov::Model.
21+
// Serialize it to IR so further investigation can be done on the isolated subgraph
22+
// without rerunning the full model pipeline.
23+
ov::pass::Serialize("subgraph.xml", "subgraph.bin").run_on_model(subgraph);
24+
```
25+
26+
## Behavior
27+
28+
- The original model is **not modified**.
29+
- The extracted model is a deep clone — changes to it do not affect the source model.
30+
- Subgraph `Parameter` nodes inherit the element type and partial shape of their corresponding input ports.
31+
- Node order within the extracted model follows topological order.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (C) 2018-2026 Intel Corporation
2+
// SPDX-License-Identifier: Apache-2.0
3+
//
4+
5+
#pragma once
6+
7+
#include <map>
8+
#include <memory>
9+
#include <string>
10+
#include <vector>
11+
12+
#include "openvino/core/model.hpp"
13+
#include "openvino/core/node.hpp"
14+
#include "transformations_visibility.hpp"
15+
16+
namespace ov::util {
17+
18+
/**
19+
* @brief Extracts a subgraph bounded by the given input and output ports as a standalone model.
20+
* The original model is not modified; the extracted model is a deep clone.
21+
*
22+
* @param subgraph_inputs Input ports that form the subgraph boundary. Each port is replaced
23+
* by a new Parameter whose element type and partial shape match the port.
24+
* @param subgraph_outputs Output ports that define the subgraph results.
25+
* @return A new ov::Model representing the extracted subgraph.
26+
*/
27+
TRANSFORMATIONS_API std::shared_ptr<ov::Model> extract_subgraph(const std::vector<ov::Input<ov::Node>>& subgraph_inputs,
28+
const ov::OutputVector& subgraph_outputs);
29+
30+
/**
31+
* @brief Extracts a subgraph by resolving boundary ports from node friendly names.
32+
*
33+
* Convenience wrapper over the port-based overload. Each multimap entry maps a node
34+
* friendly name to a port index; multiple entries with the same name select different
35+
* ports of the same node. Throws ov::Exception if any name is not found in the model.
36+
*
37+
* @param model Source model.
38+
* @param subgraph_inputs Map of { friendly_name -> input_port_index } for boundary inputs.
39+
* @param subgraph_outputs Map of { friendly_name -> output_port_index } for boundary outputs.
40+
* @return A new ov::Model representing the extracted subgraph.
41+
*/
42+
TRANSFORMATIONS_API std::shared_ptr<ov::Model> extract_subgraph(
43+
const std::shared_ptr<ov::Model>& model,
44+
const std::multimap<std::string, size_t>& subgraph_inputs,
45+
const std::multimap<std::string, size_t>& subgraph_outputs);
46+
47+
} // namespace ov::util

src/common/transformations/tests/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,16 @@ if(CMAKE_COMPILER_IS_GNUCXX OR OV_COMPILER_IS_CLANG)
88
ov_add_compiler_flags(-Wno-missing-declarations)
99
endif()
1010

11+
set(EXCLUDED_PATHS "")
12+
if(NOT ENABLE_DEBUG_CAPS)
13+
list(APPEND EXCLUDED_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/utils/extract_subgraph_test")
14+
endif()
15+
1116
ov_add_test_target(
1217
NAME ${TARGET_NAME}
1318
ROOT ${CMAKE_CURRENT_SOURCE_DIR}
19+
EXCLUDED_SOURCE_PATHS
20+
${EXCLUDED_PATHS}
1421
DEPENDENCIES
1522
LINK_LIBRARIES
1623
gmock

0 commit comments

Comments
 (0)