Compartilhar via


Inicializar provedores de execução com o Windows ML

Esta página discute maneiras mais avançadas de seu aplicativo lidar normalmente com o download e o registro de EPs (provedores de execução) usando o Windows ML. Mesmo que um EP já esteja baixado no dispositivo, você deve registrar os EPs sempre que o aplicativo for executado para que eles apareçam no ONNX Runtime.

Baixar e registrar-se em uma chamada

Para o desenvolvimento inicial, pode ser bom simplesmente chamar EnsureAndRegisterCertifiedAsync(), que baixará todos os novos EPs (ou novas versões de EPs) compatíveis com seu dispositivo e drivers se eles ainda não estiverem baixados e, em seguida, registrar todos os EPs. Observe que, na primeira execução, esse método pode levar vários segundos ou até mesmo minutos, dependendo da velocidade da rede e dos EPs que precisam ser baixados.

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

Dica

Em aplicativos de produção, embrulhe a EnsureAndRegisterCertifiedAsync() chamada em um bloco try-catch para lidar com possíveis falhas de rede ou download normalmente.

Registrar somente provedores existentes

Se você quiser evitar o download e registrar apenas os provedores de execução que já estão presentes no computador:

var catalog = ExecutionProviderCatalog.GetDefault();

// Register only providers already present on the machine
// This avoids potentially long download times
await catalog.RegisterCertifiedAsync();

Descobrir se há novos EPs (sem baixar)

Se você quiser ver se há novos EPs compatíveis com seu dispositivo e drivers disponíveis para download, mas não quiser iniciar o download, você pode usar o FindAllProviders() método e, em seguida, ver se algum provedor tem um ReadyState de NotPresent. Em seguida, você pode decidir lidar com isso como quiser (iniciando seus usuários em uma "Tela de atualização", perguntando se eles querem atualizar etc.). Você pode optar por continuar usando os EPs já baixados (chamando RegisterCertifiedAsync() conforme mostrado acima) se não quiser fazer com que os usuários aguardem agora.

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();
}

Baixar e registrar um EP específico

Se houver um provedor de execução específico que seu aplicativo deseja usar, você poderá baixar e registrar um provedor de execução específico sem baixar todos os EPs compatíveis.

Primeiro você usará FindAllProviders() para obter todos os EPs compatíveis e, em seguida, poderá chamar EnsureReadyAsync() um ExecutionProvider específico para baixar o provedor de execução específico e chamar TryRegister() para registrar o provedor de execução específico.

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();
    }
}

Exemplo de aplicativo de produção

Para aplicativos de produção, aqui está um exemplo do que seu aplicativo pode querer fazer para fornecer a si mesmo e aos usuários o controle sobre quando os downloads ocorrem. Você pode verificar se novos provedores de execução estão disponíveis e baixá-los condicionalmente:

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();
    }
}