Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Important
Die Windows ML-Runtime-APIs sind derzeit experimentell und werden für die Verwendung in Produktionsumgebungen nicht unterstützt. Apps, die diese APIs ausprobieren, sollten nicht im Microsoft Store veröffentlicht werden.
Dieses Lernprogramm zeigt die standardmäßige Runtime-API-Sequenz, ohne zu beschreiben, wie Ihre App das Modell erwirbt oder packt. Das Modell kann sich überall dort befinden, auf den Ihre App zugreifen kann; übergeben Sie einen absoluten oder relativen Pfad an LoadModelFromFile.
Im folgenden Hilfsprogramm wird absichtlich davon ausgegangen, dass ein Modell mit einem Input FLOAT32 mit fester Form verwendet wird. Dadurch wird der Tensor-Allokierungscode auf die Runtime-API beschränkt und ist keine Produktbeschränkung. Wenn Ihre App freie Dimensionen verwendet, binden Sie konkrete Tensorabmessungen für jeden Lauf; wenn sie andere Datentypen verwendet, erstellen Sie einen übereinstimmenden Eingabespeicher.
Bevor Sie anfangen
Schließen Sie das Einrichten eines C++-Projekts für die Windows ML-Runtime-API ab. Sie benötigen auch ein ONNX-Modell, dessen Eingabespezifikation Sie verstehen.
Hinzufügen eines Helfers zum Ausführen eines Modells
Fügen Sie ihrem Projekt die folgenden Kopfzeilen und den RunModel Helper hinzu:
// Copyright (C) Microsoft Corporation. All rights reserved.
#include <Windows.h>
#include <cstdint>
#include <iostream>
#include <string>
#include <vector>
#include <winrt/base.h>
#include <WinMLRuntime.h>
#pragma comment(lib, "windowsapp.lib")
void RunModel(std::wstring const& modelPath)
{
winrt::com_ptr<IWinMLRuntime> runtime;
winrt::check_hresult(WinMLCreateRuntime(
__uuidof(IWinMLRuntime),
runtime.put_void()));
winrt::com_ptr<IWinMLModel> model;
winrt::check_hresult(runtime->LoadModelFromFile(
modelPath.c_str(),
nullptr,
nullptr,
model.put()));
winrt::com_ptr<IWinMLExecutionTarget> target;
winrt::check_hresult(runtime->CreateCpuExecutionTarget(target.put()));
winrt::com_ptr<IWinMLPipelineBuilder> builder;
winrt::check_hresult(runtime->CreatePipelineBuilder(builder.put()));
winrt::com_ptr<IWinMLStage> stage;
winrt::check_hresult(builder->AddModelStage(
model.get(),
target.get(),
L"model",
stage.put()));
winrt::com_ptr<IWinMLPipeline> pipeline;
winrt::check_hresult(builder->Build(pipeline.put()));
winrt::com_ptr<IWinMLModelSchema> schema;
winrt::check_hresult(model->QueryInterface(
__uuidof(IWinMLModelSchema),
schema.put_void()));
WINML_TENSOR_SCHEMA_DESC inputSchema = {};
winrt::check_hresult(schema->GetInputTensorDesc(0, &inputSchema));
if (inputSchema.dataType != WINML_TENSOR_DATA_TYPE_FLOAT32 ||
(inputSchema.dimensionCount > 0 &&
inputSchema.dimensions == nullptr))
{
winrt::throw_hresult(E_INVALIDARG);
}
UINT64 elementCount = 1;
for (UINT32 i = 0; i < inputSchema.dimensionCount; ++i)
{
const UINT64 dimension = inputSchema.dimensions[i];
if (dimension == 0 ||
dimension == UINT64_MAX ||
elementCount > UINT64_MAX / dimension)
{
winrt::throw_hresult(E_INVALIDARG);
}
elementCount *= dimension;
}
if (elementCount > SIZE_MAX)
{
winrt::throw_hresult(E_BOUNDS);
}
std::vector<float> inputData(
static_cast<size_t>(elementCount),
0.5f);
WINML_TENSOR_DESC inputDesc = {};
inputDesc.dataType = inputSchema.dataType;
inputDesc.dimensionCount = inputSchema.dimensionCount;
inputDesc.dimensions = inputSchema.dimensions;
winrt::com_ptr<IWinMLRawTensorFactory> tensorFactory;
winrt::check_hresult(target->QueryInterface(
__uuidof(IWinMLRawTensorFactory),
tensorFactory.put_void()));
winrt::com_ptr<IWinMLTensor> inputTensor;
winrt::check_hresult(tensorFactory->CreateTensor(
&inputDesc,
inputData.data(),
inputData.size() * sizeof(float),
inputTensor.put()));
winrt::check_hresult(stage->BindInput(0, inputTensor.get()));
winrt::check_hresult(pipeline->Run());
winrt::com_ptr<IWinMLTensor> outputTensor;
winrt::check_hresult(stage->GetOutput(0, outputTensor.put()));
winrt::com_ptr<IWinMLTensorDataLock> outputLock;
winrt::check_hresult(outputTensor->Lock(
WINML_TENSOR_LOCK_MODE_READ,
WINML_TENSOR_LOCK_FLAG_NONE,
outputLock.put()));
BYTE* outputBytes = nullptr;
UINT64 outputSizeInBytes = 0;
winrt::check_hresult(outputLock->GetData(
&outputBytes,
&outputSizeInBytes));
(void)outputBytes;
std::wcout << L"Output bytes: " << outputSizeInBytes << L'\n';
}
Übergeben Sie das Ausführungsziel sowohl an AddModelStage als auch an die Tensorfabrik, um die Modellvorbereitung und die Tensorplatzierung auf demselben Ziel beizubehalten.
Lock richtet ein CPU-Zugriffsfenster für den Ausgabe-Tensor ein. Es führt alle erforderlichen Zuordnungen oder Synchronisierungen aus, und der von GetData zurückgegebene Zeiger bleibt nur gültig, solange outputLock aktiv ist.
Hilfsprogramm aufrufen
Rufen Sie RunModel mit dem Modellpfad auf. Beispielsweise akzeptiert der folgende Befehl wmain den Pfad in der Befehlszeile:
int wmain(int argc, wchar_t** argv)
{
if (argc != 2)
{
std::wcerr << L"Usage: RuntimeApp.exe <model-path>\n";
return 1;
}
RunModel(argv[1]);
return 0;
}
Erstellen und Ausführen der App:
.\x64\Release\RuntimeApp.exe C:\models\model.onnx
Ersetzen Sie den Pfad durch den Pfad Ihres Modells. Interpretieren Sie den zurückgegebenen Tensor gemäß dem Ausgabeschema dieses Modells; Klassifizierungsbezeichnungen, Token-Sampling, Bildvorverarbeitung und anderes modellspezifisches Verhalten gehören zu Ihrer App.