How Does ONNX Runtime Execute a Model Across Hardware?

ONNX Runtime loads an .onnx model into an in-memory computation graph inside its C++ InferenceSession, runs provider-independent Basic graph optimizations (constant folding, redundant node elimination, and basic fusions), and then partitions the graph across registered Execution Providers in priority order using GetCapability(). On the CPU and CUDA providers it applies Extended graph optimizations (such as Attention and LayerNorm fusion) before running C++ kernels or CUDA / cuDNN / cuBLAS kernels; with the TensorRT provider, supported subgraphs are compiled into an NVIDIA TensorRT engine while unsupported operators fall back to CUDA or the CPU.
Execution provider

Showing the CUDA execution provider: 10 stages, 9 steps.

Your application passes model path to ONNX model (.onnx) ONNX model (.onnx) loaded into InferenceSession InferenceSession runs level-1 passes in Basic graph passes Basic graph passes handed to GetCapability split GetCapability split fuses CPU/CUDA nodes in Extended & layout opt Extended & layout opt dispatches fused graph to CPU EP kernels Extended & layout opt dispatches GPU nodes to CUDA EP (cuDNN/CUDA) GetCapability split allocates subgraphs to TensorRT EP TensorRT EP runs TensorRT engine on NVIDIA GPU TensorRT EP unsupported GPU ops fall back to CUDA EP (cuDNN/CUDA) GetCapability split unclaimed ops fall back to CPU EP kernels CUDA EP (cuDNN/CUDA) launches CUDA/cuDNN kernels on NVIDIA GPU CPU EP kernels runs on CPU Your application application ONNX model (.onnx) model format InferenceSession runtime Basic graph passes compiler GetCapability split framework component Extended & layout opt compiler TensorRT EP compiler CUDA EP (cuDNN/CUDA) kernel CPU EP kernels kernel CPU hardware NVIDIA GPU hardware

The selected path, step by step

  1. Your application passes model path to ONNX model (.onnx): Your application passes the .onnx model file (or bytes) and the priority-ordered execution provider list when creating an InferenceSession.
  2. ONNX model (.onnx) loaded into InferenceSession: InferenceSession parses the ONNX protobuf graph, operator nodes, and initializers into ONNX Runtime's in-memory Graph representation.
  3. InferenceSession runs level-1 passes in Basic graph passes: Before partitioning the graph across providers, ONNX Runtime applies Basic graph optimizations such as constant folding, dead-node elimination, and Conv+Add fusion.
  4. Basic graph passes handed to GetCapability split: The simplified graph is passed to ONNX Runtime's graph partitioner to assign nodes or subgraphs to registered execution providers.
  5. GetCapability split fuses CPU/CUDA nodes in Extended & layout opt: For nodes assigned to the CPU or CUDA execution providers, ONNX Runtime runs Extended graph optimizations (complex node fusions) and CPU layout optimizations.
  6. Extended & layout opt dispatches GPU nodes to CUDA EP (cuDNN/CUDA): Nodes claimed by CUDAExecutionProvider (including fused Attention, LayerNorm, and BiasGelu nodes) run through the CUDA execution provider.
  7. GetCapability split unclaimed ops fall back to CPU EP kernels: Any operator node not supported by the GPU execution providers is assigned to the built-in CPUExecutionProvider.
  8. CUDA EP (cuDNN/CUDA) launches CUDA/cuDNN kernels on NVIDIA GPU: The CUDA execution provider launches CUDA, cuDNN, and cuBLAS kernels on the NVIDIA GPU.
  9. CPU EP kernels runs on CPU: The CPU execution provider runs its C++ kernels on the host CPU.

Why graph optimizations happen in two stages

ONNX Runtime splits graph transformations into levels that run before and after hardware partitioning. Basic graph optimizations—constant folding, dead-node elimination, and simple operator fusions like Conv+Add—are semantics-preserving rewrites that run before partitioning, so every execution provider benefits from them.

Extended graph optimizations (such as multi-node Attention, LayerNorm, and Bias+GELU fusions) and NCHWc layout transformations run after GetCapability() partitioning, because they emit fused operator nodes implemented specifically by the CPU, CUDA, or ROCm execution providers.

How GetCapability() partitions a model with fallbacks

Unlike a single-backend engine, an ONNX Runtime session takes a priority-ordered list of execution providers—for example, TensorrtExecutionProvider, then CUDAExecutionProvider, then CPUExecutionProvider. ONNX Runtime queries each provider's GetCapability() interface in order to claim subgraphs or individual nodes.

Any operator that a higher-priority accelerator provider cannot run is automatically assigned to the next provider in the list, with the built-in CPU execution provider acting as the final fallback.

Every stage

ONNX model (.onnx)

model format

A serialized ONNX computation graph containing standard operators, tensor types, and constant weight initializers exported from PyTorch, TensorFlow, or scikit-learn.

  • ONNX provides an open source format for AI models, both deep learning and traditional ML. It defines an extensible computation graph model, as well as definitions of built-in operators and standard data types.
    ONNX README (onnx/onnx) Source repository
  • supporting models from deep learning frameworks such as PyTorch and TensorFlow/Keras as well as classical machine learning libraries such as scikit-learn, LightGBM, XGBoost, etc.
    ONNX Runtime README (microsoft/onnxruntime) Source repository

InferenceSession

runtime

ONNX Runtime's C++ session engine. When initialized, it parses the model into an in-memory graph, runs graph optimizations, and coordinates execution providers.

In the atlas: C++

Basic graph passes

compiler

