Skip to content

Add API to get ep graph partitioning info - #26781

Merged
adrianlizarraga merged 13 commits into
mainfrom
adrianl/SessionQueryPartitionInfo_Revival
Jan 16, 2026
Merged

Add API to get ep graph partitioning info#26781
adrianlizarraga merged 13 commits into
mainfrom
adrianl/SessionQueryPartitionInfo_Revival

Conversation

@adrianlizarraga

@adrianlizarraga adrianlizarraga commented Dec 12, 2025

Copy link
Copy Markdown
Contributor

Description

  • Adds API functions to get information about the subgraphs/nodes assigned to the EPs in the session.
    • Session_GetEpGraphAssignmentInfo: Returns a list of "subgraphs", each with information about the assigned EP and nodes.
      • Note: App must enable session configuration "session.record_ep_graph_assignment_info" to signal ORT to collect this information. If not enabled, API returns empty results.
    • EpAssignedSubgraph_GetEpName: Returns the name of the EP to which the subgraph is assigned
    • EpAssignedSubgraph_GetNodes: Returns a list of assigned nodes
    • EpAssignedNode_GetName: Returns the assigned node's name
    • EpAssignedNode_GetDomain: Returns the assigned node's domain
    • EpAssignedNode_GetOperatorType: Returns the assigned node's operator type
  • Also adds C++ and Python bindings

Structure of returned information

The API returns a list of "subgraphs". Each subgraph has the following information:

  • Subgraph info:
    • EP name: The name of the execution provider to which this subgraph is assigned.
    • nodes: Name and operator type of each node. Ex: [{"multiply", "Mul"}, ...]

Python example program (taken from unit tests):

    def test_get_graph_provider_assignment_info(self):
        """
        Tests querying for information about the nodes assigned to the CPU EP.
        """

        # Create session options that enables recording EP graph partitioning info.
        session_options = onnxrt.SessionOptions()
        session_options.add_session_config_entry("session.record_ep_graph_assignment_info", "1")

        session = onnxrt.InferenceSession(get_name("add_mul_add.onnx"), sess_options=session_options)

        # Query session for information on each subgraph assigned to an EP.
        ep_subgraphs = session.get_provider_graph_assignment_info()

        # Check that all 3 nodes are assigned to CPU EP (each in its own subgraph)
        self.assertEqual(len(ep_subgraphs), 3)
        for ep_subgraph in ep_subgraphs:
            self.assertEqual(ep_subgraph.ep_name, "CPUExecutionProvider")
            self.assertEqual(len(ep_subgraph.get_nodes()), 1)

        # Serialize each node to an identifier (concatenates operator type and node name)
        node_ids: list[str] = [f"{n.op_type}/{n.name}" for s in ep_subgraphs for n in s.get_nodes()]

        # Should have 1 Mul and 2 Adds.
        self.assertEqual(len(node_ids), 3)
        self.assertIn("Add/add_0", node_ids)
        self.assertIn("Add/add_1", node_ids)
        self.assertIn("Mul/mul_0", node_ids)

C++ program (taken from unit test):

  // Check the ep graph partitioning (Mul on plugin EP, others on CPU EP).
  // Model has 3 subgraphs (in no particular order):
  // - Subgraph 1: Add assigned to CPU EP.
  // - Subgraph 2: Mul assigned to plugin EP.
  // - Subgraph 3: Add assigned to CPU EP.
  std::vector<Ort::ConstEpAssignedSubgraph> ep_subgraphs = session.GetEpGraphAssignmentInfo();
  ASSERT_EQ(ep_subgraphs.size(), 3);

  for (Ort::ConstEpAssignedSubgraph ep_subgraph : ep_subgraphs) {
    std::string ep_name = ep_subgraph.EpName();
    ASSERT_TRUE(ep_name == Utils::example_ep_info.ep_name || ep_name == kCpuExecutionProvider);

    const std::vector<Ort::ConstEpAssignedNode> ep_nodes = ep_subgraph.GetNodes();
    ASSERT_GE(ep_nodes.size(), 1);  // All of these subgraphs just have one node.

    if (ep_name == kCpuExecutionProvider) {
      std::string op_type = ep_nodes[0].OpType();
      std::string node_name = ep_nodes[0].Name();

      ASSERT_EQ(op_type, "Add");
      ASSERT_TRUE(node_name == "add_0" || node_name == "add_1");
    } else {
      ASSERT_TRUE(ep_name == Utils::example_ep_info.ep_name);

      std::string op_type = ep_nodes[0].OpType();
      std::string node_name = ep_nodes[0].Name();
      ASSERT_EQ(op_type, "Mul");
      ASSERT_EQ(node_name, "mul_0");
    }
  }

Motivation and Context

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new API to retrieve information about how the graph is partitioned across execution providers (EPs). The feature allows applications to query which nodes are assigned to which EPs after session creation.

Key changes:

  • Adds C API functions (Session_GetEpGraphPartitioningInfo and related accessors) to query EP graph partitioning information
  • Implements C++ and Python bindings for the new API
  • Introduces OrtEpAssignedSubgraph and OrtEpAssignedNode structures to represent partitioning data

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
include/onnxruntime/core/session/onnxruntime_c_api.h Declares new C API functions for retrieving EP partitioning info and accessing subgraph/node details
include/onnxruntime/core/session/onnxruntime_cxx_api.h Adds C++ wrapper classes ConstEpAssignedSubgraph and ConstEpAssignedNode with GetEpGraphPartitioningInfo() method
include/onnxruntime/core/session/onnxruntime_cxx_inline.h Implements inline methods for the C++ wrapper classes
include/onnxruntime/core/session/onnxruntime_session_options_config_keys.h Adds config key to enable recording of EP graph partitioning information
onnxruntime/core/session/ort_apis.h Declares implementation functions for the new C API
onnxruntime/core/session/onnxruntime_c_api.cc Implements the C API functions with proper null checks and ORT_MINIMAL_BUILD guards
onnxruntime/core/session/ep_graph_partition_info.h Defines data structures (OrtEpAssignedNode, OrtEpAssignedSubgraph) for storing partitioning information
onnxruntime/core/session/inference_session.h Adds member variables to store graph partitioning info and getter method
onnxruntime/core/session/inference_session.cc Implements RecordPartitionInfo() function and integrates it into the graph transformation pipeline
onnxruntime/core/framework/graph_partitioner.h Adds OnPartitionAssignmentFunction callback type and constructor parameter
onnxruntime/core/framework/graph_partitioner.cc Invokes the callback when a subgraph is assigned to an EP
onnxruntime/python/onnxruntime_pybind_state.cc Exposes Python bindings for OrtEpAssignedNode and OrtEpAssignedSubgraph classes
onnxruntime/python/onnxruntime_inference_collection.py Adds get_provider_graph_partitioning_info() method to InferenceSession Python API
onnxruntime/__init__.py Exports the new Python classes
onnxruntime/test/python/onnxruntime_test_python.py Adds Python unit test validating the new API with CPU EP
onnxruntime/test/autoep/test_execution.cc Adds C++ unit test validating the API with both plugin EP and CPU EP

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread onnxruntime/test/python/onnxruntime_test_python.py Outdated
Comment thread onnxruntime/test/python/onnxruntime_test_python.py Outdated
Comment thread onnxruntime/core/framework/graph_partitioner.h Outdated
Comment thread onnxruntime/python/onnxruntime_inference_collection.py Outdated
Comment thread onnxruntime/test/python/onnxruntime_test_python.py Outdated
adrianlizarraga and others added 2 commits January 5, 2026 04:03
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@adrianlizarraga
adrianlizarraga marked this pull request as ready for review January 13, 2026 17:54
Comment thread onnxruntime/core/session/inference_session.cc Outdated
Comment thread onnxruntime/core/session/inference_session.cc Outdated
Comment thread onnxruntime/core/session/onnxruntime_c_api.cc Outdated
Comment thread include/onnxruntime/core/session/onnxruntime_c_api.h Outdated
Comment thread include/onnxruntime/core/session/onnxruntime_c_api.h Outdated
Comment thread onnxruntime/test/autoep/test_execution.cc Outdated
Comment thread onnxruntime/test/autoep/test_execution.cc
Comment thread include/onnxruntime/core/session/onnxruntime_cxx_api.h Outdated
Comment thread include/onnxruntime/core/session/onnxruntime_c_api.h Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 35 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread onnxruntime/test/autoep/test_execution.cc
Comment thread onnxruntime/python/onnxruntime_inference_collection.py
Comment thread include/onnxruntime/core/session/onnxruntime_cxx_inline.h
Comment thread include/onnxruntime/core/session/onnxruntime_cxx_api.h
Comment thread onnxruntime/core/session/inference_session.h Outdated
Comment thread onnxruntime/test/autoep/test_execution.cc
Comment thread include/onnxruntime/core/session/onnxruntime_cxx_inline.h
Comment thread onnxruntime/core/session/onnxruntime_c_api.cc Outdated
Comment thread include/onnxruntime/core/session/onnxruntime_c_api.h Outdated
Comment thread include/onnxruntime/core/session/onnxruntime_cxx_inline.h Outdated
Comment thread onnxruntime/core/framework/graph_partitioner.cc
Comment thread onnxruntime/test/shared_lib/test_inference.cc
@adrianlizarraga
adrianlizarraga merged commit d8f0318 into main Jan 16, 2026
98 of 103 checks passed
@adrianlizarraga
adrianlizarraga deleted the adrianl/SessionQueryPartitionInfo_Revival branch January 16, 2026 05:11
alex-spacemit pushed a commit to spacemit-com/onnxruntime that referenced this pull request Jan 20, 2026
### Description
- Adds API functions to get information about the subgraphs/nodes
assigned to the EPs in the session.
- `Session_GetEpGraphAssignmentInfo`: Returns a list of "subgraphs",
each with information about the assigned EP and nodes.
- Note: App must enable session configuration
`"session.record_ep_graph_assignment_info"` to signal ORT to collect
this information. If not enabled, API returns empty results.
- `EpAssignedSubgraph_GetEpName`: Returns the name of the EP to which
the subgraph is assigned
  - `EpAssignedSubgraph_GetNodes`: Returns a list of assigned nodes
  - `EpAssignedNode_GetName`: Returns the assigned node's name
  - `EpAssignedNode_GetDomain`: Returns the assigned node's domain
