From 255e58106af7b5691f1d2744d502abf23e1df55e Mon Sep 17 00:00:00 2001 From: Rahul Date: Wed, 22 May 2024 15:57:22 -0700 Subject: [PATCH 1/7] add core functions for devices, properties, version Co-authored-by: Bradley Odell --- crates/openvino/src/core.rs | 170 ++++++++++++++++++++++++++++++++++-- 1 file changed, 164 insertions(+), 6 deletions(-) diff --git a/crates/openvino/src/core.rs b/crates/openvino/src/core.rs index 577cac7..ee574ca 100644 --- a/crates/openvino/src/core.rs +++ b/crates/openvino/src/core.rs @@ -4,16 +4,23 @@ use crate::error::LoadingError; use crate::{cstr, drop_using_function, try_unsafe, util::Result}; use crate::{model::CompiledModel, Model}; -use crate::{DeviceType, SetupError, Tensor}; +use crate::{DeviceType, PropertyKey, RwPropertyKey, SetupError, Tensor, Version}; use openvino_sys::{ - self, ov_core_compile_model, ov_core_create, ov_core_create_with_config, ov_core_free, - ov_core_read_model, ov_core_read_model_from_memory_buffer, ov_core_t, + self, ov_available_devices_free, ov_core_compile_model, ov_core_create, + ov_core_create_with_config, ov_core_free, ov_core_get_available_devices, ov_core_get_property, + ov_core_get_versions_by_device_name, ov_core_read_model, ov_core_read_model_from_memory_buffer, + ov_core_set_property, ov_core_t, ov_core_versions_free, }; -use std::ffi::CString; - +use std::borrow::Cow; +use std::collections::HashMap; +use std::ffi::{CStr, CString}; use std::os::raw::c_char; +use std::slice; +use std::str::FromStr; + +const EMPTY_C_STR: &'static CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"\0") }; -/// See [`Core`](https://docs.openvino.ai/2023.3/api/c_cpp_api/group__ov__core__c__api.html). +/// See [`Core`](https://docs.openvino.ai/2024/api/c_cpp_api/group__ov__core__c__api.html). pub struct Core { ptr: *mut ov_core_t, } @@ -40,6 +47,157 @@ impl Core { Ok(Core { ptr }) } + /// Gets device plugins version information. + /// Device name can be complex and identify multiple devices at once like `HETERO:CPU,GPU`; + /// in this case, the returned map contains multiple entries, each per device. + pub fn versions(&self, device_name: impl AsRef) -> Result> { + let device_name = cstr!(device_name.as_ref()); + let mut ov_version_list = openvino_sys::ov_core_version_list_t { + versions: std::ptr::null_mut(), + size: 0, + }; + try_unsafe!(ov_core_get_versions_by_device_name( + self.ptr, + device_name, + std::ptr::addr_of_mut!(ov_version_list) + ))?; + + let ov_versions = + unsafe { slice::from_raw_parts(ov_version_list.versions, ov_version_list.size) }; + + let mut versions: HashMap = + HashMap::with_capacity(ov_version_list.size); + for ov_version in ov_versions { + let c_str_device_name = unsafe { std::ffi::CStr::from_ptr(ov_version.device_name) }; + let device_name = c_str_device_name.to_string_lossy(); + let device_type = DeviceType::from_str(device_name.as_ref()).unwrap(); + versions.insert(device_type, Version::from(&ov_version.version)); + } + + unsafe { ov_core_versions_free(std::ptr::addr_of_mut!(ov_version_list)) }; + Ok(versions) + } + + /// Gets devices available for inference. + pub fn available_devices(&self) -> Result> { + let mut ov_available_devices = openvino_sys::ov_available_devices_t { + devices: std::ptr::null_mut(), + size: 0, + }; + try_unsafe!(ov_core_get_available_devices( + self.ptr, + std::ptr::addr_of_mut!(ov_available_devices) + ))?; + + let ov_devices = unsafe { + slice::from_raw_parts(ov_available_devices.devices, ov_available_devices.size) + }; + + let mut devices = Vec::with_capacity(ov_available_devices.size); + for ov_device in ov_devices { + let c_str_device_name = unsafe { std::ffi::CStr::from_ptr(*ov_device) }; + let device_name = c_str_device_name.to_string_lossy(); + let device_type = DeviceType::from_str(device_name.as_ref()).unwrap(); + devices.push(device_type); + } + + unsafe { ov_available_devices_free(std::ptr::addr_of_mut!(ov_available_devices)) }; + Ok(devices) + } + + /// Gets properties related to this Core. + /// + /// The method extracts information that can be set via the [set_property] method. + pub fn property(&self, key: PropertyKey) -> Result> { + let ov_prop_key = cstr!(key.as_ref()); + let mut ov_prop_value = std::ptr::null_mut(); + try_unsafe!(ov_core_get_property( + self.ptr, + EMPTY_C_STR.as_ptr(), + ov_prop_key, + std::ptr::addr_of_mut!(ov_prop_value) + ))?; + let rust_prop = unsafe { CStr::from_ptr(ov_prop_value) }.to_string_lossy(); + Ok(rust_prop) + } + + /// Sets a property for this Core instance. + pub fn set_property(&mut self, key: RwPropertyKey, value: &str) -> Result<()> { + let ov_prop_key = cstr!(key.as_ref()); + let ov_prop_value = cstr!(value); + try_unsafe!(ov_core_set_property( + self.ptr, + EMPTY_C_STR.as_ptr(), + ov_prop_key, + ov_prop_value, + ))?; + Ok(()) + } + + /// Sets properties for this Core instance. + pub fn set_properties<'a>( + &mut self, + properties: impl IntoIterator, + ) -> Result<()> { + for (prop_key, prop_value) in properties { + self.set_property(prop_key, prop_value)?; + } + Ok(()) + } + + /// Gets properties related to device behaviour. + /// + /// The method extracts information that can be set via the [set_device_property] method. + pub fn device_property( + &self, + device_name: impl AsRef, + key: PropertyKey, + ) -> Result> { + let ov_device_name = cstr!(device_name.as_ref()); + let ov_prop_key = cstr!(key.as_ref()); + let mut ov_prop_value = std::ptr::null_mut(); + try_unsafe!(ov_core_get_property( + self.ptr, + ov_device_name, + ov_prop_key, + std::ptr::addr_of_mut!(ov_prop_value) + ))?; + let rust_prop = unsafe { CStr::from_ptr(ov_prop_value) }.to_string_lossy(); + Ok(rust_prop) + } + + /// Sets a property for a device. + pub fn set_device_property( + &mut self, + device_name: impl AsRef, + key: RwPropertyKey, + value: &str, + ) -> Result<()> { + let ov_device_name = cstr!(device_name.as_ref()); + let ov_prop_key = cstr!(key.as_ref()); + let ov_prop_value = cstr!(value); + try_unsafe!(ov_core_set_property( + self.ptr, + ov_device_name, + ov_prop_key, + ov_prop_value, + ))?; + Ok(()) + } + + /// Sets properties for a device. + pub fn set_device_properties<'a>( + &mut self, + device_name: impl AsRef, + properties: impl IntoIterator, + ) -> Result<()> { + let device_name = device_name.as_ref(); + for (prop_key, prop_value) in properties { + self.set_device_property(device_name, prop_key, prop_value)?; + } + Ok(()) + } + /// Read a Model from a pair of files: `model_path` points to an XML file containing the /// OpenVINO model IR and `weights_path` points to the binary weights file. pub fn read_model_from_file(&mut self, model_path: &str, weights_path: &str) -> Result { From dd9ee338f69732e060e9b9bea8b59b53e86262c7 Mon Sep 17 00:00:00 2001 From: Rahul Date: Wed, 22 May 2024 15:59:22 -0700 Subject: [PATCH 2/7] formatting comments --- crates/openvino/src/core.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/openvino/src/core.rs b/crates/openvino/src/core.rs index ee574ca..1fa3efa 100644 --- a/crates/openvino/src/core.rs +++ b/crates/openvino/src/core.rs @@ -106,7 +106,6 @@ impl Core { } /// Gets properties related to this Core. - /// /// The method extracts information that can be set via the [set_property] method. pub fn property(&self, key: PropertyKey) -> Result> { let ov_prop_key = cstr!(key.as_ref()); @@ -146,7 +145,6 @@ impl Core { } /// Gets properties related to device behaviour. - /// /// The method extracts information that can be set via the [set_device_property] method. pub fn device_property( &self, From 47d5607c6d285f37ac0119fcf88777434aae3482 Mon Sep 17 00:00:00 2001 From: Rahul Date: Wed, 22 May 2024 16:19:04 -0700 Subject: [PATCH 3/7] remove static keywork for constant --- crates/openvino/src/core.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/openvino/src/core.rs b/crates/openvino/src/core.rs index 1fa3efa..f7681a7 100644 --- a/crates/openvino/src/core.rs +++ b/crates/openvino/src/core.rs @@ -18,7 +18,7 @@ use std::os::raw::c_char; use std::slice; use std::str::FromStr; -const EMPTY_C_STR: &'static CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"\0") }; +const EMPTY_C_STR: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"\0") }; /// See [`Core`](https://docs.openvino.ai/2024/api/c_cpp_api/group__ov__core__c__api.html). pub struct Core { From 6eb8eb73b9d0144e805ae7df9dd5ec382622bb34 Mon Sep 17 00:00:00 2001 From: Rahul Date: Thu, 23 May 2024 09:52:42 -0700 Subject: [PATCH 4/7] change return type from hashmap to vector --- crates/openvino/src/core.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/crates/openvino/src/core.rs b/crates/openvino/src/core.rs index f7681a7..bd1f31d 100644 --- a/crates/openvino/src/core.rs +++ b/crates/openvino/src/core.rs @@ -12,7 +12,6 @@ use openvino_sys::{ ov_core_set_property, ov_core_t, ov_core_versions_free, }; use std::borrow::Cow; -use std::collections::HashMap; use std::ffi::{CStr, CString}; use std::os::raw::c_char; use std::slice; @@ -50,7 +49,7 @@ impl Core { /// Gets device plugins version information. /// Device name can be complex and identify multiple devices at once like `HETERO:CPU,GPU`; /// in this case, the returned map contains multiple entries, each per device. - pub fn versions(&self, device_name: impl AsRef) -> Result> { + pub fn versions(&self, device_name: impl AsRef) -> Result> { let device_name = cstr!(device_name.as_ref()); let mut ov_version_list = openvino_sys::ov_core_version_list_t { versions: std::ptr::null_mut(), @@ -65,13 +64,12 @@ impl Core { let ov_versions = unsafe { slice::from_raw_parts(ov_version_list.versions, ov_version_list.size) }; - let mut versions: HashMap = - HashMap::with_capacity(ov_version_list.size); + let mut versions: Vec<(DeviceType, Version)> = Vec::with_capacity(ov_version_list.size); for ov_version in ov_versions { let c_str_device_name = unsafe { std::ffi::CStr::from_ptr(ov_version.device_name) }; let device_name = c_str_device_name.to_string_lossy(); let device_type = DeviceType::from_str(device_name.as_ref()).unwrap(); - versions.insert(device_type, Version::from(&ov_version.version)); + versions.push((device_type, Version::from(&ov_version.version))); } unsafe { ov_core_versions_free(std::ptr::addr_of_mut!(ov_version_list)) }; From ec8cdd0c89b21de4b90d918c8a3ad3e9c44adc75 Mon Sep 17 00:00:00 2001 From: Rahul Date: Thu, 23 May 2024 10:06:43 -0700 Subject: [PATCH 5/7] Rename to get_*, use simpler &str in place of AsRef --- crates/openvino/src/core.rs | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/crates/openvino/src/core.rs b/crates/openvino/src/core.rs index bd1f31d..bc9f1b0 100644 --- a/crates/openvino/src/core.rs +++ b/crates/openvino/src/core.rs @@ -49,8 +49,8 @@ impl Core { /// Gets device plugins version information. /// Device name can be complex and identify multiple devices at once like `HETERO:CPU,GPU`; /// in this case, the returned map contains multiple entries, each per device. - pub fn versions(&self, device_name: impl AsRef) -> Result> { - let device_name = cstr!(device_name.as_ref()); + pub fn versions(&self, device_name: &str) -> Result> { + let device_name = cstr!(device_name); let mut ov_version_list = openvino_sys::ov_core_version_list_t { versions: std::ptr::null_mut(), size: 0, @@ -105,7 +105,7 @@ impl Core { /// Gets properties related to this Core. /// The method extracts information that can be set via the [set_property] method. - pub fn property(&self, key: PropertyKey) -> Result> { + pub fn get_property(&self, key: PropertyKey) -> Result> { let ov_prop_key = cstr!(key.as_ref()); let mut ov_prop_value = std::ptr::null_mut(); try_unsafe!(ov_core_get_property( @@ -144,12 +144,8 @@ impl Core { /// Gets properties related to device behaviour. /// The method extracts information that can be set via the [set_device_property] method. - pub fn device_property( - &self, - device_name: impl AsRef, - key: PropertyKey, - ) -> Result> { - let ov_device_name = cstr!(device_name.as_ref()); + pub fn get_device_property(&self, device_name: &str, key: PropertyKey) -> Result> { + let ov_device_name = cstr!(device_name); let ov_prop_key = cstr!(key.as_ref()); let mut ov_prop_value = std::ptr::null_mut(); try_unsafe!(ov_core_get_property( @@ -165,11 +161,11 @@ impl Core { /// Sets a property for a device. pub fn set_device_property( &mut self, - device_name: impl AsRef, + device_name: &str, key: RwPropertyKey, value: &str, ) -> Result<()> { - let ov_device_name = cstr!(device_name.as_ref()); + let ov_device_name = cstr!(device_name); let ov_prop_key = cstr!(key.as_ref()); let ov_prop_value = cstr!(value); try_unsafe!(ov_core_set_property( @@ -184,10 +180,10 @@ impl Core { /// Sets properties for a device. pub fn set_device_properties<'a>( &mut self, - device_name: impl AsRef, + device_name: &str, properties: impl IntoIterator, ) -> Result<()> { - let device_name = device_name.as_ref(); + let device_name = device_name; for (prop_key, prop_value) in properties { self.set_device_property(device_name, prop_key, prop_value)?; } From 465583b6154228a5e9e5c0ffd5d2301ed02b6284 Mon Sep 17 00:00:00 2001 From: Rahul Date: Thu, 23 May 2024 10:19:24 -0700 Subject: [PATCH 6/7] remove cow usage from returns --- crates/openvino/src/core.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/crates/openvino/src/core.rs b/crates/openvino/src/core.rs index bc9f1b0..19f2dfa 100644 --- a/crates/openvino/src/core.rs +++ b/crates/openvino/src/core.rs @@ -11,7 +11,6 @@ use openvino_sys::{ ov_core_get_versions_by_device_name, ov_core_read_model, ov_core_read_model_from_memory_buffer, ov_core_set_property, ov_core_t, ov_core_versions_free, }; -use std::borrow::Cow; use std::ffi::{CStr, CString}; use std::os::raw::c_char; use std::slice; @@ -105,7 +104,7 @@ impl Core { /// Gets properties related to this Core. /// The method extracts information that can be set via the [set_property] method. - pub fn get_property(&self, key: PropertyKey) -> Result> { + pub fn get_property(&self, key: PropertyKey) -> Result { let ov_prop_key = cstr!(key.as_ref()); let mut ov_prop_value = std::ptr::null_mut(); try_unsafe!(ov_core_get_property( @@ -114,7 +113,10 @@ impl Core { ov_prop_key, std::ptr::addr_of_mut!(ov_prop_value) ))?; - let rust_prop = unsafe { CStr::from_ptr(ov_prop_value) }.to_string_lossy(); + let rust_prop = unsafe { CStr::from_ptr(ov_prop_value) } + .to_str() + .unwrap() + .to_owned(); Ok(rust_prop) } @@ -144,7 +146,7 @@ impl Core { /// Gets properties related to device behaviour. /// The method extracts information that can be set via the [set_device_property] method. - pub fn get_device_property(&self, device_name: &str, key: PropertyKey) -> Result> { + pub fn get_device_property(&self, device_name: &str, key: PropertyKey) -> Result { let ov_device_name = cstr!(device_name); let ov_prop_key = cstr!(key.as_ref()); let mut ov_prop_value = std::ptr::null_mut(); @@ -154,7 +156,10 @@ impl Core { ov_prop_key, std::ptr::addr_of_mut!(ov_prop_value) ))?; - let rust_prop = unsafe { CStr::from_ptr(ov_prop_value) }.to_string_lossy(); + let rust_prop = unsafe { CStr::from_ptr(ov_prop_value) } + .to_str() + .unwrap() + .to_owned(); Ok(rust_prop) } From 47ba2053d7053089ad6ee4711bd2704e4dd84af2 Mon Sep 17 00:00:00 2001 From: Rahul Date: Thu, 23 May 2024 10:42:01 -0700 Subject: [PATCH 7/7] remove leftover redundant assignment --- crates/openvino/src/core.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/openvino/src/core.rs b/crates/openvino/src/core.rs index 19f2dfa..7a8acb2 100644 --- a/crates/openvino/src/core.rs +++ b/crates/openvino/src/core.rs @@ -188,7 +188,6 @@ impl Core { device_name: &str, properties: impl IntoIterator, ) -> Result<()> { - let device_name = device_name; for (prop_key, prop_value) in properties { self.set_device_property(device_name, prop_key, prop_value)?; }