Skip to main content

MetalKernel

Struct MetalKernel 

Source
pub struct MetalKernel { /* private fields */ }
Expand description

A custom Metal kernel, compiled from source on first use and cached by MLX.

The kernel body is written against the names given at construction: each input a is a const device T* a, or const constant T* a when it has fewer than eight elements. Non-scalar inputs also expose a_shape, a_strides and a_ndim when referenced in the source. A 0-d input is a const constant T& a and has no shape, strides or ndim arguments. Each output is a device T* (or an atomic pointer with atomic_outputs), and Metal attributes such as thread_position_in_grid are declared automatically when referenced.

Kernels only run on the GPU. MetalKernel::apply uses the stream selected by crate::with_stream or crate::with_device, falling back to the GPU outside a scope, even when the default device is the CPU. Selecting a CPU scope returns an error.

use mlx_rs::{fast::{MetalKernel, MetalKernelApplyOptions, MetalKernelOptions, MetalKernelOutput}, Array, Dtype};

let kernel = MetalKernel::new(
    "double",
    &["a"],
    &["out"],
    "uint i = thread_position_in_grid.x; out[i] = 2 * a[i];",
    MetalKernelOptions::default(),
)?;
let a = Array::from_slice(&[1.0_f32, 2.0, 3.0, 4.0], &[4]);
// SAFETY: Four threads read four f32 inputs and initialize distinct f32 outputs.
let out = unsafe {
    kernel.apply(
        &[&a],
        &[MetalKernelOutput { shape: vec![4], dtype: Dtype::Float32 }],
        (4, 1, 1),
        (4, 1, 1),
        MetalKernelApplyOptions::default(),
    )?
};
assert_eq!(out[0].as_slice::<f32>(), &[2.0, 4.0, 6.0, 8.0]);

Implementations§

Source§

impl MetalKernel

Source

pub fn new( name: &str, input_names: &[&str], output_names: &[&str], source: &str, options: MetalKernelOptions, ) -> Result<Self>

Builds a kernel from its name, input and output names, and Metal body source.

At least one output name is required. Compilation is deferred until the outputs are evaluated, so source errors surface from Array::eval, not apply.

Source

pub unsafe fn apply( &self, inputs: &[impl AsRef<Array>], outputs: &[MetalKernelOutput], grid: (i32, i32, i32), thread_group: (i32, i32, i32), options: MetalKernelApplyOptions, ) -> Result<Vec<Array>>

Runs the kernel over grid threads in groups of thread_group, returning one array per entry of outputs.

inputs and outputs must match the counts given at construction. Like other operations the result is lazy; the kernel compiles and runs when the outputs are evaluated. Source and threadgroup errors surface from Array::eval. The kernel and option values may be dropped before evaluating the outputs.

§Safety

For the given inputs, outputs, template arguments and launch configuration, the kernel must only access memory inside the input and output buffers and must never write an input. It must write every output element before it is read unless init_value is set, only write values valid for the output dtype, and have no unsynchronized conflicting accesses. These requirements apply throughout deferred execution.

Trait Implementations§

Source§

impl Debug for MetalKernel

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Drop for MetalKernel

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> IntoOption<T> for T

Source§

fn into_option(self) -> Option<T>

Convert into an Option.
Source§

impl<T> IntoStrideBy for T

Source§

fn stride_by(self, stride: i32) -> StrideBy<T>

Create a stride indexing operation.
§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.