- `EpAssignedNode_GetOperatorType`: Returns the assigned node's operator
type
- Also adds C++ and Python bindings

#### Structure of returned information
The API returns a list of "subgraphs". Each subgraph has the following
information:
- Subgraph info:
- EP name: The name of the execution provider to which this subgraph is
assigned.
- nodes: Name and operator type of each node. Ex: `[{"multiply", "Mul"},
...]`

Python example program (taken from unit tests):
```python
    def test_get_graph_provider_assignment_info(self):
        """
        Tests querying for information about the nodes assigned to the CPU EP.
        """

        # Create session options that enables recording EP graph partitioning info.
        session_options = onnxrt.SessionOptions()
        session_options.add_session_config_entry("session.record_ep_graph_assignment_info", "1")

        session = onnxrt.InferenceSession(get_name("add_mul_add.onnx"), sess_options=session_options)

        # Query session for information on each subgraph assigned to an EP.
        ep_subgraphs = session.get_provider_graph_assignment_info()

        # Check that all 3 nodes are assigned to CPU EP (each in its own subgraph)
        self.assertEqual(len(ep_subgraphs), 3)
        for ep_subgraph in ep_subgraphs:
            self.assertEqual(ep_subgraph.ep_name, "CPUExecutionProvider")
            self.assertEqual(len(ep_subgraph.get_nodes()), 1)

        # Serialize each node to an identifier (concatenates operator type and node name)
        node_ids: list[str] = [f"{n.op_type}/{n.name}" for s in ep_subgraphs for n in s.get_nodes()]

        # Should have 1 Mul and 2 Adds.
        self.assertEqual(len(node_ids), 3)
        self.assertIn("Add/add_0", node_ids)
        self.assertIn("Add/add_1", node_ids)
        self.assertIn("Mul/mul_0", node_ids)
```

C++ program (taken from unit test):
```c++
  // Check the ep graph partitioning (Mul on plugin EP, others on CPU EP).
  // Model has 3 subgraphs (in no particular order):
  // - Subgraph 1: Add assigned to CPU EP.
  // - Subgraph 2: Mul assigned to plugin EP.
  // - Subgraph 3: Add assigned to CPU EP.
  std::vector<Ort::ConstEpAssignedSubgraph> ep_subgraphs = session.GetEpGraphAssignmentInfo();
  ASSERT_EQ(ep_subgraphs.size(), 3);

  for (Ort::ConstEpAssignedSubgraph ep_subgraph : ep_subgraphs) {
    std::string ep_name = ep_subgraph.EpName();
    ASSERT_TRUE(ep_name == Utils::example_ep_info.ep_name || ep_name == kCpuExecutionProvider);

    const std::vector<Ort::ConstEpAssignedNode> ep_nodes = ep_subgraph.GetNodes();
    ASSERT_GE(ep_nodes.size(), 1);  // All of these subgraphs just have one node.

    if (ep_name == kCpuExecutionProvider) {
      std::string op_type = ep_nodes[0].OpType();
      std::string node_name = ep_nodes[0].Name();

      ASSERT_EQ(op_type, "Add");
      ASSERT_TRUE(node_name == "add_0" || node_name == "add_1");
    } else {
      ASSERT_TRUE(ep_name == Utils::example_ep_info.ep_name);

      std::string op_type = ep_nodes[0].OpType();
      std::string node_name = ep_nodes[0].Name();
      ASSERT_EQ(op_type, "Mul");
      ASSERT_EQ(node_name, "mul_0");
    }
  }
```

