cera 0.2.2

Rust-native LLM inference engine
Documentation
#include <metal_stdlib>
using namespace metal;

// Batched f32 linear: y[tok, row] = dot(x[tok, :], w[row, :]).
//   w: [m, k] row-major (out_dim × in_dim — the MmapWeight linear layout)
//   x: [n, k] row-major (n tokens × in_dim)
//   y: [n, m] row-major (n tokens × out_dim)
//
// One threadgroup of 32 threads (one simdgroup) per (output feature, token).
// Mirrors gemv_f32.metal but with a token index, so the whole token batch runs
// in a single dispatch. No TILE_K restriction: the inner loop handles any k.
//
// Dispatch: threadgroups (m, n, 1), threads (32, 1, 1).

struct Params { uint m; uint k; uint n; uint _pad; };

kernel void vit_linear(
    const device float* w [[buffer(0)]],
    const device float* x [[buffer(1)]],
    device float* y [[buffer(2)]],
    constant Params& p [[buffer(3)]],
    uint3 tid_v [[thread_position_in_threadgroup]],
    uint3 tg [[threadgroup_position_in_grid]]
) {
    uint tid = tid_v.x;
    uint row = tg.x;
    uint tok = tg.y;
    if (row >= p.m || tok >= p.n) return;

    uint w_off = row * p.k;
    uint x_off = tok * p.k;
    float partial = 0.0f;
    for (uint c = tid; c < p.k; c += 32u) {
        partial += w[w_off + c] * x[x_off + c];
    }
    float total = simd_sum(partial);
    if (tid == 0u) {
        y[tok * p.m + row] = total;
    }
}