Questo argomento illustra come installare e usare Windows ML per individuare, scaricare e registrare provider di esecuzione (EPS) da usare con onNX Runtime fornito con Windows ML. Windows ML gestisce la complessità della gestione dei pacchetti e della selezione hardware, consentendo di scaricare i provider di esecuzione più recenti compatibili con l'hardware degli utenti.
Se non si ha già familiarità con il runtime ONNX, è consigliabile leggere la documentazione sul runtime ONNX. In breve, Windows ML fornisce una copia del runtime ONNX, oltre alla possibilità di scaricare dinamicamente provider di esecuzione (EPS).
Prerequisiti
- .NET 8 o versione successiva per usare tutte le API di Windows ML
- Con .NET 6 è possibile installare provider di esecuzione usando le
Microsoft.Windows.AI.MachineLearning API, ma non è possibile usare le Microsoft.ML.OnnxRuntime API.
- Riferirsi a un TFM specifico per Windows 10 come
net8.0-windows10.0.19041.0 o versione successiva
C++20 o versione successiva.
- Carico di lavoro di Visual Studio 2022 con C++ (include il compilatore C)
- CMake 3.21 o versione successiva
Versioni da Python 3.10 a 3.13, nei dispositivi x64 e ARM64.
Passaggio 1: Installare o aggiornare Windows ML
Le API C di Windows ML sono incluse nella versione Microsoft.WindowsAppSDK.ML del 1.8.2141 o versione successiva. Il pacchetto NuGet fornisce i file di configurazione di CMake in build/cmake/ che sono direttamente utilizzabili. Il @WINML_VERSION@ token viene risolto in fase di compilazione NuGet, quindi non è necessaria alcuna elaborazione aggiuntiva.
Per usare il pacchetto NuGet...
- Scaricare o ripristinare il pacchetto NuGet (ad esempio, tramite
nuget restore o il download manuale)
- Estrarre o fare riferimento alla directory radice del pacchetto
- Impostare
CMAKE_PREFIX_PATH nella build/cmake sottodirectory del pacchetto
CMakeLists.txt di esempio
cmake_minimum_required(VERSION 3.21)
project(MyApp LANGUAGES CXX)
# C++20 standard for modern features (std::format, etc.)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(microsoft.windows.ai.machinelearning CONFIG REQUIRED)
add_executable(MyApp main.cpp)
target_link_libraries(MyApp PRIVATE WindowsML::Api WindowsML::OnnxRuntime)
add_custom_command(TARGET MyApp POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_RUNTIME_DLLS:MyApp> $<TARGET_FILE_DIR:MyApp>
COMMAND_EXPAND_LISTS
VERBATIM
)
Comandi di compilazione di esempio
# Point CMAKE_PREFIX_PATH to the NuGet package's cmake directory
cmake -B build -S . -DCMAKE_PREFIX_PATH="C:/packages/Microsoft.WindowsAppSDK.ML/build/cmake"
cmake --build build --config Release
Il pacchetto NuGet include la propria configurazione CMake in build/cmake/ che è in grado di interpretare la struttura delle directory di NuGet (con directory specifiche per l'architettura in lib/native/ e runtimes/). L'architettura viene determinata da CMAKE_GENERATOR_PLATFORM, CMAKE_VS_PLATFORM_NAMEo CMAKE_SYSTEM_PROCESSOR.
Il portfile vcpkg genera un file di configurazione sottile separato che mappa al layout vcpkg standard (lib/ e bin/). Entrambe le configurazioni condividono lo stesso file di destinazioni (microsoft.windows.ai.machinelearning-targets.cmake) che definisce le destinazioni IMPORT.
Le stesse destinazioni (WindowsML::WindowsML, WindowsML::Api, WindowsML::OnnxRuntime, WindowsML::DirectML) sono disponibili in entrambe le modalità di utilizzo. Usare l'espressione generatore standard di CMake 3.21 $<TARGET_RUNTIME_DLLS> per copiare le DLL di runtime nella directory di output della build.
Il binding Python sfrutta il progetto pywinrt per la proiezione della Windows App SDK. Assicurarsi che l'installazione di Python non provena da Microsoft Store (è possibile installare una versione non in pacchetto da python.org o tramite winget). L'esempio dipende dall'uso dell'API di dipendenza dinamica di Windows App SDK, valida solo per le app non in pacchetto.
Installare i pacchetti Python con questi comandi:
pip install wasdk-Microsoft.Windows.AI.MachineLearning[all] wasdk-Microsoft.Windows.ApplicationModel.DynamicDependency.Bootstrap onnxruntime-windowsml
Assicurarsi che la wasdk- versione dei pacchetti corrisponda alla versione di WindowsAppRuntime.
Passaggio 2: Scaricare e registrare gli EP
Il modo più semplice per iniziare è consentire a Windows ML di individuare, scaricare e registrare automaticamente la versione più recente di tutti i provider di esecuzione compatibili. I provider di esecuzione devono essere registrati con il runtime ONNX all'interno di Windows ML prima di poterli usare. E se non sono ancora stati scaricati, devono essere scaricati per primi. La chiamata EnsureAndRegisterCertifiedAsync() eseguirà entrambe queste operazioni in un unico passaggio.
using Microsoft.ML.OnnxRuntime;
using Microsoft.Windows.AI.MachineLearning;
// First we create a new instance of EnvironmentCreationOptions
EnvironmentCreationOptions envOptions = new()
{
logId = "WinMLDemo", // Use an ID of your own choice
logLevel = OrtLoggingLevel.ORT_LOGGING_LEVEL_ERROR
};
// And then use that to create the ORT environment
using var ortEnv = OrtEnv.CreateInstanceWithOptions(ref envOptions);
// 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();
Il modo più semplice per iniziare è consentire a Windows ML di individuare, scaricare e registrare automaticamente la versione più recente di tutti i provider di esecuzione compatibili. I provider di esecuzione devono essere registrati con il runtime ONNX all'interno di Windows ML prima di poterli usare. E se non sono ancora stati scaricati, devono essere scaricati per primi. La chiamata EnsureAndRegisterCertifiedAsync() eseguirà entrambe queste operazioni in un unico passaggio.
#include <winrt/Microsoft.Windows.AI.MachineLearning.h>
#include <winml/onnxruntime_cxx_api.h>
// First we need to create an ORT environment
Ort::Env env(ORT_LOGGING_LEVEL_ERROR, "WinMLDemo"); // Use an ID of your own choice
// 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();
Con le API C, è necessario scaricare un provider di esecuzione specifico e quindi registrare manualmente il percorso con ONNX Runtime.
#include <WinMLEpCatalog.h>
#include <onnxruntime_cxx_api.h> // Or <onnxruntime_c_api.h> if just using C
#include <filesystem>
#include <string>
// Initialize ONNX Runtime
Ort::Env env(ORT_LOGGING_LEVEL_ERROR, "WinMLDemo"); // Use an ID of your own choice
// --- Windows ML: Get EP catalog handle ---
WinMLEpCatalogHandle catalog = nullptr;
HRESULT hr = WinMLEpCatalogCreate(&catalog);
if (FAILED(hr))
{
// Handle error
return;
}
// --- Windows ML: Find, download, and register a specific EP (in this case, QNN) ---
WinMLEpHandle ep = nullptr;
hr = WinMLEpCatalogFindProvider(catalog, "QNN", NULL, &ep);
if (SUCCEEDED(hr))
{
// Windows ML: Download the EP if it isn't already downloaded
WinMLEpEnsureReady(ep);
// Windows ML: Get the EP library path
size_t pathSize = 0;
WinMLEpGetLibraryPathSize(ep, &pathSize);
std::string libraryPathUtf8(pathSize, '\0');
WinMLEpGetLibraryPath(ep, pathSize, libraryPathUtf8.data(), nullptr);
// Register the EP with ONNX Runtime using the C++ API
std::filesystem::path libraryPath(libraryPathUtf8);
env.RegisterExecutionProviderLibrary("QNN", libraryPath.wstring());
}
// --- Windows ML: Release the EP catalog handle ---
WinMLEpCatalogRelease(catalog);
Con le API Python è possibile enumerare tutti i provider di esecuzione compatibili e quindi registrare manualmente i percorsi con ONNX Runtime.
import sys
from pathlib import Path
import traceback
_winml_instance = None
class WinML:
def __new__(cls, *args, **kwargs):
global _winml_instance
if _winml_instance is None:
_winml_instance = super(WinML, cls).__new__(cls, *args, **kwargs)
_winml_instance._initialized = False
return _winml_instance
def __init__(self):
if self._initialized:
return
self._initialized = True
self._fix_winrt_runtime()
from winui3.microsoft.windows.applicationmodel.dynamicdependency.bootstrap import (
InitializeOptions,
initialize
)
import winui3.microsoft.windows.ai.machinelearning as winml
self._win_app_sdk_handle = initialize(options=InitializeOptions.ON_NO_MATCH_SHOW_UI)
self._win_app_sdk_handle.__enter__()
catalog = winml.ExecutionProviderCatalog.get_default()
self._providers = catalog.find_all_providers()
self._ep_paths : dict[str, str] = {}
for provider in self._providers:
provider.ensure_ready_async().get()
if provider.library_path == '':
continue
self._ep_paths[provider.name] = provider.library_path
self._registered_eps : list[str] = []
def __del__(self):
self._providers = None
self._win_app_sdk_handle.__exit__(None, None, None)
def _fix_winrt_runtime(self):
"""
This function removes the msvcp140.dll from the winrt-runtime package.
So it does not cause issues with other libraries.
"""
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()
def register_execution_providers_to_ort(self) -> list[str]:
import onnxruntime as ort
for name, path in self._ep_paths.items():
if name not in self._registered_eps:
try:
ort.register_execution_provider_library(name, path)
self._registered_eps.append(name)
except Exception as e:
print(f"Failed to register execution provider {name}: {e}", file=sys.stderr)
traceback.print_exc()
return self._registered_eps
WinML().register_execution_providers_to_ort()
Suggerimento
Nelle applicazioni di produzione, incapsulare la chiamata EnsureAndRegisterCertifiedAsync() in un blocco try-catch per gestire correttamente eventuali errori di rete o di download.
Passaggi successivi
Dopo aver registrato i provider di esecuzione, è possibile usare le API di runtime ONNX all'interno di Windows ML. Ti converrà...
-
Selezionare i provider di esecuzione : indicare al runtime quali provider di esecuzione si vuole usare
-
Ottenere i modelli : usare il catalogo dei modelli per scaricare in modo dinamico i modelli o includerli in locale
-
Eseguire l'inferenza del modello - Compilare, caricare e inferenza del modello
Vedere anche