Questa pagina illustra i modi più avanzati in cui l'app può gestire normalmente il download e la registrazione di provider di esecuzione tramite Windows ML. Anche se un EP è già scaricato nel dispositivo, devi registrare gli EP ogni volta che viene eseguita l'app in modo che vengano visualizzati in ONNX Runtime.
Scaricare e registrarsi in una sola chiamata
Per lo sviluppo iniziale, può essere bello chiamare EnsureAndRegisterCertifiedAsync()semplicemente , che scaricherà eventuali nuovi EPS (o nuove versioni di EPS) compatibili con il dispositivo e i driver se non sono già scaricati e quindi registrare tutti gli EPS. Si noti che alla prima esecuzione questo metodo può richiedere più secondi o anche minuti a seconda della velocità di rete e degli EPS che devono essere scaricati.
// 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.
Suggerimento
Nelle applicazioni di produzione eseguire il wrapping della EnsureAndRegisterCertifiedAsync() chiamata in un blocco try-catch per gestire correttamente potenziali errori di rete o download.
Registrare solo i provider esistenti
Se si vuole evitare di scaricare e registrare solo i provider di esecuzione già presenti nel computer:
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.
Scoprire se sono presenti nuovi indirizzi IP (senza download)
Se vuoi verificare se sono disponibili nuovi EP compatibili con il tuo dispositivo e i driver da scaricare, ma non vuoi avviare il download, puoi usare il FindAllProviders() metodo e quindi verificare se i provider hanno readyState of NotPresent. È quindi possibile decidere di gestirlo, ma si vuole (avviare gli utenti in una schermata di aggiornamento, chiedere loro se vogliono aggiornare e così via). È possibile scegliere di continuare a usare gli EPS già scaricati (chiamando RegisterCertifiedAsync() come illustrato in precedenza) se non si vuole fare in modo che gli utenti attendino subito.
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)
Scaricare e registrare un EP specifico
Se è presente un provider di esecuzione specifico che l'app vuole usare, è possibile scaricare e registrare un provider di esecuzione specifico senza scaricare tutti gli EP compatibili.
Si userà FindAllProviders() prima di tutto per ottenere tutti gli EPS compatibili e quindi è possibile chiamare EnsureReadyAsync() su un determinato ExecutionProvider per scaricare il provider di esecuzione specifico e chiamare TryRegister() per registrare il provider di esecuzione specifico.
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)
Esempio di app di produzione
Per le applicazioni di produzione, di seguito è riportato un esempio di ciò che l'app potrebbe voler fare per offrire agli utenti il controllo su quando si verificano i download. È possibile verificare se sono disponibili nuovi provider di esecuzione e scaricarli in modo condizionale:
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)