Основные понятия API среды выполнения машинного обучения Windows

Important

В настоящее время API среды выполнения машинного обучения Windows является экспериментальным и не поддерживается для использования в производственных средах. Приложения, тестирующие этот API, не должны быть опубликованы в Microsoft Store.

Windows ML Runtime API — это собственная локальная платформа вывода искусственного интеллекта, созданная специально для Windows. С помощью API среды выполнения машинного обучения Windows у вас есть явный контроль над загрузкой модели, назначением аппаратного устройства выполнения, управлением владением тензорами, составом конвейера, компиляцией и диагностикой.

Мы рекомендуем использовать Runtime API для оптимальной производительности инференса модели в Windows, но если приложение должно работать на других платформах или если у вас уже есть кроссплатформенный код ONNX Runtime, можно также использовать ONNX Runtime через Windows ML.

Как объекты сочетаются друг с другом

IWinMLRuntime
  |-- loads --> IWinMLModel
  |-- creates -> IWinMLExecutionTarget
  `-- creates -> IWinMLPipelineBuilder
                   |-- adds/connects -> IWinMLStage
                   `-- Build() ------> IWinMLPipeline

IWinMLExecutionTarget -- creates --> IWinMLTensor
IWinMLStage ----------- binds -----> IWinMLTensor
IWinMLPipeline -------- Run() -----> stage outputs

Каждый метод возвращает HRESULT, и каждый указатель интерфейса следует обычному подсчету ссылок COM. Необязательные возможности обнаруживаются с QueryInterface; недоступная возможность возвращает E_NOINTERFACE.

Runtime

Создайте IWinMLRuntime с помощью WinMLCreateRuntime. Используйте его для загрузки артефактов модели, создания целевых объектов выполнения и создания построителей конвейеров.

Модели и схемы

IWinMLModel является неизменяемым непрозрачным объектом, представляющим собой артефакт модели. LoadModelFromFile принимает любой абсолютный или относительный путь к файлу, который приложение может читать; расположение модели зависит от способа упаковки приложения.

При загрузке проверяется, распознается ли артефакт и структурно читаем. Целевая совместимость подтверждается позже, когда метод Build построителя конвейера завершается успешно.

Отразите объявленную порядковую схему модели через IWinMLModelSchema. Некоторые артефакты ONNX также предоставляют имена через необязательное IWinMLOrtModelSchema, но идентификатор выполнения по-прежнему определяется позицией.

Фигуры и операторы

Объявленная схема модели может содержать свободные измерения, представленные UINT64_MAX. Бетон IWinMLTensor всегда имеет определенные размеры. Конвейеры, поддерживаемые ORT, могут привязывать и запускать конкретные значения для нефиксированной размерности.

Фиксированные или явно ограниченные формы остаются основой оптимизированного проектирования, так как они позволяют Build проверять совместимость, выделять стабильные ресурсы и определять, допустимо ли воспроизведение или итерация, выполняемая в памяти устройства. Они также обеспечивают самую широкую совместимость среди бэкендов выполнения. Это различие между оптимизацией и переносимостью, а не огульный отказ от моделей, в объявленной схеме ONNX которых содержатся свободные измерения.

Стандартные операторы ONNX также повышают переносимость бэкенда. Успешная загрузка модели не гарантирует, что каждая целевая платформа может выполнять каждый оператор; Build выполняет проверку совместимости.

Backends

Файл модели выбирает бэкенд. Приложение использует одни и те же объекты Runtime в любом случае: модель, цель выполнения, построитель конвейеров, этапы, привязки и Run.

Файл модели Backend Аппаратное ускорение
.onnx, .ort Среда выполнения ONNX Поставщики исполнения (EP), которые Windows устанавливает и поддерживает в актуальном состоянии через каталог EP Windows ML
.gguf llama.cpp модули llama.cpp, поставляемые вместе с вашим приложением: модуль ЦП в пакете и дополнительный модуль CUDA для графических процессоров NVIDIA. CPU и CUDA — единственные бэкенды llama.cpp, которые Windows ML проверяет в этом выпуске.

Бэкенды различаются тем, что можно выразить с помощью этапа:

Capability Среда выполнения ONNX llama.cpp
Форма сцены Любой граф ONNX; несколько этапов можно соединить в одном конвейере Один этап декодирования на каждый файл GGUF: идентификаторы токенов (вход 0), на выходе — логиты (выход 0)
Состояние последовательности (кэш KV) Объявите пары тензоров состояния с IWinMLStatefulStageOptions; среда выполнения управляет ими. Принадлежит серверной части; объявлять нечего
Длина контекста SetSequenceCapacityHint перед Build, или объявленная емкость модели SetSequenceCapacityHint перед Build задает длину контекста llama.cpp
Параметры привязки поставщика и этапа ORT Поддерживается (WinMLRuntimeOrt.h) Не поддерживается; Build возвращает HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED)
Отчет после размещения Build IWinMLOrtStageDiagnostics указывает запрошенных и выбранных поставщиков IWinMLStage::GetExecutionTarget сообщает о ЦП или GPU

Один конвейер может смешивать бэкенды. Например, этап Whisper в среде выполнения ONNX может передавать данные в языковую модель GGUF в llama.cpp.

Цели выполнения

IWinMLExecutionTarget — это неизменяемый токен размещения, который задаёт класс оборудования и, необязательно, конкретный адаптер. Каждая серверная часть обрабатывает это при выполнении Build:

Цель этапа Среда выполнения ONNX llama.cpp
nullptr передано для AddModelStage Автоматическое размещение выбирает совместимый GPU EP при доступности, с переходом на ЦП при недоступности. Перенаправляется в модуль CUDA, если он развернут и модель помещается; в противном случае выполняется на ЦП.
CreateCpuExecutionTarget Выбирает совместимый CPU EP с поставщиком CPU ORT в качестве базового варианта. Выполняется на ЦП.
CreateExecutionTarget с типом GPU, CreateExecutionTargetFromAdapter или CreateExecutionTargetFromD3D12 Сопоставляет идентификатор адаптера с совместимым устройством GPU EP. Если ни одно устройство поставщика не подходит, Build завершается ошибкой. Требуется по крайней мере частичный перенос обработки на модуль CUDA. Build возвращает HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), когда модуль CUDA не развернут, и HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY), когда модель не помещается. Модуль выбирает GPU; идентификатор адаптера не используется.
CreateExecutionTarget с видом NPU или адаптером NPU Сопоставляется с совместимым устройством NPU EP. Не поддерживается; Build возвращает HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED).
IWinMLOrtCompatibility::CreateExecutionTarget(provider, kind, hardwareTarget) Закрепляет один зарегистрированный EP. Если hardwareTarget задано значение nullptr, среда выполнения связывает поставщика с одним из своих устройств; на компьютере с двумя gpu, это позволяет избежать связывания поставщика с адаптером, который он не поддерживает. Не поддерживается; Build возвращает HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED).

IWinMLRuntime::CreateExecutionTarget(kind, preference) выбирает адаптер запрошенного класса, не требуя от вас самостоятельно перечислять устройства, и preference ранжирует адаптеры, если существует несколько, например интегрированный и дискретный GPU:

ComPtr<IWinMLExecutionTarget> target;
THROW_IF_FAILED(runtime->CreateExecutionTarget(
    WINML_EXECUTION_TARGET_KIND_GPU,
    WINML_EXECUTION_TARGET_PREFERENCE_PERFORMANCE,
    target.GetAddressOf()));

Для явного выбора адаптера требуется совместимый поставщик ONNX Runtime, чтобы предоставить этот идентификатор оборудования через ORT. Если подходящее устройство поставщика не найдено, Build завершается с ошибкой вместо того, чтобы молча выбирать другой адаптер или ЦП.

CreateExecutionTargetFromD3D12 сохраняет устройство вызывающего и необязательную очередь у цели, но выполнение ORT использует только идентификатор адаптера для выбора EP. Поставщик ORT владеет своими ресурсами выполнения, и очередь команд вызывающего объекта не используется для отправки ORT.

Целевой объект D3D12 по-прежнему предоставляет доступ через IWinMLD3D12ExecutionTarget–QueryInterface. Повторное использование одного явного целевого объекта на этапах выражает связь с тем же адаптером; отдельные целевые объекты делают границы передачи явными.

