CUDA Buffer Kernels FFI #
Foreign-function declarations for TorchLean's float32 Cuda.Buffer kernels: reductions, indexing,
matmul/BMM, attention, broadcast/view helpers, and related tensor operations. The declarations here
are the Lean side of the explicit CUDA trust boundary documented in docs/TRUST_BOUNDARIES.md.
Sum down the rows of a 2D row-major buffer.
Input b has shape (rows, cols) and is stored as length rows*cols.
Output is length cols (sum down the rows for each column).
Sum across the columns of a 2D row-major buffer.
Input b has shape (rows, cols) and is stored as length rows*cols.
Output is length rows (sum across the columns for each row).
Maximum down the rows of a 2D row-major buffer.
Input b has shape (rows, cols) and is stored as length rows*cols.
Output is length cols (max down the rows for each column).
Maximum across the columns of a 2D row-major buffer.
Input b has shape (rows, cols) and is stored as length rows*cols.
Output is length rows (max across the columns for each row).
Stable row-wise hard-masked softmax for flat (rows, cols) buffers.
The row maximum and denominator are computed only from entries whose mask value is nonzero. Blocked entries are exactly zero in the output. A row with no allowed entries is defined to be all zeros.
Concatenate two 1D buffers a (length n) and b (length m).
Slice a 1D buffer b (length n) starting at start for len elements.
Requires start + len ≤ n.
Broadcast a rank-one row tensor of length cols to a (rows, cols) matrix.
Output is row-major of length rows*cols, with out[i, j] = vec[j].
Broadcast a column-vector (length rows) to a (rows, cols) matrix.
Output is row-major of length rows*cols, with out[i, j] = vec[i].
Layer normalization over the columns of a row-major (rows, cols) buffer.
gamma and beta each have length cols. The result is (output, normalized, invStd), where
normalized has shape (rows, cols) and invStd has length rows. Keeping these two values is
enough for TorchLean's layer-normalization VJP; the native kernel does not create or own an
autograd graph.
TorchLean's layer-normalization VJP evaluated by a fused buffer kernel.
Given the upstream derivative, cached normalized values and inverse standard deviations, and
gamma, returns (dX, dGamma, dBeta). The formula and parent association remain part of the
TorchLean tape; this primitive only evaluates that formula.
Batched matrix multiply over row-major buffers, optionally transposing either logical operand.
The logical multiplication always has shape (batch, m, n) × (batch, n, p). When
transposeA = 1, the stored shape of A is (batch, n, m); when transposeB = 1, the stored
shape of B is (batch, p, n). Other flag values are rejected by the native boundary.
cuBLAS consumes these layouts directly. In particular, backward rules can request Aᵀ B or
A Bᵀ without first allocating a transposed buffer.
Batched matrix multiplication A B for ordinary row-major operands.
Instances For
Batched multiplication A Bᵀ.
A is stored as (batch, m, n) and B as (batch, p, n); the result has shape
(batch, m, p).
Instances For
Batched multiplication Aᵀ B.
A is stored as (batch, n, m) and B as (batch, n, p); the result has shape
(batch, m, p).
Instances For
Real-valued 1D FFT over row-major batches, returning a packed half-spectrum.
Input:
x: lengthbatch*n, interpreted as shape(batch, n).
Output:
- length
batch*(n/2+1)*2, interpreted as shape(batch, n/2+1, 2); - the last channel stores
[real, imag]for each nonredundant frequency bin.
CUDA uses cuFFT R2C under the hood. The CPU stub uses a direct reference DFT, so this primitive
remains available in non-CUDA builds for tests and portability. This is a low-level runtime
primitive; differentiable tensor/autograd wrappers should spell out their backward convention
separately because half-spectrum packing has normalization and conjugate-symmetry edge cases.
Inverse of rfft1dPacked for packed half-spectra.
Input:
spec: lengthbatch*(n/2+1)*2, interpreted as(batch, n/2+1, 2).
Output:
- length
batch*n, interpreted as(batch, n).
The CUDA implementation uses cuFFT C2R and explicitly scales by 1/n, matching the CPU reference
and the usual normalized inverse FFT convention used by high-level ML APIs.
Fused real-FFT spectral convolution for one FNO1D block.
Input:
x: lengthgrid*width, row-major shape(grid, width);wRe,wIm: lengthmodes*width*width, row-major shape(modes, width, width).
Semantics:
- apply an unnormalized real FFT along the grid axis for each input channel,
- keep frequency bins
0 ≤ k < modes, - multiply each retained complex vector by
wRe[k] + i*wIm[k], - zero all other bins,
- apply the normalized inverse real FFT.
This is the CUDA/cuFFT-backed runtime primitive intended to replace dense DFT matrix multiplies in float32 FNO examples. The three backward primitives below are its explicit VJP components.
VJP component ∂L/∂x for spectralConv1dRfftFwd.
VJP component ∂L/∂wRe for spectralConv1dRfftFwd.
VJP component ∂L/∂wIm for spectralConv1dRfftFwd.
Diagonal selective-scan forward kernel for state-space models.
Inputs:
A,B,h0: lengthstate, representing per-channel recurrence parameters and initial state,X: lengthseqLen*state, row-major token/state inputs.
Output:
- length
seqLen*state, row-major hidden states, withh[t,j] = A[j] * h[t-1,j] + B[j] * X[t,j], starting fromh0[j].
This is the runtime primitive corresponding to the proof layer affine scan contract in
NN.Spec.Layers.SelectiveScan and NN.MLTheory.Proofs.StateSpace.Scan.
Backward kernel for selectiveScanDiagFwd.
Given out = selectiveScanDiagFwd A B X h0 and an upstream gradient dY with the same
seqLen*state layout as out, returns (dA, dB, dX, dH0).
Diagonal selective-scan forward kernel with token-dependent coefficients.
Inputs:
A,B,X: lengthseqLen*state, row-major by(time, flattened_state_channel),h0: lengthstate.
Output:
- length
seqLen*state, withh[t,j] = A[t,j] * h[t-1,j] + B[t,j] * X[t,j].
This is the runtime primitive corresponding to full Mamba-style selective scans where the token controls the affine transition coefficients.
Reverse accumulation for token-dependent diagonal coefficients.
With g[t] = dY[t] + A[t+1] * g[t+1], the returned arrays are
dA[t] = g[t] * h[t-1], dB[t] = g[t] * X[t], dX[t] = g[t] * B[t], and
dH0 = A[0] * g[0]. Empty sequences return an empty coefficient/input gradient and zero dH0.
The native kernel walks time backwards independently for each state channel.
Native fused scaled dot-product attention forward over split attention heads.
Inputs are row-major buffers with shapes:
Q,K,V:(batch, n, d), wherebatchis usually the number of heads,mask:(batch, n, n)encoded as0.0/1.0whenhasMask != 0; otherwise ignored.
Output has shape (batch, n, d).
Both the native CUDA and optional LibTorch providers use hard-mask semantics: blocked mask entries contribute zero softmax numerator. The LibTorch provider has separate extern names because it is an external implementation and, for its backward entry point, an external autograd boundary.
Gather k scalars from a 1D vector using host indices.
Input:
Indices that fit in UInt32 but are out of bounds are totalized to 0.
Large Nat values outside the FFI index range are rejected by the runtime.
Broadcast a buffer to a new shape (TorchLean Shape.CanBroadcastTo semantics).
Arguments:
x: input bufferinDims: input dimension list (outermost-first)outDims: output dimension list (outermost-first)axisMap: lengthoutDims.size;axisMap[j] = 0means the output axisjis an inserted/broadcast axis (input coordinate is0), otherwiseaxisMap[j] = inAxis+1tells which input axis to read.
This shape-driven mapping is generated in Lean from a Shape.CanBroadcastTo proof so the kernel
does not need to interpret the proof object.
Adjoint of broadcastTo for sum-accumulation: reduce a broadcasted gradient back to the input
shape by summing over broadcasted axes.
This uses the same (inDims,outDims,axisMap) convention as broadcastTo.
Swap adjacent axes at depth for a contiguous buffer described by dims.
depth = 0 swaps the first two axes; depth = 1 swaps axes 1 and 2; etc.
Reduce-sum along axis for an N-D contiguous buffer described by dims (outermost-first).
The returned buffer is laid out row-major with shape dims with the axis dimension removed.
Gather k rows from a row-major matrix.
Input:
Output:
- shape
(k, cols)stored row-major as lengthk*cols
Indices that fit in UInt32 but are out of bounds are totalized to 0 rows.
Large Nat values outside the FFI index range are rejected by the runtime.
Scatter-add k rows given host indices.
Semantics: out = mat with out[indices[r], j] += values[r, j] for each r < k, j < cols.
Indices that fit in UInt32 but are out of bounds are ignored; repeated indices accumulate
(scatter-add). Large Nat values outside the FFI index range are rejected by the runtime.