### Motivation and Context
<!-- - Why is this change required? What problem does it solve?
- If it fixes an open issue, please link to the issue here. -->

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
tianleiwu pushed a commit that referenced this pull request Jan 21, 2026
### Description
- Adds API functions to get information about the subgraphs/nodes
assigned to the EPs in the session.
- `Session_GetEpGraphAssignmentInfo`: Returns a list of "subgraphs",
each with information about the assigned EP and nodes.
- Note: App must enable session configuration
`"session.record_ep_graph_assignment_info"` to signal ORT to collect
this information. If not enabled, API returns empty results.
- `EpAssignedSubgraph_GetEpName`: Returns the name of the EP to which
the subgraph is assigned
  - `EpAssignedSubgraph_GetNodes`: Returns a list of assigned nodes
  - `EpAssignedNode_GetName`: Returns the assigned node's name
  - `EpAssignedNode_GetDomain`: Returns the assigned node's domain
- `EpAssignedNode_GetOperatorType`: Returns the assigned node's operator
type
- Also adds C++ and Python bindings

#### Structure of returned information
The API returns a list of "subgraphs". Each subgraph has the following
information:
- Subgraph info:
- EP name: The name of the execution provider to which this subgraph is
assigned.
- nodes: Name and operator type of each node. Ex: `[{"multiply", "Mul"},
...]`

Python example program (taken from unit tests):
```python
    def test_get_graph_provider_assignment_info(self):
        """
        Tests querying for information about the nodes assigned to the CPU EP.
        """

        # Create session options that enables recording EP graph partitioning info.
        session_options = onnxrt.SessionOptions()
        session_options.add_session_config_entry("session.record_ep_graph_assignment_info", "1")

        session = onnxrt.InferenceSession(get_name("add_mul_add.onnx"), sess_options=session_options)

        # Query session for information on each subgraph assigned to an EP.
        ep_subgraphs = session.get_provider_graph_assignment_info()

        # Check that all 3 nodes are assigned to CPU EP (each in its own subgraph)
        self.assertEqual(len(ep_subgraphs), 3)
        for ep_subgraph in ep_subgraphs:
            self.assertEqual(ep_subgraph.ep_name, "CPUExecutionProvider")
            self.assertEqual(len(ep_subgraph.get_nodes()), 1)

        # Serialize each node to an identifier (concatenates operator type and node name)
        node_ids: list[str] = [f"{n.op_type}/{n.name}" for s in ep_subgraphs for n in s.get_nodes()]

        # Should have 1 Mul and 2 Adds.
        self.assertEqual(len(node_ids), 3)
        self.assertIn("Add/add_0", node_ids)
        self.assertIn("Add/add_1", node_ids)
        self.assertIn("Mul/mul_0", node_ids)
```

C++ program (taken from unit test):
```c++
  // Check the ep graph partitioning (Mul on plugin EP, others on CPU EP).
  // Model has 3 subgraphs (in no particular order):
  // - Subgraph 1: Add assigned to CPU EP.
  // - Subgraph 2: Mul assigned to plugin EP.
  // - Subgraph 3: Add assigned to CPU EP.
  std::vector<Ort::ConstEpAssignedSubgraph> ep_subgraphs = session.GetEpGraphAssignmentInfo();
  ASSERT_EQ(ep_subgraphs.size(), 3);

  for (Ort::ConstEpAssignedSubgraph ep_subgraph : ep_subgraphs) {
    std::string ep_name = ep_subgraph.EpName();
    ASSERT_TRUE(ep_name == Utils::example_ep_info.ep_name || ep_name == kCpuExecutionProvider);

    const std::vector<Ort::ConstEpAssignedNode> ep_nodes = ep_subgraph.GetNodes();
    ASSERT_GE(ep_nodes.size(), 1);  // All of these subgraphs just have one node.

    if (ep_name == kCpuExecutionProvider) {
      std::string op_type = ep_nodes[0].OpType();
      std::string node_name = ep_nodes[0].Name();

      ASSERT_EQ(op_type, "Add");
      ASSERT_TRUE(node_name == "add_0" || node_name == "add_1");
    } else {
      ASSERT_TRUE(ep_name == Utils::example_ep_info.ep_name);

      std::string op_type = ep_nodes[0].OpType();
      std::string node_name = ep_nodes[0].Name();
      ASSERT_EQ(op_type, "Mul");
      ASSERT_EQ(node_name, "mul_0");
    }
  }
```

