После установки поставщиков выполнения Машинного обучения Windows на устройстве необходимо зарегистрировать их, прежде чем их можно будет использовать с средой выполнения ONNX. На этой странице рассматриваются API регистрации и шаблоны.
Проверка зарегистрированных ЭП
По умолчанию в среде выполнения ONNX присутствуют только включенные поставщики выполнения . Вы можете увидеть, какие устройства EP доступны в среде выполнения ONNX, вызвав API среды выполнения GetEpDevices() ONNX.
// Get all ONNX Runtime EP devices
IReadOnlyList<OrtEpDevice> ortEpDevices = OrtEnv.Instance().GetEpDevices();
foreach (var ortEpDevice in ortEpDevices)
{
Console.WriteLine($"{ortEpDevice.EpName} (DeviceType: {ortEpDevice.HardwareDevice.Type})");
}
// Get all ONNX Runtime EP devices
Ort::Env env;
auto ortEpDevices = env.GetEpDevices();
for (const auto& ortEpDevice : ortEpDevices)
{
std::wcout << ortEpDevice.EpName() << L" (DeviceType: " << ortEpDevice.HardwareDevice().Type() << L")" << std::endl;
}
#include <onnxruntime_cxx_api.h>
#include <format>
#include <iostream>
// Get all ONNX Runtime EP devices
Ort::Env env(ORT_LOGGING_LEVEL_ERROR, "MyApp");
auto ortEpDevices = env.GetEpDevices();
for (const auto& ortEpDevice : ortEpDevices)
{
const char* epName = ortEpDevice.EpName();
if (epName)
{
std::cout << std::format(" - {}\n", epName);
}
}
import onnxruntime as ort
# Get all ONNX Runtime EP devices
ort_ep_devices = ort.get_ep_devices()
for ort_ep_device in ort_ep_devices:
print(f"{ort_ep_device.ep_name} (DeviceType: {ort_ep_device.hardware_device.type})")
Перед регистрацией любого из поставщиков выполнения Windows ML этот код будет выводить следующее:
CPUExecutionProvider (DeviceType: CPU)
DmlExecutionProvider (DeviceType: GPU)
Регистрация всех установленных EPS
Чтобы зарегистрировать все доступные поставщики выполнения Windows ML, установленные на компьютере для использования с средой выполнения ONNX, используйте RegisterCertifiedAsync() API.
var catalog = ExecutionProviderCatalog.GetDefault();
// Register providers already present on the machine
await catalog.RegisterCertifiedAsync();
auto catalog = winrt::Microsoft::Windows::AI::MachineLearning::ExecutionProviderCatalog::GetDefault();
// Register providers already present on the machine
catalog.RegisterCertifiedAsync().get();
API C не поддерживают один RegisterCertifiedAsync() вызов. Вместо этого перечислите поставщиков и зарегистрируйте их по отдельности.Ort::Env::RegisterExecutionProviderLibrary()
#include <WinMLEpCatalog.h>
#include <onnxruntime_cxx_api.h>
#include <filesystem>
#include <string>
struct RegisterContext
{
Ort::Env* env;
};
BOOL CALLBACK RegisterInstalledCallback(
WinMLEpHandle ep,
const WinMLEpInfo* info,
void* context)
{
auto* ctx = static_cast<RegisterContext*>(context);
if (!info || !info->name)
return TRUE;
if (info->certification != WinMLEpCertification_Certified)
return TRUE;
if (FAILED(WinMLEpEnsureReady(ep)))
return TRUE;
size_t pathSize = 0;
if (FAILED(WinMLEpGetLibraryPathSize(ep, &pathSize)) || pathSize == 0)
return TRUE;
std::string libraryPathUtf8(pathSize, '\0');
if (FAILED(WinMLEpGetLibraryPath(ep, pathSize, libraryPathUtf8.data(), nullptr)))
return TRUE;
std::filesystem::path libraryPath(libraryPathUtf8);
ctx->env->RegisterExecutionProviderLibrary(info->name, libraryPath.wstring());
return TRUE;
}
// Register all installed certified providers
WinMLEpCatalogHandle catalog = nullptr;
HRESULT hr = WinMLEpCatalogCreate(&catalog);
if (FAILED(hr)) return;
RegisterContext ctx = { &env };
WinMLEpCatalogEnumProviders(catalog, RegisterInstalledCallback, &ctx);
WinMLEpCatalogRelease(catalog);
# Please DO NOT use this API. It won't register EPs to the python ort env.
# Instead, register providers individually as shown below.
После запуска RegisterCertifiedAsync() на совместимом устройстве Qualcomm, на котором уже установлен поставщик выполнения QNN, среда выполнения ONNX GetEpDevices() теперь будет включать два дополнительных устройства EP, и предыдущий код выдаст следующий результат...
CPUExecutionProvider (DeviceType: CPU)
DmlExecutionProvider (DeviceType: GPU)
QNNExecutionProvider (DeviceType: NPU)
QNNExecutionProvider (DeviceType: GPU)
Получение всех установленных EPS
Чтобы определить, какие поставщики выполнения в настоящее время установлены на устройстве пользователя, можно проверить, что ReadyState поставщика выполнения не равен NotPresent.
// Get all installed execution providers
IEnumerable<ExecutionProvider> installedProviders = ExecutionProviderCatalog
.GetDefault()
.FindAllProviders()
.Where(i => i.ReadyState != ExecutionProviderReadyState.NotPresent);
auto catalog = ExecutionProviderCatalog::GetDefault();
// Get all installed execution providers
auto allProviders = catalog.FindAllProviders();
std::vector<ExecutionProvider> installedProviders;
for (auto const& p : allProviders)
{
if (p.ReadyState() != ExecutionProviderReadyState::NotPresent)
{
installedProviders.push_back(p);
}
}
#include <WinMLEpCatalog.h>
#include <vector>
#include <string>
struct InstalledProvider
{
std::string name;
WinMLEpHandle handle;
};
struct CollectContext
{
std::vector<InstalledProvider> installedProviders;
};
BOOL CALLBACK CollectInstalledCallback(
WinMLEpHandle ep,
const WinMLEpInfo* info,
void* context)
{
auto* ctx = static_cast<CollectContext*>(context);
if (info && info->name && info->readyState != WinMLEpReadyState_NotPresent)
{
ctx->installedProviders.push_back({ info->name, ep });
}
return TRUE;
}
// Get all installed execution providers
WinMLEpCatalogHandle catalog = nullptr;
HRESULT hr = WinMLEpCatalogCreate(&catalog);
if (FAILED(hr)) return;
CollectContext ctx;
WinMLEpCatalogEnumProviders(catalog, CollectInstalledCallback, &ctx);
// ctx.installedProviders now contains all installed providers
WinMLEpCatalogRelease(catalog);
catalog = winml.ExecutionProviderCatalog.get_default()
# Get all installed execution providers
installed_providers = [
p for p in catalog.find_all_providers()
if p.ready_state != winml.ExecutionProviderReadyState.NOT_PRESENT
]
Каждый ExecutionProvider имеет свойство ReadyState , указывающее его текущее состояние на устройстве. Понимание этих состояний помогает определить, какие действия необходимо предпринять приложению.
| ReadyState |
Определение |
Дальнейшие шаги |
NotPresent |
EP не установлен на клиентском устройстве. |
Вызов EnsureReadyAsync() для скачивания и установки EP и добавления его в граф зависимостей среды выполнения приложения. |
NotReady |
EP устанавливается на клиентском устройстве, но не добавлен в граф зависимостей среды выполнения приложения. |
Вызовите EnsureReadyAsync(), чтобы добавить EP в граф зависимостей времени выполнения вашего приложения. |
Ready |
EP устанавливается на клиентском устройстве и добавлен в граф зависимостей среды выполнения приложения. |
Вызовите TryRegister(), чтобы зарегистрировать EP в ONNX Runtime. |
Регистрация установленного поставщика
Если у вашего приложения есть конкретный провайдер выполнения, вы можете зарегистрировать только этого провайдера, не регистрируя все имеющиеся EP. Сначала необходимо вызвать EnsureReadyAsync(), чтобы добавить поставщика в граф зависимостей вашего приложения. Затем используйте TryRegister() для регистрации EP в onNX Runtime.
// Add the provider to the app's dependency graph if needed
var result = await installedProvider.EnsureReadyAsync();
// If adding to the app's dependency graph succeeded
if (result.Status == ExecutionProviderReadyResultState.Success)
{
// Register it with ONNX Runtime
bool registered = installedProvider.TryRegister();
}
// Add the provider to the app's dependency graph if needed
auto result = installedProvider.EnsureReadyAsync().get();
// If adding to the app's dependency graph succeeded
if (result.Status() == ExecutionProviderReadyResultState::Success)
{
// Register it with ONNX Runtime
bool registered = installedProvider.TryRegister();
}
При использовании API C необходимо выполнить вызов WinMLEpEnsureReady для подготовки поставщика, а затем получить путь к библиотеке и зарегистрировать его в Ort::Env::RegisterExecutionProviderLibrary.
#include <WinMLEpCatalog.h>
#include <onnxruntime_cxx_api.h>
#include <filesystem>
#include <string>
// Assumes an Ort::Env has already been created
// Ort::Env env(ORT_LOGGING_LEVEL_ERROR, "MyApp");
// Prepare the provider (download if necessary)
HRESULT hr = WinMLEpEnsureReady(ep);
if (SUCCEEDED(hr))
{
// Get the library path
size_t pathSize = 0;
WinMLEpGetLibraryPathSize(ep, &pathSize);
std::string libraryPathUtf8(pathSize, '\0');
WinMLEpGetLibraryPath(ep, pathSize, libraryPathUtf8.data(), nullptr);
// Register it with ONNX Runtime
std::filesystem::path libraryPath(libraryPathUtf8);
env.RegisterExecutionProviderLibrary(providerName, libraryPath.wstring());
}
# Add the provider to the app's dependency graph if needed
result = installed_provider.ensure_ready_async().get()
# If adding to the app's dependency graph succeeded
if result.status == winml.ExecutionProviderReadyResultState.SUCCESS:
# Register it with ONNX Runtime
ort.register_execution_provider_library(installed_provider.name, installed_provider.library_path)
Дальнейшие шаги
Теперь, когда вы зарегистрировали поставщиков выполнения для использования с onNX Runtime, см. раздел "Выбор поставщиков выполнения" в onNX Runtime , чтобы узнать, как использовать эти поставщики выполнения в среде выполнения ONNX.
См. также