共用方式為


使用 Windows ML 執行 ONNX 模型

這很重要

Windows ML API 目前為實驗性, 不支援 在生產環境中使用。 嘗試這些 API 的應用程式不應該發佈至 Microsoft 市集。

使用 Microsoft.Windows.AI.MachineLearning 命名空間中的 Windows Machine Learning (ML) 類型,您可以在 Windows 應用程式中本機執行 ONNX 模型,而不需要手動管理基礎執行提供者 (EP) 套件。 API 會處理下載、更新和初始化 EP;您接著可以繼續使用 Microsoft.Windows.AI.MachineLearning 和/或 ONNX Runtime

先決條件

  • 執行版本 24H2 (組建 26100) 或更新版本的 Windows 11 計算機。

除了上述內容之外,還有特定語言的必要條件,視您的應用程式所撰寫的語言而定。

  • .NET 8 或更新版本
  • 目標是達到 TFM windows10.0.26100 或更高

步驟 1:安裝 WinML 執行時間套件和 NuGet 套件

運行時間套件會透過 Microsoft Store 發佈。 在 Windows 終端機中執行下列命令來安裝它(標識碼是運行時間套件的市集目錄識別碼):

winget install --id 9MVL55DVGWWW

然後根據您的應用程式程式設計語言,遵循下列步驟。

在您的 .NET 專案中,新增 Microsoft.Windows.AI.MachineLearning NuGet 套件(如果使用 NuGet 套件管理員,請務必包含發行前版本套件)。

dotnet add package Microsoft.Windows.AI.MachineLearning --prerelease

然後在您的程式代碼中匯入命名空間。

using Microsoft.ML.OnnxRuntime;
using Microsoft.Windows.AI.MachineLearning;

步驟 2:下載並註冊最新的 EPs

然後,我們將使用 Windows ML 來確保裝置上擁有最新的執行提供者(EPs),並在 ONNX 執行環境中註冊。

// 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);

// Then, initialize Windows ML infrastructure
Infrastructure infrastructure = new();

// Ensure the latest execution providers are available (downloads them if they aren't)
await infrastructure.DownloadPackagesAsync();

// And register the EPs with ONNX Runtime
await infrastructure.RegisterExecutionProviderLibrariesAsync();

步驟 3:設定執行提供者

ONNX 執行時間允許應用程式根據 裝置原則來設定執行提供者(EPs),或明確允許更充分地控制提供者選項,以及應該使用哪些裝置。

建議您從明確選取 EP 開始,讓您可以在結果中有更多的可預測性。 完成此工作之後,您可以嘗試使用裝置原則,以自然且以結果為導向的方式選取執行提供者。

若要明確選取一或多個 EP,您將使用 GetEpDevices 上的 OrtApi函式,以透過所有可用的裝置來列舉。 SessionOptionsAppendExecutionProvider_V2 然後可用來明確附加特定裝置,並提供自定義提供者選項給所需的 EP。

using Microsoft.ML.OnnxRuntime;

// Get all available EP devices from the environment
var epDevices = ortEnv.GetEpDevices();

// Accumulate devices by EpName
// Passing all devices for a given EP in a single call allows the execution provider
// to select the best configuration or combination of devices, rather than being limited
// to a single device. This enables optimal use of available hardware if supported by the EP.
var epDeviceMap = epDevices
    .GroupBy(device => device.EpName)
    .ToDictionary(g => g.Key, g => g.ToList());

// For demonstration, list all found EPs, vendors, and device types
foreach (var epGroup in epDeviceMap)
{
    var epName = epGroup.Key;
    var devices = epGroup.Value;

    Console.WriteLine($"Execution Provider: {epName}");
    foreach (var device in devices)
    {
        string deviceType = GetDeviceTypeString(device.HardwareDevice.Type);
        Console.WriteLine($" | Vendor: {device.EpVendor,-16} | Device Type: {deviceType,-8}");
    }
}

// Configure and append each EP type only once, with all its devices
var sessionOptions = new SessionOptions();
foreach ((var epName, var devices) in epDeviceMap)
{
    Dictionary<string, string> epOptions = new();
    switch (epName)
    {
        case "VitisAIExecutionProvider":
            // Demonstrating passing no options for VitisAI
            sessionOptions.AppendExecutionProvider(ortEnv, devices, epOptions);
            Console.WriteLine($"Successfully added {epName} EP");
            break;

        case "OpenVINOExecutionProvider":
            // Configure threading for OpenVINO EP, pick the first device found
            epOptions["num_of_threads"] = "4";
            sessionOptions.AppendExecutionProvider(ortEnv, [devices.First()], epOptions);
            Console.WriteLine($"Successfully added {epName} EP (first device only)");
            break;

        case "QNNExecutionProvider":
            // Configure performance mode for QNN EP
            epOptions["htp_performance_mode"] = "high_performance";
            sessionOptions.AppendExecutionProvider(ortEnv, devices, epOptions);
            Console.WriteLine($"Successfully added {epName} EP");
            break;

        default:
            Console.WriteLine($"Skipping EP: {epName}");
            break;
    }
}

