Windows ML では、特定の実行プロバイダー (IP) が Windows ML ExecutionProviderCatalog API を介してシステム全体で動的にダウンロード、インストール、共有され、 自動的に更新されます。 使用可能な IP を確認するには、「 サポートされている実行プロバイダー」を参照してください。
このページでは、ユーザーのデバイスに EP をインストールする方法について説明します。 インストールが完了したら、 実行プロバイダー を使用する前に ONNX Runtime に登録する必要があります。
互換性のあるすべての拡張パックをインストールする
初期開発では、 EnsureAndRegisterCertifiedAsync()を呼び出すだけで、ユーザーのデバイスで使用できるすべての IP をダウンロードしてインストールし、1 回の呼び出しですべての EP を ONNX ランタイムに登録することができます。 初回実行時には、ダウンロードする必要があるネットワーク速度と IP によっては、この方法に数秒または数分かかる場合があることに注意してください。
// Get the default ExecutionProviderCatalog
var catalog = ExecutionProviderCatalog.GetDefault();
// Ensure execution providers compatible with device are present (downloads if necessary)
// and then registers all present execution providers with ONNX Runtime
await catalog.EnsureAndRegisterCertifiedAsync();
// Get the default ExecutionProviderCatalog
winrt::Microsoft::Windows::AI::MachineLearning::ExecutionProviderCatalog catalog =
winrt::Microsoft::Windows::AI::MachineLearning::ExecutionProviderCatalog::GetDefault();
// Ensure execution providers compatible with device are present (downloads if necessary)
// and then registers all present execution providers with ONNX Runtime
catalog.EnsureAndRegisterCertifiedAsync().get();
# Please DO NOT use this API. It won't register EPs to the python ort env.
互換性のあるすべての EP を見つける
FindAllProviders() メソッドを呼び出すと、ユーザーのデバイスで使用できる IP (インストールされていない IP を含む) を確認できます。
ExecutionProviderCatalog catalog = ExecutionProviderCatalog.GetDefault();
// Find all available EPs (including non-installed EPs)
ExecutionProvider[] providers = catalog.FindAllProviders();
foreach (var provider in providers)
{
Console.WriteLine($"{provider.Name}: {provider.ReadyState}");
}
auto catalog = ExecutionProviderCatalog::GetDefault();
// Find all available EPs (including non-installed EPs)
auto providers = catalog.FindAllProviders();
for (auto const& provider : providers)
{
std::wcout << provider.Name() << L": " << static_cast<int>(provider.ReadyState()) << std::endl;
}
# winml: winui3.microsoft.windows.ai.machinelearning
catalog = winml.ExecutionProviderCatalog.get_default()
# Find all available EPs (including non-installed EPs)
providers = catalog.find_all_providers()
for provider in providers:
print(f"{provider.name}: {provider.ready_state}")
返される実行プロバイダーは、ユーザーのデバイスと使用可能な実行プロバイダーによって異なります。 現在実行プロバイダーがインストールされていない互換性のある Qualcomm デバイスでは、上記のコードによって次の出力が出力されます。
QNNExecutionProvider: NotPresent
各 ExecutionProvider には、デバイス上の現在の状態を示す ReadyState プロパティがあります。 これらの状態を理解することは、アプリで実行する必要があるアクションを決定するのに役立ちます。
| ReadyState |
Definition |
次のステップ |
NotPresent |
EP はクライアント デバイスにインストールされていません。 |
EnsureReadyAsync()を呼び出して EP をダウンロードしてインストールし、アプリのランタイム依存関係グラフに追加します。 |
NotReady |
EP はクライアント デバイスにインストールされますが、アプリのランタイム依存関係グラフには追加されていません。 |
EnsureReadyAsync()を呼び出して、EP をアプリのランタイム依存関係グラフに追加します。 |
Ready |
EP はクライアント デバイスにインストールされ、アプリのランタイム依存関係グラフに追加されています。 |
TryRegister() を呼び出して、EP を ONNX Runtime に登録します。 |
特定の EP をインストールする
アプリで使用する特定の ExecutionProvider があり、その ReadyState が NotPresent場合は、 EnsureReadyAsync()を呼び出してダウンロードしてインストールできます。
// Download and install a NotPresent EP
var result = await provider.EnsureReadyAsync();
// Check that the download and install was successful
bool installed = result.Status == ExecutionProviderReadyResultState.Success;
// Download and install a NotPresent EP
auto result = provider.EnsureReadyAsync().get();
// Check that the download and install was successful
bool installed = result.Status() == ExecutionProviderReadyResultState::Success;
# Download and install a NotPresent EP
result = provider.ensure_ready_async().get()
# Check that the download and install was successful
installed = result.status == winml.ExecutionProviderReadyResultState.SUCCESS
インストール進行中
AP をダウンロードしてインストールするための API には、進行状況の更新プログラムを提供するコールバックが含まれているため、進行状況インジケーターを表示してユーザーに通知することができます。
// Start the download and install of a NotPresent EP
var operation = provider.EnsureReadyAsync();
// Listen to progress callback
operation.Progress = (asyncInfo, progressInfo) =>
{
// Dispatch to UI thread (varies based on UI platform)
_dispatcherQueue.TryEnqueue(() =>
{
// progressInfo is out of 100, convert to 0-1 range
double normalizedProgress = progressInfo / 100.0;
// Display the progress to the user
Progress = normalizedProgress;
};
};
// Await for the download and install to complete
var result = await operation;
// Check that the download and install was successful
bool installed = result.Status == ExecutionProviderReadyResultState.Success;
// Start the download and install of a NotPresent EP
auto operation = provider.EnsureReadyAsync();
// Listen to progress callback
operation.Progress([this](auto const& asyncInfo, double progressInfo)
{
// Dispatch to UI thread (varies based on UI platform)
dispatcherQueue.TryEnqueue([this, progressInfo]()
{
// progressInfo is out of 100, convert to 0-1 range
double normalizedProgress = progressInfo / 100.0;
// Display the progress to the user
Progress(normalizedProgress);
});
});
// Await for the download and install to complete
auto result = operation.get();
// Check that the download and install was successful
bool installed = result.Status() == ExecutionProviderReadyResultState::Success;
# Start the download and install of a NotPresent EP
operation = provider.ensure_ready_async()
# Listen to progress callback
def on_progress(async_info, progress_info):
# progress_info is out of 100, convert to 0-1 range
normalized_progress = progress_info / 100.0
# Display the progress to the user
print(f"Progress: {normalized_progress:.0%}")
operation.progress = on_progress
# Await for the download and install to complete
result = operation.get()
# Check that the download and install was successful
installed = result.status == winml.ExecutionProviderReadyResultState.SUCCESS
次のステップ
実行プロバイダーをインストールしたので、「 実行プロバイダーの登録 」を参照して、ONNX Runtime で使用するために実行プロバイダーを登録する方法を確認してください。
運用アプリの例
実稼働アプリケーションの場合、ダウンロードがいつ行われるかを自分とユーザーが制御できるように、アプリが実行する可能性のある操作の例を次に示します。 登録する前に、新しい実行プロバイダーが使用可能かどうかを確認し、条件付きでダウンロードできます。
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 == "MIGraphXExecutionProvider" ||
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)
こちらも参照ください