Expand description
Fused operations with dedicated GPU kernels, as MLX’s mx.fast: rms_norm,
layer_norm, rope, cross_entropy, scaled_dot_product_attention and
gated_delta (mlx-lm’s Gated DeltaNet kernels); nuvec’s add_rms_norm (a residual
connection and its norm), norm_rope (norm, RoPE and a cache write) and
paged_attention with paged_write (a block-table KV cache); and, through
crate::Array::softmax and crate::Array::logsumexp over the last axis, MLX’s
softmax and log-sum-exp kernels.
Each operation is one GPU kernel (MLX’s, or nuvec’s own) with an equivalent graph of ordinary operations, its fallback. As in MLX, the fallback runs on the CPU stream, and it defines the forward-mode derivative and batching; reverse mode uses dedicated kernels where MLX has them.
Like every operation, these return arrays: invalid arguments give a failed array that
carries the error and the caller’s location (see crate::Array::check).
§Memory
The norms, RoPE, norm_rope, cross entropy, softmax, log-sum-exp, the gated delta rule
and the paged kernels hold no scratch beyond their inputs and outputs on the GPU (the
fallback graphs on the CPU hold their intermediates). Attention’s scratch depends on its
plan: see scaled_dot_product_attention. Rotation frequencies are computed per call,
never cached.
use nuvec_core::{array, fast};
let x = array![[1.0, 2.0], [3.0, 4.0]];
let y = fast::rms_norm(&x, None, 1e-5); // x / sqrt(mean(x²) + eps), per row
let v = y.to_vec::<f32>().unwrap();
assert!((v[0] - 1.0 / 2.5f32.sqrt()).abs() < 1e-5);Structs§
- Attention
Options - The options of
scaled_dot_product_attentionandplan_attention: the mask, attention sinks, a sliding window and a cap on score memory. Build them withAttentionOptions::causalorDefaultand the chained setters: - Attention
Plan - How an attention call runs and the memory it holds (see
plan_attention). - Kernel
Call - A recorded call of a custom kernel.
- Kernel
Config - How a
MetalKernelis launched. - Metal
Kernel - A Metal kernel built from source, as MLX’s
mx.fast.metal_kernel: a name, the names of its inputs and outputs, and the body of a kernel function. Calling it generates the function’s signature as MLX does: - Rotation
- The rotation of
norm_rope:rope’s parameters. - Step
Options - Options of
gated_delta_steps_with.
Enums§
- Attention
Kernel - The kernel family an attention call runs (see
plan_attention). - Attention
Mask - The mask of
scaled_dot_product_attention. - FastOp
- A fused operation (see
crate::fast). - Template
Arg - A template argument of a custom kernel.
Functions§
- add_
rms_ norm - A residual connection followed by RMS normalisation:
h = x + residualandrms_norm(h, weight, eps), returned as(h, normed), from one GPU kernel. The results equalx + residualthenrms_normexactly; a weight that would widen the sum’s dtype runs the two operations. - causal_
conv1d_ slots - A causal depthwise convolution for a batch of sequences whose last inputs live in a
pool (Gated DeltaNet’s convolution state): sequence
b’s window ispool[slots[b]](poolis[slots, K − 1, C],slots[B]distinct integers in range) followed by its new inputsx[b](xis[B, L, C]), convolved withw([C, K, 1], one filter per channel) and, withsilu, passed throughsilu. Returns the outputs ([B, L, C]) and the pool with each slot holding its window’s lastK − 1inputs, written in place when the evaluation owns it. - cross_
entropy - Cross entropy over the last axis of
logitsagainst integer class indicestargets(the logits’ shape without the last axis; negative indices count from the end), as MLX’sfast.cross_entropy:logsumexp(logits) - logits[target]per row, in float32. - gated_
delta - The gated delta rule, Gated DeltaNet’s recurrence (as mlx-lm’s
gated_delta_updateonce its gates are computed). For each steptand value head, withSits state ([Dv, Dk]): - gated_
delta_ slots gated_deltafor a batch of sequences whose states live in a pool: sequencebstarts frompool[slots[b]](poolis[slots, Hv, Dv, Dk],slots[B]integers, distinct) and its final state replaces it. Returns the outputs and the updated pool, which is written in place when the evaluation owns it, so decoding many sequences moves no states. Each sequence’s results equalgated_delta’s on its state alone.- gated_
delta_ steps gated_deltareturning the state after every step,[B, T, Hv, Dv, Dk](stept’s state at indext; the last isgated_delta’s final state), so that a caller can roll the recurrence back to any step, as speculative decoding does after a rejected draft. The outputs equalgated_delta’s bit for bit; writing every step’s state costsTtimes the state’s bytes.- gated_
delta_ steps_ with gated_delta_stepsfor a runtime that stores its states in another dtype than float32 (bfloat16, say): each step’s output is computed from the state the previous step stored, and its state is then stored inoptions.storage, sostates[t]and the outputs equalt + 1serialgated_deltacalls on a state kept in that dtype, bit for bit (each step runs the kernel serial decode runs). With float32 storage it isgated_delta_steps.- layer_
norm - Layer normalisation over the last axis,
(x - mean) / sqrt(var + eps) · weight + bias, as MLX’sfast.layer_norm: statistics in float32, the result in the promoted type. - moe_
route - A mixture of experts’ routing from its router’s probabilities
probs([..., E]): the indices (uint32) of each row’sklargest probabilities and those probabilities ([..., k]each), divided by their sum withnormalize(mlx-lm’snorm_topk_prob). - norm_
rope - An attention layer’s query or key preparation in one kernel: each head’s features of
x([B, H, L, D], any strides, as the transposed projection) optionally normalised asrms_normwithnorm = (weight, eps)(Qwen 3’sq_normandk_norm), then rotated asropeat positionsoffset..offset + L. - norm_
rope_ at norm_ropefor sequences at their own positions (a batched decoding step): each[b, h, l]row ofx([B, H, L, D], any strides) optionally normalised asrms_normwithnorm = (weight, eps), then rotated asropeat positionpositions[b] + l(positions:[B]integers).- norm_
rope_ kv - Gemma 4’s keys and values from one projection (
attention_k_eq_v): K isx([B, H, L, D], any strides) normalised withk_norm = (weight, eps)and rotated at positionsoffset..(asnorm_rope); V isxRMS-normalised without a weight (v_eps; mlx-lm’sRMSNormNoScale). Withcaches = (k_cache, v_cache)both are written atoffset(in place when the evaluation owns them), asnorm_ropewrites one. - paged_
attention - Attention over a paged KV cache, for a batch of sequences of different lengths.
- paged_
write cache([blocks, kv_heads, block_size, D]) with the positionsnewholds ([T, kv_heads, D], or[B, T, kv_heads, D]for several sequences) written into their slots:slots(integers,new’s leading shape) holds blockslot / block_size, positionslot % block_sizeof each. Slots must be distinct; out-of-range slots (negative, or at leastblocks · block_size) are skipped. In place when the evaluation owns the cache; on the GPU,newis read through its strides (a transposed view of a contiguous cache needs no copy).- plan_
attention - How
scaled_dot_product_attentionwill run for these shapes ([B, H, L, D]each), dtype and options, on the calling thread’s default device, without evaluating or allocating anything. Masks and sinks inoptionsare read for their shape and dtype only. Errors are those the attention call would report. - residual_
rms_ norm - A normalised residual branch:
s = (h + rms_norm(x, weight, eps)) · scale(no multiply without a scale) and, withnext = (weight, eps),rms_normofs, returned as(s, normed). Gemma 4’s sandwich norm, residual add and layer scalar, and the next layer’s input norm. On the GPU it is one kernel equal to that composition bit for bit when every input hash’s floating-point dtype, the weights are 1-D and the scale has one element (otherwise the composition, with MLX’s type promotion). - rms_
norm - Root-mean-square normalisation over the last axis,
x / sqrt(mean(x²) + eps) · weight, as MLX’sfast.rms_norm: statistics in float32, the result in the promoted type ofxandweight(1-D, the last axis’s size). - rope
- Rotary position embeddings, as MLX’s
fast.rope, ofx(at least 3-D:[B, ..., T, D], positions alongT): the firstdimsfeatures (even) are rotated in pairs, the two halves (or interleaved pairs,traditional) by angle(offset + t) · scale · θᵢ, withθᵢ = base^(-2i/dims)or1 / freqs[i]. Exactly one ofbaseandfreqsis given.offsetis an integer scalar or one per batch entry. - scaled_
dot_ product_ attention - Scaled dot-product attention, as MLX’s
fast.scaled_dot_product_attention:softmax(scale · q kᵀ + mask) vover[B, H, L, D]arrays, with the mask, sinks, window and score cap inAttentionOptions. - weighted_
sum - The experts’ outputs
x([..., k, D]) weighted byw([..., k]) and summed over thekexperts:(x * w[..., None]).sum(-2), products and sum inx’s dtype as mlx-lm’s MoE blocks compute them. On the GPU it is one kernel equal to that composition bit for bit when both have one floating-point dtype andk < 32(otherwise the composition).