use crate::sys::mlx;
pub struct Stream {
raw: mlx::mlx_stream,
}
impl Stream {
pub fn new_default_gpu() -> Self {
Stream {
raw: unsafe { mlx::mlx_default_gpu_stream_new() },
}
}
#[inline]
pub fn as_raw(&self) -> mlx::mlx_stream {
self.raw
}
}
impl Drop for Stream {
fn drop(&mut self) {
unsafe { mlx::mlx_stream_free(self.raw) };
}
}
pub struct Array {
raw: mlx::mlx_array,
}
impl Array {
#[inline]
pub fn from_raw(raw: mlx::mlx_array) -> Self {
Array { raw }
}
#[inline]
pub fn new() -> Self {
Array {
raw: unsafe { mlx::mlx_array_new() },
}
}
pub fn from_data(data: *const std::os::raw::c_void, shape: &[i32], dtype: mlx::mlx_dtype) -> Self {
let arr = Array {
raw: unsafe {
mlx::mlx_array_new_data(data, shape.as_ptr(), shape.len() as i32, dtype)
},
};
let tr = crate::trace::tracer();
if tr.active() {
tr.record_copy_wrap((arr.size() * arr.itemsize()) as u64);
}
arr
}
pub fn from_data_managed(
data: *const std::os::raw::c_void,
shape: &[i32],
dtype: mlx::mlx_dtype,
) -> Self {
unsafe extern "C" fn noop_dtor(_: *mut std::os::raw::c_void) {}
let arr = Array {
raw: unsafe {
mlx::mlx_array_new_data_managed(
data as *mut std::os::raw::c_void,
shape.as_ptr(),
shape.len() as i32,
dtype,
Some(noop_dtor),
)
},
};
let tr = crate::trace::tracer();
if tr.active() {
let aligned = (data as usize) % 16384 == 0;
tr.record_managed_wrap((arr.size() * arr.itemsize()) as u64, aligned);
}
arr
}
#[inline]
pub fn as_raw(&self) -> mlx::mlx_array {
self.raw
}
pub fn ndim(&self) -> usize {
unsafe { mlx::mlx_array_ndim(self.raw) }
}
pub fn shape(&self) -> Vec<i64> {
let nd = self.ndim();
let sh = unsafe { mlx::mlx_array_shape(self.raw) };
(0..nd).map(|i| unsafe { *sh.add(i) } as i64).collect()
}
#[allow(dead_code)]
pub fn size(&self) -> usize {
unsafe { mlx::mlx_array_size(self.raw) }
}
pub fn itemsize(&self) -> usize {
unsafe { mlx::mlx_array_itemsize(self.raw) }
}
#[allow(dead_code)]
pub fn dtype(&self) -> mlx::mlx_dtype {
unsafe { mlx::mlx_array_dtype(self.raw) }
}
#[allow(dead_code)]
pub fn eval(&self) {
unsafe { mlx::mlx_array_eval(self.raw) };
}
pub fn data_bytes(&self) -> *const u8 {
unsafe { mlx::mlx_array_data_uint8(self.raw) as *const u8 }
}
}
impl Default for Array {
fn default() -> Self {
Array::new()
}
}
impl Drop for Array {
fn drop(&mut self) {
unsafe { mlx::mlx_array_free(self.raw) };
}
}
pub struct VectorArray {
raw: mlx::mlx_vector_array,
}
impl VectorArray {
pub fn new() -> Self {
VectorArray {
raw: unsafe { mlx::mlx_vector_array_new() },
}
}
#[inline]
pub fn from_raw(raw: mlx::mlx_vector_array) -> Self {
VectorArray { raw }
}
pub fn append(&mut self, a: mlx::mlx_array) {
unsafe { mlx::mlx_vector_array_append_value(self.raw, a) };
}
pub fn size(&self) -> usize {
unsafe { mlx::mlx_vector_array_size(self.raw) }
}
pub fn get(&self, i: usize) -> Array {
let mut a = unsafe { mlx::mlx_array_new() };
unsafe { mlx::mlx_vector_array_get(&mut a, self.raw, i) };
Array::from_raw(a)
}
#[inline]
pub fn as_raw(&self) -> mlx::mlx_vector_array {
self.raw
}
#[inline]
pub fn into_raw(self) -> mlx::mlx_vector_array {
let raw = self.raw;
std::mem::forget(self);
raw
}
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut mlx::mlx_vector_array {
&mut self.raw
}
}
impl Default for VectorArray {
fn default() -> Self {
VectorArray::new()
}
}
impl Drop for VectorArray {
fn drop(&mut self) {
unsafe { mlx::mlx_vector_array_free(self.raw) };
}
}
pub fn eval(outputs: &VectorArray) -> Result<(), String> {
let rc = unsafe { mlx::mlx_eval(outputs.as_raw()) };
if rc != 0 {
return Err("mlx_eval failed".to_string());
}
Ok(())
}
pub struct Closure {
raw: mlx::mlx_closure,
}
impl Closure {
pub fn new_func_payload(
fun: unsafe extern "C" fn(
*mut mlx::mlx_vector_array,
mlx::mlx_vector_array,
*mut std::os::raw::c_void,
) -> std::os::raw::c_int,
payload: *mut std::os::raw::c_void,
) -> Self {
let raw = unsafe { mlx::mlx_closure_new_func_payload(Some(fun), payload, None) };
Closure { raw }
}
pub fn compile(base: &Closure, shapeless: bool) -> Result<Closure, String> {
let mut res = unsafe { mlx::mlx_closure_new() };
let rc = unsafe { mlx::mlx_compile(&mut res, base.raw, shapeless) };
if rc != 0 {
unsafe { mlx::mlx_closure_free(res) };
return Err("mlx_compile failed".to_string());
}
Ok(Closure { raw: res })
}
pub fn apply(&self, input: &VectorArray) -> Result<VectorArray, String> {
let mut res = unsafe { mlx::mlx_vector_array_new() };
let rc = unsafe { mlx::mlx_closure_apply(&mut res, self.raw, input.as_raw()) };
if rc != 0 {
unsafe { mlx::mlx_vector_array_free(res) };
return Err("mlx_closure_apply failed".to_string());
}
Ok(VectorArray::from_raw(res))
}
}
impl Drop for Closure {
fn drop(&mut self) {
unsafe { mlx::mlx_closure_free(self.raw) };
}
}