Запустить модель GGUF

  1. Загрузите файл с помощью LoadModelFromFile. Расширение .gguf выбирается llama.cpp. Для шардированной модели сохраните каждый шард в одной папке и загрузите первый шард.
  2. Добавьте один этап модели с CPU, GPU или целью nullptr. Чтобы задать длину контекста, выполните запрос IWinMLStatefulStageOptions на этапе и вызовите SetSequenceCapacityHint.
  3. Вызовите Build. Затем привяжите идентификаторы маркеров запроса к входу 0, запросите выход 0, затем вызовите Run. Каждый последующий запуск принимает следующий токен; серверная часть сохраняет кэш KV между запусками.
  4. Вызовите ResetExecutionState перед независимой последовательностью.
// Create the runtime and an execution target (CPU here; GPU also available).
ComPtr<IWinMLRuntime> runtime;
THROW_IF_FAILED(WinMLCreateRuntime(IID_PPV_ARGS(runtime.GetAddressOf())));
ComPtr<IWinMLExecutionTarget> target;
THROW_IF_FAILED(runtime->CreateCpuExecutionTarget(target.GetAddressOf()));

ComPtr<IWinMLModel> model;
THROW_IF_FAILED(runtime->LoadModelFromFile(
    L"C:\\models\\qwen2.5-0.5b-instruct.gguf", nullptr, model.GetAddressOf()));

ComPtr<IWinMLPipelineBuilder> builder;
THROW_IF_FAILED(runtime->CreatePipelineBuilder(builder.GetAddressOf()));

ComPtr<IWinMLStage> stage;
THROW_IF_FAILED(builder->AddModelStage(
    model.Get(), target.Get(), L"decoder", stage.GetAddressOf()));
THROW_IF_FAILED(stage->RequestOutput(0));

// Set the llama.cpp context length before Build.
ComPtr<IWinMLStatefulStageOptions> stateOptions;
THROW_IF_FAILED(stage->QueryInterface(IID_PPV_ARGS(stateOptions.GetAddressOf())));
THROW_IF_FAILED(stateOptions->SetSequenceCapacityHint(4096));

ComPtr<IWinMLPipeline> pipeline;
THROW_IF_FAILED(builder->Build(pipeline.GetAddressOf()));

// Bind token IDs to input 0 and run one token at a time; the backend keeps
// the KV cache between runs.
THROW_IF_FAILED(stage->BindInput(0, tokenIdsTensor.Get()));
THROW_IF_FAILED(pipeline->Run());

ComPtr<IWinMLTensor> logits;
THROW_IF_FAILED(stage->GetOutput(0, logits.GetAddressOf()));

// Start an independent sequence on the same pipeline.
THROW_IF_FAILED(pipeline->ResetExecutionState());

Форматирование токенизатора и диалога исходит из файла GGUF, поэтому модель GGUF не нуждается в отдельных файлах токенизатора. Чтобы пропустить цикл токенов, используйте Text Generation API, который работает с моделями GGUF и ONNX.

Разверните серверную часть llama.cpp

Бэкенд llama.cpp локален для приложения. Когда проект явно включается, пакет NuGet Windows ML копирует адаптер llama.cpp среды выполнения, ядро llama.cpp и модуль ЦП рядом с вашим приложением. Для ускорения GPU требуется необязательный модуль CUDA, созданный для той же ревизии llama.cpp, что и пакет, и помещенный рядом с приложением.

Пошаговое руководство для обоих этапов см. в примерах модели GGUF и примерах llama.cpp.

Конвейеры и этапы

Создайте конвейер с помощью one-shot IWinMLPipelineBuilder:

  1. Добавьте этапы модели или процессора с целями выполнения.
  2. Подключите порты этапа по порядковому индексу.
  3. Вызовите Build один раз, чтобы заморозить граф, выполнить размещение и проверить совместимость.

Для двух этапов модели добавьте оба этапа, подключите выходной порядковый номер первого этапа к входному порядковому номеру второго этапа и выполните сборку один раз. Приложение предоставляет модели и подключает любые внешние входные данные. Для этого не нужен API среды выполнения для конкретной модели: эмбеддинг, декодер, предварительная обработка изображений и другие архитектуры приложений используют те же примитивы этапов и тензоров.

Каждый IWinMLStage владеет позиционными входными привязками и предоставляет текущие выходные тензоры. Входные привязки сохраняются между запусками. Вызовите BindOutput перед выполнением, когда приложение предоставляет выходное хранилище.

