Cette page décrit les méthodes plus avancées de votre application pour gérer correctement le téléchargement et l’inscription de fournisseurs d’exécution à l’aide de Windows ML. Même si un EP est déjà téléchargé sur l’appareil, vous devez inscrire les EPs chaque fois que votre application s’exécute afin qu’elles apparaissent dans ONNX Runtime.
Télécharger et inscrire dans un appel
Pour le développement initial, il peut être agréable d’appeler EnsureAndRegisterCertifiedAsync()simplement, qui télécharge les nouveaux EPs (ou nouvelles versions d’EPs) compatibles avec votre appareil et pilotes s’ils ne sont pas déjà téléchargés, puis inscrivent tous les EPS. Notez que lors de la première exécution, cette méthode peut prendre plusieurs secondes ou même minutes en fonction de la vitesse de votre réseau et des adresses IP qui doivent être téléchargées.
// Get the default ExecutionProviderCatalog
var catalog = ExecutionProviderCatalog.GetDefault();
// Ensure and register all compatible execution providers with ONNX Runtime
// This downloads any necessary components and registers them
await catalog.EnsureAndRegisterCertifiedAsync();
// Get the default ExecutionProviderCatalog
winrt::Microsoft::Windows::AI::MachineLearning::ExecutionProviderCatalog catalog =
winrt::Microsoft::Windows::AI::MachineLearning::ExecutionProviderCatalog::GetDefault();
// Ensure and register all compatible execution providers with ONNX Runtime
catalog.EnsureAndRegisterCertifiedAsync().get();
# Please DO NOT use this API. It won't register EPs to the python ort env.
Conseil / Astuce
Dans les applications de production, habillage de l’appel EnsureAndRegisterCertifiedAsync() dans un bloc try-catch pour gérer les échecs potentiels de réseau ou de téléchargement correctement.
Inscrire des fournisseurs existants uniquement
Si vous souhaitez éviter de télécharger et d’inscrire uniquement des fournisseurs d’exécution déjà présents sur l’ordinateur :
var catalog = ExecutionProviderCatalog.GetDefault();
// Register only providers already present on the machine
// This avoids potentially long download times
await catalog.RegisterCertifiedAsync();
auto catalog = winrt::Microsoft::Windows::AI::MachineLearning::ExecutionProviderCatalog::GetDefault();
// Register only providers already present on the machine
catalog.RegisterCertifiedAsync().get();
# Please DO NOT use this API. It won't register EPs to the python ort env.
Découvrez s’il existe de nouveaux EPs (sans téléchargement)
Si vous souhaitez voir s’il existe de nouveaux EPs compatibles avec votre appareil et les pilotes disponibles pour le téléchargement, mais que vous ne souhaitez pas démarrer le téléchargement, vous pouvez utiliser la FindAllProviders() méthode, puis voir si les fournisseurs ont un ReadyState de NotPresent. Vous pouvez ensuite décider de gérer cela, mais vous le souhaitez (lancer vos utilisateurs dans un « écran de mise à jour », en leur demandant s’ils veulent mettre à jour, etc.). Vous pouvez choisir de continuer à utiliser les adresses IP déjà téléchargées (en appelant RegisterCertifiedAsync() comme indiqué ci-dessus) si vous ne souhaitez pas que vos utilisateurs attendent maintenant.
var catalog = ExecutionProviderCatalog.GetDefault();
// Check if there are new EPs that need to be downloaded
if (catalog.FindAllProviders().Any(provider => provider.ReadyState == ExecutionProviderReadyState.NotPresent))
{
// TODO: There are new EPs, decide how your app wants to handle that
}
else
{
// All EPs are already present, just register them
await catalog.RegisterCertifiedAsync();
}
auto catalog = winrt::Microsoft::Windows::AI::MachineLearning::ExecutionProviderCatalog::GetDefault();
auto providers = catalog.FindAllProviders();
// Check if any providers need to be downloaded
bool needsDownload = false;
for (const auto& provider : providers)
{
if (provider.ReadyState() == winrt::Microsoft::Windows::AI::MachineLearning::ExecutionProviderReadyState::NotPresent)
{
needsDownload = true;
break;
}
}
if (needsDownload)
{
// TODO: There are new EPs, decide how your app wants to handle that
}
else
{
// All EPs are already present, just register them
catalog.RegisterCertifiedAsync().get();
}
# winml: winui3.microsoft.windows.ai.machinelearning
catalog = winml.ExecutionProviderCatalog.get_default()
providers = catalog.find_all_providers()
if any(provider.ready_state == winml.ExecutionProviderReadyState.NOT_PRESENT for provider in providers):
# TODO: There are new EPs, decide how your app wants to handle that
pass
else:
# Register the providers one by one
for provider in providers:
provider.ensure_ready_async().get()
ort.register_execution_provider_library(provider.name, provider.library_path)
Télécharger et inscrire un EP spécifique
S’il existe un fournisseur d’exécution spécifique que votre application souhaite utiliser, vous pouvez télécharger et inscrire un fournisseur d’exécution particulier sans télécharger tous les EPs compatibles.
Vous allez d’abord utiliser FindAllProviders() pour obtenir tous les EPs compatibles, puis vous pouvez appeler EnsureReadyAsync() un executionProvider particulier pour télécharger le fournisseur d’exécution spécifique et appeler TryRegister() pour inscrire le fournisseur d’exécution spécifique.
var catalog = ExecutionProviderCatalog.GetDefault();
// Get the QNN provider, if present
var qnnProvider = catalog.FindAllProviders()
.FirstOrDefault(i => i.Name == "QNNExecutionProvider");
if (qnnProvider != null)
{
// Download it
var result = await qnnProvider.EnsureReadyAsync();
// If download succeeded
if (result != null && result.Status == ExecutionProviderReadyResultState.Success)
{
// Register it
bool registered = qnnProvider.TryRegister();
}
}
auto catalog = winrt::Microsoft::Windows::AI::MachineLearning::ExecutionProviderCatalog::GetDefault();
// Get the QNN provider, if present
auto providers = catalog.FindAllProviders();
winrt::Microsoft::Windows::AI::MachineLearning::ExecutionProvider qnnProvider{ nullptr };
for (auto const& p : providers)
{
if (p.Name() == L"QNNExecutionProvider")
{
qnnProvider = p;
break;
}
}
if (qnnProvider)
{
// Download required components for this provider (if not already present)
auto result = qnnProvider.EnsureReadyAsync().get();
if (result && result.Status() == winrt::Microsoft::Windows::AI::MachineLearning::ExecutionProviderReadyResultState::Success)
{
// Register the provider with ONNX Runtime
bool registered = qnnProvider.TryRegister();
}
}
catalog = winml.ExecutionProviderCatalog.get_default()
providers = catalog.find_all_providers()
qnn_provider = next((provider for provider in providers if provider.name == 'QNNExecutionProvider'), None)
if qnn_provider is not None:
# Download required components for this provider (if not already present)
result = qnn_provider.ensure_ready_async().get()
if result == winml.ExecutionProviderReadyResultState.SUCCESS:
# Register the provider with ONNX Runtime
ort.register_execution_provider_library(qnn_provider.name, qnn_provider.library_path)
Exemple d’application de production
Pour les applications de production, voici un exemple de ce que votre application peut vouloir faire pour vous donner à vous-même et à vos utilisateurs le contrôle du moment où les téléchargements se produisent. Vous pouvez vérifier si de nouveaux fournisseurs d’exécution sont disponibles et les télécharger de manière conditionnelle :
using Microsoft.Windows.AI.MachineLearning;
var catalog = ExecutionProviderCatalog.GetDefault();
// Filter to the EPs our app supports/uses
var providers = catalog.FindAllProviders().Where(p =>
p.Name == "VitisAIExecutionProvider" ||
p.Name == "OpenVINOExecutionProvider" ||
p.Name == "QNNExecutionProvider" ||
p.Name == "NvTensorRtRtxExecutionProvider"
);
if (providers.Any(p => p.ReadyState == ExecutionProviderReadyState.NotPresent))
{
// Show UI to user asking if they want to download new execution providers
bool userWantsToDownload = await ShowDownloadDialogAsync();
if (userWantsToDownload)
{
// Download all EPs
foreach (var p in providers)
{
if (p.ReadyState == ExecutionProviderReadyState.NotPresent)
{
// Ignore result handling here; production code could inspect status
await p.EnsureReadyAsync();
}
}
// And register all EPs
await catalog.RegisterCertifiedAsync();
}
else
{
// Register only already-present EPs
await catalog.RegisterCertifiedAsync();
}
}
using namespace winrt::Microsoft::Windows::AI::MachineLearning;
auto catalog = ExecutionProviderCatalog::GetDefault();
auto allProviders = catalog.FindAllProviders();
// Filter to the EPs our app supports/uses
std::vector<ExecutionProvider> targetProviders;
for (auto const& p : allProviders)
{
auto name = p.Name();
if (name == L"VitisAIExecutionProvider" ||
name == L"OpenVINOExecutionProvider" ||
name == L"QNNExecutionProvider" ||
name == L"NvTensorRtRtxExecutionProvider")
{
targetProviders.push_back(p);
}
}
bool needsDownload = false;
for (auto const& p : targetProviders)
{
if (p.ReadyState() == ExecutionProviderReadyState::NotPresent)
{
needsDownload = true;
break;
}
}
if (needsDownload)
{
// Show UI to user or check application settings to confirm download
bool userWantsToDownload = ShowDownloadDialog();
if (userWantsToDownload)
{
// Download only the missing target providers
for (auto const& p : targetProviders)
{
if (p.ReadyState() == ExecutionProviderReadyState::NotPresent)
{
// Ignore result handling here; production code could inspect status
p.EnsureReadyAsync().get();
}
}
// Register all (both previously present and newly downloaded) providers
catalog.RegisterCertifiedAsync().get();
}
else
{
// User deferred download; register only already-present providers
catalog.RegisterCertifiedAsync().get();
}
}
else
{
// All target EPs already present
catalog.RegisterCertifiedAsync().get();
}
# remove the msvcp140.dll from the winrt-runtime package.
# So it does not cause issues with other libraries.
from pathlib import Path
from importlib import metadata
site_packages_path = Path(str(metadata.distribution('winrt-runtime').locate_file('')))
dll_path = site_packages_path / 'winrt' / 'msvcp140.dll'
if dll_path.exists():
dll_path.unlink()
from winui3.microsoft.windows.applicationmodel.dynamicdependency.bootstrap import (
InitializeOptions,
initialize
)
import winui3.microsoft.windows.ai.machinelearning as winml
import onnxruntime as ort
with initialize(options=InitializeOptions.ON_NO_MATCH_SHOW_UI):
catalog = winml.ExecutionProviderCatalog.get_default()
# Filter EPs that the app supports
providers = [provider for provider in catalog.find_all_providers() if provider.name in [
'VitisAIExecutionProvider',
'OpenVINOExecutionProvider',
'QNNExecutionProvider',
'NvTensorRtRtxExecutionProvider'
]]
# Download and make ready missing EPs if the user wants to
if any(provider.ready_state == winml.ExecutionProviderReadyState.NOT_PRESENT for provider in providers):
# Ask the user if they want to download the missing packages
if user_wants_to_download:
for provider in [provider for provider in providers if provider.ready_state == winml.ExecutionProviderReadyState.NOT_PRESENT]:
provider.ensure_ready_async().get()
# Make ready the existing EPs
for provider in [provider for provider in providers if provider.ready_state == winml.ExecutionProviderReadyState.NOT_READY]:
provider.ensure_ready_async().get()
# Register all ready EPs
for provider in [provider for provider in providers if provider.ready_state == winml.ExecutionProviderReadyState.READY]:
ort.register_execution_provider_library(provider.name, provider.library_path)