이 페이지에서는 앱이 Windows ML을 사용하여 EP(실행 공급자) 다운로드 및 등록을 정상적으로 처리할 수 있는 고급 방법에 대해 설명합니다. EP가 디바이스에 이미 다운로드되어 있더라도 앱이 실행될 때마다 EP가 ONNX 런타임에 표시되도록 등록해야 합니다.
한 번의 통화로 다운로드 및 등록
초기 개발의 경우 디바이스 및 드라이버와 호환되는 새 EP(또는 새 버전의 EP)를 아직 다운로드하지 않은 경우 다운로드한 다음 모든 EP를 등록하는 호출 EnsureAndRegisterCertifiedAsync()이 좋을 수 있습니다. 처음 실행할 때 이 메서드는 다운로드해야 하는 네트워크 속도 및 EP에 따라 몇 초 또는 몇 분 정도 걸릴 수 있습니다.
// 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.
팁 (조언)
프로덕션 애플리케이션에서 호출을 EnsureAndRegisterCertifiedAsync() try-catch 블록으로 래핑하여 잠재적인 네트워크 또는 다운로드 오류를 정상적으로 처리합니다.
기존 공급자만 등록
다운로드를 방지하고 컴퓨터에 이미 있는 실행 공급자만 등록하려면 다음을 수행합니다.
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.
다운로드하지 않고 새 EP가 있는지 검색
디바이스 및 다운로드할 수 있는 드라이버와 호환되는 새 EP가 있는지 확인하지만 다운로드를 시작하지 않으려는 경우 이 메서드를 사용한 FindAllProviders() 다음 공급자에 NotPresent의 ReadyState가 있는지 확인할 수 있습니다. 그런 다음 원하는 대로 처리하도록 결정할 수 있습니다(사용자를 "업데이트 화면"으로 시작하고 업데이트할 것인지 묻는 등). 사용자가 지금 기다리지 않으려면 이미 다운로드한 EP를 계속 사용할 수 있습니다(위와 같이 호출 RegisterCertifiedAsync() ).
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)
특정 EP 다운로드 및 등록
앱에서 사용하려는 특정 실행 공급자가 있는 경우 호환되는 모든 EP를 다운로드하지 않고 특정 실행 공급자를 다운로드하고 등록할 수 있습니다.
먼저 호환되는 모든 EP를 가져오는 데 사용한 FindAllProviders() 다음 특정 EnsureReadyAsync()를 호출 하여 특정 실행 공급자를 다운로드하고 TryRegister() 호출하여 특정 실행 공급자를 등록할 수 있습니다.
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)
프로덕션 앱 예제
프로덕션 애플리케이션의 경우 앱이 자신과 사용자에게 다운로드가 발생하는 시기를 제어하기 위해 수행할 수 있는 작업의 예는 다음과 같습니다. 새 실행 공급자를 사용할 수 있는지 확인하고 조건부로 다운로드할 수 있습니다.
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)