Дополнительные возможности этапа включают определённый целевой объект, материализованную схему, политику размещения выходных данных и управление состоянием последовательности. Используется QueryInterface для проверки каждой возможности.

Выполнение конвейера

IWinMLPipeline::Run выполняет подготовленный конвейер синхронно. Вызов ResetExecutionState между независимыми последовательностями для очистки управляемого средой выполнения состояния.

Необязательные интерфейсы выполнения обеспечивают отправку на временной шкале устройства и итеративное воспроизведение с фиксированным числом, когда построенный граф и выбранный бэкенд их поддерживают. Базовый Run путь остается общим ориентиром.

Тензоры и блокировки

IWinMLTensor представляет типизированные многомерные данные. Создайте тензоры из фабрики, запрашиваемой у целевой платформы выполнения, чтобы размещение тензоров следовало целевому размещению.

Фабрики охватывают необработанные байты, данные изображения, звуковые данные, идентификаторы токенов и составные процессоры тензоров. Необязательные интерфейсы тензора поддерживают мутацию, привязки буфера D3D12 и синхронизацию.

Вызовите IWinMLTensor::Lock перед доступом к тензорным байтам на ЦП. Возвращенный IWinMLTensorDataLock устанавливает окно доступа к ЦП, выполняет необходимое сопоставление или синхронизацию и управляет временем жизни указателя, возвращенного GetData.

Компиляция и внешние веса

Предварительная компиляция — это необязательная возможность целевой платформы выполнения, предоставляемая через IWinMLModelCompiler. Скомпилированные артефакты перезагружаются с помощью обычных методов загрузки модели. Приложения могут предоставлять внешние коэффициенты через IWinMLResourceMapReader.

Нагрузки для текста

Текстовые задачи используют ту же среду выполнения, цель, конвейер, этап и примитивы тензоров. Приложение может самостоятельно управлять метаданными пакета модели, выборкой, политикой остановки и накоплением сгенерированных токенов напрямую или использовать API создания текста для координации этих операций через совместимый конвейер среды выполнения.

IWinMLTokenizer предоставляет низкоуровневые операции кодирования и декодирования. Объект IWinMLTokenizerDecoder поддерживает независимый курсор добавочного декодирования для одной последовательности. API генерации текста добавляет сеансы генерации текста, параметры, потоковую передачу обновлений, отмену, причины завершения и завершенные результаты без изменения владения базовыми объектами среды выполнения.

Совместимость ONNX Runtime

Необязательные интерфейсы в WinMLRuntimeOrt.h предоставляют удобные возможности для ONNX:

  • IWinMLOrtCompatibility выбирает уже зарегистрированного поставщика выполнения ONNX Runtime.
  • IWinMLOrtModelSchema отражает имена входных и выходных параметров.
  • IWinMLOrtNamedBindings привязывает этап с поддержкой ORT по имени.
  • IWinMLOrtStageDiagnostics отчеты, запрошенные и выбранные после Build.

Эти интерфейсы определяют имена и политику поставщика во время установки. Выполнение продолжает использовать тот же контракт конвейера обработки по позиции.

Запросите IWinMLOrtCompatibility у среды выполнения, чтобы закрепить этап модели ONNX за поставщиком выполнения, который вы уже зарегистрировали, вместо того чтобы позволить Build выбрать его автоматически:

ComPtr<IWinMLOrtCompatibility> ortCompatibility;
THROW_IF_FAILED(runtime->QueryInterface(IID_PPV_ARGS(ortCompatibility.GetAddressOf())));

ComPtr<IWinMLExecutionTarget> target;
THROW_IF_FAILED(ortCompatibility->CreateExecutionTarget(
    L"MyRegisteredProvider",
    WINML_EXECUTION_TARGET_KIND_GPU,
    /* hardwareTarget */ nullptr,
    target.GetAddressOf()));

Передача nullptr позволяет среде выполнения hardwareTarget связать поставщика с одним из своих собственных устройств этого класса оборудования; вместо этого передайте существующий IWinMLExecutionTarget, чтобы привязать поставщика к этому конкретному адаптеру. Этот целевой объект не поддерживается для .gguf этапов; Build возвращает HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED).

См. также