Level-1 semantics-preserving graph rewrites—constant folding, redundant node elimination, and Conv/Add/BatchNorm fusions—applied before partitioning.

GetCapability split

framework component

Queries registered execution providers via GetCapability() in priority order to allocate supported subgraphs or nodes to each provider.

In the atlas: C++

Extended & layout opt

compiler

Post-partitioning complex operator fusions (Attention, LayerNormalization, SkipLayerNorm, BiasGelu on CPU/CUDA) and NCHWc data layout transforms on CPU.

TensorRT EP

compiler

Compiles supported ONNX subgraphs into optimized NVIDIA TensorRT engines for the target GPU.

CUDA EP (cuDNN/CUDA)

kernel

Runs assigned operators on the NVIDIA GPU using precompiled CUDA kernels and NVIDIA libraries including cuDNN, cuBLAS, and cuBLASLt.

In the atlas: CUDA

CPU EP kernels

kernel

ONNX Runtime's built-in C++ CPU execution provider. Runs the full graph on CPU or any operator nodes not claimed by a higher-priority GPU provider.

In the atlas: C++

CPU

hardware

The host CPU executing the CPU execution provider's C++ kernels.

NVIDIA GPU

hardware

The NVIDIA GPU executing compiled TensorRT engines and CUDA / cuDNN / cuBLAS kernels.

Every step

FromStepToWhenWhat happensSource
Your applicationpasses model path toONNX model (.onnx)any execution providerYour application passes the .onnx model file (or bytes) and the priority-ordered execution provider list when creating an InferenceSession.Project docs
ONNX model (.onnx)loaded intoInferenceSessionany execution providerInferenceSession parses the ONNX protobuf graph, operator nodes, and initializers into ONNX Runtime's in-memory Graph representation.Project docs
InferenceSessionruns level-1 passes inBasic graph passesany execution providerBefore partitioning the graph across providers, ONNX Runtime applies Basic graph optimizations such as constant folding, dead-node elimination, and Conv+Add fusion.Project docs
Basic graph passeshanded toGetCapability splitany execution providerThe simplified graph is passed to ONNX Runtime's graph partitioner to assign nodes or subgraphs to registered execution providers.Project docs
GetCapability splitfuses CPU/CUDA nodes inExtended & layout optCPU (Default) or CUDA (NVIDIA)For nodes assigned to the CPU or CUDA execution providers, ONNX Runtime runs Extended graph optimizations (complex node fusions) and CPU layout optimizations.Project docs
Extended & layout optdispatches fused graph toCPU EP kernelsCPU (Default)When using the default CPU execution provider, all optimized and layout-transformed nodes are executed by the CPU EP's C++ kernels.Project docs
Extended & layout optdispatches GPU nodes toCUDA EP (cuDNN/CUDA)CUDA (NVIDIA)Nodes claimed by CUDAExecutionProvider (including fused Attention, LayerNorm, and BiasGelu nodes) run through the CUDA execution provider.Project docs
GetCapability splitallocates subgraphs toTensorRT EPTensorRT (NVIDIA)With TensorrtExecutionProvider registered first, GetCapability() assigns supported ONNX subgraphs to TensorRT to be compiled into TensorRT engines.Project docs
TensorRT EPruns TensorRT engine onNVIDIA GPUTensorRT (NVIDIA)The compiled TensorRT engine executes its fused layers directly on the NVIDIA GPU.Project docs
TensorRT EPunsupported GPU ops fall back toCUDA EP (cuDNN/CUDA)TensorRT (NVIDIA)Operators that TensorRT does not support are assigned to the second-priority CUDAExecutionProvider rather than dropping all the way to the CPU.Project docs
GetCapability splitunclaimed ops fall back toCPU EP kernelsCUDA (NVIDIA) or TensorRT (NVIDIA)Any operator node not supported by the GPU execution providers is assigned to the built-in CPUExecutionProvider.Project docs
CUDA EP (cuDNN/CUDA)launches CUDA/cuDNN kernels onNVIDIA GPUCUDA (NVIDIA) or TensorRT (NVIDIA)The CUDA execution provider launches CUDA, cuDNN, and cuBLAS kernels on the NVIDIA GPU.Project docs
CPU EP kernelsruns onCPUany execution providerThe CPU execution provider runs its C++ kernels on the host CPU.Project docs

What this does not show

Documented inference paths for an ONNX (.onnx) model in ONNX Runtime using three execution providers: the default CPU provider, the NVIDIA CUDA provider, and the NVIDIA TensorRT provider. Other execution providers (CoreML, DirectML, OpenVINO, QNN, ROCm, WebGPU) and ONNX Runtime Training are out of scope. ONNX Runtime uses the same GetCapability() partitioning architecture for more than a dozen other execution providers, including CoreML, DirectML, OpenVINO, and WebGPU.

How this page is checked

Every stage and step above quotes the source that supports it. The quotes were checked against the ONNX specification README and the ONNX Runtime documentation (Execution Providers, Graph Optimizations, CUDA Execution Provider, TensorRT Execution Provider) on 2026-11-11. The data is a versioned JSON file under the same CC BY 4.0 license as the dataset. Found something wrong or out of date? Open an issue with the better source.

What these tools are written in is in the main atlas: Python, C++, CUDA. More execution paths: What Actually Happens When You Run JAX Code, How Does llama.cpp Run a Model on Your Hardware, What Actually Happens When You Run MLX on a Mac, What Actually Happens When You Run a PyTorch Model, What Actually Happens When vLLM Serves a Request, or compare them all.

Explore the full graph →