如需詳細資訊,請參閱 ONNX Runtime OrtApi 檔。 若要瞭解 EP 的版本控制策略,請參閱 執行提供者的版本控制檔

步驟 4:編譯模型

ONNX 模型必須編譯成優化表示法,可在裝置的基礎硬體上有效率地執行。 您在步驟 3 中設定的執行提供者有助於執行此轉換。

從 1.22 版開始,ONNX 運行時間已引進新的 API,以更妥善地封裝編譯步驟。 ONNX 運行時間編譯檔提供更多詳細數據(請參閱 OrtCompileApi 結構)。

備註

編譯可能需要幾分鐘的時間才能完成。 如此一來,任何UI都會保持回應,請考慮將此作為應用程式中的背景作業。

// Prepare compilation options using our session we configured in step 3
OrtModelCompilationOptions compileOptions = new(sessionOptions);
compileOptions.SetInputModelPath(modelPath);
compileOptions.SetOutputModelPath(compiledModelPath);

// Compile the model
compileOptions.CompileModel();

步驟 5:執行模型推斷

既然模型已針對裝置上的本機硬體進行編譯,我們可以建立推斷會話並推斷模型。

// Create inference session using compiled model
using InferenceSession session = new(compiledModelPath, sessionOptions);

步驟 6:散發您的應用程式

散發應用程式之前,C# 和C++開發人員必須採取其他步驟,以確保安裝應用程式時,用戶的裝置上已安裝 Windows ML 運行時間。 請參閱 散發您的應用程式 頁面以深入瞭解。

模型編譯

ONNX 模型會以圖形表示,其中節點會對應至運算符(例如矩陣乘法、卷積和其他數學進程),而邊緣會定義它們之間的數據流。

這個以圖表為基礎的結構允許有效率的執行和優化,方法是允許運算元融合等轉換(也就是將多個相關作業結合成單一優化作業),以及圖表剪除(也就是從圖形中移除多餘的節點)。

模型編譯是指利用執行提供者 (EP) 將 ONNX 模型轉換成優化表示法的程式,可在裝置的基礎硬體上有效率地執行。

設計供編譯使用

以下是在應用程式中處理編譯的一些想法。

  • 編譯效能。 編譯可能需要幾分鐘的時間才能完成。 如此一來,任何UI都會保持回應,請考慮將此作為應用程式中的背景作業。
  • 使用者介面更新。 請考慮讓使用者知道您的應用程式是否正在執行任何編譯工作,並在完成時通知它們。
  • 優雅的後援機制。 如果載入已編譯的模型時發生問題,請嘗試擷取失敗的診斷數據,並盡可能讓應用程式回復為使用原始模型,讓應用程式的相關 AI 功能仍然可以使用。

使用裝置原則進行執行提供者選取

除了明確選取 EP 之外,您也可以使用裝置原則,這是一種自然、結果導向的方式,可讓您指定 AI 工作負載的執行方式。 若要這樣做,您將使用 SessionOptions.SetEpSelectionPolicy 上的 OrtApi函式,傳入 OrtExecutionProviderDevicePolicy 值。 您可以使用各種不同的值來自動選取,例如 MAX_PERFORMANCEPREFER_NPUMAX_EFFICIENCY等等。 如需您可以使用的其他值,請參閱 ONNX OrtExecutionProviderDevicePolicy 檔

// Configure the session to select an EP and device for MAX_EFFICIENCY which typically
// will choose an NPU if available with a CPU fallback.
var sessionOptions = new SessionOptions();
sessionOptions.SetEpSelectionPolicy(ExecutionProviderDevicePolicy.MAX_EFFICIENCY);

提供有關 Windows ML 的意見反應

我們很想聽到您關於使用 Windows ML 的意見反應! 如果您遇到任何問題,請使用 Windows 上的意見反應中樞應用程式回報您的問題。

意見反應應在 開發人員平臺 -> Windows Machine Learning 類別下提交。

另請參閱