Skip to content

Add runtime detection of usable execution providers#27697

Open
sagarbhure-msft wants to merge 1 commit intomicrosoft:mainfrom
sagarbhure-msft:feature/runtime-provider-detection
Open

Add runtime detection of usable execution providers#27697
sagarbhure-msft wants to merge 1 commit intomicrosoft:mainfrom
sagarbhure-msft:feature/runtime-provider-detection

Conversation

@sagarbhure-msft
Copy link

@sagarbhure-msft sagarbhure-msft commented Mar 17, 2026

Overview

Adds runtime-aware APIs to detect usable execution providers.

Unlike get_available_providers() (compile-time), these APIs verify that required runtime dependencies (CUDA, cuDNN, shared libs, etc.) are actually present.

This PR adds two new APIs that check whether provider shared libraries actually exist on disk at runtime, without loading them.


New APIs

Python:

 import onnxruntime as ort
 
 # Returns only providers whose shared libraries are present
 ort.get_usable_providers()
 
 # Check a specific provider
 ort.is_provider_usable("CUDAExecutionProvider")

C++:

 onnxruntime::GetUsableExecutionProviderNames();
 onnxruntime::IsExecutionProviderUsable("CUDAExecutionProvider");

Key Changes

  • Extended existing ProviderInfo struct in kProvidersInPriorityOrder with library_base_name field — single source of truth, no
    duplicate EP lists
  • Runtime check uses std::filesystem::exists(GetRuntimePath() / lib_filename) — no DLL loading, no hardware init, no error logs,
    no memory footprint increase
  • Static providers (CPU, DML, CoreML, XNNPACK, etc.) have library_base_name = nullptr → always usable if compiled in
  • QNN static build (BUILD_QNN_EP_STATIC_LIB) and WebGPU plugin EP adapters handled
  • ORT_MINIMAL_BUILD falls back to compile-time availability (documented in API docstrings)
  • No changes to provider_bridge_ort.cc or .h

Motivation

get_available_providers() can report providers as available even when runtime dependencies are missing.

Current workaround (bad):

try:
    ort.InferenceSession(model, providers=["CUDAExecutionProvider"])
    has_cuda = True
except:
    has_cuda = False

New APIs remove the need for exception-based checks.


Tested on Real Hardware

Machine: AMD Ryzen AI MAX+ 395 / Radeon 8060S, Windows

CPU-only build (onnxruntime 1.24.3)

get_available_providers: ['AzureExecutionProvider', 'CPUExecutionProvider']
get_usable_providers:    ['CPUExecutionProvider']

DirectML build (onnxruntime-directml 1.24.3)

get_available_providers: ['DmlExecutionProvider', 'CPUExecutionProvider']
get_usable_providers:    ['DmlExecutionProvider', 'CPUExecutionProvider']

Both providers correctly reported as usable, verified with real inference

Who this affects

  • Consumer-facing ML inference applications
  • Cross-platform software distributed to users with varying hardware setups
  • Applications that want to avoid silent CPU fallbacks or confusing runtime errors

Fixes #27177

@sagarbhure-msft
Copy link
Author

@microsoft-github-policy-service agree

@sagarbhure-msft
Copy link
Author

sagarbhure-msft commented Mar 19, 2026

Friendly nudge — would love eyes on this when someone gets a chance. cc @microsoft/onnxruntime-api

cc: @yuslepukhin

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds runtime-aware “usable execution provider” detection to ONNX Runtime so consumers can query which EPs are actually loadable on the current machine (vs. merely compiled in), and exposes this via Python bindings alongside unit tests.

Changes:

  • Introduces C++ APIs IsExecutionProviderUsable() and GetUsableExecutionProviderNames() and wires them to runtime provider library checks.
  • Adds get_usable_providers() and is_provider_usable() to the Python module and exports them from onnxruntime/__init__.py.
  • Adds unit tests covering basic usability expectations and ordering properties.

Reviewed changes

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

Show a summary per file
File Description
onnxruntime/core/providers/get_execution_providers.h Declares new runtime usability query APIs.
onnxruntime/core/providers/get_execution_providers.cc Implements usable-vs-available logic (with minimal build fallback).
onnxruntime/core/session/provider_bridge_ort.h Declares IsProviderLibraryLoadable helper for runtime checks.
onnxruntime/core/session/provider_bridge_ort.cc Implements provider library loadability checks via provider bridge infrastructure.
onnxruntime/python/onnxruntime_pybind_module.cc Exposes new usability APIs to Python via pybind11.
onnxruntime/init.py Re-exports new Python APIs at top-level.
onnxruntime/test/providers/get_execution_providers_test.cc Adds tests for usability behavior and ordering.

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

Copy link
Member

@yuslepukhin yuslepukhin left a comment

Choose a reason for hiding this comment

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

🕐

@sagarbhure-msft sagarbhure-msft force-pushed the feature/runtime-provider-detection branch 2 times, most recently from 452b646 to bef8eb3 Compare March 21, 2026 14:38
Redesigned based on PR review feedback. Uses std::filesystem::exists()
to check provider library presence — no DLL loading, no memory footprint
increase, no error logs, no hardware initialization.

Extended existing kProvidersInPriorityOrder with library_base_name field
as single source of truth (no duplicate EP lists).

Fixes microsoft#27177
@sagarbhure-msft sagarbhure-msft force-pushed the feature/runtime-provider-detection branch from bef8eb3 to 109b00f Compare March 21, 2026 14:45
@sagarbhure-msft
Copy link
Author

Addressed all review feedback - redesigned to use filesystem checks, no library loading.

Thanks @yuslepukhin and @copilot for the thorough review. I've completely redesigned the implementation:

Key changes:

  • No DLL/SO loading — uses std::filesystem::exists() to check library file presence. Zero memory footprint, zero hardware init, zero error logs.
  • Single source of truth — extended existing ProviderInfo struct in kProvidersInPriorityOrder with library_base_name field. No duplicate EP lists.
  • Edge cases — QNN static build (BUILD_QNN_EP_STATIC_LIB), WebGPU + EP adapters, minimal builds all handled.
  • Branch rebased onto latest origin/main.
  • No changes to provider_bridge_ort.cc/.h — implementation is self-contained in the providers layer (5 files, down from 7)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] Reliable runtime detection of usable Execution Providers (e.g. CUDA)

3 participants