use std::marker::PhantomData;
use crate::error::check;
use crate::{c_chars_to_string, sys, DType, Result, Runtime, TensorSet};
#[derive(Debug)]
pub struct Model<'rt> {
ptr: *mut sys::nrt_model_t,
_rt: PhantomData<&'rt Runtime>,
}
unsafe impl Send for Model<'_> {}
unsafe impl Sync for Model<'_> {}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TensorUsage {
Input,
Output,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TensorInfo {
pub name: String,
pub usage: TensorUsage,
pub size: usize,
pub dtype: Option<DType>,
pub shape: Vec<usize>,
}
impl Runtime {
pub fn load(&self, neff: &[u8], vnc: i32) -> Result<Model<'_>> {
let mut ptr = std::ptr::null_mut();
let status =
unsafe { sys::nrt_load(neff.as_ptr() as *const _, neff.len(), vnc, -1, &mut ptr) };
check(status, "nrt_load")?;
Ok(Model { ptr, _rt: PhantomData })
}
pub fn load_collectives(
&self,
neff: &[u8],
vnc: i32,
device_id: u32,
device_count: u32,
) -> Result<Model<'_>> {
let mut ptr = std::ptr::null_mut();
let status = unsafe {
sys::nrt_load_collectives(
neff.as_ptr() as *const _,
neff.len(),
vnc,
-1,
device_id,
device_count,
&mut ptr,
)
};
check(status, "nrt_load_collectives")?;
Ok(Model { ptr, _rt: PhantomData })
}
}
impl Model<'_> {
pub fn as_ptr(&self) -> *mut sys::nrt_model_t {
self.ptr
}
pub fn execute(&self, inputs: &TensorSet, outputs: &mut TensorSet) -> Result<()> {
let status = unsafe { sys::nrt_execute(self.ptr, inputs.as_ptr(), outputs.as_ptr()) };
check(status, "nrt_execute")
}
pub fn execute_repeat(
&self,
inputs: &TensorSet,
outputs: &mut TensorSet,
repeat_count: i32,
) -> Result<()> {
let status = unsafe {
sys::nrt_execute_repeat(self.ptr, inputs.as_ptr(), outputs.as_ptr(), repeat_count)
};
check(status, "nrt_execute_repeat")
}
pub fn vnc_count(&self) -> Result<u32> {
let mut count = 0;
check(
unsafe { sys::nrt_get_model_vnc_count(self.ptr, &mut count) },
"nrt_get_model_vnc_count",
)?;
Ok(count)
}
pub fn tensor_info(&self) -> Result<Vec<TensorInfo>> {
let mut array = std::ptr::null_mut();
check(
unsafe { sys::nrt_get_model_tensor_info(self.ptr, &mut array) },
"nrt_get_model_tensor_info",
)?;
let infos = unsafe {
let count = (*array).tensor_count as usize;
let infos = (*array).tensor_array.as_slice(count);
infos.iter().map(|info| tensor_info(info)).collect()
};
check(unsafe { sys::nrt_free_model_tensor_info(array) }, "nrt_free_model_tensor_info")?;
Ok(infos)
}
}
unsafe fn tensor_info(info: &sys::nrt_tensor_info_t) -> TensorInfo {
let shape = if info.shape.is_null() {
vec![]
} else {
std::slice::from_raw_parts(info.shape, info.ndim as usize)
.iter()
.map(|&d| d as usize)
.collect()
};
let usage = if info.usage == sys::NRT_TENSOR_USAGE_OUTPUT {
TensorUsage::Output
} else {
TensorUsage::Input
};
TensorInfo {
name: c_chars_to_string(&info.name),
usage,
size: info.size,
dtype: DType::from_raw(info.dtype),
shape,
}
}
impl Drop for Model<'_> {
fn drop(&mut self) {
unsafe { sys::nrt_unload(self.ptr) };
}
}