### Motivation and Context
<!-- - Why is this change required? What problem does it solve?
- If it fixes an open issue, please link to the issue here. -->

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
(cherry picked from commit d8f0318)
tianleiwu added a commit that referenced this pull request Jan 23, 2026
### Description
This PR cherry-picks the following changes for the 1.24.0 release.

### Cherry-picked Commits
| Commit | Commit Title | Author |
|---|---|---|
| 744e7fe | Add type definitions, registration, utilities for
INT2/UINT2 support (#26824) | vraspar |
| 530a1fb | [QNN EP] Add BFloat16 dtype support in QNN EP (#26987) |
tirupath-qti |
| 8e050d1 | Implement new experimental lookup-based matrix
multiplication method(TMAC) (#26695) | vraspar |
| 2d2ba6b | [MLAS/CPU EP] Improve performance of Silu activation path
within the QuickGelu CPU kernel (#26753) | Hariharan Seshadri |
| 1c02b79 | [QNN EP] Add support for handling 0-dimension for Concat
Op (#27000) | Ashwath Shankarnarayan |
| cc2b01b | Fix ClipQuantFusion crash when Clip has multiple input
edges (#27016) | Edward Chen |
| bbd3850 | [QNN EP] Support quantized BatchNorm with per-channel DQ
params on QNN HTP (#26959) | qti-yuduo |
| d8f0318 | Add API to get ep graph partitioning info (#26781) |
Adrian Lizarraga |
| b912b18 | [OVEP] OpenVINO EP Features and bug-fixes for ORT-1.24 -
Follow up (#27007) | Preetha Veeramalai |
| ba11af4 | [QNN-EP] Add MatMulNBits translation for GPU (#26340) |
quic-tirupath |
| c03c419 | [MLAS/NEON] Add dedicated kernel for depthwise
convolution for ARM64 using NEON intrinsics (#26688) | Hariharan
Seshadri |
| e7dfd69 | [QNN-EP] Support alternate Layernorm fusion pattern in
QNN preprocess (#26060) | qti-mattsinc |
| 4013dc1 | Implement multithreading in qgemm_kleidi (#26301) |
Melike Kaptan |
| 9f06181 | [CXX] Enable users to specify custom OrtSyncStream via
RunOptions (#26988) | Dmitri Smirnov |
| cfccd64 | Added support for QMX kernels in MLAS (#26849) |
qti-vaiskv |
| 29d9b2f | Tweak external resource importer handle structs (#27040)
| Scott McKay |
| 9d108d0 | [QNN EP] Add QuickGELU operator support for QNN provider
(#27034) | tirupath-qti |
| b35688f | Add INT2 and UINT2 support for QDQ, transpose and cast
ops (#27022) | vraspar |
| 6d34aba | Introducing BF16 Pointwise NCHWc Convolution for Arm64
(#26838) | Rohanjames1997 |
| 36017ad | [EP ABI] Add CreateCustomOpDomains() API for plugin EP to
register custom ops (#27050) | Chi Lo |
| 50a03e4 | Add a new pipeline for CUDA 13 nuget builds (#27023) |
eserscor |
| a0d4439 | [EP ABI] Update Graph_GetGraphView() implementation
(#26711) | Chi Lo |
| 34bb209 | [webgpu] Fix a bug for im2col (#27069) | Wenqin Yang |
| 46e8d45 | [QNN EP] Add FusedMatMul operator support (#27044) |
tirupath-qti |
| 5e7e7a3 | Disable Float32_2Bits_Asymmetric_256x256 test (#27046) |
vraspar |
| 39f966e | Fix Doxygen documentation build error in
onnxruntime_c_api.h (#27083) | Nick Eubanks |
| 8a7a797 | Print tensor for new packed type of 2 bits (#27064) |
Tianlei Wu |
| 01f40e6 | Fix GPU JAR testing on Linux (#27011) | eserscor |
| b6ed7f3 | Fix warning around ununsed code in QNN Android Emulator
builds by clang (#27026) | Hariharan Seshadri |
| d7daa45 | Raise the timeout for the ios simulator job (#27045) |
Hariharan Seshadri |
| 7e1d818 | upgrade emsdk to 4.0.23 (#27029) | Yulong Wang |
| 347b990 | Fix failing mainline build on Arm64 linux (#27101) |
Rohanjames1997 |
| f481b17 | Add dedicated API to support extracting compatibility
string from model metadata (#27015) | adrastogi |

---------

Signed-off-by: Liqun Fu <liqun.fu@microsoft.com>
Signed-off-by: bfilipek <bartlomiej.filipek@intel.com>
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jonathan Clohessy <jonathan.clohessy@arm.com>
Signed-off-by: Christian Bourjau <christian.bourjau@quantco.com>
Signed-off-by: melkap01 <melike.kaptan@arm.com>
Co-authored-by: vraspar <vrajang@outlook.com>
Co-authored-by: tirupath-qti <tirupath@qti.qualcomm.com>
Co-authored-by: Ashwath Shankarnarayan <ashwshan@qti.qualcomm.com>
Co-authored-by: Liqun Fu <liqun.fu@microsoft.com>
Co-authored-by: carzh <wolfivyaura@gmail.com>
Co-authored-by: Hector Li <hecli@microsoft.com>
Co-authored-by: carzh <carolinezhu@microsoft.com>
Co-authored-by: Vrajang Parikh <vrparikh@microsoft.com>
Co-authored-by: Hariharan Seshadri <shariharan91@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Edward Chen <18449977+edgchen1@users.noreply.github.com>
Co-authored-by: Yuduo Wu <yuduow@qti.qualcomm.com>
Co-authored-by: Adrian Lizarraga <adlizarraga@microsoft.com>
Co-authored-by: Preetha Veeramalai <preetha.veeramalai@intel.com>
Co-authored-by: jatinwadhwa921 <110383850+jatinwadhwa921@users.noreply.github.com>
Co-authored-by: jatinwadhwa921 <jatin.wadhwa@intel.com>
Co-authored-by: saurabh <saurabh1.kale@intel.com>
Co-authored-by: Ankit Maheshkar <ankit.maheshkar@intel.com>
Co-authored-by: sfatimar <sahar.fatima@intel.com>
Co-authored-by: Javier Martinez <javier.e.martinez@intel.com>
Co-authored-by: Bartlomiej Filipek <bartlomiej.filipek@intel.com>
Co-authored-by: bopeng1234 <bo.peng@intel.com>
Co-authored-by: Eric Crawford <eric.r.crawford@intel.com>
Co-authored-by: MayureshV1 <47039074+MayureshV1@users.noreply.github.com>
Co-authored-by: TejalKhade28 <tejal.khade@intel.com>
Co-authored-by: Vishnudas Thaniel S <vishnudas.thaniel.s@intel.com>
Co-authored-by: Yaru Du <yaru.du@intel.com>
Co-authored-by: Ryan Metcalfe <107415876+RyanMetcalfeInt8@users.noreply.github.com>
Co-authored-by: Dvoretckii, Mikhail <mikhail.dvoretckii@intel.com>
Co-authored-by: Pallavi Gupta <pallavi.gupta@intel.com>
Co-authored-by: Jianhui Dai <jianhui.j.dai@intel.com>
Co-authored-by: Jiajia Qin <jiajiaqin@microsoft.com>
Co-authored-by: Changming Sun <chasun@microsoft.com>
Co-authored-by: Fei Chen <feich@microsoft.com>
Co-authored-by: Yulong Wang <7679871+fs-eire@users.noreply.github.com>
Co-authored-by: Akupadhye <aupadhye@qti.qualcomm.com>
Co-authored-by: Wang Ning <ning4.wang@intel.com>
Co-authored-by: Maximilian Müller <44298237+gedoensmax@users.noreply.github.com>
Co-authored-by: Chi Lo <54722500+chilo-ms@users.noreply.github.com>
Co-authored-by: George Wu <jywu@microsoft.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Wanming Lin <wanming.lin@intel.com>
Co-authored-by: quic-calvnguy <quic_calvnguy@quicinc.com>
Co-authored-by: Jie Chen <jie.a.chen@intel.com>
Co-authored-by: xhcao <xinghua.cao@intel.com>
Co-authored-by: Wei-Sheng Chin <wschin@outlook.com>
Co-authored-by: quic-hungjuiw <quic_hungjuiw@quicinc.com>
Co-authored-by: Ian Hunter <ianfhunter@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com>
Co-authored-by: Jeff Kilpatrick <jkilpatrick@qti.qualcomm.com>
Co-authored-by: Jeff Kilpatrick <jkilpat@qti.qualcomm.com>
Co-authored-by: Scott McKay <skottmckay@gmail.com>
Co-authored-by: Nenad Banfic <46795300+nenad1002@users.noreply.github.com>
Co-authored-by: derdeljan-msft <derdeljan@microsoft.com>
Co-authored-by: n1harika <niharika.sathish@intel.com>
Co-authored-by: Ryan Metcalfe <ryan.metcalfe@intel.com>
Co-authored-by: Jaswanth Gannamaneni <jaswanth.gannamaneni@intel.com>
Co-authored-by: Klimenko, Mikhail <mikhail.klimenko@intel.com>
Co-authored-by: liang <gxgaoliang@126.com>
Co-authored-by: Garth Long <garth.long@intel.com>
Co-authored-by: Jonathan Clohessy <jonathan.clohessy@arm.com>
Co-authored-by: Akshay Sonawane <111780983+apsonawane@users.noreply.github.com>
Co-authored-by: Christopher Warrington <chwarr@microsoft.com>
Co-authored-by: Ishwar Raut <iraut@nvidia.com>
Co-authored-by: Gaurav Garg <gaugarg@nvidia.com>
Co-authored-by: Xinpeng Dou <15529241576@163.com>
Co-authored-by: adrastogi <aditya.rastogi@microsoft.com>
Co-authored-by: Aditya Rastogi <adityar@ntdev.microsoft.com>
Co-authored-by: qti-hungjuiw <hungjuiw@qti.qualcomm.com>
Co-authored-by: Pradeep Sakhamoori <psakhamoori@microsoft.com>
Co-authored-by: Adam Pocock <adam.pocock@oracle.com>
Co-authored-by: mingyue <131847423+mingyueliuh@users.noreply.github.com>
Co-authored-by: Susanta Bhattacharjee <susanta.bhattacharjee@intel.com>
Co-authored-by: Jozef Wludzik <jozef.wludzik@intel.com>
Co-authored-by: Rajeev Sekar <rajeevsekar21@gmail.com>
Co-authored-by: Mayuresh M Varerkar <mayuresh.m.varerkar@intel.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Wenqin Yang <wenqin.yang@intel.com>
Co-authored-by: xieofxie <xieofxie@126.com>
Co-authored-by: hualxie <hualxie@microsoft.com>
Co-authored-by: Joshua Lochner <admin@xenova.com>
Co-authored-by: Christian Bourjau <cbourjau@users.noreply.github.com>
Co-authored-by: Xiaofei Han <xiaofeihan@microsoft.com>
Co-authored-by: Dmitri Smirnov <yuslepukhin@users.noreply.github.com>
Co-authored-by: chunghow-qti <chunghow@qti.qualcomm.com>
Co-authored-by: Guenther Schmuelling <guschmue@microsoft.com>
Co-authored-by: Jiawei Shao <jiawei.shao@intel.com>
Co-authored-by: czekun <chen.zekun@intel.com>
Co-authored-by: Jaskaran Singh Nagi <jaskaran.singh.nagi@intel.com>
Co-authored-by: quic-tirupath <quic_tirupath@quicinc.com>
Co-authored-by: qti-mattsinc <mattsinc@qti.qualcomm.com>
Co-authored-by: Melike Kaptan <melike.kaptan@arm.com>
Co-authored-by: Damien Dooley <damien.dooley@arm.com>
Co-authored-by: qti-vaiskv <vaiskv@qti.qualcomm.com>
Co-authored-by: Rohanjames1997 <rohan.james4@gmail.com>
Co-authored-by: eserscor <erscor@microsoft.com>
Co-authored-by: eserscor <247253654+eserscor@users.noreply.github.com>
Co-authored-by: Nick Eubanks <nieubank@microsoft.com>
Co-authored-by: adrastogi <8368026+adrastogi@users.noreply.github.com>
Co-authored-by: Rohanjames1997 <rohanjms@amazon.com>
@tianleiwu tianleiwu added cherry-picked Cherry-picked for a cherrypicks branch and removed release:1.24.0 labels Jan 23, 2026
alex-spacemit pushed a commit to spacemit-com/onnxruntime that referenced this pull request Jan 27, 2026
- Adds API functions to get information about the subgraphs/nodes
assigned to the EPs in the session.
- `Session_GetEpGraphAssignmentInfo`: Returns a list of "subgraphs",
each with information about the assigned EP and nodes.
- Note: App must enable session configuration
`"session.record_ep_graph_assignment_info"` to signal ORT to collect
this information. If not enabled, API returns empty results.
- `EpAssignedSubgraph_GetEpName`: Returns the name of the EP to which
the subgraph is assigned
  - `EpAssignedSubgraph_GetNodes`: Returns a list of assigned nodes
  - `EpAssignedNode_GetName`: Returns the assigned node's name
  - `EpAssignedNode_GetDomain`: Returns the assigned node's domain
- `EpAssignedNode_GetOperatorType`: Returns the assigned node's operator
type
- Also adds C++ and Python bindings

The API returns a list of "subgraphs". Each subgraph has the following
information:
- Subgraph info:
- EP name: The name of the execution provider to which this subgraph is
assigned.
- nodes: Name and operator type of each node. Ex: `[{"multiply", "Mul"},
...]`

Python example program (taken from unit tests):
```python
    def test_get_graph_provider_assignment_info(self):
        """
        Tests querying for information about the nodes assigned to the CPU EP.
        """

        # Create session options that enables recording EP graph partitioning info.
        session_options = onnxrt.SessionOptions()
        session_options.add_session_config_entry("session.record_ep_graph_assignment_info", "1")

        session = onnxrt.InferenceSession(get_name("add_mul_add.onnx"), sess_options=session_options)

        # Query session for information on each subgraph assigned to an EP.
        ep_subgraphs = session.get_provider_graph_assignment_info()

        # Check that all 3 nodes are assigned to CPU EP (each in its own subgraph)
        self.assertEqual(len(ep_subgraphs), 3)
        for ep_subgraph in ep_subgraphs:
            self.assertEqual(ep_subgraph.ep_name, "CPUExecutionProvider")
            self.assertEqual(len(ep_subgraph.get_nodes()), 1)

        # Serialize each node to an identifier (concatenates operator type and node name)
        node_ids: list[str] = [f"{n.op_type}/{n.name}" for s in ep_subgraphs for n in s.get_nodes()]

        # Should have 1 Mul and 2 Adds.
        self.assertEqual(len(node_ids), 3)
        self.assertIn("Add/add_0", node_ids)
        self.assertIn("Add/add_1", node_ids)
        self.assertIn("Mul/mul_0", node_ids)
```

C++ program (taken from unit test):
```c++
  // Check the ep graph partitioning (Mul on plugin EP, others on CPU EP).
  // Model has 3 subgraphs (in no particular order):
  // - Subgraph 1: Add assigned to CPU EP.
  // - Subgraph 2: Mul assigned to plugin EP.
  // - Subgraph 3: Add assigned to CPU EP.
  std::vector<Ort::ConstEpAssignedSubgraph> ep_subgraphs = session.GetEpGraphAssignmentInfo();
  ASSERT_EQ(ep_subgraphs.size(), 3);

  for (Ort::ConstEpAssignedSubgraph ep_subgraph : ep_subgraphs) {
    std::string ep_name = ep_subgraph.EpName();
    ASSERT_TRUE(ep_name == Utils::example_ep_info.ep_name || ep_name == kCpuExecutionProvider);

    const std::vector<Ort::ConstEpAssignedNode> ep_nodes = ep_subgraph.GetNodes();
    ASSERT_GE(ep_nodes.size(), 1);  // All of these subgraphs just have one node.

    if (ep_name == kCpuExecutionProvider) {
      std::string op_type = ep_nodes[0].OpType();
      std::string node_name = ep_nodes[0].Name();

      ASSERT_EQ(op_type, "Add");
      ASSERT_TRUE(node_name == "add_0" || node_name == "add_1");
    } else {
      ASSERT_TRUE(ep_name == Utils::example_ep_info.ep_name);

      std::string op_type = ep_nodes[0].OpType();
      std::string node_name = ep_nodes[0].Name();
      ASSERT_EQ(op_type, "Mul");
      ASSERT_EQ(node_name, "mul_0");
    }
  }
```

<!-- - Why is this change required? What problem does it solve?
- If it fixes an open issue, please link to the issue here. -->

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cherry-picked Cherry-picked for a cherrypicks branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants