mod access_graph;
pub mod artifacts;
#[path = "benchmark_statistics.rs"]
pub mod benchmark;
mod buffer_pool;
pub mod bundle;
mod dependency_frontier;
pub mod fabric;
pub mod image;
pub mod inference;
pub mod jobs;
pub mod plan_cache;
pub mod residency;
mod runtime;
#[cfg(target_os = "linux")]
pub mod storage;
mod target;
pub mod tensor;
pub use access_graph::{AccessGraph, AccessView};
pub use buffer_pool::{BufferPool, PooledBuffer};
pub use runtime::*;
pub mod execution;
#[path = "loom/model.rs"]
pub mod model;
pub use execution::{Access, Completion, Runtime};
pub mod gpu {
pub use crate::runtime::*;
}
pub use target::{TARGET_KEY, Target};
pub mod loom;
#[cfg(feature = "npu")]
pub mod npu;
#[cfg(doctest)]
#[doc = include_str!("../README.md")]
pub struct Readme;
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
#[error("resource busy: {0}")]
Busy(String),
#[error("unsupported capability: {0}")]
Unsupported(String),
#[error("device execution failed: {0}")]
DeviceLost(String),
#[error("{backend} {operation} failed ({code}): {message}")]
Backend {
backend: &'static str,
operation: &'static str,
code: i32,
message: Box<str>,
},
#[error("{source}")]
Execution {
#[source]
source: std::sync::Arc<Error>,
},
#[error("execution cancelled")]
Cancelled,
#[error("{0}")]
Message(String),
#[error("Loom compilation failed: {message}")]
Compile {
message: String,
diagnostics: Vec<loom::Diagnostic>,
report: Option<Box<serde_json::Value>>,
},
#[error("{0}")]
Io(#[from] std::io::Error),
#[error("{0}")]
Json(#[from] serde_json::Error),
#[error("{0}")]
Library(#[from] libloading::Error),
#[error("{0}")]
Download(#[source] Box<ureq::Error>),
#[error("{context}: {message}")]
Runtime {
context: String,
code: i32,
message: String,
},
#[error("{context}: {source}")]
Context {
context: String,
#[source]
source: Box<Error>,
},
}
impl Error {
pub fn compiler_diagnostics(&self) -> Option<&[loom::Diagnostic]> {
match self {
Self::Compile { diagnostics, .. } => Some(diagnostics),
Self::Context { source, .. } => source.compiler_diagnostics(),
Self::Execution { source } => source.compiler_diagnostics(),
_ => None,
}
}
pub fn compiler_report(&self) -> Option<&serde_json::Value> {
match self {
Self::Compile { report, .. } => report.as_deref(),
Self::Context { source, .. } => source.compiler_report(),
Self::Execution { source } => source.compiler_report(),
_ => None,
}
}
pub fn context(self, context: impl Into<String>) -> Self {
Self::Context {
context: context.into(),
source: Box::new(self),
}
}
}
pub type Result<T> = std::result::Result<T, Error>;
pub mod runner;
pub(crate) fn cached_init<T: Clone>(
cache: &std::sync::Mutex<Option<T>>,
initialize: impl FnOnce() -> Result<T>,
) -> Result<T> {
let mut cached = cache
.lock()
.map_err(|_| Error::Message("initialization cache poisoned".into()))?;
if let Some(value) = cached.as_ref() {
return Ok(value.clone());
}
let value = initialize()?;
*cached = Some(value.clone());
Ok(value)
}
#[cfg(test)]
mod initialization_tests {
#[test]
fn failures_retry_and_concurrent_success_initializes_once() {
use std::sync::{
Mutex,
atomic::{AtomicUsize, Ordering},
};
let cache = Mutex::new(None);
assert!(
super::cached_init(&cache, || Err::<usize, _>(super::Error::Message(
"transient".into()
)))
.is_err()
);
let calls = AtomicUsize::new(0);
std::thread::scope(|scope| {
for _ in 0..8 {
scope.spawn(|| {
assert_eq!(
super::cached_init(&cache, || {
calls.fetch_add(1, Ordering::Relaxed);
Ok(42)
})
.unwrap(),
42
);
});
}
});
assert_eq!(calls.load(Ordering::Relaxed), 1);
}
}