Skip to content

EP vendor compatibility ignores CPU vendor, marking OpenVINO EP [incompatible] on Intel-CPU machines #1274

Description

@xieofxie

Summary

EPCatalog.is_compatible() decides EP↔hardware compatibility (the "L2" vendor check) using only GPU and NPU vendor strings. CPU is never considered.

OpenVINO EP supports Intel CPU as a valid device, so on a machine with an Intel CPU but no Intel GPU/NPU, the EP is incorrectly reported as [incompatible] and is excluded from EP/device selection.

Repro

Machine: Intel Core i9-10900X CPU + NVIDIA GeForce RTX 4080 (no Intel iGPU, no NPU).

winml sys output:

OpenVINOExecutionProvider  [incompatible]
  [incompatible] Catalog (catalog default)
    Version: 1.3.0+b130ce1
    Path: C:\Program Files\WindowsApps\MicrosoftCorporationII.WinML.Intel.OpenVINO.EP.1.8_1.8.69.0_x64__8wekyb3d8bbwe\ExecutionProvider\onnxruntime_providers_openvino_plugin.dll

The DLL is installed and registers successfully (it is not an L1 [failed] row) — it is purely the L2 vendor rule that rejects it.

Detected vendor strings on this machine:

>>> from winml.modelkit.ep_path import _get_detected_vendors
>>> sorted(_get_detected_vendors())
['NVIDIA', 'NVIDIA GeForce RTX 4080']

>>> from winml.modelkit.sysinfo.hardware import CPU
>>> [(c.manufacturer, c.name) for c in CPU.get_all()]
[('GenuineIntel', 'Intel(R) Core(TM) i9-10900X CPU @ 3.70GHz')]

"Intel" is present on the CPU, but the CPU is not scanned, so EP_CATALOG.is_compatible("OpenVINOExecutionProvider") returns False.

Root cause

src/winml/modelkit/ep_path.py_get_detected_vendors() iterates only GPU and NPU:

strings: set[str] = set()
for cls in (GPU, NPU):
    for hw in cls.get_all():
        for attr in ("manufacturer", "name"):
            ...

EPCatalog.Row(name="OpenVINOExecutionProvider", ..., vendor_requirements=frozenset({"Intel"})) therefore never matches on a discrete-GPU-only Intel system.

winml.modelkit.sysinfo.hardware.CPU already exposes manufacturer ("GenuineIntel") and name ("Intel(R) Core(TM) i9-10900X ..."), so the data is available — it is simply not aggregated.

Impact

Beyond the misleading winml sys label, the same predicate gates real EP selection and validation:

  • src/winml/modelkit/commands/sys.py:893,896 — status shown as incompatible, and the device list is suppressed for the row.
  • src/winml/modelkit/config/build.py:355 — build config validation rejects the EP.
  • src/winml/modelkit/session/ep_device.py:496,612,692,764 — EP/device deduction skips the EP, so OpenVINOExecutionProvider with a CPU device cannot be auto-selected (and explicit selection is likely rejected).

Net effect: OpenVINO CPU inference is unreachable on Intel-CPU machines without an Intel GPU/NPU.

Expected behavior

An EP whose vendor requirement is satisfied by any detected device class — CPU included — should be treated as compatible. OpenVINO on an Intel CPU should show as [primary] (or [shadowed]), list its available devices, and be selectable for build/session.

Notes / open questions for design

  • Adding CPU to the _get_detected_vendors() scan is the minimal fix, but it makes the check coarser: matching is a plain substring test over a flat vendor set, so it cannot express "this EP needs an Intel NPU" vs "an Intel CPU is enough". If any future EP needs device-class-specific gating, vendor_requirements should become vendor+device-class pairs rather than bare strings.
  • Vendor requirements are currently modeled per-EP, not per-device — worth confirming whether the other gated EPs (QNN/Qualcomm, VitisAI/MIGraphX/AMD) should also honor CPU vendor, or whether CPU should be opt-in per catalog row.
  • _get_detected_vendors() is functools.cached and raises RuntimeError on detection failure by design; a CPU addition must preserve that behavior (no silent empty-set fallback).
  • Tests to extend: tests/unit/ep_path/test_compat.py, tests/unit/session/test_is_compatible.py, tests/unit/session/test_ep_device.py.

Metadata

Metadata

Labels

bugSomething isn't workinghardwareHardware relatedneed triageNeeds triage

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions