Add OpenVINO backend for Intel iGPU/dGPU (Arc)
Mirrors the rocm/cuda pattern: ort::ep::OpenVINO with device_type "GPU" (covers both Intel integrated graphics and Arc discrete GPUs through the same EP), load-dynamic/dlopen so no OpenVINO toolkit is needed at build time, and its own --openvino flag / backend = "openvino" config value. Folded into the `full` feature alongside npu/rocm/cuda. OpenVINO's provider options go through a generic key/value FFI interface rather than a fixed C struct (unlike MIGraphX's OrtMIGraphXProviderOptions), so it should be less exposed to the ABI-version-skew crash MIGraphX hit -- but that's inference from the EP's design, not verified against real hardware. Like CUDA, this is compile-checked only: no Intel GPU in this dev environment to runtime-verify against. Version bump: breadmill 0.2.2 -> 0.2.3.
This commit is contained in:
parent
e5922e9c90
commit
c6ed6a41d8
8 changed files with 112 additions and 35 deletions
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "breadmill"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
|
||||
|
|
@ -14,13 +14,17 @@ npu = ["ort/vitis", "ort/load-dynamic"]
|
|||
# libonnxruntime_providers_rocm.so, which most distros don't package.
|
||||
rocm = ["ort/migraphx", "ort/load-dynamic"]
|
||||
cuda = ["ort/cuda", "ort/load-dynamic"]
|
||||
# Intel iGPU/dGPU (Arc) + CPU via OpenVINO. One EP covers Intel's whole
|
||||
# hardware line by device_type string ("CPU"/"GPU"/"GPU.0"/"NPU"/"HETERO:...");
|
||||
# we always request "GPU" since CPU is already covered by the cpu backend.
|
||||
openvino = ["ort/openvino", "ort/load-dynamic"]
|
||||
# All backends in one binary. Safe to combine: every backend here uses
|
||||
# ort's load-dynamic (dlopen) mode, so none of this links against an actual
|
||||
# NPU/ROCm/CUDA toolkit at build time — which ONNX Runtime actually gets
|
||||
# loaded (and thus which EPs are really available) is decided at runtime by
|
||||
# ORT_DYLIB_PATH / the dynamic linker, per the --npu/--rocm/--cuda flag or
|
||||
# `backend` config value in use for that run.
|
||||
full = ["npu", "rocm", "cuda"]
|
||||
# NPU/ROCm/CUDA/OpenVINO toolkit at build time — which ONNX Runtime actually
|
||||
# gets loaded (and thus which EPs are really available) is decided at
|
||||
# runtime by ORT_DYLIB_PATH / the dynamic linker, per the --npu/--rocm/
|
||||
# --cuda/--openvino flag or `backend` config value in use for that run.
|
||||
full = ["npu", "rocm", "cuda", "openvino"]
|
||||
|
||||
[[bin]]
|
||||
name = "breadmill"
|
||||
|
|
|
|||
|
|
@ -27,6 +27,11 @@ pub enum Backend {
|
|||
Rocm,
|
||||
/// NVIDIA GPU via the CUDA ONNX Runtime execution provider.
|
||||
Cuda,
|
||||
/// Intel iGPU/dGPU (Arc) via the OpenVINO ONNX Runtime execution
|
||||
/// provider, requesting device_type "GPU". `cache_dir` stores OpenVINO's
|
||||
/// compiled-model blobs between runs (its own `with_cache_dir`, not an
|
||||
/// env var — unlike MIGraphX this doesn't need a workaround).
|
||||
OpenVino { cache_dir: PathBuf },
|
||||
}
|
||||
|
||||
pub struct OrtEmbedder {
|
||||
|
|
@ -165,6 +170,7 @@ fn configure_eps(builder: SessionBuilder, backend: &Backend) -> Result<SessionBu
|
|||
Backend::Npu { cache_dir } => npu_session(builder, cache_dir),
|
||||
Backend::Rocm => rocm_session(builder),
|
||||
Backend::Cuda => cuda_session(builder),
|
||||
Backend::OpenVino { cache_dir } => openvino_session(builder, cache_dir),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -253,6 +259,36 @@ fn cuda_session(builder: SessionBuilder) -> Result<SessionBuilder, String> {
|
|||
Ok(builder)
|
||||
}
|
||||
|
||||
// ---- OpenVINO EP (Intel iGPU/dGPU) -------------------------------------------
|
||||
|
||||
#[cfg(feature = "openvino")]
|
||||
fn openvino_session(builder: SessionBuilder, cache_dir: &Path) -> Result<SessionBuilder, String> {
|
||||
let ov_cache = cache_dir.join("openvino");
|
||||
std::fs::create_dir_all(&ov_cache).map_err(|e| e.to_string())?;
|
||||
eprintln!("breadmill: using OpenVINO execution provider (device_type GPU)");
|
||||
eprintln!("breadmill: OpenVINO model cache: {}", ov_cache.display());
|
||||
eprintln!(
|
||||
"breadmill: note — check the log line above/below for \"Successfully registered \
|
||||
`OpenVINOExecutionProvider`\"; if it's missing, the ONNX Runtime in use wasn't built \
|
||||
with OpenVINO support and inference silently fell back to CPU"
|
||||
);
|
||||
builder
|
||||
.with_execution_providers([
|
||||
ort::ep::OpenVINO::default()
|
||||
.with_device_type("GPU")
|
||||
.with_cache_dir(ov_cache.to_string_lossy())
|
||||
.build(),
|
||||
ort::ep::CPU::default().build(),
|
||||
])
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "openvino"))]
|
||||
fn openvino_session(builder: SessionBuilder, _cache_dir: &Path) -> Result<SessionBuilder, String> {
|
||||
eprintln!("breadmill: OpenVINO backend requested but not compiled in (rebuild with --features openvino); using CPU");
|
||||
Ok(builder)
|
||||
}
|
||||
|
||||
/// Locate the VitisAI EP config file required by the AMD Ryzen AI SDK.
|
||||
///
|
||||
/// Search order:
|
||||
|
|
|
|||
|
|
@ -39,12 +39,14 @@ fn main() {
|
|||
let use_npu = raw_args.iter().any(|a| a == "--npu");
|
||||
let use_rocm = raw_args.iter().any(|a| a == "--rocm");
|
||||
let use_cuda = raw_args.iter().any(|a| a == "--cuda");
|
||||
let use_openvino = raw_args.iter().any(|a| a == "--openvino");
|
||||
|
||||
// Build a view of argv without backend flags for command matching.
|
||||
let backend_flags = ["--npu", "--rocm", "--cuda", "--openvino"];
|
||||
let args: Vec<&str> = raw_args
|
||||
.iter()
|
||||
.skip(1)
|
||||
.filter(|a| a.as_str() != "--npu" && a.as_str() != "--rocm" && a.as_str() != "--cuda")
|
||||
.filter(|a| !backend_flags.contains(&a.as_str()))
|
||||
.map(|s| s.as_str())
|
||||
.collect();
|
||||
|
||||
|
|
@ -59,7 +61,7 @@ fn main() {
|
|||
}
|
||||
}
|
||||
Some("--reindex") | Some("reindex") => {
|
||||
if let Err(e) = run_daemon(true, use_npu, use_rocm, use_cuda) {
|
||||
if let Err(e) = run_daemon(true, use_npu, use_rocm, use_cuda, use_openvino) {
|
||||
eprintln!("breadmill: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
|
@ -76,7 +78,7 @@ fn main() {
|
|||
cli_status();
|
||||
}
|
||||
None | Some("serve") | Some("--serve") => {
|
||||
if let Err(e) = run_daemon(false, use_npu, use_rocm, use_cuda) {
|
||||
if let Err(e) = run_daemon(false, use_npu, use_rocm, use_cuda, use_openvino) {
|
||||
eprintln!("breadmill: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
|
@ -84,7 +86,7 @@ fn main() {
|
|||
Some(cmd) => {
|
||||
eprintln!("breadmill: unknown command: {}", cmd);
|
||||
eprintln!(
|
||||
"usage: breadmill [serve|reindex|fetch-model|query <text>|status] [--npu|--rocm|--cuda] [--version]"
|
||||
"usage: breadmill [serve|reindex|fetch-model|query <text>|status] [--npu|--rocm|--cuda|--openvino] [--version]"
|
||||
);
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
|
@ -93,7 +95,13 @@ fn main() {
|
|||
|
||||
// ---- Daemon -----------------------------------------------------------------
|
||||
|
||||
fn run_daemon(force_reindex: bool, use_npu: bool, use_rocm: bool, use_cuda: bool) -> Result<(), String> {
|
||||
fn run_daemon(
|
||||
force_reindex: bool,
|
||||
use_npu: bool,
|
||||
use_rocm: bool,
|
||||
use_cuda: bool,
|
||||
use_openvino: bool,
|
||||
) -> Result<(), String> {
|
||||
let config = breadsearch_shared::Config::load();
|
||||
let state_dir = breadsearch_shared::state_dir();
|
||||
let cache_dir = breadsearch_shared::cache_dir();
|
||||
|
|
@ -115,6 +123,8 @@ fn run_daemon(force_reindex: bool, use_npu: bool, use_rocm: bool, use_cuda: bool
|
|||
"rocm"
|
||||
} else if use_cuda {
|
||||
"cuda"
|
||||
} else if use_openvino {
|
||||
"openvino"
|
||||
} else {
|
||||
config.model.backend.as_str()
|
||||
};
|
||||
|
|
@ -132,6 +142,10 @@ fn run_daemon(force_reindex: bool, use_npu: bool, use_rocm: bool, use_cuda: bool
|
|||
eprintln!("breadmill: CUDA backend selected");
|
||||
Backend::Cuda
|
||||
}
|
||||
"openvino" => {
|
||||
eprintln!("breadmill: OpenVINO backend selected");
|
||||
Backend::OpenVino { cache_dir: cache_dir.clone() }
|
||||
}
|
||||
_ => Backend::Cpu,
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue