Skip to main content

Cuda

Struct Cuda 

Source
pub struct Cuda;
Expand description

The CUDA backend (ferrox-cuda).

Trait Implementations§

Source§

impl BackendCaps for Cuda

Source§

const GEMM_FALLBACK: &'static str = "CUDA per-position matvec"

apply_batch_with_acts decomposes a CUDA prefill into one matvec per position for every kind off Cuda::gemm_supported.

Source§

fn matvec_kernel(kind: QuantKind) -> Option<&'static str>

The decode path, and the arm that has actually run on a GPU – for six of its nine kinds.

DERIVED from ferrox_cuda::matvec_kinds::KINDS, not restated. That table is compiled on every build (it is CUDA C text and three strings per row; nothing in it needs cudarc), and ferrox-cuda is an unconditional dependency for exactly this reason. The set used to be written out here as a matches! and checked against the kernel table by a test that only ran under --features cuda; over-claiming there sends a decode to an NVRTC module that does not exist, and under-claiming leaves a kernel nothing ever calls. Both have happened.

The name is returned only to share BackendCaps::matvec_kernel’s shape with Metal; nothing on the CUDA path reads it, because ferrox-cuda’s launchers are named functions rather than entries in a string-keyed table.

Source§

fn gemm_supported(kind: QuantKind) -> bool

The mul_mm prefill path.

DERIVED from ferrox_cuda::mul_mm::KINDS, for the same reason and by the same mechanism as Cuda::matvec_kernel above. It equals that set, and the_matvec_table_and_the_mul_mm_table_name_the_same_kinds in ferrox-cuda is what keeps it equal – a kind with one kernel and not the other splits a forward pass across two devices.

It did not until 2026-09-04: only Q8_0 and Q4_0 had a matrix-matrix product, so a K-quant prefill decomposed into one matvec launch per position. Measured on a GTX 1080, that cost Llama-3.2-3B Q4_K_M 4.88 tok/s of pp512 against llama.cpp’s 1586.80, a 325x gap on the most common quantization in circulation (#131). IQ4_XS is still absent: it is a codebook lookup rather than an affine dequant.

Q5_0 joined on 2026-09-05, matvec and GEMM together, because a_cuda_kind_with_a_matvec_also_has_a_gemm makes half of it fail the suite – and because half of it is the shape that cost Metal a Q5_0 decode path: GPU prefill with every decode step on the host.

IQ4_NL, IQ4_XS and MXFP4 joined on 2026-09-09, matvec and GEMM together. They are CODEBOOK formats: the stored 4-bit code is an index into a sixteen-entry table, not a magnitude, so the kernel carries that table in __constant__ memory. gpt-oss ships MXFP4 and no GPU backend had it at all, so every expert decoded on the host with the device idle.

UNRUN ON HARDWARE. The kernel is checked against a scalar twin and by executing the emitted CUDA C on the host, and has never executed on a GPU. See crates/ferrox-cuda/src/mul_mm.rs.

Source§

const ID: Backend = Backend::Cuda

How crate::kernel_registry reports this backend. Dispatch and observability read the same constant, so a backend cannot be dispatched to under one name and reported under another.
Source§

const NAME: &'static str = "CUDA"

Human-readable name, for the one message a dispatch failure prints.

Auto Trait Implementations§

§

impl Freeze for Cuda

§

impl RefUnwindSafe for Cuda

§

impl Send for Cuda

§

impl Sync for Cuda

§

impl Unpin for Cuda

§

impl UnsafeUnpin for Cuda

§

impl UnwindSafe for Cuda

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
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> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

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

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

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.