Skip to main content

logicaffeine_compile/codegen_cuda/lane/
kernels.rs

1//! The lane's kernel library: one CUDA kernel per kind of op a step runs, each templated over the forms the fusion
2//! rules ask of it (a residual added before a norm, an activation quantized in a producer's epilogue, a result written
3//! into the row of a cache a position names). The planner instantiates them; no kernel here knows a model.
4//!
5//! Every kernel computes what the language's sugar means, the formula the VM runs: an RMSNorm divides by
6//! `sqrt(mean + 1e-6)` then scales, an attention scores `(q·k)/√hd` and normalizes by a max-subtracted softmax, an
7//! arg-max keeps the first of equal maxima. Accumulation is `f32` in a fixed order (the same inputs give the same
8//! bits on every run); the projections are the one place the numerics are a choice — [`Q8MatKind`] picks the
9//! activation precision of every Q8_0 GEMV:
10//!
11//!   • `Dequant` — the activation stays `f32`, the int8 weight is scaled in the kernel, the dot accumulates in `f64`:
12//!     the precise lane, logits a hair from the `f64` reference;
13//!   • `Int8Act` — the activation quantized to int8 per 32-block and multiplied by `__dp4a` against the weight
14//!     (llama.cpp's MMVQ shape): the fast lane;
15//!   • `TwoPassInt8` — the activation split into a high and a low int8 word, two `__dp4a` per block: ~14-bit
16//!     activations at the fast lane's memory cost.
17//!
18//! A quantized activation is a group of 32 values sharing one scale `s = max|v| / 127`; the high word is
19//! `round(v / s)`, the low word `round((v − hi·s) / (s/128))` with `v − hi·s` one fused multiply-add, as the `f64`
20//! reference computes it.
21//!
22//! A Q8_0 matrix is uploaded split, its int8 values in one array and its block scales in another, so the GEMV reads
23//! 16-byte words. A matrix in any other GGUF format keeps its blocks as the checkpoint stores them, and [`BLOCKS`]
24//! decodes a 32-weight sub-block of a row into int8 levels with a scale and an offset per 16 — `weight = scale·level +
25//! offset`, exactly the CPU dequantizer's arithmetic — so one row dot serves every format under every numerics: the
26//! offset term multiplies the activation's sum, which the int8 lanes take with a `__dp4a` against ones.
27//!
28//! [`Q8MatKind`]: crate::codegen_cuda::qwen_emit::Q8MatKind
29
30use crate::codegen_cuda::qwen_emit::Q8MatKind;
31
32/// The template argument that names a numerics mode in the library: 0 `f32` activations, 1 int8, 2 two-pass int8.
33pub fn mode(kind: Q8MatKind) -> u32 {
34    match kind {
35        Q8MatKind::Dequant => 0,
36        Q8MatKind::Int8Act => 1,
37        Q8MatKind::TwoPassInt8 => 2,
38    }
39}
40
41/// The numerics a per-head matmul — a latent's expansion half — runs under: its activation `f32` under every numerics,
42/// with `f64` sums under the precise one (0) and `f32` sums under the quantized ones (3), so the absorbed latent
43/// attention computes what the expanded one does.
44pub fn head_mode(kind: Q8MatKind) -> u32 {
45    match kind {
46        Q8MatKind::Dequant => 0,
47        Q8MatKind::Int8Act | Q8MatKind::TwoPassInt8 => 3,
48    }
49}
50
51/// The helpers every kernel shares: the storage types, row addressing, warp and block reductions, the activation
52/// quantizer.
53pub const PRELUDE: &str = r#"
54#include <cstddef>
55#include <cuda_fp16.h>
56#include <cuda_bf16.h>
57// An element as the storage type `T` holds it — `f32` as computed, binary16 and bfloat16 rounded to the nearest, ties
58// to even — and as the `f32` every kernel computes in, widened exactly.
59template<typename T> __device__ __forceinline__ T lk_to(float v){ return v; }
60template<> __device__ __forceinline__ __half lk_to<__half>(float v){ return __float2half_rn(v); }
61template<> __device__ __forceinline__ __nv_bfloat16 lk_to<__nv_bfloat16>(float v){ return __float2bfloat16_rn(v); }
62__device__ __forceinline__ float lk_from(float v){ return v; }
63__device__ __forceinline__ float lk_from(__half v){ return __half2float(v); }
64__device__ __forceinline__ float lk_from(__nv_bfloat16 v){ return __bfloat162float(v); }
65template<typename T> __device__ __forceinline__ float lk_kept(float v){ return lk_from(lk_to<T>(v)); }
66// Two and four consecutive elements from `p` as `f32`: one load of their bytes, eight-byte aligned for four binary16
67// values as for two `f32`.
68__device__ __forceinline__ float2 lk_from2(const float* p){ return *(const float2*)p; }
69__device__ __forceinline__ float2 lk_from2(const __half* p){ return __half22float2(*(const __half2*)p); }
70__device__ __forceinline__ float4 lk_from4(const float* p){ return *(const float4*)p; }
71__device__ __forceinline__ float4 lk_from4(const __half* p){
72  uint2 u = *(const uint2*)p;
73  float2 a = __half22float2(*(const __half2*)&u.x), b = __half22float2(*(const __half2*)&u.y);
74  return make_float4(a.x, a.y, b.x, b.y);
75}
76// One element of a result's array as it is written: `f32`, or binary16 rounded to the nearest.
77struct lk_ref {
78  void* p; bool h;
79  __device__ __forceinline__ void operator=(float v) const { if(h) *(__half*)p = __float2half_rn(v); else *(float*)p = v; }
80};
81// A result's array — `f32`, or binary16 that every value written is rounded to — taken from a typed pointer, so a kernel
82// writes either through one pointer type. It can be offset and written, never read.
83struct lk_out {
84  void* p = nullptr; bool h = false;
85  lk_out() = default;
86  __host__ __device__ lk_out(std::nullptr_t) {}
87  __host__ __device__ lk_out(float* q) : p(q) {}
88  __host__ __device__ lk_out(__half* q) : p(q), h(true) {}
89  __host__ __device__ explicit operator bool() const { return p != nullptr; }
90  __device__ __forceinline__ void* at(long i) const { return h ? (void*)((__half*)p + i) : (void*)((float*)p + i); }
91  __device__ __forceinline__ lk_out operator+(long i) const { lk_out o; o.p = at(i); o.h = h; return o; }
92  __device__ __forceinline__ lk_ref operator[](long i) const { return lk_ref{at(i), h}; }
93};
94// A result written into the row a 1-based position names, or the buffer itself when no position is given.
95#define LK_ROW(p, row, pitch) ((p) + ((row) ? (long)(*(row) - 1) * (long)(pitch) : 0L))
96
97__device__ __forceinline__ float lk_warp_sum(float v){
98  for(int o = 16; o > 0; o >>= 1) v += __shfl_down_sync(0xffffffffu, v, o);
99  return __shfl_sync(0xffffffffu, v, 0);
100}
101__device__ __forceinline__ double lk_warp_sum_d(double v){
102  for(int o = 16; o > 0; o >>= 1) v += __shfl_down_sync(0xffffffffu, v, o);
103  return __shfl_sync(0xffffffffu, v, 0);
104}
105__device__ __forceinline__ float lk_warp_max(float v){
106  for(int o = 16; o > 0; o >>= 1) v = fmaxf(v, __shfl_down_sync(0xffffffffu, v, o));
107  return __shfl_sync(0xffffffffu, v, 0);
108}
109__device__ __forceinline__ double lk_warp_sum(double v){ return lk_warp_sum_d(v); }
110// The `V` values each lane holds summed over the warp's lanes, `V` a power of two to 32: lane `l` returns the total of
111// value `l % V`. At a distance `W` below `V` each lane keeps one half of its values and sends the other, the halves
112// summed apart; at and past `V` the whole set is summed. Starting at a distance `W` below 16 sums over each run of
113// `2·W` lanes apart.
114template<int V, int W = 16>
115__device__ __forceinline__ float lk_lane_sums(float (&v)[V]){
116  if constexpr(W >= V){
117    #pragma unroll
118    for(int i = 0; i < V; ++i) v[i] += __shfl_xor_sync(0xffffffffu, v[i], W);
119  } else {
120    bool up = threadIdx.x & W;
121    #pragma unroll
122    for(int i = 0; i < W; ++i){
123      float send = up ? v[i] : v[i + W], keep = up ? v[i + W] : v[i];
124      v[i] = keep + __shfl_xor_sync(0xffffffffu, send, W);
125    }
126  }
127  if constexpr(W > 1) return lk_lane_sums<V, W / 2>(v);
128  else return v[0];
129}
130// The precise numerics (Q 0) sum in f64, the quantized in f32.
131template<int Q> struct lk_acc { typedef float t; };
132template<> struct lk_acc<0> { typedef double t; };
133// The products that read their activation `f32`: every one under the precise numerics (Q 0), and under Q 3 — the
134// latent's expansion halves under the quantized numerics, which sum in f32.
135template<int Q> __host__ __device__ constexpr bool lk_f32_acts(){ return Q == 0 || Q == 3; }
136// Every thread of the block gets the total over `vw` warps, in the accumulator `A` (`float` or `double`); `red` is 32 of
137// them in shared memory. Warp `w` of the block's `nw` plays the warps `w`, `w + nw`, … below `vw`, value `j` of each
138// lane its lane's of the `j`-th: each warp summed over its lanes, then the warps' sums in order — the tree a block of
139// `vw` warps sums its values by.
140template<int VW, typename A>
141__device__ __forceinline__ A lk_warps_sum(const A (&v)[VW], int vw, A* red){
142  int lane = threadIdx.x & 31, warp = threadIdx.x >> 5, nw = blockDim.x >> 5;
143  A s[VW];
144  #pragma unroll
145  for(int j = 0; j < VW; ++j) s[j] = lk_warp_sum(v[j]);
146  __syncthreads();
147  #pragma unroll
148  for(int j = 0; j < VW; ++j) if(lane == 0 && warp + j * nw < vw) red[warp + j * nw] = s[j];
149  __syncthreads();
150  return lk_warp_sum(lane < vw ? red[lane] : (A)0);
151}
152// Every thread of the block gets the block's total.
153template<typename A>
154__device__ __forceinline__ A lk_block_sum(A v, A* red){
155  const A one[1] = {v};
156  return lk_warps_sum<1>(one, (blockDim.x + 31) >> 5, red);
157}
158__device__ __forceinline__ float lk_block_max(float v, float* red){
159  int lane = threadIdx.x & 31, warp = threadIdx.x >> 5, nw = (blockDim.x + 31) >> 5;
160  v = lk_warp_max(v);
161  __syncthreads();
162  if(lane == 0) red[warp] = v;
163  __syncthreads();
164  return lk_warp_max(lane < nw ? red[lane] : -INFINITY);
165}
166// An activation: ACT 0 silu `x / (1 + e^-x)`, 1 sigmoid `1 / (1 + e^-x)`, 2 gelu in ggml's tanh form
167// `x / (1 + e^-2z)`, `z = √(2/π)·(x + 0.044715·x³)`.
168template<int ACT>
169__device__ __forceinline__ float lk_act(float v){
170  if(ACT == 0) return v / (1.0f + expf(-v));
171  if(ACT == 1) return 1.0f / (1.0f + expf(-v));
172  float z = 0.7978845608028654f * (v + 0.044715f * v * v * v);
173  return v / (1.0f + expf(-2.0f * z));
174}
175// The two-word scale of values whose largest magnitude is `a`, and value `v`'s two words under scale `s`, by quotients:
176// `v ≈ s·(h + l/128)` (the two-word activation quantizer's); by products with the scale's reciprocal `r` where a kernel
177// takes many values under one scale; four words packed into one, the first lowest.
178__device__ __forceinline__ float lk_two_scale(float a){ return (a > 1e-30f ? a : 1e-30f) / 127.0f; }
179__device__ __forceinline__ void lk_two_words(float v, float s, int& h, int& l){
180  h = __float2int_rn(v / s); h = h > 127 ? 127 : (h < -128 ? -128 : h);
181  l = __float2int_rn(__fmaf_rn(-(float)h, s, v) / (s * 0.0078125f)); l = l > 127 ? 127 : (l < -128 ? -128 : l);
182}
183__device__ __forceinline__ void lk_two_words_r(float v, float s, float r, int& h, int& l){
184  h = __float2int_rn(v * r); h = h > 127 ? 127 : (h < -128 ? -128 : h);
185  l = __float2int_rn(__fmaf_rn(-(float)h, s, v) * r * 128.f); l = l > 127 ? 127 : (l < -128 ? -128 : l);
186}
187__device__ __forceinline__ int lk_int8x4(int a, int b, int c, int d){
188  return (int)((unsigned)(a & 255) | ((unsigned)(b & 255) << 8) | ((unsigned)(c & 255) << 16) | ((unsigned)(d & 255) << 24));
189}
190// Quantize the 32-value group this warp holds, one value per lane, as group `g`.
191template<int Q>
192__device__ __forceinline__ void lk_quant_lane(float v, signed char* __restrict__ qh, signed char* __restrict__ ql,
193                                              float* __restrict__ qs, long i, long g){
194  float a = lk_warp_max(fabsf(v));
195  if(Q == 1){
196    float s = a > 0.f ? a / 127.0f : 1.0f;
197    if((threadIdx.x & 31) == 0) qs[g] = s;
198    qh[i] = (signed char)__float2int_rn(v / s);
199  } else {
200    float s = lk_two_scale(a);
201    int h, l;
202    lk_two_words(v, s, h, l);
203    if((threadIdx.x & 31) == 0) qs[g] = s;
204    qh[i] = (signed char)h; ql[i] = (signed char)l;
205  }
206}
207// Quantize a pair of values `i`, `i + 1` of a 32-value group sixteen lanes of a warp hold, a pair a lane, as group
208// `i >> 5` — the group's largest magnitude taken over the sixteen lanes on every lane (a lane `on` false holds none of
209// it), and each value and the scale then what `lk_quant_lane` makes of the group.
210template<int Q>
211__device__ __forceinline__ void lk_quant_pair(float x, float y, bool on, signed char* __restrict__ qh, signed char* __restrict__ ql,
212                                              float* __restrict__ qs, long i){
213  float a = on ? fmaxf(fabsf(x), fabsf(y)) : 0.f;
214  #pragma unroll
215  for(int o = 8; o > 0; o >>= 1) a = fmaxf(a, __shfl_xor_sync(0xffffffffu, a, o));
216  if(!on) return;
217  if(Q == 1){
218    float s = a > 0.f ? a / 127.0f : 1.0f;
219    if((threadIdx.x & 15) == 0) qs[i >> 5] = s;
220    qh[i] = (signed char)__float2int_rn(x / s);
221    qh[i + 1] = (signed char)__float2int_rn(y / s);
222  } else {
223    float s = lk_two_scale(a);
224    int h, l;
225    lk_two_words(x, s, h, l);
226    qh[i] = (signed char)h; ql[i] = (signed char)l;
227    lk_two_words(y, s, h, l);
228    qh[i + 1] = (signed char)h; ql[i + 1] = (signed char)l;
229    if((threadIdx.x & 15) == 0) qs[i >> 5] = s;
230  }
231}
232// Where an attention quantizes its output for the projection that reads it: its words, low words and scales.
233struct lk_qout { signed char* q; signed char* l; float* s; const float* g; int ga; };
234// Values `i`, `i + 1` of an attention's output: gated by `lk_act` (`ga`) of the gate's own values `g[i]`, `g[i + 1]` where
235// `g` is given, as a product with the activation computes it; written `f32` where `out` is given; quantized under `QO`
236// into `qo` (`lk_quant_pair`) — every lane of the warp calls it, `on` the lanes that hold a pair.
237template<int QO>
238__device__ __forceinline__ void lk_attn_store(float* __restrict__ out, lk_qout qo, long i, bool on, float x, float y){
239  if(on && qo.g){
240    const float gx = qo.g[i], gy = qo.g[i + 1];
241    x *= qo.ga == 0 ? lk_act<0>(gx) : qo.ga == 1 ? lk_act<1>(gx) : lk_act<2>(gx);
242    y *= qo.ga == 0 ? lk_act<0>(gy) : qo.ga == 1 ? lk_act<1>(gy) : lk_act<2>(gy);
243  }
244  if(on && out) *(float2*)(out + i) = make_float2(x, y);
245  if(QO > 0) lk_quant_pair<QO>(x, y, on, qo.q, qo.l, qo.s, i);
246}
247// One step of a Q8_0 dot's partial sum, as its two factors: the partial `p` becomes `fmaf(a, b, p)` for the int8 dot
248// `d` (and, in two words, the low words' `e`) of a block of weight scale `w` and activation scale `s`, each operation
249// spelled out, so every kernel that sums as the GEMV sums takes the same steps (`lk_q8_acc` takes one).
250template<int Q>
251__device__ __forceinline__ float2 lk_q8_term(float w, float s, float d, float e){
252  if(Q == 1) return make_float2(__fmul_rn(w, s), d);
253  return make_float2(w, __fmaf_rn(s, d, __fmul_rn(__fmul_rn(s, 0.0078125f), e)));
254}
255template<int Q>
256__device__ __forceinline__ float lk_q8_acc(float acc, float w, float s, float d, float e){
257  const float2 t = lk_q8_term<Q>(w, s, d, e);
258  return __fmaf_rn(t.x, t.y, acc);
259}
260// The four partials of a quantized Q8_0 dot summed in the one order every kernel that sums as the GEMV sums takes.
261__device__ __forceinline__ float lk_q8_sum4(float p0, float p1, float p2, float p3){ return (p0 + p2) + (p1 + p3); }
262// The int8 dot of one 32-value block two lanes hold sixteen values each of (`w` and `x` their words), exact, in both.
263__device__ __forceinline__ int lk_q8_block_dot(int4 w, int4 x){
264  int d = __dp4a(w.x, x.x, 0) + __dp4a(w.y, x.y, 0) + __dp4a(w.z, x.z, 0) + __dp4a(w.w, x.w, 0);
265  return d + __shfl_xor_sync(0xffffffffu, d, 1);
266}
267// The scratch, in `float2`, a warp of a quantized Q8_0 GEMV takes for `U` dots at once over more than one activation
268// row: a round's steps of up to eight dots at a time, a dot's sixteen 20 apart, so a half-warp's chain reads fall on
269// distinct banks.
270template<int U> __host__ __device__ constexpr int lk_q8_scratch(){ return (U < 8 ? U : 8) * 20; }
271// Round `c` of rows `o … o + W − 1` dotted with one activation row (`lk_q8_rows_dot`): its first `n` blocks' steps
272// into each row's partials in lanes `2q`, chained in order from pairs `q`, `q + 4`, `q + 8`, `q + 12` by `shfl_down`;
273// a whole round's sixteen (`WHOLE`) need no test of the blocks past the row's end.
274template<int Q, int W, bool WHOLE>
275__device__ __forceinline__ void lk_q8_round(float (&acc)[W], const signed char* __restrict__ wq, const __half* __restrict__ ws, long o, int K,
276                                            const signed char* __restrict__ xq, const signed char* __restrict__ xl, const float* __restrict__ xs,
277                                            int c, int n){
278  const int lane = threadIdx.x & 31, j = lane >> 1, nb = K >> 5, blk = c * 16 + j;
279  const bool in = WHOLE || j < n;
280  const int4 zero = make_int4(0, 0, 0, 0);
281  const int4 h = in ? ((const int4*)xq)[c * 32 + lane] : zero;
282  const int4 l = Q == 2 && in ? ((const int4*)xl)[c * 32 + lane] : zero;
283  const float s = in ? xs[blk] : 0.f;
284  #pragma unroll
285  for(int r = 0; r < W; ++r){
286    const int4 w = in ? ((const int4*)(wq + (o + r) * K))[c * 32 + lane] : zero;
287    const float wsc = in ? __half2float(ws[(o + r) * nb + blk]) : 0.f;
288    const int d = lk_q8_block_dot(w, h), e = Q == 2 ? lk_q8_block_dot(w, l) : 0;
289    const float2 t = lk_q8_term<Q>(wsc, s, (float)d, (float)e);
290    if(in) acc[r] = __fmaf_rn(t.x, t.y, acc[r]);
291    #pragma unroll
292    for(int k = 1; k < 4; ++k){
293      const float a = __shfl_down_sync(0xffffffffu, t.x, 8 * k), b = __shfl_down_sync(0xffffffffu, t.y, 8 * k);
294      if(WHOLE || j + 4 * k < n) acc[r] = __fmaf_rn(a, b, acc[r]);
295    }
296  }
297}
298// Rows `o … o + W − 1` of a Q8_0 matrix (int8 values `wq`, a half scale per 32 in `ws`) dotted with the `M` activation
299// rows of `K` values — one warp of a block of at most `WARPS` — row `r`'s dots at `out + r·M`, in every lane. Under the
300// precise numerics (Q 0) the activations are `f32` and the sums `f64`, four values a lane at a time. Quantized (int8
301// words, two under Q 2), each 32-value block's dot is exact in int32 and its step (`lk_q8_term`) goes into partial
302// `b mod 4` of block `b`, a partial's blocks in order; the four partials sum as `lk_q8_sum4` sums them. The row goes
303// 512 values (16 blocks) a round, sixteen bytes a lane: lanes `2j`, `2j + 1` block `j` of each (`lk_q8_block_dot`),
304// so a round's steps of partial `q` are pairs `q`, `q + 4`, `q + 8` and `q + 12`'s. With one activation row each row's
305// partials chain in lanes `2q`, reading the steps by `shfl_down`; with more, the round's steps go through the warp's
306// scratch (`lk_q8_scratch`), up to eight dots' a time, and lane `4u + q` chains the time's dot `u`'s partial `q`. The
307// blocks past the row's end are none of its partials'.
308template<int Q, int M, int W, int WARPS = 8>
309__device__ __forceinline__ void lk_q8_rows_dot(const signed char* __restrict__ wq, const __half* __restrict__ ws, long o, int K,
310                                               const float* __restrict__ x, const signed char* __restrict__ xq,
311                                               const signed char* __restrict__ xl, const float* __restrict__ xs, float* out){
312  const int lane = threadIdx.x & 31, nb = K >> 5;
313  if constexpr(Q == 0){
314    double acc[W][M];
315    #pragma unroll
316    for(int r = 0; r < W; ++r)
317      #pragma unroll
318      for(int t = 0; t < M; ++t) acc[r][t] = 0.0;
319    for(int g = lane; g < (K >> 2); g += 32){
320      char4 w[W];
321      double sc[W];
322      #pragma unroll
323      for(int r = 0; r < W; ++r){ w[r] = ((const char4*)(wq + (o + r) * K))[g]; sc[r] = (double)__half2float(ws[(o + r) * nb + (g >> 3)]); }
324      #pragma unroll
325      for(int t = 0; t < M; ++t){
326        const float* xt = x + (long)t * K + 4 * g;
327        float x0 = xt[0], x1 = xt[1], x2 = xt[2], x3 = xt[3];
328        #pragma unroll
329        for(int r = 0; r < W; ++r) acc[r][t] += sc[r] * ((double)w[r].x * x0 + (double)w[r].y * x1 + (double)w[r].z * x2 + (double)w[r].w * x3);
330      }
331    }
332    #pragma unroll
333    for(int r = 0; r < W; ++r)
334      #pragma unroll
335      for(int t = 0; t < M; ++t) out[r * M + t] = (float)lk_warp_sum_d(acc[r][t]);
336  } else if constexpr(M == 1){
337    float acc[W];
338    #pragma unroll
339    for(int r = 0; r < W; ++r) acc[r] = 0.f;
340    const int full = nb >> 4, rest = nb & 15;
341    for(int c = 0; c < full; ++c) lk_q8_round<Q, W, true>(acc, wq, ws, o, K, xq, xl, xs, c, 16);
342    if(rest) lk_q8_round<Q, W, false>(acc, wq, ws, o, K, xq, xl, xs, full, rest);
343    #pragma unroll
344    for(int r = 0; r < W; ++r){
345      float v = acc[r];
346      v += __shfl_down_sync(0xffffffffu, v, 4);
347      v += __shfl_down_sync(0xffffffffu, v, 2);
348      out[r] = __shfl_sync(0xffffffffu, v, 0);
349    }
350  } else {
351    constexpr int U = W * M, G = U < 8 ? U : 8, R = (U + G - 1) / G;
352    __shared__ float2 lk_q8s[WARPS][lk_q8_scratch<U>()];
353    const int warp = threadIdx.x >> 5, j = lane >> 1, u0 = lane >> 2, q = lane & 3;
354    if(warp >= WARPS) __trap();
355    float2* sm = lk_q8s[warp];
356    float acc[R];
357    #pragma unroll
358    for(int i = 0; i < R; ++i) acc[i] = 0.f;
359    const int4 zero = make_int4(0, 0, 0, 0);
360    for(int c = 0; c * 16 < nb; ++c){
361      const int blk = c * 16 + j, n = min(16, nb - c * 16);
362      const bool in = j < n;
363      int4 w[W];
364      float wsc[W];
365      #pragma unroll
366      for(int r = 0; r < W; ++r){
367        w[r] = in ? ((const int4*)(wq + (o + r) * K))[c * 32 + lane] : zero;
368        wsc[r] = in ? __half2float(ws[(o + r) * nb + blk]) : 0.f;
369      }
370      float2 st[U];
371      #pragma unroll
372      for(int t = 0; t < M; ++t){
373        const int4 h = in ? ((const int4*)(xq + (long)t * K))[c * 32 + lane] : zero;
374        const int4 l = Q == 2 && in ? ((const int4*)(xl + (long)t * K))[c * 32 + lane] : zero;
375        const float s = in ? xs[(long)t * nb + blk] : 0.f;
376        #pragma unroll
377        for(int r = 0; r < W; ++r){
378          const int d = lk_q8_block_dot(w[r], h), e = Q == 2 ? lk_q8_block_dot(w[r], l) : 0;
379          st[r * M + t] = lk_q8_term<Q>(wsc[r], s, (float)d, (float)e);
380        }
381      }
382      // Up to eight dots' steps a time: pair `j` writes its block's (the even lane an even dot's, the odd an odd's),
383      // then lane `4u + q` chains dot `u`'s partial `q` over blocks `q`, `q + 4`, `q + 8`, `q + 12`.
384      #pragma unroll
385      for(int i = 0; i < R; ++i){
386        #pragma unroll
387        for(int g = 0; g < G; ++g) if(i * G + g < U && (lane & 1) == (g & 1)) sm[g * 20 + j] = st[i * G + g];
388        __syncwarp();
389        if(u0 < G && i * G + u0 < U){
390          #pragma unroll
391          for(int k = 0; k < 4; ++k) if(q + 4 * k < n){ const float2 v = sm[u0 * 20 + q + 4 * k]; acc[i] = __fmaf_rn(v.x, v.y, acc[i]); }
392        }
393        __syncwarp();
394      }
395    }
396    #pragma unroll
397    for(int i = 0; i < R; ++i){
398      float v = acc[i];
399      v += __shfl_down_sync(0xffffffffu, v, 2);
400      v += __shfl_down_sync(0xffffffffu, v, 1);
401      #pragma unroll
402      for(int g = 0; g < G; ++g) if(i * G + g < U) out[i * G + g] = __shfl_sync(0xffffffffu, v, 4 * g);
403    }
404  }
405}
406"#;
407
408/// A stream held back for a span of the global timer. Under `--stagger <seed>` one runs before each launch of a step, its
409/// span drawn from the seed, the form and the launch, so launches its streams leave unordered run in another order
410/// under each seed.
411pub const STALL: &str = r#"
412__global__ void lk_stall(unsigned long long ns){
413  unsigned long long t0, t;
414  asm volatile("mov.u64 %0, %%globaltimer;" : "=l"(t0));
415  do { __nanosleep(256); asm volatile("mov.u64 %0, %%globaltimer;" : "=l"(t)); } while(t - t0 < ns);
416}
417// The stall before launch `i` of the form of `rows` rows under `seed`: under 128 µs, drawn by splitmix64.
418static unsigned long long lk_stall_ns(unsigned long long seed, unsigned long long rows, unsigned long long i){
419  unsigned long long z = seed * 0x9e3779b97f4a7c15ULL + rows * 0xbf58476d1ce4e5b9ULL + i * 0x94d049bb133111ebULL;
420  z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;
421  z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;
422  return (z ^ (z >> 31)) % 128000ULL;
423}
424"#;
425
426/// Two projections of one activation through a gate, `y = act(x·Wg)·(x·Wu)`: a warp `W` consecutive output rows dots
427/// their gate and up rows (formats `FG`, `FU`) with each of the `M` activation rows as the plain GEMV of each format dots
428/// them (`lk_gemv_dot`), adds their biases, and gates them — `ACT` −1 SwiGLU as `lk_swiglu` computes it, otherwise
429/// `u·act(g)` as the gated product `lk_binary` computes it. With a quantized output (`QO`) a block of `32 / W` warps
430/// takes 32 outputs, one quantized block a row, quantized as `lk_quant_lane` quantizes it; without, a block of 8 warps
431/// takes `8·W`.
432const GLU: &str = r#"
433template<int FG, int FU, int Q, int M, int ACT, bool OUTF, int QO, int W = 1>
434__global__ void __launch_bounds__(QO > 0 ? 1024 / W : 256) lk_gemv_glu(lk_w wg, lk_w wu, const float* __restrict__ x,
435    const signed char* __restrict__ xq, const signed char* __restrict__ xl, const float* __restrict__ xs,
436    const float* __restrict__ bg, const float* __restrict__ bu, float* __restrict__ y, signed char* __restrict__ yq,
437    signed char* __restrict__ yl, float* __restrict__ ys, int K, int N){
438  __shared__ float v[M][32];
439  int lane = threadIdx.x & 31, warp = threadIdx.x >> 5;
440  long o = ((long)blockIdx.x * (blockDim.x >> 5) + warp) * W;
441  if(o < N){
442    float g[W * M], u[W * M];
443    lk_gemv_dot<FG, Q, M, W, (QO > 0 ? 32 / W : 8)>(wg, o, K, x, xq, xl, xs, g);
444    lk_gemv_dot<FU, Q, M, W, (QO > 0 ? 32 / W : 8)>(wu, o, K, x, xq, xl, xs, u);
445    if(lane == 0){
446      #pragma unroll
447      for(int r = 0; r < W; ++r){
448        #pragma unroll
449        for(int t = 0; t < M; ++t){
450          float gv = bg ? g[r * M + t] + bg[o + r] : g[r * M + t], uv = bu ? u[r * M + t] + bu[o + r] : u[r * M + t];
451          float val = ACT < 0 ? gv / (1.0f + expf(-gv)) * uv : uv * lk_act<(ACT < 0 ? 0 : ACT)>(gv);
452          if(QO > 0) v[t][warp * W + r] = val;
453          else if(OUTF) y[(long)t * N + o + r] = val;
454        }
455      }
456    }
457  }
458  if(QO > 0){
459    __syncthreads();
460    if(warp < M){
461      long at = (long)warp * N + (long)blockIdx.x * 32 + lane;
462      float val = v[warp][lane];
463      if(OUTF) y[at] = val;
464      lk_quant_lane<QO>(val, yq, yl, ys, at, at >> 5);
465    }
466  }
467}
468"#;
469
470/// The positions the attention scores at a time (`LK_TILE` in its source).
471pub const ATTN_TILE: usize = 64;
472
473/// The fewest positions a split of an attention's span takes: below it a split's partial costs more than its scores.
474pub const ATTN_MIN_SPLIT: usize = 32;
475
476/// The key and value elements an attention block reads a position, across its heads: four latent-attention heads'
477/// worth (`(576 + 512) · 4`), which scored best from a thousand positions on (the 3060's attention measurements),
478/// against two heads' at a hundred.
479pub const ATTN_BLOCK_VALUES: usize = 4352;
480
481/// The dynamic shared memory an attention block takes: its `g` query heads of `hd` (`f32`), then — in accumulators of
482/// `acc` bytes — their scores over a tile and each head's maximum, sum and fold factor over each of `splits` chunks.
483pub fn attn_smem_bytes(g: usize, hd: usize, splits: usize, acc: usize) -> usize {
484    (g * hd * 4).next_multiple_of(16) + (g * ATTN_TILE + 3 * g * splits) * acc
485}
486
487/// The pairs of each head's values a thread of an attention block (256 threads) accumulates: `lk_attention` weighs at
488/// most `g` times as many of its block's `g` heads' value slots a thread.
489pub fn attn_values_per_thread(vd: usize) -> usize {
490    vd.div_ceil(512)
491}
492
493/// The blocks of an attention (`lk_attention`'s `MB`) a multiprocessor holds at once, by the registers it leaves them:
494/// three for a launch of more blocks than the chip holds at two (`blocks` over `sms`), which come in waves, so
495/// occupancy bounds them — on the 3060, 5.7% faster for Llama-3.2-1B's batch of 64 and 3.4% for Gemma-3-1B's; two for a
496/// launch under one wave, whose blocks' latency bounds it, and for the `f64` sums (`acc` 8 bytes), which need the
497/// registers.
498pub fn attn_blocks_a_multiprocessor(blocks: usize, sms: usize, acc: usize) -> usize {
499    if acc == 4 && blocks > 2 * sms {
500        3
501    } else {
502        2
503    }
504}
505
506/// The path an attention launch takes past a row of one chunk (`lk_attention`'s `PATH`, `lk_attn_path`), fixed where it
507/// launches so its kernel compiles that path alone and ptxas allots its registers to it: the chunks' partials of a
508/// grid of `z` split blocks a row folded by the last to arrive, held side by side by the row's one block (`side`
509/// chunks at a time), weighed one at a time by it, or none where a row is one chunk (`splits` 1).
510pub fn attn_path(z: usize, side: usize, splits: usize) -> &'static str {
511    if z > 1 {
512        "LK_ATTN_SPLIT"
513    } else if side > 0 {
514        "LK_ATTN_HELD"
515    } else if splits > 1 {
516        "LK_ATTN_CHUNKS"
517    } else {
518        "LK_ATTN_ONE"
519    }
520}
521
522/// The lanes a key's dot takes in an attention of heads `hd` wide (`lk_attn_run_width`, `lk_attention`'s `RW`): a
523/// half warp for a head of 9 to 16 fours, the whole warp otherwise.
524pub fn attn_run_width(hd: usize) -> usize {
525    if hd / 4 > 8 && hd / 4 <= 16 {
526        16
527    } else {
528        32
529    }
530}
531
532/// The most shared memory an attention block (`lk_attention`) keeps its chunks' partials in, so a row it takes whole
533/// (a batch's sequence, a chunk's row) weighs each chunk once: a block of 256 threads keeps three to a streaming
534/// multiprocessor.
535pub const ATTN_HELD_BYTES: usize = 32 * 1024;
536
537/// The bytes of a block's `g` heads' partials over `splits` chunks — each chunk's maximum, sum and `vd` weighed values,
538/// in the accumulator's `acc` bytes — and whether the block holds them (`held`): a row cut into chunks, the partials
539/// within `ATTN_HELD_BYTES`.
540pub fn attn_held_bytes(g: usize, vd: usize, splits: usize, acc: usize) -> usize {
541    g * splits * (vd + 2) * acc
542}
543pub fn attn_holds(g: usize, vd: usize, splits: usize, acc: usize) -> bool {
544    splits > 1 && attn_held_bytes(g, vd, splits, acc) <= ATTN_HELD_BYTES
545}
546
547/// The chunks of its row a block that holds them weighs side by side (`lk_attn_side`): as many as its threads' value
548/// slots hold — each chunk `vd / 2` pairs a head, a thread `attn_values_per_thread` a head — and no more than the row's
549/// `splits`; one where a chunk fills them.
550pub fn attn_side_chunks(vd: usize, splits: usize) -> usize {
551    (512 * attn_values_per_thread(vd) / vd).clamp(1, splits.max(1))
552}
553
554/// The shared memory a block weighing `side` chunks side by side takes past `attn_smem_bytes`' one tile of scores:
555/// a tile of its `g` heads' scores for each other chunk.
556pub fn attn_side_bytes(g: usize, side: usize, acc: usize) -> usize {
557    side.saturating_sub(1) * g * ATTN_TILE * acc
558}
559
560/// The most chunks an attention cuts a row's span into: enough blocks for two a streaming multiprocessor (`sms`) over
561/// the `blocks` the head blocks of one row give, and no more than give each chunk `ATTN_MIN_SPLIT` positions of
562/// `span`.
563pub fn attn_splits(blocks: usize, span: usize, sms: usize) -> usize {
564    (2 * sms).div_ceil(blocks).clamp(1, span.div_ceil(ATTN_MIN_SPLIT).max(1))
565}
566
567/// The query heads an attention block takes together: the largest divisor of `group`, at most 16, whose keys and values
568/// a position stay within `ATTN_BLOCK_VALUES` (one head whatever its width), whose accumulators (`g` heads' value
569/// pairs a thread, twice over in a block that takes every chunk) stay within 32 registers, and whose queries, scores
570/// and chunk sums fit `smem` bytes — `None` when not even one head fits.
571pub fn attn_heads_per_block(group: usize, hd: usize, vd: usize, span: usize, sms: usize, smem: usize, acc: usize) -> Option<usize> {
572    let vpt = attn_values_per_thread(vd);
573    (1..=group.min(16)).rev().find(|&g| {
574        group % g == 0
575            && (g == 1 || g * (hd + vd) <= ATTN_BLOCK_VALUES)
576            && g * vpt <= 16
577            && attn_smem_bytes(g, hd, attn_splits(1, span, sms), acc) <= smem
578    })
579}
580
581/// The query vectors a block of the tiled attention takes: heads of one key/value group over consecutive rows.
582pub const ATTN_TILE_Q: usize = 32;
583
584/// The heads of one group a tiled attention block takes: the largest power of two dividing `group`, at most 32 — the
585/// block's rows `ATTN_TILE_Q` over it.
586pub fn attn_tile_heads(group: usize) -> usize {
587    1 << group.trailing_zeros().min(5)
588}
589
590/// The query vectors a block of the flash attention (`lk_attention_flash`) takes: 64 for heads and values to 128 wide,
591/// 32 past them, so a thread's outputs stay 64 registers and the block's shared memory within a block's.
592pub fn attn_flash_queries(hd: usize, vd: usize) -> usize {
593    if hd <= 128 && vd <= 128 {
594        64
595    } else {
596        32
597    }
598}
599
600/// The flash attention block's dynamic shared memory: its queries, two stages of a tile's keys 32 values of the head at
601/// a time and of its values 16 keys at a time, and the tile's weights — rows padded four values.
602pub fn attn_flash_smem_bytes(hd: usize, vd: usize) -> usize {
603    let bq = attn_flash_queries(hd, vd);
604    (bq * (hd + 4) + 2 * 64 * 36 + 2 * 16 * (vd + 4) + 64 * (bq + 4)) * 4
605}
606
607/// The threads of a flash attention block: 256 over 64 queries (a thread 4 queries by 4 keys), 128 over 32 — where the
608/// 3060 measured each fastest.
609pub fn attn_flash_threads(hd: usize, vd: usize) -> usize {
610    if attn_flash_queries(hd, vd) == 64 {
611        256
612    } else {
613        128
614    }
615}
616
617/// The groups of four values, 128 apart, a thread of the tiled attention accumulates for each of its queries.
618pub fn attn_tile_values(vd: usize) -> usize {
619    vd.div_ceil(128)
620}
621
622/// The tiled attention block's dynamic shared memory: a 32-wide chunk of its queries and of a tile's 64 keys, the
623/// tile's scores, and eight keys' values.
624pub fn attn_tile_smem_bytes(vd: usize) -> usize {
625    (32 * 32 + 32 * 64 + 64 * 32 + 8 * vd) * 4
626}
627
628/// The threads of the block that groups a block's expert choices (`lk_moe_group`): a warp a 32 choices, as many warps
629/// as 32 and as each warp's count of every one of `experts` experts, beside the running offsets, fits 48 KB.
630pub fn moe_group_threads(experts: usize) -> usize {
631    32 * (48 * 1024 / (4 * experts)).saturating_sub(1).clamp(1, 32)
632}
633
634/// The shared memory of `lk_moe_group` at `threads`: the running offsets and each warp's counts.
635pub fn moe_group_smem_bytes(experts: usize, threads: usize) -> usize {
636    (1 + threads / 32) * experts * 4
637}
638
639/// The bytes of the lane's sums under the numerics of kernel mode `mode` ([`mode`]), and their CUDA type: `f64` for the
640/// precise numerics (mode 0) — every sum of every kernel, a norm's, a convolution's, the delta rule's, the router's
641/// softmax and the experts' — `f32` for the others.
642pub fn accumulator(mode: u32) -> (usize, &'static str) {
643    if mode == 0 {
644        (8, "double")
645    } else {
646        (4, "float")
647    }
648}
649
650/// The template argument that names a weight format in the block library: its GGUF type id.
651pub fn format_arg(ty: crate::model::quant::GgmlType) -> u32 {
652    ty.id()
653}
654
655/// The activation rows a block of `lk_gemv_f32` takes, together (its `LK_F32_ROWS`): few enough that a wide chunk's rows
656/// spread over the chip, every row's dots summed as one row's are.
657pub const GEMV_F32_ROWS: usize = 4;
658
659/// The outputs a block of the decode step's expert down projection takes (`W` of `lk_moe_down`), and the warps its
660/// shared expert's rows take (`SW`): four outputs where `d` divides by four, so each kept expert's warp has four rows'
661/// weight loads in flight over one load of the hidden row — and a warp a row of the shared expert's where its rows are
662/// wider than an expert's, so no warp holds the block back. Against a block of one output on the 3060, DeepSeek-V2-Lite's
663/// down projections (Q8_0 beside a shared Q6_K, Q5_0 beside a shared Q4_K) drop 13–31%, gpt-oss-20b's (MXFP4) 23–36%
664/// and Qwen3-30B-A3B's shape (Q4_K, Q6_K) 16–33%; eight outputs lost but in MXFP4.
665pub fn moe_down_rows(d: usize, dff: usize, sdff: usize) -> (usize, usize) {
666    let w = [4, 2, 1].into_iter().find(|w| d % w == 0).expect("one divides every width");
667    (w, if sdff > dff { w } else { 1 })
668}
669
670/// The blocks and threads of a decode step's down projection (`lk_moe_down`, `lk_moe_down_norm`) over a row of `d`:
671/// `moe_down_rows` outputs a block, a warp each of the `k` kept experts and the shared expert's warps where its
672/// intermediate `sdff` is not 0.
673pub fn moe_down_launch(d: usize, dff: usize, k: usize, sdff: usize) -> (usize, usize) {
674    let (rows, shared) = moe_down_rows(d, dff, sdff);
675    (d / rows, 32 * (k + if sdff > 0 { shared } else { 0 }))
676}
677
678/// The threads of a block-format projection that norms its row in its last block (`lk_gemv_blk_norm`): eight warps,
679/// four where a warp takes `per_warp` rows past one.
680pub fn gemv_blk_norm_threads(per_warp: usize) -> usize {
681    32 * if per_warp == 1 { 8 } else { 4 }
682}
683
684/// Whether a block of `threads` runs a norm of a row of `cols` as the norm's own block does, each of its threads one of
685/// the norm's (`norm_threads`). A narrower block plays several of the norm's warps a warp, one after another, and the
686/// row's norm runs on that one block alone: DeepSeek-V2-Lite's 320-thread down blocks playing the norm's 1024 decoded at
687/// 142.0 tokens a second on the 3060, 146.7 with the norm's tail cut and 146.3 with the norm its own launch.
688pub fn block_holds_its_norm(threads: usize, cols: usize) -> bool {
689    threads >= norm_threads(cols)
690}
691
692/// The fewest rows a batch's Q8_0 projection takes to the tensor cores (`lk_gemv_mma`); fewer run on the GEMV.
693pub const GEMV_MMA_MIN_ROWS: usize = 2;
694/// The most rows `lk_gemv_mma` takes in one launch: four m-tiles of 16.
695pub const GEMV_MMA_ROWS: usize = 64;
696
697/// `lk_gemv_mma`'s m-tiles for `m` rows (at most `GEMV_MMA_ROWS`): 1, 2 or 4.
698pub fn gemv_mma_tiles(m: usize) -> usize {
699    match m {
700        0..=16 => 1,
701        17..=32 => 2,
702        _ => 4,
703    }
704}
705
706/// `lk_gemv_mma`'s shape over `mt` m-tiles, `(nt, mw, nw)`: four n-tiles of 8 outputs a block over one m-tile, a warp
707/// each; eight over two, a warp each n-tile over both; sixteen over four, a warp each two n-tiles over two m-tiles — so
708/// a block stages its activation rows once for `32·mt` outputs, and over four m-tiles each fragment a warp loads feeds
709/// two products. On the 3060 at 64 rows the two-by-two warps beat a warp each n-tile over all four m-tiles on
710/// Llama-3.2-1B's down projection (8192 by 2048) 117 µs to 102, its output projection 33.8 to 30.9, its query, key and
711/// value 35.6 to 32.9 and its gate and up 171.6 to 168.8; at 16 and 32 rows two n-tiles a warp gain nothing.
712pub fn gemv_mma_shape(mt: usize) -> (usize, usize, usize) {
713    match mt {
714        4 => (16, 2, 2),
715        _ => (4 * mt, mt, 1),
716    }
717}
718
719/// `lk_gemv_mma`'s launch over `m` rows (at most `GEMV_MMA_ROWS`) of a projection of `n` outputs and `k` on a chip of
720/// `sms` multiprocessors, `(mt, nt, mw, nw)`: the widest tile its rows fill (`gemv_mma_shape`), except that a narrow
721/// projection of long rows over four m-tiles — its blocks of 128 outputs leaving more than half the chip idle, each
722/// running long (`k` at least 2048) — takes blocks of 64 outputs, twice as many. On the 3060 at 64 rows: Gemma-3-1B's
723/// down projection (6912 by 1152) 94 µs to 54 (62 as the 32-row tile in two slabs of grid layers), Qwen3.5-0.8B's (3584
724/// by 1024) 54 to 31 (35) and its output projection (2048 by 1024) 33 to 20 (22); wider or shorter projections are
725/// faster in blocks of 128.
726pub fn gemv_mma_launch(m: usize, n: usize, k: usize, sms: usize) -> (usize, usize, usize, usize) {
727    let mt = gemv_mma_tiles(m);
728    let (nt, mw, nw) = gemv_mma_shape(mt);
729    if mt == 4 && 2 * n.div_ceil(8 * nt) <= sms && k >= 2048 {
730        return (mt, nt / 2, mw, nw);
731    }
732    (mt, nt, mw, nw)
733}
734
735/// `lk_gemv_mma`'s threads: a warp each `nw` n-tiles over each `mw` of its `mt` m-tiles.
736pub fn gemv_mma_threads(mt: usize, nt: usize, mw: usize, nw: usize) -> usize {
737    32 * (nt / nw) * (mt / mw)
738}
739
740/// `lk_gemv_mma`'s shared memory (`lk_mma_smem`): its stages (three, two under the two-word numerics), a stage four
741/// blocks of each of its `8·nt` matrix rows and `16·mt` activation rows (both words' under two words), rows 144 bytes
742/// apart, and the stage's scales.
743pub fn gemv_mma_smem_bytes(two: bool, mt: usize, nt: usize) -> usize {
744    let stage = 8 * nt * 144 + if two { 2 } else { 1 } * 16 * mt * 144 + 8 * nt * 8 + 16 * mt * 16;
745    stage * if two { 2 } else { 3 }
746}
747
748/// The output rows a warp of a GEMV takes (`W` of `lk_row_dot`): four in a block format when one activation row meets
749/// a matrix of at least 2048 rows of at least 64 sub-blocks — four rows' weight loads in flight over one load of the
750/// activation outran one row a warp by 12–20% on the 3060 there, and lost where fewer warps would cover the chip or a
751/// row leaves lanes idle — one otherwise. A Q8_0 row already moves sixteen bytes a lane at a time.
752pub fn rows_a_warp(ty: crate::model::quant::GgmlType, n: usize, k: usize, m: usize) -> usize {
753    let four = ty != crate::model::quant::GgmlType::Q8_0 && m == 1 && n >= 2048 && k / 32 >= 64 && n % 32 == 0;
754    if four {
755        4
756    } else {
757        1
758    }
759}
760
761/// Whether a per-head matmul whose rows are its inputs stages them (`lk_head_axpy_staged`, `AXPY_W` sub-blocks and
762/// `AXPY_R` row groups a block): under the quantized numerics in every block format but Q6_K and Q8_0 — 1.7–2.8 times
763/// the per-lane kernel on the 3060 there (19.9 µs to 9.7 for DeepSeek-V2-Lite's Q4_K absorption); the per-lane kernel
764/// keeps the precise numerics' `f64` sums, Q6_K's heavier decode and Q8_0's one activation row. The choice reads no
765/// count of activation rows: a prompt's chunk and a decode step sum alike, so a prompt continues alike in chunks or a
766/// token at a time.
767pub fn axpy_staged(ty: crate::model::quant::GgmlType, numerics_mode: u32) -> bool {
768    use crate::model::quant::GgmlType as T;
769    numerics_mode != 0 && ty != T::Q6K && ty != T::Q8_0
770}
771
772/// The sub-blocks of outputs and the row groups a block of the staged per-head matmul takes.
773pub const AXPY_W: usize = 4;
774pub const AXPY_R: usize = 2;
775
776/// The bytes of the staged per-head matmul's own sums in shared memory (`red`): an `f32` for each lane of each of its
777/// `AXPY_R · AXPY_W` warps — it stages only under the quantized numerics, which sum in `f32`.
778pub const AXPY_SUMS: usize = AXPY_R * AXPY_W * 32 * 4;
779
780/// The bytes of a row the staged per-head matmul holds in shared memory (`lk_axpy_pitch`): the units of `AXPY_W`
781/// sub-blocks and one more, 15 bytes of alignment slack, rounded to an odd number of words.
782pub fn axpy_pitch(ty: crate::model::quant::GgmlType) -> usize {
783    use crate::model::quant::GgmlType as T;
784    let w = AXPY_W;
785    let bytes = match ty {
786        T::Q8_0 => w * 34,
787        _ => {
788            let (unit, subs) = match ty {
789                T::Q4_0 => (18, 1),
790                T::Q4_1 => (20, 1),
791                T::Q5_0 => (22, 1),
792                T::Q5_1 => (24, 1),
793                T::Mxfp4 => (17, 1),
794                T::Iq4Nl => (18, 1),
795                T::Iq4Xs => (136, 8),
796                T::Q2K => (84, 8),
797                T::Q3K => (110, 8),
798                T::Q4K => (144, 8),
799                T::Q5K => (176, 8),
800                T::Q6K => (210, 8),
801                other => panic!("no staged decode of {other:?}"),
802            };
803            (w.div_ceil(subs) + 1) * unit + 15
804        }
805    };
806    let words = bytes.div_ceil(4);
807    4 * if words % 2 == 0 { words + 1 } else { words }
808}
809
810/// The blocks an arg-max over `n` values spreads across: a run of at least 2048 values a block, at most 64 blocks.
811pub fn argmax_blocks(n: usize) -> usize {
812    n.div_ceil(2048).clamp(1, 64)
813}
814
815/// The warps an expert router's row takes (`WPE` of `lk_moe_route`): four for an `f32` router whose row splits into four
816/// parts of whole 16-byte words, so its experts fill four times the blocks; one for a quantized router, whose row is
817/// its format's one dot.
818pub fn route_warps(f32_router: bool, d: usize) -> usize {
819    if f32_router && d % 16 == 0 && d >= 512 {
820        4
821    } else {
822        1
823    }
824}
825
826/// The widest head a rotation turns: its block holds the head's values in shared memory (`lk_rope_head`'s `hv`).
827pub const ROPE_HEAD: usize = 1024;
828
829/// The threads of a block that norms a row of `cols` (`lk_rmsnorm`, and the norm inside a rotation): the row's width in
830/// whole warps, at most 1024 — each thread then holds at most `cols / 1024` values.
831pub fn norm_threads(cols: usize) -> usize {
832    cols.next_multiple_of(32).min(1024)
833}
834
835/// Whether the block library decodes `ty`: the formats with a sub-block decoder below.
836pub fn decodes(ty: crate::model::quant::GgmlType) -> bool {
837    use crate::model::quant::GgmlType as T;
838    matches!(ty, T::Q4_0 | T::Q4_1 | T::Q5_0 | T::Q5_1 | T::Q2K | T::Q3K | T::Q4K | T::Q5K | T::Q6K | T::Mxfp4 | T::Iq4Nl | T::Iq4Xs)
839}
840
841/// One library kernel: its name and its source.
842#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
843pub enum Kernel {
844    Blocks,
845    GatherQ8,
846    GatherBlk,
847    GatherF32,
848    RmsNorm,
849    GatherNorm,
850    Quant,
851    GemvQ8,
852    GemvQ8Norm,
853    GemvBlk,
854    GemvBlkNorm,
855    GemvParts,
856    Mma,
857    GemmBlk,
858    GemmF32,
859    GemvF32,
860    Binary,
861    Scale,
862    SwiGlu,
863    Unary,
864    Rope,
865    GemvPartsRope,
866    SetRow,
867    Attention,
868    AttentionTiled,
869    AttentionShared,
870    AttentionFlash,
871    AttentionMma,
872    AttentionI8,
873    ArgMax,
874    Conv,
875    L2Norm,
876    Decay,
877    Gates,
878    DeltaStep,
879    DeltaNorm,
880    DeltaStepNorm,
881    DeltaChunks,
882    Moe,
883    MoeNorm,
884    Slice,
885    Join,
886    Heads,
887    HeadTiled,
888    Glu,
889    GemvMma,
890}
891
892impl Kernel {
893    /// The kernel's CUDA name.
894    pub fn name(self) -> &'static str {
895        match self {
896            Kernel::Blocks => "lk_w",
897            Kernel::GatherQ8 => "lk_gather_q8",
898            Kernel::GatherBlk => "lk_gather_blk",
899            Kernel::GatherF32 => "lk_gather_f32",
900            Kernel::RmsNorm => "lk_rmsnorm",
901            Kernel::GatherNorm => "lk_gather_norm",
902            Kernel::Quant => "lk_quant",
903            Kernel::GemvQ8 => "lk_gemv_q8",
904            Kernel::GemvQ8Norm => "lk_gemv_q8_norm",
905            Kernel::GemvBlk => "lk_gemv_blk",
906            Kernel::GemvBlkNorm => "lk_gemv_blk_norm",
907            Kernel::GemvParts => "lk_gemv_parts",
908            Kernel::Mma => "lk_mma_s8",
909            Kernel::GemmBlk => "lk_gemm_blk",
910            Kernel::GemmF32 => "lk_gemm_f32",
911            Kernel::GemvF32 => "lk_gemv_f32",
912            Kernel::Binary => "lk_binary",
913            Kernel::Scale => "lk_scale",
914            Kernel::SwiGlu => "lk_swiglu",
915            Kernel::Unary => "lk_unary",
916            Kernel::Rope => "lk_rope",
917            Kernel::GemvPartsRope => "lk_gemv_parts_rope",
918            Kernel::SetRow => "lk_set_row",
919            Kernel::Attention => "lk_attention",
920            Kernel::AttentionTiled => "lk_attention_tiled",
921            Kernel::AttentionShared => "lk_attention_shared",
922            Kernel::AttentionFlash => "lk_attention_flash",
923            Kernel::AttentionMma => "lk_attention_mma",
924            Kernel::AttentionI8 => "lk_attention_i8",
925            Kernel::ArgMax => "lk_argmax",
926            Kernel::Conv => "lk_conv",
927            Kernel::L2Norm => "lk_l2norm",
928            Kernel::Decay => "lk_decay",
929            Kernel::Gates => "lk_gates",
930            Kernel::DeltaStep => "lk_delta_step",
931            Kernel::DeltaNorm => "lk_delta_norm",
932            Kernel::DeltaStepNorm => "lk_delta_step",
933            Kernel::DeltaChunks => "lk_delta_state",
934            Kernel::Moe => "lk_moe",
935            Kernel::MoeNorm => "lk_moe_norm",
936            Kernel::Slice => "lk_slice",
937            Kernel::Join => "lk_join",
938            Kernel::Heads => "lk_head",
939            Kernel::HeadTiled => "lk_head_tiled",
940            Kernel::Glu => "lk_gemv_glu",
941            Kernel::GemvMma => "lk_gemv_mma",
942        }
943    }
944
945    /// The kernel's CUDA source.
946    pub fn source(self) -> &'static str {
947        match self {
948            Kernel::Blocks => BLOCKS,
949            Kernel::GatherQ8 => GATHER_Q8,
950            Kernel::GatherBlk => GATHER_BLK,
951            Kernel::GatherF32 => GATHER_F32,
952            Kernel::RmsNorm => RMSNORM,
953            Kernel::GatherNorm => GATHER_NORM,
954            Kernel::Quant => QUANT,
955            Kernel::GemvQ8 => GEMV_Q8,
956            Kernel::GemvQ8Norm => GEMV_Q8_NORM,
957            Kernel::GemvBlk => GEMV_BLK,
958            Kernel::GemvBlkNorm => GEMV_BLK_NORM,
959            Kernel::GemvParts => GEMV_PARTS,
960            Kernel::Mma => MMA,
961            Kernel::GemmBlk => GEMM_BLK,
962            Kernel::GemmF32 => GEMM_F32,
963            Kernel::GemvF32 => GEMV_F32,
964            Kernel::Binary => BINARY,
965            Kernel::Scale => SCALE,
966            Kernel::SwiGlu => SWIGLU,
967            Kernel::Unary => UNARY,
968            Kernel::Rope => ROPE,
969            Kernel::GemvPartsRope => GEMV_PARTS_ROPE,
970            Kernel::SetRow => SET_ROW,
971            Kernel::Attention => ATTENTION,
972            Kernel::AttentionTiled => ATTENTION_TILED,
973            Kernel::AttentionShared => ATTENTION_SHARED,
974            Kernel::AttentionFlash => ATTENTION_FLASH,
975            Kernel::AttentionMma => ATTENTION_MMA,
976            Kernel::AttentionI8 => ATTENTION_I8,
977            Kernel::ArgMax => ARGMAX,
978            Kernel::Conv => CONV,
979            Kernel::L2Norm => L2NORM,
980            Kernel::Decay => DECAY,
981            Kernel::Gates => GATES,
982            Kernel::DeltaStep => DELTA_STEP,
983            Kernel::DeltaNorm => DELTA_NORM,
984            Kernel::DeltaStepNorm => DELTA_STEP_NORM,
985            Kernel::DeltaChunks => DELTA_CHUNKS,
986            Kernel::Moe => MOE,
987            Kernel::MoeNorm => MOE_NORM,
988            Kernel::Slice => SLICE,
989            Kernel::Join => JOIN,
990            Kernel::Heads => HEADS,
991            Kernel::HeadTiled => HEAD_TILED,
992            Kernel::Glu => GLU,
993            Kernel::GemvMma => GEMV_MMA,
994        }
995    }
996}
997
998/// A weight matrix as the kernels read it, and the sub-block decoders of every format besides Q8_0 (template argument
999/// `F`, the GGUF type id): a Q8_0 matrix is its int8 values `q` and block scales `s`; any other is its blocks `b`, a row
1000/// every `rb` bytes. `lk_sub<F>` decodes sub-block `sb` (weights `32·sb …`) of a row into 32 int8 levels and, per half,
1001/// a scale and an offset; a weight is `scale·level + offset` rounded as the CPU dequantizer rounds it (a product, then a
1002/// sum); `lk_level<F>` decodes one element of a sub-block alike. `lk_row_dot<F, Q, M>` is a row's dot with `M` activation
1003/// rows (`ld` apart) under numerics `Q`, one warp; `lk_dot<F, Q, M>` the same for any format, a Q8_0 matrix's split
1004/// arrays included; `lk_gemv_dot<F, Q, M>` a row's dot with `M` activation rows of its length as the plain GEMV of its
1005/// format takes it, the one dot of a format every kernel shares so a fused launch computes what its parts computed.
1006pub const BLOCKS: &str = r#"
1007struct lk_w { const signed char* q; const __half* s; const unsigned char* b; long rb; };
1008// A part's outputs: an `f32` array or a binary16 table, set from either pointer; the host reads an `f32` part's back as
1009// its pointer, a kernel through `lk_part_out`.
1010struct lk_part_y {
1011  void* p = nullptr;
1012  bool h = false;
1013  lk_part_y() = default;
1014  __host__ __device__ lk_part_y(std::nullptr_t) {}
1015  __host__ __device__ lk_part_y(float* q) : p(q) {}
1016  __host__ __device__ lk_part_y(__half* q) : p(q), h(true) {}
1017  __host__ operator float*() const { return (float*)p; }
1018};
1019// Up to `LK_PARTS` matrices one activation is projected by (the planner's `GEMM_PARTS`), their outputs side by side:
1020// part `p`'s matrix `w[p]`, outputs `y[p]` (rows from the one-based position `row[p]` names, `pitch[p]` apart, where it
1021// names one), bias `bias[p]`, and its outputs `end[p − 1] … end[p] − 1` of the launch's.
1022#define LK_PARTS 6
1023struct lk_parts {
1024  lk_w w[LK_PARTS];
1025  lk_part_y y[LK_PARTS];
1026  const float* bias[LK_PARTS];
1027  int end[LK_PARTS];
1028  const int* row[LK_PARTS];
1029  long pitch[LK_PARTS];
1030};
1031__device__ __forceinline__ lk_out lk_part_out(const lk_parts& parts, int p){
1032  return parts.y[p].h ? lk_out((__half*)parts.y[p].p) : lk_out((float*)parts.y[p].p);
1033}
1034// The little-endian f16 at `p`, as an `f32`.
1035__device__ __forceinline__ float lk_h(const unsigned char* p){ return __half2float(__ushort_as_half((unsigned short)(p[0] | (p[1] << 8)))); }
1036__device__ __forceinline__ float lk_e8m0_half(unsigned char x){
1037  unsigned int bits = x < 2 ? 0x00200000u << x : ((unsigned int)(x - 1)) << 23;
1038  return __uint_as_float(bits);
1039}
1040__device__ __forceinline__ void lk_scale_min_k4(int j, const unsigned char* q, int& sc, int& m){
1041  if(j < 4){ sc = q[j] & 63; m = q[j + 4] & 63; }
1042  else { sc = (q[j + 4] & 0xf) | ((q[j - 4] >> 6) << 4); m = (q[j + 4] >> 4) | ((q[j] >> 6) << 4); }
1043}
1044// Word `i` of four, by selects rather than an index, so the four stay in registers.
1045__device__ __forceinline__ unsigned int lk_pick4(const unsigned int* a, int i){ return i == 0 ? a[0] : i == 1 ? a[1] : i == 2 ? a[2] : a[3]; }
1046// The IQ4 formats' sixteen non-linear levels (ggml's `kvalues_iq4nl`): one by its nibble, and four to a word.
1047__device__ __forceinline__ int lk_iq4_level(int n){
1048  const signed char kv[16] = {-127, -104, -83, -65, -49, -35, -22, -10, 1, 13, 25, 38, 53, 69, 89, 113};
1049  return kv[n];
1050}
1051// The levels of the low nibbles of `q`'s four bytes (`lo`) and of their high nibbles (`hi`), four to a word, from a
1052// table of sixteen int8 levels four to a word (`t0` levels 0–3 … `t3` 12–15), by byte permutes: each nibble's low three
1053// bits pick a byte from levels 0–7 and from 8–15, its fourth bit picks between them — no memory read.
1054__device__ __forceinline__ void lk_table16(unsigned int q, unsigned int t0, unsigned int t1, unsigned int t2, unsigned int t3,
1055                                           int& lo, int& hi){
1056  unsigned int t[2], sel = 0x32103210u | ((q & 0x88888888u) >> 1);
1057  #pragma unroll
1058  for(int i = 0; i < 2; ++i){
1059    unsigned int s = q >> (16 * i);
1060    t[i] = __byte_perm(__byte_perm(t0, t1, s), __byte_perm(t2, t3, s), sel >> (16 * i));
1061  }
1062  lo = (int)__byte_perm(t[0], t[1], 0x6420);
1063  hi = (int)__byte_perm(t[0], t[1], 0x7531);
1064}
1065// IQ4's levels and MXFP4's doubled E2M1 values (ggml's `kvalues_mxfp4`), four to a word.
1066__device__ __forceinline__ void lk_iq4_word(unsigned int q, int& lo, int& hi){
1067  lk_table16(q, 0xBFAD9881u, 0xF6EADDCFu, 0x26190D01u, 0x71594535u, lo, hi);
1068}
1069__device__ __forceinline__ void lk_mxfp4_word(unsigned int q, int& lo, int& hi){
1070  lk_table16(q, 0x03020100u, 0x0C080604u, 0xFDFEFF00u, 0xF4F8FAFCu, lo, hi);
1071}
1072// The `n` bytes from `p`, any alignment, as words: aligned word loads joined by funnel shifts. Reads up to three bytes
1073// past them, which every block-format upload's 32 trailing bytes cover.
1074template<int N>
1075__device__ __forceinline__ void lk_words(const unsigned char* p, unsigned int* q){
1076  const unsigned int* a = (const unsigned int*)((size_t)p & ~(size_t)3);
1077  unsigned int sh = 8 * (unsigned int)((size_t)p & 3), w[N + 1];
1078  #pragma unroll
1079  for(int i = 0; i <= N; ++i) w[i] = a[i];
1080  #pragma unroll
1081  for(int i = 0; i < N; ++i) q[i] = __funnelshift_r(w[i], w[i + 1], sh);
1082}
1083// An IQ4_XS sub-block's scale: the super-block's `d` times its 6-bit signed scale (low four bits from `sl`, the byte of
1084// `scales_l` it shares with its neighbour, high two from `sh`, the super-block's `scales_h`), as the CPU dequantizer
1085// rounds it.
1086__device__ __forceinline__ float lk_iq4xs_scale(float d, unsigned int sh, unsigned int sl, int ib){
1087  int ls = (int)((sl >> (4 * (ib & 1))) & 0xf) | (int)(((sh >> (2 * ib)) & 3) << 4);
1088  return d * (float)(ls - 32);
1089}
1090template<int F>
1091__device__ __forceinline__ void lk_sub(const unsigned char* __restrict__ row, int sb, signed char* v, float* d, float* c){
1092  if(F == 2 || F == 3){
1093    const unsigned char* b = row + (long)sb * (F == 2 ? 18 : 20);
1094    float dd = lk_h(b), cc = F == 3 ? lk_h(b + 2) : 0.f;
1095    const unsigned char* qs = b + (F == 2 ? 2 : 4);
1096    #pragma unroll
1097    for(int j = 0; j < 16; ++j){ v[j] = (qs[j] & 0xf) - (F == 2 ? 8 : 0); v[j + 16] = (qs[j] >> 4) - (F == 2 ? 8 : 0); }
1098    d[0] = d[1] = dd; c[0] = c[1] = cc;
1099  } else if(F == 6 || F == 7){
1100    const unsigned char* b = row + (long)sb * (F == 6 ? 22 : 24);
1101    float dd = lk_h(b), cc = F == 7 ? lk_h(b + 2) : 0.f;
1102    const unsigned char* h = b + (F == 6 ? 2 : 4);
1103    unsigned int qh = h[0] | (h[1] << 8) | (h[2] << 16) | ((unsigned int)h[3] << 24);
1104    const unsigned char* qs = h + 4;
1105    #pragma unroll
1106    for(int j = 0; j < 16; ++j){
1107      v[j] = ((qs[j] & 0xf) | (((qh >> j) << 4) & 0x10)) - (F == 6 ? 16 : 0);
1108      v[j + 16] = ((qs[j] >> 4) | ((qh >> (j + 12)) & 0x10)) - (F == 6 ? 16 : 0);
1109    }
1110    d[0] = d[1] = dd; c[0] = c[1] = cc;
1111  } else if(F == 39){
1112    const unsigned char* b = row + (long)sb * 17;
1113    const signed char kv[16] = {0, 1, 2, 3, 4, 6, 8, 12, 0, -1, -2, -3, -4, -6, -8, -12};
1114    float dd = lk_e8m0_half(b[0]);
1115    #pragma unroll
1116    for(int j = 0; j < 16; ++j){ v[j] = kv[b[1 + j] & 0xf]; v[j + 16] = kv[b[1 + j] >> 4]; }
1117    d[0] = d[1] = dd; c[0] = c[1] = 0.f;
1118  } else if(F == 20 || F == 23){
1119    const unsigned char* b = F == 20 ? row + (long)sb * 18 : row + (long)(sb >> 3) * 136;
1120    int ib = sb & 7;
1121    float dd = F == 20 ? lk_h(b) : lk_iq4xs_scale(lk_h(b), b[2] | (b[3] << 8), b[4 + (ib >> 1)], ib);
1122    const unsigned char* qs = F == 20 ? b + 2 : b + 8 + 16 * ib;
1123    #pragma unroll
1124    for(int j = 0; j < 16; ++j){ v[j] = lk_iq4_level(qs[j] & 0xf); v[j + 16] = lk_iq4_level(qs[j] >> 4); }
1125    d[0] = d[1] = dd; c[0] = c[1] = 0.f;
1126  } else if(F == 12 || F == 13){
1127    const unsigned char* b = row + (long)(sb >> 3) * (F == 12 ? 144 : 176);
1128    int j = sb & 7, p = j >> 1, hi = j & 1, sc, m;
1129    lk_scale_min_k4(j, b + 4, sc, m);
1130    float dd = lk_h(b) * (float)sc, cc = -lk_h(b + 2) * (float)m;
1131    const unsigned char* ql = b + (F == 12 ? 16 : 48) + p * 32;
1132    #pragma unroll
1133    for(int l = 0; l < 32; ++l){
1134      int lv = hi ? ql[l] >> 4 : ql[l] & 0xf;
1135      if(F == 13) lv += (b[16 + l] & (1 << (2 * p + hi))) ? 16 : 0;
1136      v[l] = (signed char)lv;
1137    }
1138    d[0] = d[1] = dd; c[0] = c[1] = cc;
1139  } else if(F == 10){
1140    const unsigned char* b = row + (long)(sb >> 3) * 84;
1141    int j = sb & 7, part = j >> 2, k = j & 3;
1142    const unsigned char* q = b + 16 + part * 32;
1143    float dd = lk_h(b + 80), dm = lk_h(b + 82);
1144    #pragma unroll
1145    for(int l = 0; l < 32; ++l) v[l] = (signed char)((q[(l & 15) + (l >> 4) * 16] >> (2 * k)) & 3);
1146    #pragma unroll
1147    for(int h = 0; h < 2; ++h){ int sc = b[part * 8 + k * 2 + h]; d[h] = dd * (float)(sc & 0xf); c[h] = -(dm * (float)(sc >> 4)); }
1148  } else if(F == 11){
1149    const unsigned char* b = row + (long)(sb >> 3) * 110;
1150    int j = sb & 7, part = j >> 2, k = j & 3, mbit = 1 << (part * 4 + k);
1151    const unsigned char* q = b + 32 + part * 32;
1152    const unsigned char* p = b + 96;
1153    unsigned int a0 = p[0] | (p[1] << 8) | (p[2] << 16) | ((unsigned int)p[3] << 24);
1154    unsigned int a1 = p[4] | (p[5] << 8) | (p[6] << 16) | ((unsigned int)p[7] << 24);
1155    unsigned int t = p[8] | (p[9] << 8) | (p[10] << 16) | ((unsigned int)p[11] << 24);
1156    unsigned int aux[4] = {(a0 & 0x0f0f0f0fu) | ((t & 0x03030303u) << 4), (a1 & 0x0f0f0f0fu) | (((t >> 2) & 0x03030303u) << 4),
1157                           ((a0 >> 4) & 0x0f0f0f0fu) | (((t >> 4) & 0x03030303u) << 4), ((a1 >> 4) & 0x0f0f0f0fu) | (((t >> 6) & 0x03030303u) << 4)};
1158    float dd = lk_h(b + 108);
1159    #pragma unroll
1160    for(int l = 0; l < 32; ++l){
1161      int at = (l & 15) + (l >> 4) * 16;
1162      v[l] = (signed char)(((q[at] >> (2 * k)) & 3) - ((b[at] & mbit) ? 0 : 4));
1163    }
1164    #pragma unroll
1165    for(int h = 0; h < 2; ++h){
1166      int is = part * 8 + k * 2 + h;
1167      int sc = (signed char)((lk_pick4(aux, is >> 2) >> (8 * (is & 3))) & 0xff);
1168      d[h] = dd * (float)(sc - 32); c[h] = 0.f;
1169    }
1170  } else if(F == 14){
1171    const unsigned char* b = row + (long)(sb >> 3) * 210;
1172    int j = sb & 7, part = j >> 2, k = j & 3;
1173    const unsigned char* ql = b + part * 64;
1174    const unsigned char* qh = b + 128 + part * 32;
1175    const signed char* sc = (const signed char*)(b + 192 + part * 8);
1176    float dd = lk_h(b + 208);
1177    #pragma unroll
1178    for(int l = 0; l < 32; ++l){
1179      int lo = (k & 1) ? ql[l + 32] : ql[l];
1180      lo = (k & 2) ? lo >> 4 : lo & 0xf;
1181      v[l] = (signed char)((lo | (((qh[l] >> (2 * k)) & 3) << 4)) - 32);
1182    }
1183    d[0] = dd * (float)sc[2 * k]; d[1] = dd * (float)sc[2 * k + 1]; c[0] = c[1] = 0.f;
1184  }
1185}
1186// Element `l` of sub-block `sb` of a row in format `F`, as `lk_sub` decodes it: its int8 level, and the scale `d` and
1187// offset `c` of its half — the decoder of one weight a lane reads alone.
1188template<int F>
1189__device__ __forceinline__ int lk_level(const unsigned char* __restrict__ row, int sb, int l, float& d, float& c){
1190  if(F == 2 || F == 3){
1191    const unsigned char* b = row + (long)sb * (F == 2 ? 18 : 20);
1192    d = lk_h(b); c = F == 3 ? lk_h(b + 2) : 0.f;
1193    const unsigned char* qs = b + (F == 2 ? 2 : 4);
1194    return (l < 16 ? (qs[l] & 0xf) : (qs[l - 16] >> 4)) - (F == 2 ? 8 : 0);
1195  } else if(F == 6 || F == 7){
1196    const unsigned char* b = row + (long)sb * (F == 6 ? 22 : 24);
1197    d = lk_h(b); c = F == 7 ? lk_h(b + 2) : 0.f;
1198    const unsigned char* h = b + (F == 6 ? 2 : 4);
1199    unsigned int qh = h[0] | (h[1] << 8) | (h[2] << 16) | ((unsigned int)h[3] << 24);
1200    const unsigned char* qs = h + 4;
1201    int q = l < 16 ? ((qs[l] & 0xf) | (((qh >> l) << 4) & 0x10)) : ((qs[l - 16] >> 4) | ((qh >> (l - 4)) & 0x10));
1202    return q - (F == 6 ? 16 : 0);
1203  } else if(F == 39){
1204    const unsigned char* b = row + (long)sb * 17;
1205    const signed char kv[16] = {0, 1, 2, 3, 4, 6, 8, 12, 0, -1, -2, -3, -4, -6, -8, -12};
1206    d = lk_e8m0_half(b[0]); c = 0.f;
1207    return kv[l < 16 ? (b[1 + l] & 0xf) : (b[1 + l - 16] >> 4)];
1208  } else if(F == 20 || F == 23){
1209    const unsigned char* b = F == 20 ? row + (long)sb * 18 : row + (long)(sb >> 3) * 136;
1210    int ib = sb & 7;
1211    d = F == 20 ? lk_h(b) : lk_iq4xs_scale(lk_h(b), b[2] | (b[3] << 8), b[4 + (ib >> 1)], ib); c = 0.f;
1212    const unsigned char* qs = F == 20 ? b + 2 : b + 8 + 16 * ib;
1213    return lk_iq4_level(l < 16 ? (qs[l] & 0xf) : (qs[l - 16] >> 4));
1214  } else if(F == 12 || F == 13){
1215    const unsigned char* b = row + (long)(sb >> 3) * (F == 12 ? 144 : 176);
1216    int j = sb & 7, p = j >> 1, hi = j & 1, sc, m;
1217    lk_scale_min_k4(j, b + 4, sc, m);
1218    d = lk_h(b) * (float)sc; c = -lk_h(b + 2) * (float)m;
1219    const unsigned char* ql = b + (F == 12 ? 16 : 48) + p * 32;
1220    int lv = hi ? ql[l] >> 4 : ql[l] & 0xf;
1221    if(F == 13) lv += (b[16 + l] & (1 << (2 * p + hi))) ? 16 : 0;
1222    return lv;
1223  } else if(F == 10){
1224    const unsigned char* b = row + (long)(sb >> 3) * 84;
1225    int j = sb & 7, part = j >> 2, k = j & 3;
1226    const unsigned char* q = b + 16 + part * 32;
1227    float dd = lk_h(b + 80), dm = lk_h(b + 82);
1228    int sc = b[part * 8 + k * 2 + (l >> 4)];
1229    d = dd * (float)(sc & 0xf); c = -(dm * (float)(sc >> 4));
1230    return (q[(l & 15) + (l >> 4) * 16] >> (2 * k)) & 3;
1231  } else if(F == 11){
1232    const unsigned char* b = row + (long)(sb >> 3) * 110;
1233    int j = sb & 7, part = j >> 2, k = j & 3, mbit = 1 << (part * 4 + k);
1234    const unsigned char* q = b + 32 + part * 32;
1235    const unsigned char* p = b + 96;
1236    unsigned int a0 = p[0] | (p[1] << 8) | (p[2] << 16) | ((unsigned int)p[3] << 24);
1237    unsigned int a1 = p[4] | (p[5] << 8) | (p[6] << 16) | ((unsigned int)p[7] << 24);
1238    unsigned int t = p[8] | (p[9] << 8) | (p[10] << 16) | ((unsigned int)p[11] << 24);
1239    unsigned int aux[4] = {(a0 & 0x0f0f0f0fu) | ((t & 0x03030303u) << 4), (a1 & 0x0f0f0f0fu) | (((t >> 2) & 0x03030303u) << 4),
1240                           ((a0 >> 4) & 0x0f0f0f0fu) | (((t >> 4) & 0x03030303u) << 4), ((a1 >> 4) & 0x0f0f0f0fu) | (((t >> 6) & 0x03030303u) << 4)};
1241    int is = part * 8 + k * 2 + (l >> 4);
1242    int sc = (signed char)((lk_pick4(aux, is >> 2) >> (8 * (is & 3))) & 0xff);
1243    d = lk_h(b + 108) * (float)(sc - 32); c = 0.f;
1244    int at = (l & 15) + (l >> 4) * 16;
1245    return ((q[at] >> (2 * k)) & 3) - ((b[at] & mbit) ? 0 : 4);
1246  } else {
1247    const unsigned char* b = row + (long)(sb >> 3) * 210;
1248    int j = sb & 7, part = j >> 2, k = j & 3;
1249    const unsigned char* ql = b + part * 64;
1250    const unsigned char* qh = b + 128 + part * 32;
1251    const signed char* sc = (const signed char*)(b + 192 + part * 8);
1252    d = lk_h(b + 208) * (float)sc[2 * k + (l >> 4)]; c = 0.f;
1253    int lo = (k & 1) ? ql[l + 32] : ql[l];
1254    lo = (k & 2) ? lo >> 4 : lo & 0xf;
1255    return (lo | (((qh[l] >> (2 * k)) & 3) << 4)) - 32;
1256  }
1257}
1258__device__ __forceinline__ int lk_pack4(const signed char* v){
1259  return (v[0] & 0xff) | ((v[1] & 0xff) << 8) | ((v[2] & 0xff) << 16) | ((unsigned int)(v[3] & 0xff) << 24);
1260}
1261// A word of four bytes from an address 2-byte aligned, or 4-byte aligned.
1262__device__ __forceinline__ int lk_w16(const unsigned char* p){
1263  const unsigned short* h = (const unsigned short*)p;
1264  return (int)((unsigned int)h[0] | ((unsigned int)h[1] << 16));
1265}
1266__device__ __forceinline__ int lk_w32(const unsigned char* p){ return *(const int*)p; }
1267// The fifth bits of four levels, from four consecutive bits of `qh`, placed at bit 4 of each byte.
1268__device__ __forceinline__ int lk_bit4(unsigned int b){
1269  return (int)(((b << 4) & 0x10u) | ((b << 11) & 0x1000u) | ((b << 18) & 0x100000u) | ((b << 25) & 0x10000000u));
1270}
1271// Sub-block `sb` of a row in format `F`, as `lk_sub` decodes it, its 32 levels packed four to an int for `__dp4a` (`w[i]`
1272// the levels 4i … 4i+3) — read a word at a time, never a level at a time; the scale and offset of each half as `lk_sub`.
1273template<int F>
1274__device__ __forceinline__ void lk_sub4(const unsigned char* __restrict__ row, int sb, int* w, float* d, float* c){
1275  if(F == 2 || F == 3){
1276    const unsigned char* b = row + (long)sb * (F == 2 ? 18 : 20);
1277    float dd = lk_h(b), cc = F == 3 ? lk_h(b + 2) : 0.f;
1278    const unsigned char* qs = b + (F == 2 ? 2 : 4);
1279    #pragma unroll
1280    for(int i = 0; i < 4; ++i){
1281      int q = F == 2 ? lk_w16(qs + 4 * i) : lk_w32(qs + 4 * i);
1282      w[i] = q & 0x0F0F0F0F; w[i + 4] = (q >> 4) & 0x0F0F0F0F;
1283      if(F == 2){ w[i] = __vsub4(w[i], 0x08080808); w[i + 4] = __vsub4(w[i + 4], 0x08080808); }
1284    }
1285    d[0] = d[1] = dd; c[0] = c[1] = cc;
1286  } else if(F == 6 || F == 7){
1287    const unsigned char* b = row + (long)sb * (F == 6 ? 22 : 24);
1288    float dd = lk_h(b), cc = F == 7 ? lk_h(b + 2) : 0.f;
1289    const unsigned char* h = b + (F == 6 ? 2 : 4);
1290    unsigned int qh = F == 6 ? (unsigned int)lk_w16(h) : (unsigned int)lk_w32(h);
1291    const unsigned char* qs = h + 4;
1292    #pragma unroll
1293    for(int i = 0; i < 4; ++i){
1294      int q = F == 6 ? lk_w16(qs + 4 * i) : lk_w32(qs + 4 * i);
1295      w[i] = (q & 0x0F0F0F0F) | lk_bit4((qh >> (4 * i)) & 0xF);
1296      w[i + 4] = ((q >> 4) & 0x0F0F0F0F) | lk_bit4((qh >> (16 + 4 * i)) & 0xF);
1297      if(F == 6){ w[i] = __vsub4(w[i], 0x10101010); w[i + 4] = __vsub4(w[i + 4], 0x10101010); }
1298    }
1299    d[0] = d[1] = dd; c[0] = c[1] = cc;
1300  } else if(F == 12 || F == 13){
1301    const unsigned char* b = row + (long)(sb >> 3) * (F == 12 ? 144 : 176);
1302    int j = sb & 7, p = j >> 1, hi = j & 1, sc, m;
1303    lk_scale_min_k4(j, b + 4, sc, m);
1304    float dd = lk_h(b) * (float)sc, cc = -lk_h(b + 2) * (float)m;
1305    const unsigned char* ql = b + (F == 12 ? 16 : 48) + p * 32;
1306    #pragma unroll
1307    for(int i = 0; i < 8; ++i){
1308      int q = (lk_w32(ql + 4 * i) >> (4 * hi)) & 0x0F0F0F0F;
1309      if(F == 13) q |= ((lk_w32(b + 16 + 4 * i) >> (2 * p + hi)) & 0x01010101) << 4;
1310      w[i] = q;
1311    }
1312    d[0] = d[1] = dd; c[0] = c[1] = cc;
1313  } else if(F == 10){
1314    const unsigned char* b = row + (long)(sb >> 3) * 84;
1315    int j = sb & 7, part = j >> 2, k = j & 3;
1316    const unsigned char* q = b + 16 + part * 32;
1317    float dd = lk_h(b + 80), dm = lk_h(b + 82);
1318    #pragma unroll
1319    for(int i = 0; i < 8; ++i) w[i] = (lk_w32(q + 4 * i) >> (2 * k)) & 0x03030303;
1320    #pragma unroll
1321    for(int h = 0; h < 2; ++h){ int sc = b[part * 8 + k * 2 + h]; d[h] = dd * (float)(sc & 0xf); c[h] = -(dm * (float)(sc >> 4)); }
1322  } else if(F == 11){
1323    const unsigned char* b = row + (long)(sb >> 3) * 110;
1324    int j = sb & 7, part = j >> 2, k = j & 3, bit = part * 4 + k;
1325    const unsigned char* q = b + 32 + part * 32;
1326    const unsigned char* p = b + 96;
1327    unsigned int a0 = (unsigned int)lk_w16(p), a1 = (unsigned int)lk_w16(p + 4), t = (unsigned int)lk_w16(p + 8);
1328    unsigned int aux[4] = {(a0 & 0x0f0f0f0fu) | ((t & 0x03030303u) << 4), (a1 & 0x0f0f0f0fu) | (((t >> 2) & 0x03030303u) << 4),
1329                           ((a0 >> 4) & 0x0f0f0f0fu) | (((t >> 4) & 0x03030303u) << 4), ((a1 >> 4) & 0x0f0f0f0fu) | (((t >> 6) & 0x03030303u) << 4)};
1330    float dd = lk_h(b + 108);
1331    #pragma unroll
1332    for(int i = 0; i < 8; ++i){
1333      int lo = (lk_w16(q + 4 * i) >> (2 * k)) & 0x03030303;
1334      int missing = (~(lk_w16(b + 4 * i) >> bit) & 0x01010101) << 2;
1335      w[i] = __vsub4(lo, missing);
1336    }
1337    #pragma unroll
1338    for(int h = 0; h < 2; ++h){
1339      int is = part * 8 + k * 2 + h;
1340      int sc = (signed char)((lk_pick4(aux, is >> 2) >> (8 * (is & 3))) & 0xff);
1341      d[h] = dd * (float)(sc - 32); c[h] = 0.f;
1342    }
1343  } else if(F == 14){
1344    const unsigned char* b = row + (long)(sb >> 3) * 210;
1345    int j = sb & 7, part = j >> 2, k = j & 3;
1346    const unsigned char* ql = b + part * 64 + ((k & 1) ? 32 : 0);
1347    const unsigned char* qh = b + 128 + part * 32;
1348    const signed char* sc = (const signed char*)(b + 192 + part * 8);
1349    float dd = lk_h(b + 208);
1350    #pragma unroll
1351    for(int i = 0; i < 8; ++i){
1352      int lo = (lk_w16(ql + 4 * i) >> (4 * (k >> 1))) & 0x0F0F0F0F;
1353      int hi = ((lk_w16(qh + 4 * i) >> (2 * k)) & 0x03030303) << 4;
1354      w[i] = __vsub4(lo | hi, 0x20202020);
1355    }
1356    d[0] = dd * (float)sc[2 * k]; d[1] = dd * (float)sc[2 * k + 1]; c[0] = c[1] = 0.f;
1357  } else if(F == 20 || F == 23){
1358    const unsigned char* b = F == 20 ? row + (long)sb * 18 : row + (long)(sb >> 3) * 136;
1359    int ib = sb & 7;
1360    float dd = F == 20 ? lk_h(b) : lk_iq4xs_scale(lk_h(b), b[2] | (b[3] << 8), b[4 + (ib >> 1)], ib);
1361    const unsigned char* qs = F == 20 ? b + 2 : b + 8 + 16 * ib;
1362    #pragma unroll
1363    for(int i = 0; i < 4; ++i) lk_iq4_word((unsigned int)(F == 20 ? lk_w16(qs + 4 * i) : lk_w32(qs + 4 * i)), w[i], w[i + 4]);
1364    d[0] = d[1] = dd; c[0] = c[1] = 0.f;
1365  } else if(F == 39){
1366    const unsigned char* b = row + (long)sb * 17;
1367    unsigned int q[4];
1368    lk_words<4>(b + 1, q);
1369    #pragma unroll
1370    for(int i = 0; i < 4; ++i) lk_mxfp4_word(q[i], w[i], w[i + 4]);
1371    d[0] = d[1] = lk_e8m0_half(b[0]); c[0] = c[1] = 0.f;
1372  } else {
1373    signed char v[32];
1374    lk_sub<F>(row, sb, v, d, c);
1375    #pragma unroll
1376    for(int i = 0; i < 8; ++i) w[i] = lk_pack4(v + 4 * i);
1377  }
1378}
1379// A sub-block's 32 weights (its levels `wv`, four to a word, and each half's scale `d` and offset `c`) dotted with an
1380// activation's 32 int8 words `h` (and its low words `l` under Q 2), before the activation's scale.
1381template<int Q>
1382__device__ __forceinline__ float lk_sub_dot(const int* wv, const float* d, const float* c, const int* h, const int* l){
1383  int dh0 = 0, dh1 = 0, sh0 = 0, sh1 = 0;
1384  #pragma unroll
1385  for(int i = 0; i < 4; ++i){ dh0 = __dp4a(wv[i], h[i], dh0); sh0 = __dp4a(0x01010101, h[i], sh0); }
1386  #pragma unroll
1387  for(int i = 4; i < 8; ++i){ dh1 = __dp4a(wv[i], h[i], dh1); sh1 = __dp4a(0x01010101, h[i], sh1); }
1388  float part = d[0] * (float)dh0 + c[0] * (float)sh0 + d[1] * (float)dh1 + c[1] * (float)sh1;
1389  if(Q == 2){
1390    int dl0 = 0, dl1 = 0, sl0 = 0, sl1 = 0;
1391    #pragma unroll
1392    for(int i = 0; i < 4; ++i){ dl0 = __dp4a(wv[i], l[i], dl0); sl0 = __dp4a(0x01010101, l[i], sl0); }
1393    #pragma unroll
1394    for(int i = 4; i < 8; ++i){ dl1 = __dp4a(wv[i], l[i], dl1); sl1 = __dp4a(0x01010101, l[i], sl1); }
1395    part += 0.0078125f * (d[0] * (float)dl0 + c[0] * (float)sl0 + d[1] * (float)dl1 + c[1] * (float)sl1);
1396  }
1397  return part;
1398}
1399// Rows `row … row + W − 1` of `w` dotted with the `M` activation rows `ld` apart (f32 `x` under Q 0 and 3, the int8
1400// words `xq` (and `xl`) with a scale per 32 in `xs` otherwise), row `r`'s dot with activation row `t` in `out[r·M + t]` —
1401// one warp, every lane's sums reduced. Each row's dot is the same whatever `W`: the rows only share the activation's
1402// loads. Under Q 0 each weight is dequantized as the CPU dequantizer rounds it and summed in f64; under Q 3 a lane
1403// takes half a sub-block, its levels a word at a time and its inputs sixteen bytes at a time, and sums each half's
1404// `d·Σ level·x + c·Σ x` in f32.
1405template<int F, int M, int W>
1406__device__ __forceinline__ void lk_row_dot_f32(lk_w w, long row, int K, const float* __restrict__ x, long ld, float* out){
1407  int lane = threadIdx.x & 31, nb = K >> 5;
1408  const unsigned char* r0 = w.b + row * w.rb;
1409  float acc[W][M];
1410  #pragma unroll
1411  for(int r = 0; r < W; ++r)
1412    #pragma unroll
1413    for(int t = 0; t < M; ++t) acc[r][t] = 0.f;
1414  for(int u = lane; u < 2 * nb; u += 32){
1415    int sb = u >> 1, hf = u & 1;
1416    #pragma unroll
1417    for(int r = 0; r < W; ++r){
1418      int wv[8]; float d[2], c[2];
1419      lk_sub4<F>(r0 + r * w.rb, sb, wv, d, c);
1420      #pragma unroll
1421      for(int t = 0; t < M; ++t){
1422        const float4* xt = (const float4*)(x + (long)t * ld + sb * 32 + 16 * hf);
1423        float sd = 0.f, sx = 0.f;
1424        #pragma unroll
1425        for(int k = 0; k < 4; ++k){
1426          float4 xv = xt[k];
1427          int lv = wv[4 * hf + k];
1428          sd = fmaf((float)(signed char)lv, xv.x, sd); sd = fmaf((float)(signed char)(lv >> 8), xv.y, sd);
1429          sd = fmaf((float)(signed char)(lv >> 16), xv.z, sd); sd = fmaf((float)(signed char)(lv >> 24), xv.w, sd);
1430          sx += (xv.x + xv.y) + (xv.z + xv.w);
1431        }
1432        acc[r][t] = fmaf(d[hf], sd, fmaf(c[hf], sx, acc[r][t]));
1433      }
1434    }
1435  }
1436  #pragma unroll
1437  for(int r = 0; r < W; ++r)
1438    #pragma unroll
1439    for(int t = 0; t < M; ++t) out[r * M + t] = lk_warp_sum(acc[r][t]);
1440}
1441template<int F, int Q, int M, int W = 1>
1442__device__ __forceinline__ void lk_row_dot(lk_w w, long row, int K, const float* __restrict__ x,
1443                                           const signed char* __restrict__ xq, const signed char* __restrict__ xl,
1444                                           const float* __restrict__ xs, long ld, float* out){
1445  int lane = threadIdx.x & 31, nb = K >> 5;
1446  const unsigned char* r0 = w.b + row * w.rb;
1447  if(Q == 3){
1448    lk_row_dot_f32<F, M, W>(w, row, K, x, ld, out);
1449  } else if(Q == 0){
1450    typedef typename lk_acc<Q>::t A;
1451    A acc[W][M];
1452    #pragma unroll
1453    for(int r = 0; r < W; ++r)
1454      #pragma unroll
1455      for(int t = 0; t < M; ++t) acc[r][t] = 0;
1456    for(int sb = lane; sb < nb; sb += 32){
1457      #pragma unroll
1458      for(int r = 0; r < W; ++r){
1459        signed char v[32]; float d[2], c[2];
1460        lk_sub<F>(r0 + r * w.rb, sb, v, d, c);
1461        #pragma unroll
1462        for(int t = 0; t < M; ++t){
1463          const float* xt = x + (long)t * ld + sb * 32;
1464          #pragma unroll
1465          for(int i = 0; i < 32; ++i) acc[r][t] += (A)__fadd_rn(__fmul_rn(d[i >> 4], (float)v[i]), c[i >> 4]) * (A)xt[i];
1466        }
1467      }
1468    }
1469    #pragma unroll
1470    for(int r = 0; r < W; ++r)
1471      #pragma unroll
1472      for(int t = 0; t < M; ++t) out[r * M + t] = (float)lk_warp_sum(acc[r][t]);
1473  } else {
1474    float acc[W][M];
1475    #pragma unroll
1476    for(int r = 0; r < W; ++r)
1477      #pragma unroll
1478      for(int t = 0; t < M; ++t) acc[r][t] = 0.f;
1479    static_assert(W == 1 || M == 1, "several rows a warp meet one activation row");
1480    for(int sb = lane; sb < nb; sb += 32){
1481      if(W == 1){
1482        // The weight row decoded once, dotted with each activation row in turn.
1483        int wv[8]; float d[2], c[2];
1484        lk_sub4<F>(r0, sb, wv, d, c);
1485        #pragma unroll
1486        for(int t = 0; t < M; ++t){
1487          const int* l = Q == 2 ? (const int*)(xl + (long)t * ld) + sb * 8 : nullptr;
1488          acc[0][t] += xs[(long)t * (ld >> 5) + sb] * lk_sub_dot<Q>(wv, d, c, (const int*)(xq + (long)t * ld) + sb * 8, l);
1489        }
1490      } else {
1491        // The activation's words loaded once, each weight row decoded and dotted in turn.
1492        const int* hp = (const int*)xq + sb * 8;
1493        const int* lp = Q == 2 ? (const int*)xl + sb * 8 : nullptr;
1494        int h[8], l[8];
1495        #pragma unroll
1496        for(int i = 0; i < 8; ++i){ h[i] = hp[i]; l[i] = Q == 2 ? lp[i] : 0; }
1497        float s = xs[sb];
1498        #pragma unroll
1499        for(int r = 0; r < W; ++r){
1500          int wv[8]; float d[2], c[2];
1501          lk_sub4<F>(r0 + r * w.rb, sb, wv, d, c);
1502          acc[r][0] += s * lk_sub_dot<Q>(wv, d, c, h, Q == 2 ? l : nullptr);
1503        }
1504      }
1505    }
1506    #pragma unroll
1507    for(int r = 0; r < W; ++r)
1508      #pragma unroll
1509      for(int t = 0; t < M; ++t) out[r * M + t] = lk_warp_sum(acc[r][t]);
1510  }
1511}
1512template<int F, int Q, int M>
1513__device__ __forceinline__ void lk_dot(lk_w w, long row, int K, const float* __restrict__ x,
1514                                       const signed char* __restrict__ xq, const signed char* __restrict__ xl,
1515                                       const float* __restrict__ xs, long ld, float* out){
1516  if(F != 8){ lk_row_dot<F, Q, M>(w, row, K, x, xq, xl, xs, ld, out); return; }
1517  int lane = threadIdx.x & 31;
1518  const signed char* wq = w.q + row * K;
1519  const __half* ws = w.s + row * (K >> 5);
1520  if(Q == 3){
1521    // A lane four levels at a time, each block's `d·Σ level·x` in f32.
1522    float acc[M];
1523    #pragma unroll
1524    for(int t = 0; t < M; ++t) acc[t] = 0.f;
1525    const int* w4 = (const int*)wq;
1526    for(int g = lane; g < (K >> 2); g += 32){
1527      int lv = w4[g];
1528      float d = __half2float(ws[g >> 3]);
1529      #pragma unroll
1530      for(int t = 0; t < M; ++t){
1531        float4 xv = *(const float4*)(x + (long)t * ld + 4 * g);
1532        float sd = (float)(signed char)lv * xv.x;
1533        sd = fmaf((float)(signed char)(lv >> 8), xv.y, sd); sd = fmaf((float)(signed char)(lv >> 16), xv.z, sd);
1534        sd = fmaf((float)(signed char)(lv >> 24), xv.w, sd);
1535        acc[t] = fmaf(d, sd, acc[t]);
1536      }
1537    }
1538    #pragma unroll
1539    for(int t = 0; t < M; ++t) out[t] = lk_warp_sum(acc[t]);
1540  } else if(Q == 0){
1541    typedef typename lk_acc<Q>::t A;
1542    A acc[M];
1543    #pragma unroll
1544    for(int t = 0; t < M; ++t) acc[t] = 0;
1545    for(int k = lane; k < K; k += 32){
1546      A wv = (A)__half2float(ws[k >> 5]) * (A)wq[k];
1547      #pragma unroll
1548      for(int t = 0; t < M; ++t) acc[t] += wv * (A)x[(long)t * ld + k];
1549    }
1550    #pragma unroll
1551    for(int t = 0; t < M; ++t) out[t] = (float)lk_warp_sum(acc[t]);
1552  } else {
1553    float acc[M];
1554    #pragma unroll
1555    for(int t = 0; t < M; ++t) acc[t] = 0.f;
1556    const int* w4 = (const int*)wq;
1557    for(int g = lane; g < (K >> 2); g += 32){
1558      int blk = g >> 3, wv = w4[g];
1559      float wsc = __half2float(ws[blk]);
1560      #pragma unroll
1561      for(int t = 0; t < M; ++t){
1562        float s = xs[(long)t * (ld >> 5) + blk];
1563        int d = __dp4a(wv, ((const int*)(xq + (long)t * ld))[g], 0);
1564        if(Q == 1) acc[t] += (float)d * (wsc * s);
1565        else acc[t] += wsc * (s * (float)d + s * 0.0078125f * (float)__dp4a(wv, ((const int*)(xl + (long)t * ld))[g], 0));
1566      }
1567    }
1568    #pragma unroll
1569    for(int t = 0; t < M; ++t) out[t] = lk_warp_sum(acc[t]);
1570  }
1571}
1572// Rows `o … o + W − 1` of a matrix in format `F` (8: Q8_0, split) dotted with the `M` activation rows of `K` values as
1573// the plain GEMV of that format dots them, row `r`'s dots at `out + r·M` — one warp of a block of at most `WARPS`.
1574template<int F, int Q, int M, int W = 1, int WARPS = 8>
1575__device__ __forceinline__ void lk_gemv_dot(lk_w w, long o, int K, const float* __restrict__ x,
1576                                            const signed char* __restrict__ xq, const signed char* __restrict__ xl,
1577                                            const float* __restrict__ xs, float* out){
1578  if constexpr(F == 8) lk_q8_rows_dot<Q, M, W, WARPS>(w.q, w.s, o, K, x, xq, xl, xs, out);
1579  else lk_row_dot<F, Q, M, W>(w, o, K, x, xq, xl, xs, K, out);
1580}
1581// A weight sub-block's raw words, fetched ahead of their decoding so their loads are in flight while the kernel works
1582// on what it fetched before: the bytes `lk_sub4` reads for it, by the widest loads the format's alignment allows (16
1583// bytes in Q4_K, Q5_K and Q8_0's levels, 4 in Q4_1, Q5_1, Q2_K and IQ4_XS, 2 in Q4_0, Q5_0, Q3_K, Q6_K and IQ4_NL, 1 in
1584// MXFP4).
1585template<int F> struct lk_raw { };
1586template<> struct lk_raw<2> { unsigned int q[4]; unsigned short d; };
1587template<> struct lk_raw<3> { unsigned int q[4], dm; };
1588template<> struct lk_raw<6> { unsigned int q[4], qh; unsigned short d; };
1589template<> struct lk_raw<7> { unsigned int q[4], qh, dm; };
1590template<> struct lk_raw<8> { uint4 q0, q1; unsigned short d; };
1591template<> struct lk_raw<10> { unsigned int q[8], dm; unsigned short sc; };
1592template<> struct lk_raw<11> { unsigned int q[8], hm[8], a0, a1, t; unsigned short d; };
1593template<> struct lk_raw<12> { uint4 h, q0, q1; };
1594template<> struct lk_raw<13> { uint4 h, qh0, qh1, q0, q1; };
1595template<> struct lk_raw<14> { unsigned int ql[8], qh[8]; unsigned short sc, d; };
1596template<> struct lk_raw<39> { unsigned int q[4]; unsigned char e; };
1597template<> struct lk_raw<20> { unsigned int q[4]; unsigned short d; };
1598template<> struct lk_raw<23> { unsigned int q[4]; unsigned short d, sh; unsigned char sl; };
1599__device__ __forceinline__ unsigned short lk_u16(const unsigned char* p){ return *(const unsigned short*)p; }
1600// Sub-block `ks` of matrix row `row` (`K` values, `nb` sub-blocks), its raw words.
1601template<int F> __device__ __forceinline__ void lk_fetch(lk_raw<F>& raw, lk_w w, long row, int K, int nb, int ks){
1602  const unsigned char* r = w.b + row * w.rb;
1603  int j = ks & 7, part = j >> 2, k = j & 3;
1604  if constexpr(F == 2 || F == 6){
1605    const unsigned char* b = r + (long)ks * (F == 2 ? 18 : 22);
1606    raw.d = lk_u16(b);
1607    if constexpr(F == 6) raw.qh = (unsigned int)lk_w16(b + 2);
1608    #pragma unroll
1609    for(int i = 0; i < 4; ++i) raw.q[i] = (unsigned int)lk_w16(b + (F == 2 ? 2 : 6) + 4 * i);
1610  } else if constexpr(F == 3 || F == 7){
1611    const unsigned char* b = r + (long)ks * (F == 3 ? 20 : 24);
1612    raw.dm = (unsigned int)lk_w32(b);
1613    if constexpr(F == 7) raw.qh = (unsigned int)lk_w32(b + 4);
1614    #pragma unroll
1615    for(int i = 0; i < 4; ++i) raw.q[i] = (unsigned int)lk_w32(b + (F == 3 ? 4 : 8) + 4 * i);
1616  } else if constexpr(F == 8){
1617    const uint4* q = (const uint4*)(w.q + row * K + (long)ks * 32);
1618    raw.q0 = __ldg(q); raw.q1 = __ldg(q + 1);
1619    raw.d = __half_as_ushort(w.s[row * nb + ks]);
1620  } else if constexpr(F == 10){
1621    const unsigned char* b = r + (long)(ks >> 3) * 84;
1622    #pragma unroll
1623    for(int i = 0; i < 8; ++i) raw.q[i] = (unsigned int)lk_w32(b + 16 + part * 32 + 4 * i);
1624    raw.sc = lk_u16(b + part * 8 + k * 2);
1625    raw.dm = (unsigned int)lk_w32(b + 80);
1626  } else if constexpr(F == 11){
1627    const unsigned char* b = r + (long)(ks >> 3) * 110;
1628    #pragma unroll
1629    for(int i = 0; i < 8; ++i){ raw.q[i] = (unsigned int)lk_w16(b + 32 + part * 32 + 4 * i); raw.hm[i] = (unsigned int)lk_w16(b + 4 * i); }
1630    raw.a0 = (unsigned int)lk_w16(b + 96); raw.a1 = (unsigned int)lk_w16(b + 100); raw.t = (unsigned int)lk_w16(b + 104);
1631    raw.d = lk_u16(b + 108);
1632  } else if constexpr(F == 12 || F == 13){
1633    const unsigned char* b = r + (long)(ks >> 3) * (F == 12 ? 144 : 176);
1634    const uint4* q = (const uint4*)(b + (F == 12 ? 16 : 48) + (j >> 1) * 32);
1635    raw.h = __ldg((const uint4*)b); raw.q0 = __ldg(q); raw.q1 = __ldg(q + 1);
1636    if constexpr(F == 13){ raw.qh0 = __ldg((const uint4*)(b + 16)); raw.qh1 = __ldg((const uint4*)(b + 32)); }
1637  } else if constexpr(F == 14){
1638    const unsigned char* b = r + (long)(ks >> 3) * 210;
1639    #pragma unroll
1640    for(int i = 0; i < 8; ++i){
1641      raw.ql[i] = (unsigned int)lk_w16(b + part * 64 + ((k & 1) ? 32 : 0) + 4 * i);
1642      raw.qh[i] = (unsigned int)lk_w16(b + 128 + part * 32 + 4 * i);
1643    }
1644    raw.sc = lk_u16(b + 192 + part * 8 + 2 * k);
1645    raw.d = lk_u16(b + 208);
1646  } else if constexpr(F == 39){
1647    const unsigned char* b = r + (long)ks * 17;
1648    raw.e = b[0];
1649    #pragma unroll
1650    for(int i = 0; i < 4; ++i) raw.q[i] = (unsigned int)b[1 + 4 * i] | ((unsigned int)b[2 + 4 * i] << 8) | ((unsigned int)b[3 + 4 * i] << 16) | ((unsigned int)b[4 + 4 * i] << 24);
1651  } else if constexpr(F == 20){
1652    const unsigned char* b = r + (long)ks * 18;
1653    raw.d = lk_u16(b);
1654    #pragma unroll
1655    for(int i = 0; i < 4; ++i) raw.q[i] = (unsigned int)lk_w16(b + 2 + 4 * i);
1656  } else if constexpr(F == 23){
1657    const unsigned char* b = r + (long)(ks >> 3) * 136;
1658    raw.d = lk_u16(b); raw.sh = lk_u16(b + 2); raw.sl = b[4 + (j >> 1)];
1659    #pragma unroll
1660    for(int i = 0; i < 4; ++i) raw.q[i] = (unsigned int)lk_w32(b + 8 + 16 * j + 4 * i);
1661  } else static_assert(F != F, "a block format with no raw words");
1662}
1663__device__ __forceinline__ float lk_hf(unsigned int bits){ return __half2float(__ushort_as_half((unsigned short)(bits & 0xFFFF))); }
1664// The sub-block from its fetched words — `lk_sub4`'s levels, scales and offsets, operation for operation.
1665template<int F> __device__ __forceinline__ void lk_unpack(const lk_raw<F>& raw, int ks, int* w, float* d, float* c){
1666  int j = ks & 7, part = j >> 2, k = j & 3;
1667  if constexpr(F == 2 || F == 3){
1668    float dd, cc = 0.f;
1669    if constexpr(F == 2) dd = lk_hf(raw.d);
1670    else { dd = lk_hf(raw.dm); cc = lk_hf(raw.dm >> 16); }
1671    #pragma unroll
1672    for(int i = 0; i < 4; ++i){
1673      int q = (int)raw.q[i];
1674      w[i] = q & 0x0F0F0F0F; w[i + 4] = (q >> 4) & 0x0F0F0F0F;
1675      if(F == 2){ w[i] = __vsub4(w[i], 0x08080808); w[i + 4] = __vsub4(w[i + 4], 0x08080808); }
1676    }
1677    d[0] = d[1] = dd; c[0] = c[1] = cc;
1678  } else if constexpr(F == 6 || F == 7){
1679    float dd, cc = 0.f;
1680    if constexpr(F == 6) dd = lk_hf(raw.d);
1681    else { dd = lk_hf(raw.dm); cc = lk_hf(raw.dm >> 16); }
1682    unsigned int qh = raw.qh;
1683    #pragma unroll
1684    for(int i = 0; i < 4; ++i){
1685      int q = (int)raw.q[i];
1686      w[i] = (q & 0x0F0F0F0F) | lk_bit4((qh >> (4 * i)) & 0xF);
1687      w[i + 4] = ((q >> 4) & 0x0F0F0F0F) | lk_bit4((qh >> (16 + 4 * i)) & 0xF);
1688      if(F == 6){ w[i] = __vsub4(w[i], 0x10101010); w[i + 4] = __vsub4(w[i + 4], 0x10101010); }
1689    }
1690    d[0] = d[1] = dd; c[0] = c[1] = cc;
1691  } else if constexpr(F == 8){
1692    w[0] = raw.q0.x; w[1] = raw.q0.y; w[2] = raw.q0.z; w[3] = raw.q0.w; w[4] = raw.q1.x; w[5] = raw.q1.y; w[6] = raw.q1.z; w[7] = raw.q1.w;
1693    d[0] = d[1] = lk_hf(raw.d); c[0] = c[1] = 0.f;
1694  } else if constexpr(F == 10){
1695    float dd = lk_hf(raw.dm), dm = lk_hf(raw.dm >> 16);
1696    #pragma unroll
1697    for(int i = 0; i < 8; ++i) w[i] = ((int)raw.q[i] >> (2 * k)) & 0x03030303;
1698    #pragma unroll
1699    for(int h = 0; h < 2; ++h){ int sc = (raw.sc >> (8 * h)) & 0xFF; d[h] = dd * (float)(sc & 0xf); c[h] = -(dm * (float)(sc >> 4)); }
1700  } else if constexpr(F == 11){
1701    int bit = part * 4 + k;
1702    unsigned int a0 = raw.a0, a1 = raw.a1, t = raw.t;
1703    unsigned int aux[4] = {(a0 & 0x0f0f0f0fu) | ((t & 0x03030303u) << 4), (a1 & 0x0f0f0f0fu) | (((t >> 2) & 0x03030303u) << 4),
1704                           ((a0 >> 4) & 0x0f0f0f0fu) | (((t >> 4) & 0x03030303u) << 4), ((a1 >> 4) & 0x0f0f0f0fu) | (((t >> 6) & 0x03030303u) << 4)};
1705    float dd = lk_hf(raw.d);
1706    #pragma unroll
1707    for(int i = 0; i < 8; ++i){
1708      int lo = ((int)raw.q[i] >> (2 * k)) & 0x03030303;
1709      int missing = (~((int)raw.hm[i] >> bit) & 0x01010101) << 2;
1710      w[i] = __vsub4(lo, missing);
1711    }
1712    #pragma unroll
1713    for(int h = 0; h < 2; ++h){
1714      int is = part * 8 + k * 2 + h;
1715      int sc = (signed char)((lk_pick4(aux, is >> 2) >> (8 * (is & 3))) & 0xff);
1716      d[h] = dd * (float)(sc - 32); c[h] = 0.f;
1717    }
1718  } else if constexpr(F == 12 || F == 13){
1719    int hi = j & 1, pp = j >> 1;
1720    // Scale byte `i` of the head's twelve.
1721    auto sb = [&](int i){ unsigned int wd = i < 4 ? raw.h.y : i < 8 ? raw.h.z : raw.h.w; return (int)((wd >> (8 * (i & 3))) & 0xFF); };
1722    int sc, m;
1723    if(j < 4){ sc = sb(j) & 63; m = sb(j + 4) & 63; }
1724    else { sc = (sb(j + 4) & 0xF) | ((sb(j - 4) >> 6) << 4); m = (sb(j + 4) >> 4) | ((sb(j) >> 6) << 4); }
1725    d[0] = d[1] = lk_hf(raw.h.x) * (float)sc; c[0] = c[1] = -lk_hf(raw.h.x >> 16) * (float)m;
1726    unsigned int q[8] = {raw.q0.x, raw.q0.y, raw.q0.z, raw.q0.w, raw.q1.x, raw.q1.y, raw.q1.z, raw.q1.w};
1727    #pragma unroll
1728    for(int i = 0; i < 8; ++i){
1729      int v = (int)((q[i] >> (4 * hi)) & 0x0F0F0F0Fu);
1730      if constexpr(F == 13){
1731        unsigned int qh[8] = {raw.qh0.x, raw.qh0.y, raw.qh0.z, raw.qh0.w, raw.qh1.x, raw.qh1.y, raw.qh1.z, raw.qh1.w};
1732        v |= (int)(((qh[i] >> (2 * pp + hi)) & 0x01010101u) << 4);
1733      }
1734      w[i] = v;
1735    }
1736  } else if constexpr(F == 14){
1737    float dd = lk_hf(raw.d);
1738    #pragma unroll
1739    for(int i = 0; i < 8; ++i){
1740      int lo = ((int)raw.ql[i] >> (4 * (k >> 1))) & 0x0F0F0F0F;
1741      int hi = (((int)raw.qh[i] >> (2 * k)) & 0x03030303) << 4;
1742      w[i] = __vsub4(lo | hi, 0x20202020);
1743    }
1744    d[0] = dd * (float)(signed char)(raw.sc & 0xFF); d[1] = dd * (float)(signed char)(raw.sc >> 8); c[0] = c[1] = 0.f;
1745  } else if constexpr(F == 39){
1746    #pragma unroll
1747    for(int i = 0; i < 4; ++i) lk_mxfp4_word(raw.q[i], w[i], w[i + 4]);
1748    d[0] = d[1] = lk_e8m0_half(raw.e); c[0] = c[1] = 0.f;
1749  } else if constexpr(F == 20 || F == 23){
1750    float dd;
1751    if constexpr(F == 20) dd = lk_hf(raw.d);
1752    else dd = lk_iq4xs_scale(lk_hf(raw.d), raw.sh, raw.sl, j);
1753    #pragma unroll
1754    for(int i = 0; i < 4; ++i) lk_iq4_word(raw.q[i], w[i], w[i + 4]);
1755    d[0] = d[1] = dd; c[0] = c[1] = 0.f;
1756  } else static_assert(F != F, "a block format with no raw words");
1757}
1758"#;
1759
1760/// `Y[t,o] = Σ_k X[t,k]·W[o,k]` for the `M` rows of `X` (`M ≤ 16`) over the `N` rows of a matrix in block format `F`,
1761/// `W` consecutive output rows a warp ([`BLOCKS`]' row dot), plus the bias when there is one. With a quantized output
1762/// (`QO`) a block of `32 / W` warps takes 32 outputs, one quantized block a row, quantized as `lk_quant_lane` quantizes
1763/// it, and `y` (when not null) takes the `f32` result too.
1764const GEMV_BLK: &str = r#"
1765template<int F, int Q, int M, int W, int QO>
1766__device__ __forceinline__ void lk_gemv_blk_rows(lk_w w, const float* __restrict__ x, const signed char* __restrict__ xq,
1767                            const signed char* __restrict__ xl, const float* __restrict__ xs,
1768                            const float* __restrict__ bias, lk_out y, const int* __restrict__ yrow,
1769                            long ypitch, int K, int N, signed char* __restrict__ yq, signed char* __restrict__ yl,
1770                            float* __restrict__ ys){
1771  __shared__ float v[QO > 0 ? M : 1][32];
1772  int lane = threadIdx.x & 31, warp = threadIdx.x >> 5;
1773  long o = (((long)blockIdx.x * blockDim.x + threadIdx.x) >> 5) * W;
1774  if(o < N){
1775    lk_out yo = y ? LK_ROW(y, yrow, ypitch) : lk_out();
1776    float d[W * M];
1777    lk_row_dot<F, Q, M, W>(w, o, K, x, xq, xl, xs, K, d);
1778    if(lane == 0){
1779      #pragma unroll
1780      for(int r = 0; r < W; ++r){
1781        #pragma unroll
1782        for(int t = 0; t < M; ++t){
1783          float val = bias ? d[r * M + t] + bias[o + r] : d[r * M + t];
1784          if(yo) yo[(long)t * N + o + r] = val;
1785          if(QO > 0) v[t][warp * W + r] = val;
1786        }
1787      }
1788    }
1789  }
1790  if(QO > 0){
1791    __syncthreads();
1792    if(warp < M){
1793      long at = (long)warp * N + (long)blockIdx.x * 32 + lane;
1794      lk_quant_lane<QO>(v[warp][lane], yq, yl, ys, at, at >> 5);
1795    }
1796  }
1797}
1798template<int F, int Q, int M, int W = 1, int QO = 0>
1799__global__ void lk_gemv_blk(lk_w w, const float* __restrict__ x, const signed char* __restrict__ xq,
1800                            const signed char* __restrict__ xl, const float* __restrict__ xs,
1801                            const float* __restrict__ bias, lk_out y, const int* __restrict__ yrow,
1802                            long ypitch, int K, int N, signed char* __restrict__ yq, signed char* __restrict__ yl,
1803                            float* __restrict__ ys){
1804  lk_gemv_blk_rows<F, Q, M, W, QO>(w, x, xq, xl, xs, bias, y, yrow, ypitch, K, N, yq, yl, ys);
1805}
1806"#;
1807
1808/// `lk_gemv_blk` over a step's one row, then, in its last-arriving block, `lk_rmsnorm` over the row it wrote: a
1809/// projection in a block format with the residual add and the next norm in its epilogue. Its blocks compute and write
1810/// their outputs as `lk_gemv_blk` does — `W` rows a warp — and count in at `cnt`; the last reads the row back through
1811/// L2 and norms it as `lk_rmsnorm`'s block of `vt` threads does, its warps playing the norm's (`VW` each), then resets
1812/// the count.
1813const GEMV_BLK_NORM: &str = r#"
1814template<int F, int Q, int W, bool ADD, bool SUM, bool OUTF, int QO, int PER, typename A, bool PRE, int VW>
1815__global__ void lk_gemv_blk_norm(lk_w w, const float* __restrict__ x, const signed char* __restrict__ xq,
1816                                 const signed char* __restrict__ xl, const float* __restrict__ xs,
1817                                 const float* __restrict__ bias, float* y, int K, int N, lk_norm_of nm, int vt,
1818                                 int* __restrict__ cnt){
1819  __shared__ A red[32];
1820  __shared__ int last;
1821  lk_gemv_blk_rows<F, Q, 1, W, 0>(w, x, xq, xl, xs, bias, y, nullptr, 0, K, N, nullptr, nullptr, nullptr);
1822  __threadfence();
1823  __syncthreads();
1824  if(threadIdx.x == 0) last = atomicAdd(cnt, 1) == gridDim.x - 1;
1825  __syncthreads();
1826  if(!last) return;
1827  __threadfence();
1828  lk_out yr = nm.y ? LK_ROW(nm.y, nm.yrow, nm.ypitch) : lk_out();
1829  lk_rmsnorm_row<ADD, SUM, OUTF, QO, PER, A, PRE, true, VW>(nm.x, nm.r, nm.s, nm.w, yr, nm.yq, nm.yl, nm.ys, N, nm.eps, 0, 0,
1830                                                            nm.pw, nm.peps, red, vt);
1831  if(threadIdx.x == 0) *cnt = 0;
1832}
1833"#;
1834
1835/// The projections of one activation's `M` rows (`M ≤ 16`) by up to `GEMM_PARTS` matrices in format `F` (8: Q8_0's
1836/// split arrays), their `N` outputs side by side as `parts` lays them out: warp `o` dots `W` consecutive rows of the
1837/// part holding output `o` (a part's outputs a whole number of warps' rows) as the part's own GEMV dots them
1838/// (`lk_gemv_dot`), and writes each, plus the part's bias, where the part's outputs go.
1839const GEMV_PARTS: &str = r#"
1840template<int F, int Q, int M, int W = 1>
1841__global__ void lk_gemv_parts(const float* __restrict__ x, const signed char* __restrict__ xq, const signed char* __restrict__ xl,
1842                              const float* __restrict__ xs, int K, int N, lk_parts parts){
1843  long o = (((long)blockIdx.x * blockDim.x + threadIdx.x) >> 5) * W;
1844  if(o >= N) return;
1845  int p = 0;
1846  while(p < LK_PARTS - 1 && o >= parts.end[p]) ++p;
1847  long start = p ? parts.end[p - 1] : 0, r = o - start;
1848  long n = parts.end[p] - start;
1849  float d[W * M];
1850  lk_gemv_dot<F, Q, M, W>(parts.w[p], r, K, x, xq, xl, xs, d);
1851  if((threadIdx.x & 31) == 0){
1852    lk_out yo = LK_ROW(lk_part_out(parts, p), parts.row[p], parts.pitch[p]);
1853    const float* b = parts.bias[p];
1854    #pragma unroll
1855    for(int i = 0; i < W; ++i)
1856      #pragma unroll
1857      for(int t = 0; t < M; ++t) yo[(long)t * n + r + i] = b ? d[i * M + t] + b[r + i] : d[i * M + t];
1858  }
1859}
1860"#;
1861
1862/// A batch's GEMV on the int8 tensor cores (`lk_gemv_mma`): the `M` activation rows (at most `16·MT`, `MT` 1, 2 or 4)
1863/// by up to four Q8_0 matrices side by side (`lk_parts`, each part a whole number of 8-output tiles), every (row,
1864/// output) summed exactly as `lk_q8_rows_dot` sums it — so a batch's sequence sums as the decode step's one row does:
1865/// each 32-value block's int8 dot exact (an int32 `mma` of k 32), its step (`lk_q8_acc`) into partial `b mod 4` of
1866/// block `b`, a partial's blocks in order, and the four partials as `lk_q8_sum4` sums them. A block takes `NT` n-tiles
1867/// of 8 outputs over all `MT` m-tiles, a warp `NW` of the n-tiles over `MW` of the m-tiles — each fragment it loads, an
1868/// m-tile's activations or an n-tile's matrix rows, feeding `NW` or `MW` products — staging four blocks of every matrix
1869/// row and activation row at a time in shared memory by `cp.async` (`lk_mma_stages` stages in flight), and each stage's
1870/// scales by plain loads a stage ahead; a stage's block `j` goes into partial `j`, and a warp's four partials of each
1871/// of its elements stay in registers.
1872const GEMV_MMA: &str = r#"
1873template<int Q> __host__ __device__ constexpr int lk_mma_stages(){ return Q == 2 ? 2 : 3; }
1874
1875// A stage's row in shared memory: four blocks (128 values) and 16 bytes of padding, so the eight rows an `mma` reads
1876// fall on distinct banks.
1877#define LK_MP 144
1878// A stage: four blocks of each of the block's `8·NT` matrix rows and `16·MT` activation rows (both words' under two
1879// words), and their scales.
1880template<int Q, int MT, int NT> __host__ __device__ constexpr int lk_mma_stage_bytes(){
1881  return 8 * NT * LK_MP + (Q == 2 ? 2 : 1) * 16 * MT * LK_MP + 8 * NT * 4 * 2 + 16 * MT * 4 * 4;
1882}
1883template<int Q, int MT, int NT> __host__ __device__ constexpr int lk_mma_smem(){ return lk_mma_stages<Q>() * lk_mma_stage_bytes<Q, MT, NT>(); }
1884// One stage's four blocks (from block `blk0`, `nb` the row's), block `j` into partial `j` of `acc`: `b` the stage's
1885// buffer, `wld` this lane's address of its first n-tile's matrix rows for `ldmatrix` and `ald` of its first m-tile's
1886// activation rows, `wsr` its first n-tile's two outputs' scales, `row` its first activation row.
1887template<int Q, int MW, int NW, int AOFF, int LOFF, int XSOFF>
1888__device__ __forceinline__ void lk_mma_blocks(float (&acc)[MW][NW][4][4], const unsigned char* b, int wld, int ald, const __half* wsr,
1889                                              int row0, int blk0, int nb){
1890  #pragma unroll
1891  for(int j = 0; j < 4; ++j){
1892    if(blk0 + j < nb){
1893      int bw[NW][2];
1894      float w0[NW], w1[NW];
1895      #pragma unroll
1896      for(int n = 0; n < NW; ++n){
1897        lk_ldsm2_s8(bw[n], b + wld + n * 8 * LK_MP + 32 * j);
1898        w0[n] = __half2float(wsr[n * 32 + j]); w1[n] = __half2float(wsr[n * 32 + 4 + j]);
1899      }
1900      #pragma unroll
1901      for(int m = 0; m < MW; ++m){
1902        const int row = row0 + m * 16;
1903        int a[4], l[4];
1904        lk_ldsm_s8(a, b + AOFF + ald + m * 16 * LK_MP + 32 * j);
1905        if(Q == 2) lk_ldsm_s8(l, b + LOFF + ald + m * 16 * LK_MP + 32 * j);
1906        const float* xsr = (const float*)(b + XSOFF);
1907        const float s0 = xsr[row * 4 + j], s1 = xsr[(row + 8) * 4 + j];
1908        #pragma unroll
1909        for(int n = 0; n < NW; ++n){
1910          int c[4], cl[4] = {LK_DOT0, LK_DOT0, LK_DOT0, LK_DOT0};
1911          lk_mma_s8_from(c, a, bw[n], LK_DOT0);
1912          if(Q == 2) lk_mma_s8_from(cl, l, bw[n], LK_DOT0);
1913          float (&p)[4] = acc[m][n][j];
1914          p[0] = lk_q8_acc<Q>(p[0], w0[n], s0, lk_dot_f(c[0]), lk_dot_f(cl[0]));
1915          p[1] = lk_q8_acc<Q>(p[1], w1[n], s0, lk_dot_f(c[1]), lk_dot_f(cl[1]));
1916          p[2] = lk_q8_acc<Q>(p[2], w0[n], s1, lk_dot_f(c[2]), lk_dot_f(cl[2]));
1917          p[3] = lk_q8_acc<Q>(p[3], w1[n], s1, lk_dot_f(c[3]), lk_dot_f(cl[3]));
1918        }
1919      }
1920    }
1921  }
1922}
1923template<int Q, int MT, int NT, int MW = 1, int NW = 1>
1924__global__ void __launch_bounds__(32 * (NT / NW) * (MT / MW), MW == 1 && NW == 1 ? 512 / (32 * NT * MT) : 1) lk_gemv_mma(
1925    const signed char* __restrict__ xq, const signed char* __restrict__ xl, const float* __restrict__ xs, int K, int N, int M,
1926    lk_parts parts){
1927  constexpr int NB = 8 * NT, MS = MT / MW, ST = lk_mma_stages<Q>(), T = 32 * (NT / NW) * MS;
1928  constexpr int SB = lk_mma_stage_bytes<Q, MT, NT>(), RA = 16 * MT;
1929  constexpr int AOFF = NB * LK_MP, LOFF = AOFF + RA * LK_MP, WSOFF = AOFF + (Q == 2 ? 2 : 1) * RA * LK_MP, XSOFF = WSOFF + NB * 8;
1930  extern __shared__ __align__(16) unsigned char lk_ms[];
1931  const int tid = threadIdx.x, warp = tid >> 5, lane = tid & 31, g = lane >> 2, q4 = lane & 3;
1932  // This warp's first n-tile and first m-tile.
1933  const int ntile = (warp / MS) * NW, mbase = (warp % MS) * MW;
1934  const long o0 = (long)blockIdx.x * NB;
1935  const int nb = K >> 5, stages = (nb + 3) >> 2;
1936  auto part_of = [&](long o){ int p = 0; while(p < LK_PARTS - 1 && o >= parts.end[p]) ++p; return p; };
1937  auto row_in = [&](long o, int p){ return o - (p ? parts.end[p - 1] : 0); };
1938  // This thread's copies each stage: 16-byte chunks `tid + T·i` of the block's matrix rows (eight a row) and of its
1939  // activation rows; and its scales of the stage's, entries `tid + T·i` — matrix row `e / 4`'s block `e mod 4`, and
1940  // activation row `e / 4`'s.
1941  constexpr int WC = (NB * 8 + T - 1) / T, AC = (RA * 8 + T - 1) / T, WSC = (NB * 4 + T - 1) / T, XC = (RA * 4 + T - 1) / T;
1942  const signed char* wsrc[WC];
1943  bool win[WC];
1944  #pragma unroll
1945  for(int i = 0; i < WC; ++i){
1946    const int c = tid + T * i;
1947    const long o = o0 + (c >> 3);
1948    win[i] = c < NB * 8 && o < N;
1949    const int p = part_of(win[i] ? o : 0);
1950    wsrc[i] = parts.w[p].q + (win[i] ? row_in(o, p) : 0) * K + 16 * (c & 7);
1951  }
1952  bool sin_[WSC];
1953  const __half* wsc[WSC];
1954  #pragma unroll
1955  for(int i = 0; i < WSC; ++i){
1956    const int e = tid + T * i;
1957    const long o = o0 + (e >> 2);
1958    sin_[i] = e < NB * 4 && o < N;
1959    const int p = part_of(sin_[i] ? o : 0);
1960    wsc[i] = parts.w[p].s + (sin_[i] ? row_in(o, p) : 0) * nb + (e & 3);
1961  }
1962  bool xin[XC];
1963  const float* xsc[XC];
1964  #pragma unroll
1965  for(int i = 0; i < XC; ++i){
1966    const int e = tid + T * i;
1967    xin[i] = e < RA * 4 && (e >> 2) < M;
1968    xsc[i] = xs + (long)(xin[i] ? e >> 2 : 0) * nb + (e & 3);
1969  }
1970  auto copy = [&](int st){
1971    unsigned char* b = lk_ms + (st % ST) * SB;
1972    const int kb = st * 128;
1973    #pragma unroll
1974    for(int i = 0; i < WC; ++i){
1975      const int c = tid + T * i;
1976      if(c < NB * 8) lk_cp16(b + (c >> 3) * LK_MP + 16 * (c & 7), wsrc[i] + kb, win[i] && kb + 16 * (c & 7) < K);
1977    }
1978    #pragma unroll
1979    for(int i = 0; i < AC; ++i){
1980      const int c = tid + T * i;
1981      if(c < RA * 8){
1982        const int t = c >> 3;
1983        const bool in = t < M && kb + 16 * (c & 7) < K;
1984        const long off = (long)(in ? t : 0) * K + kb + 16 * (c & 7);
1985        lk_cp16(b + AOFF + t * LK_MP + 16 * (c & 7), xq + (in ? off : 0), in);
1986        if(Q == 2) lk_cp16(b + LOFF + t * LK_MP + 16 * (c & 7), xl + (in ? off : 0), in);
1987      }
1988    }
1989  };
1990  // A stage's scales by plain loads, a stage ahead of their use; set into the stage's buffer before its wait.
1991  __half wnext[WSC];
1992  float xnext[XC];
1993  auto load_scales = [&](int st){
1994    const int blk = st * 4 + (tid & 3);
1995    #pragma unroll
1996    for(int i = 0; i < WSC; ++i) if(tid + T * i < NB * 4) wnext[i] = sin_[i] && blk < nb ? wsc[i][st * 4] : __float2half(0.f);
1997    #pragma unroll
1998    for(int i = 0; i < XC; ++i) if(tid + T * i < RA * 4) xnext[i] = xin[i] && blk < nb ? xsc[i][st * 4] : 0.f;
1999  };
2000  auto set_scales = [&](int st){
2001    unsigned char* b = lk_ms + (st % ST) * SB;
2002    #pragma unroll
2003    for(int i = 0; i < WSC; ++i) if(tid + T * i < NB * 4) ((__half*)(b + WSOFF))[tid + T * i] = wnext[i];
2004    #pragma unroll
2005    for(int i = 0; i < XC; ++i) if(tid + T * i < RA * 4) ((float*)(b + XSOFF))[tid + T * i] = xnext[i];
2006  };
2007  float acc[MW][NW][4][4];
2008  #pragma unroll
2009  for(int m = 0; m < MW; ++m)
2010    #pragma unroll
2011    for(int n = 0; n < NW; ++n)
2012      #pragma unroll
2013      for(int p = 0; p < 4; ++p)
2014        #pragma unroll
2015        for(int e = 0; e < 4; ++e) acc[m][n][p][e] = 0.f;
2016  #pragma unroll
2017  for(int i = 0; i < ST - 1; ++i){ if(i < stages) copy(i); asm volatile("cp.async.commit_group;\n"); }
2018  if(stages > 0) load_scales(0);
2019  // Stage `st`: its scales set, its copies landed for every thread, the copy `ST − 1` stages on started into the buffer
2020  // every warp has finished reading; its buffer.
2021  auto ready = [&](int st){
2022    set_scales(st);
2023    asm volatile("cp.async.wait_group %0;\n" :: "n"(ST - 2));
2024    __syncthreads();
2025    if(st + ST - 1 < stages) copy(st + ST - 1);
2026    asm volatile("cp.async.commit_group;\n");
2027    if(st + 1 < stages) load_scales(st + 1);
2028    return lk_ms + (st % ST) * SB;
2029  };
2030  // `ldmatrix`'s row addresses: of the first n-tile's matrix rows, lane `l` row `l mod 8`'s bytes `16·(l / 8 mod 2)` on;
2031  // of an m-tile's activation rows, lane `l` row `l mod 8 + 8·(l / 8 mod 2)`'s bytes `16·(l / 16)` on.
2032  const int wld = (ntile * 8 + (lane & 7)) * LK_MP + 16 * ((lane >> 3) & 1);
2033  const int ald = (mbase * 16 + (lane & 7) + 8 * ((lane >> 3) & 1)) * LK_MP + 16 * (lane >> 4);
2034  const int row0 = mbase * 16 + g;
2035  const int wsoff = WSOFF + (ntile * 8 + 2 * q4) * 4 * 2;
2036  for(int st = 0; st < stages; ++st){
2037    const unsigned char* b = ready(st);
2038    lk_mma_blocks<Q, MW, NW, AOFF, LOFF, XSOFF>(acc, b, wld, ald, (const __half*)(b + wsoff), row0, 4 * st, nb);
2039  }
2040  asm volatile("cp.async.wait_group 0;\n");
2041  // Each element's four partials summed as `lk_q8_sum4` sums them, written as `lk_gemv_parts` writes it.
2042  #pragma unroll
2043  for(int m = 0; m < MW; ++m)
2044    #pragma unroll
2045    for(int n = 0; n < NW; ++n){
2046      float vs[4];
2047      #pragma unroll
2048      for(int e = 0; e < 4; ++e) vs[e] = lk_q8_sum4(acc[m][n][0][e], acc[m][n][1][e], acc[m][n][2][e], acc[m][n][3][e]);
2049      #pragma unroll
2050      for(int e = 0; e < 4; ++e){
2051        const float v = vs[e];
2052        const long o = o0 + (ntile + n) * 8 + 2 * q4 + (e & 1);
2053        const int t = (mbase + m) * 16 + g + 8 * (e >> 1);
2054        if(o < N && t < M){
2055          const int p = part_of(o);
2056          const long start = p ? parts.end[p - 1] : 0, rr = o - start, np = parts.end[p] - start;
2057          lk_out yo = LK_ROW(lk_part_out(parts, p), parts.row[p], parts.pitch[p]);
2058          const float* bias = parts.bias[p];
2059          yo[(long)t * np + rr] = bias ? v + bias[rr] : v;
2060        }
2061      }
2062    }
2063}
2064"#;
2065
2066/// Rows `idx[0], idx[1], …` (1-based) of a table in block format `F`, decoded to `f32` and scaled by `scale`: one
2067/// thread per 32-weight sub-block of the output.
2068const GATHER_BLK: &str = r#"
2069// Sub-block `sb` of row `r` of a table in block format `F`, its 32 values scaled into `o`.
2070template<int F>
2071__device__ __forceinline__ void lk_gather_sub(lk_w w, long r, int sb, float* __restrict__ o, float scale){
2072  signed char v[32]; float d[2], c[2];
2073  lk_sub<F>(w.b + r * w.rb, sb, v, d, c);
2074  #pragma unroll
2075  for(int i = 0; i < 32; ++i) o[i] = __fadd_rn(__fmul_rn(d[i >> 4], (float)v[i]), c[i >> 4]) * scale;
2076}
2077template<int F>
2078__global__ void lk_gather_blk(lk_w w, const int* __restrict__ idx, float* __restrict__ out, int cols, float scale){
2079  int sb = blockIdx.x * blockDim.x + threadIdx.x; if(sb >= (cols >> 5)) return;
2080  lk_gather_sub<F>(w, (long)(idx[blockIdx.y] - 1), sb, out + (long)blockIdx.y * cols + sb * 32, scale);
2081}
2082"#;
2083
2084/// Rows `idx[0], idx[1], …` (1-based) of a Q8_0 table, scaled to `f32` and by `scale`, one row of the output per
2085/// index (`gridDim.y` of them).
2086const GATHER_Q8: &str = r#"
2087// Value `c` of row `r` of a Q8_0 table, scaled.
2088__device__ __forceinline__ float lk_gather_q8_at(const signed char* __restrict__ wq, const __half* __restrict__ ws, long r, int c,
2089                                                 int cols, float scale){
2090  return (float)wq[r * cols + c] * __half2float(ws[r * (cols >> 5) + (c >> 5)]) * scale;
2091}
2092__global__ void lk_gather_q8(const signed char* __restrict__ wq, const __half* __restrict__ ws,
2093                             const int* __restrict__ idx, float* __restrict__ out, int cols, float scale){
2094  int c = blockIdx.x * blockDim.x + threadIdx.x; if(c >= cols) return;
2095  out[(long)blockIdx.y * cols + c] = lk_gather_q8_at(wq, ws, (long)(idx[blockIdx.y] - 1), c, cols, scale);
2096}
2097"#;
2098
2099/// Rows `idx[0], idx[1], …` (1-based) of an `f32` table, scaled by `scale`, one row of the output per index (`gridDim.y`
2100/// of them).
2101const GATHER_F32: &str = r#"
2102// Value `c` of row `r` of an `f32` table, scaled.
2103__device__ __forceinline__ float lk_gather_f32_at(const float* __restrict__ t, long r, int c, int cols, float scale){
2104  return t[r * cols + c] * scale;
2105}
2106__global__ void lk_gather_f32(const float* __restrict__ t, const int* __restrict__ idx, float* __restrict__ out, int cols,
2107                              float scale){
2108  int c = blockIdx.x * blockDim.x + threadIdx.x; if(c >= cols) return;
2109  out[(long)blockIdx.y * cols + c] = lk_gather_f32_at(t, (long)(idx[blockIdx.y] - 1), c, cols, scale);
2110}
2111"#;
2112
2113/// Per-row RMSNorm, one block per row: `y = v / sqrt(mean(v²) + eps) · w` (no `w` for the weightless sugar) with `v = x (+ r)`. `ADD` adds the
2114/// residual first (and `SUM` writes the sum out, the residual stream the next block reads); `OUTF` writes `y`;
2115/// `Q` quantizes `y` for the GEMVs that read it (`cols` a multiple of 32). Row `r` of `x` is read `r·xp + xo` in (a part
2116/// of every row of a wider table), and `y`'s written `r·yp + yo` into the rows of a table from the row `yrow` names. A
2117/// block of `norm_threads(cols)` threads reads the row once, thread `t` keeping its `PER` values `t, t + blockDim, …`
2118/// in registers from the sum of squares to the scaling. The row's work is `lk_rmsnorm_row`, which a projection's
2119/// last-arriving block also runs over the rows the projection wrote (`L2`: read past the L1, where other blocks of the
2120/// launch wrote them), so the two compute the same norm. A block of fewer threads than the norm's own plays them:
2121/// `vt` the norm's threads, each warp of the block up to `VW` of the norm's warps (`lk_warps_sum`).
2122const RMSNORM: &str = r#"
2123// The norm a fold runs over the row its first part finished: its operands `x` and `r` (one of them that result), the
2124// sum it writes, its weight and outputs (`y` at the row `yrow` names), the norm of its added operand first (`pw`,
2125// `peps`).
2126struct lk_norm_of {
2127  const float* x; const float* r; float* s; const float* w; lk_out y; const int* yrow; long ypitch;
2128  signed char* yq; signed char* yl; float* ys; float eps; const float* pw; float peps;
2129};
2130template<bool ADD, bool SUM, bool OUTF, int Q, int PER, typename A, bool PRE, bool L2, int VW = 1>
2131__device__ __forceinline__ void lk_rmsnorm_row(const float* x, const float* r, float* __restrict__ s,
2132                           const float* __restrict__ w, lk_out yr, signed char* __restrict__ yq,
2133                           signed char* __restrict__ yl, float* __restrict__ ys, int cols, float eps, long base, long xb,
2134                           const float* __restrict__ pw, float peps, A* red, int vt){
2135  auto ld = [](const float* p){ return L2 ? __ldcg(p) : *p; };
2136  const int nw = blockDim.x >> 5, vw = vt >> 5, warp = threadIdx.x >> 5, lane = threadIdx.x & 31;
2137  // The norm's thread this thread plays `j`-th, and whether its warp is one of the norm's.
2138  auto u = [&](int j){ return (warp + j * nw) * 32 + lane; };
2139  auto on = [&](int j){ return warp + j * nw < vw; };
2140  float v[VW][PER];
2141  // Under PRE the added operand is first normed here (by `pw`, `peps`), each value as a norm of its own computes it.
2142  float p[VW][PRE ? PER : 1];
2143  if(PRE){
2144    A pacc[VW];
2145    #pragma unroll
2146    for(int j = 0; j < VW; ++j){
2147      pacc[j] = 0;
2148      #pragma unroll
2149      for(int k = 0; k < PER; ++k){
2150        int i = u(j) + k * vt;
2151        p[j][k] = on(j) && i < cols ? ld(r + base + i) : 0.f;
2152        pacc[j] += (A)p[j][k] * (A)p[j][k];
2153      }
2154    }
2155    A pden = sqrt(lk_warps_sum<VW>(pacc, vw, red) / (A)cols + (A)peps);
2156    #pragma unroll
2157    for(int j = 0; j < VW; ++j){
2158      #pragma unroll
2159      for(int k = 0; k < PER; ++k){
2160        int i = u(j) + k * vt;
2161        if(on(j) && i < cols) p[j][k] = pw ? (float)((A)p[j][k] / pden * (A)pw[i]) : (float)((A)p[j][k] / pden);
2162      }
2163    }
2164  }
2165  A acc[VW];
2166  #pragma unroll
2167  for(int j = 0; j < VW; ++j){
2168    acc[j] = 0;
2169    #pragma unroll
2170    for(int k = 0; k < PER; ++k){
2171      int i = u(j) + k * vt;
2172      v[j][k] = 0.f;
2173      if(on(j) && i < cols){
2174        v[j][k] = ld(x + xb + i);
2175        if(ADD){ v[j][k] += PRE ? p[j][k] : ld(r + base + i); if(SUM) s[base + i] = v[j][k]; }
2176      }
2177      acc[j] += (A)v[j][k] * (A)v[j][k];
2178    }
2179  }
2180  A den = sqrt(lk_warps_sum<VW>(acc, vw, red) / (A)cols + (A)eps);
2181  #pragma unroll
2182  for(int j = 0; j < VW; ++j){
2183    if(!on(j)) continue;
2184    #pragma unroll
2185    for(int k = 0; k < PER; ++k){
2186      int i = u(j) + k * vt;
2187      // A warp holds a whole 32-value group: the quantizer's maximum is the warp's.
2188      if(Q == 0 ? i < cols : (i & ~31) < cols){
2189        float o = w ? (float)((A)v[j][k] / den * (A)w[i]) : (float)((A)v[j][k] / den);
2190        if(Q == 0 || OUTF) yr[i] = o;
2191        if(Q > 0) lk_quant_lane<Q>(o, yq, yl, ys, base + i, (base + i) >> 5);
2192      }
2193    }
2194  }
2195}
2196template<bool ADD, bool SUM, bool OUTF, int Q, int PER, typename A, bool PRE = false>
2197__global__ void __launch_bounds__(1024) lk_rmsnorm(const float* __restrict__ x, const float* __restrict__ r,
2198                           float* __restrict__ s, const float* __restrict__ w, lk_out y,
2199                           signed char* __restrict__ yq, signed char* __restrict__ yl, float* __restrict__ ys, int cols,
2200                           float eps, long xp, long xo, const int* __restrict__ yrow, long ypitch, long yp, long yo,
2201                           const float* __restrict__ pw = nullptr, float peps = 0.f){
2202  __shared__ A red[32];
2203  long base = (long)blockIdx.x * cols, xb = (long)blockIdx.x * xp + xo;
2204  lk_out yr = y ? LK_ROW(y, yrow, ypitch) + (long)blockIdx.x * yp + yo : lk_out();
2205  lk_rmsnorm_row<ADD, SUM, OUTF, Q, PER, A, PRE, false>(x, r, s, w, yr, yq, yl, ys, cols, eps, base, xb, pw, peps, red, blockDim.x);
2206}
2207"#;
2208
2209/// A gather, then `lk_rmsnorm` over the row it gathered, a block a row: the embedding's rows and the first norm
2210/// (`embed_norm`). A block of `norm_threads(cols)` threads gathers its row into `out` — the raw row its later readers
2211/// take — as the gather of the table's format computes it (`F` 0: an `f32` table `t`; 8: Q8_0's split arrays; a block
2212/// format otherwise), then norms it as `lk_rmsnorm`'s block for that row does.
2213const GATHER_NORM: &str = r#"
2214template<int F, bool OUTF, int Q, int PER, typename A>
2215__global__ void __launch_bounds__(1024) lk_gather_norm(lk_w w, const float* __restrict__ t, const int* __restrict__ idx,
2216                           float* __restrict__ out, int cols, float scale, const float* __restrict__ nw, lk_out y,
2217                           signed char* __restrict__ yq, signed char* __restrict__ yl, float* __restrict__ ys, float eps,
2218                           const int* __restrict__ yrow, long ypitch){
2219  __shared__ A red[32];
2220  const long r = (long)(idx[blockIdx.x] - 1), base = (long)blockIdx.x * cols;
2221  if constexpr(F == 0){
2222    for(int c = threadIdx.x; c < cols; c += blockDim.x) out[base + c] = lk_gather_f32_at(t, r, c, cols, scale);
2223  } else if constexpr(F == 8){
2224    for(int c = threadIdx.x; c < cols; c += blockDim.x) out[base + c] = lk_gather_q8_at(w.q, w.s, r, c, cols, scale);
2225  } else {
2226    for(int sb = threadIdx.x; sb < (cols >> 5); sb += blockDim.x) lk_gather_sub<F>(w, r, sb, out + base + sb * 32, scale);
2227  }
2228  __syncthreads();
2229  lk_out yr = y ? LK_ROW(y, yrow, ypitch) + base : lk_out();
2230  lk_rmsnorm_row<false, false, OUTF, Q, PER, A, false, false>(out, nullptr, nullptr, nw, yr, yq, yl, ys, cols, eps, base, base,
2231                                                              nullptr, 0.f, red, blockDim.x);
2232}
2233"#;
2234
2235/// `lk_gemv_q8`, then, in its last-arriving block, `lk_rmsnorm` over the rows it wrote: a projection with the residual
2236/// add and the next norm in its epilogue. A block of `norm_threads(N)` threads, a warp an output row, computes each row
2237/// as `lk_gemv_q8` does and writes it to `y`; every block counts in at `cnt` once its rows are out, and the last reads
2238/// `y` back through L2 and norms each of the `M` rows as `lk_rmsnorm`'s block for that row does — the norm's `x` and
2239/// `r` are its operands, one of them `y` — then resets the count.
2240const GEMV_Q8_NORM: &str = r#"
2241template<int Q, int M, bool ADD, bool SUM, bool OUTF, int QO, int PER, typename A, bool PRE>
2242__global__ void __launch_bounds__(1024) lk_gemv_q8_norm(const signed char* __restrict__ wq, const __half* __restrict__ ws,
2243                           const float* __restrict__ ax, const signed char* __restrict__ xq,
2244                           const signed char* __restrict__ xl, const float* __restrict__ xs,
2245                           const float* __restrict__ bias, float* y, int K, int N,
2246                           const float* x, const float* r, float* __restrict__ s, const float* __restrict__ w, lk_out yo,
2247                           const int* __restrict__ yrow, long ypitch, signed char* __restrict__ yq,
2248                           signed char* __restrict__ yl, float* __restrict__ ys, float eps, int* __restrict__ cnt,
2249                           const float* __restrict__ pw = nullptr, float peps = 0.f){
2250  __shared__ A red[32];
2251  __shared__ int last;
2252  int o = (blockIdx.x * blockDim.x + threadIdx.x) >> 5;
2253  if(o < N){
2254    float v[M];
2255    lk_q8_rows_dot<Q, M, 1>(wq, ws, o, K, ax, xq, xl, xs, v);
2256    if((threadIdx.x & 31) == 0){
2257      #pragma unroll
2258      for(int t = 0; t < M; ++t) y[(long)t * N + o] = bias ? v[t] + bias[o] : v[t];
2259    }
2260  }
2261  __threadfence();
2262  __syncthreads();
2263  if(threadIdx.x == 0) last = atomicAdd(cnt, 1) == gridDim.x - 1;
2264  __syncthreads();
2265  if(!last) return;
2266  __threadfence();
2267  lk_out yr = yo ? LK_ROW(yo, yrow, ypitch) : lk_out();
2268  for(int t = 0; t < M; ++t){
2269    long base = (long)t * N;
2270    lk_rmsnorm_row<ADD, SUM, OUTF, QO, PER, A, PRE, true>(x, r, s, w, yo ? yr + base : lk_out(), yq, yl, ys, N, eps, base, base, pw, peps, red, blockDim.x);
2271  }
2272  if(threadIdx.x == 0) *cnt = 0;
2273}
2274"#;
2275
2276/// Quantize an activation of `n` values (a multiple of 32), one warp per group.
2277const QUANT: &str = r#"
2278template<int Q>
2279__global__ void lk_quant(const float* __restrict__ x, signed char* __restrict__ xq, signed char* __restrict__ xl,
2280                         float* __restrict__ xs, int n){
2281  long i = (long)blockIdx.x * blockDim.x + threadIdx.x; if(i >= n) return;
2282  lk_quant_lane<Q>(x[i], xq, xl, xs, i, i >> 5);
2283}
2284"#;
2285
2286/// `Y[t,o] = Σ_k X[t,k]·W[o,k]` for the `M` rows of `X` (`M ≤ 16`) over the `N` rows of a Q8_0 matrix (int8 rows of `K`,
2287/// an f16 scale per 32), one warp per output row: the weight row is read once for every row of `X`. `Q` is the
2288/// activations' numerics; the result may land in the rows of a cache a position names.
2289const GEMV_Q8: &str = r#"
2290template<int Q, int M>
2291__global__ void lk_gemv_q8(const signed char* __restrict__ wq, const __half* __restrict__ ws,
2292                           const float* __restrict__ x, const signed char* __restrict__ xq,
2293                           const signed char* __restrict__ xl, const float* __restrict__ xs,
2294                           const float* __restrict__ bias, lk_out y, const int* __restrict__ yrow,
2295                           long ypitch, int K, int N){
2296  int o = (blockIdx.x * blockDim.x + threadIdx.x) >> 5; if(o >= N) return;
2297  lk_out yo = LK_ROW(y, yrow, ypitch);
2298  float v[M];
2299  lk_q8_rows_dot<Q, M, 1>(wq, ws, o, K, x, xq, xl, xs, v);
2300  if((threadIdx.x & 31) == 0){
2301    #pragma unroll
2302    for(int t = 0; t < M; ++t) yo[(long)t * N + o] = bias ? v[t] + bias[o] : v[t];
2303  }
2304}
2305"#;
2306
2307/// The tensor-core GEMMs' helpers: a 16-byte `cp.async` that zero-fills when `pred` is false, the int8 `mma`s of k 32
2308/// and k 16, and the read of an `mma`'s int32 sum as a float.
2309const MMA: &str = r#"
2310// An int32 `mma` sum begun at the bits of 1.5·2²³ ends as the float 1.5·2²³ + sum, exactly while |sum| < 2²² (a block's
2311// dot of 32 int8 products is under 2¹⁹), and one float subtraction reads the sum: the conversion it replaces runs at a
2312// quarter of the float rate, and an epilogue of one a product held the tensor cores to half their rate.
2313#define LK_DOT0 0x4B400000
2314__device__ __forceinline__ float lk_dot_f(int d){ return __int_as_float(d) - 12582912.f; }
2315__device__ __forceinline__ void lk_cp16(void* smem, const void* gmem, bool pred){
2316  unsigned s = (unsigned)__cvta_generic_to_shared(smem);
2317  int n = pred ? 16 : 0;
2318  asm volatile("cp.async.cg.shared.global [%0], [%1], 16, %2;\n" :: "r"(s), "l"(gmem), "r"(n));
2319}
2320// Four `f32` of a staged tile from four elements at `g` (zeros where `pred` is false): an `f32` array's by `cp.async`,
2321// landing with the copies in flight beside it; a binary16 array's widened as it is read, there at once.
2322__device__ __forceinline__ void lk_stage4(float* smem, const float* g, bool pred){ lk_cp16(smem, g, pred); }
2323__device__ __forceinline__ void lk_stage4(float* smem, const __half* g, bool pred){
2324  *(float4*)smem = pred ? lk_from4(g) : make_float4(0.f, 0.f, 0.f, 0.f);
2325}
2326__device__ __forceinline__ void lk_mma_s8(int* c, const int* a, const int* b){
2327  asm volatile("mma.sync.aligned.m16n8k32.row.col.s32.s8.s8.s32 {%0,%1,%2,%3}, {%4,%5,%6,%7}, {%8,%9}, {%0,%1,%2,%3};\n"
2328               : "+r"(c[0]), "+r"(c[1]), "+r"(c[2]), "+r"(c[3])
2329               : "r"(a[0]), "r"(a[1]), "r"(a[2]), "r"(a[3]), "r"(b[0]), "r"(b[1]));
2330}
2331__device__ __forceinline__ void lk_mma_s8_k16(int* c, const int* a, int b){
2332  asm volatile("mma.sync.aligned.m16n8k16.row.col.s32.s8.s8.s32 {%0,%1,%2,%3}, {%4,%5}, {%6}, {%0,%1,%2,%3};\n"
2333               : "+r"(c[0]), "+r"(c[1]), "+r"(c[2]), "+r"(c[3]) : "r"(a[0]), "r"(a[1]), "r"(b));
2334}
2335// An int8 `mma` whose sums start at `c`: not volatile, so the scheduler interleaves it with the float work around it.
2336__device__ __forceinline__ void lk_mma_s8_from(int* d, const int* a, const int* b, int c){
2337  asm("mma.sync.aligned.m16n8k32.row.col.s32.s8.s8.s32 {%0,%1,%2,%3}, {%4,%5,%6,%7}, {%8,%9}, {%10,%10,%10,%10};\n"
2338      : "=r"(d[0]), "=r"(d[1]), "=r"(d[2]), "=r"(d[3]) : "r"(a[0]), "r"(a[1]), "r"(a[2]), "r"(a[3]), "r"(b[0]), "r"(b[1]), "r"(c));
2339}
2340// A `cp.async` of `B` bytes (4, 8 or 16) copying `n` of them and zero-filling the rest.
2341template<int B>
2342__device__ __forceinline__ void lk_cpn(void* smem, const void* gmem, int n){
2343  unsigned s = (unsigned)__cvta_generic_to_shared(smem);
2344  if constexpr(B == 16) asm volatile("cp.async.cg.shared.global [%0], [%1], 16, %2;\n" :: "r"(s), "l"(gmem), "r"(n));
2345  else asm volatile("cp.async.ca.shared.global [%0], [%1], %2, %3;\n" :: "r"(s), "l"(gmem), "n"(B), "r"(n));
2346}
2347// Four 8 × 8 matrices of 16-bit words from shared memory, a lane's row address each, as `mma` fragments.
2348__device__ __forceinline__ void lk_ldsm_s8(int* r, const void* p){
2349  unsigned s = (unsigned)__cvta_generic_to_shared(p);
2350  asm volatile("ldmatrix.sync.aligned.m8n8.x4.shared.b16 {%0,%1,%2,%3}, [%4];\n" : "=r"(r[0]), "=r"(r[1]), "=r"(r[2]), "=r"(r[3]) : "r"(s));
2351}
2352// Two, lanes 0 to 15 giving the rows.
2353__device__ __forceinline__ void lk_ldsm2_s8(int* r, const void* p){
2354  unsigned s = (unsigned)__cvta_generic_to_shared(p);
2355  asm volatile("ldmatrix.sync.aligned.m8n8.x2.shared.b16 {%0,%1}, [%2];\n" : "=r"(r[0]), "=r"(r[1]) : "r"(s));
2356}
2357"#;
2358
2359/// `Y[m, n] = Σ_k X[m, k]·W[n, k]` for `M` rows of int8 activations (a scale per 32, and the low words under `Q` 2) over
2360/// the `N` rows of a matrix in block format `F`, on the int8 tensor cores: a block computes a `BM` × 128 tile over
2361/// stages of 128 `k` (four sub-blocks). The activation rows land in shared memory by `cp.async`, the next stage's in a
2362/// second buffer while this one multiplies where both fit; the weight rows' sub-blocks are fetched a stage ahead as
2363/// their raw words (`lk_fetch`) and decoded from them (`lk_unpack`, as `lk_sub4` decodes) into int8 levels and each
2364/// half's scale and offset; each half's activation sum is taken for the offsets. A warp multiplies 32 × 32, one
2365/// `m16n8k32` `mma` a sub-block — two `m16n8k16` for a format whose halves scale apart (Q2_K, Q3_K, Q6_K) — each int32
2366/// dot scaled as the sub-block's dot is, `s·(d₀·dot₀ + c₀·Σ₀ + d₁·dot₁ + c₁·Σ₁)`. Rows past `M` and outputs past `N`
2367/// are zero and never stored. A Q8_0 matrix (`F` 8) is read as its levels and one scale a sub-block, and under two words
2368/// a sub-block's high and low dots fold into one exact integer, `s/128·d·(128·dot + dotₗ)`. Over a `k` of whole
2369/// 128-value scale groups a Q8_0 matrix streams (`lk_blk_streamed`): a stage is 32 of `k`, `LK_STREAM_STAGES` of them in
2370/// flight by `cp.async`, each landing on a barrier of its own and freed when every warp has read it (no barrier of the
2371/// whole block in the loop), its rows swizzled so a `ldmatrix` reads every bank once; each scale group (four stages' row
2372/// and column scales) lands with its first stage, two held; paired, a warp's 32 outputs are 16 gate rows and the same 16
2373/// up rows, so each hidden value meets its gate and up sums in one thread. Either path sums each output alike, and cuts
2374/// the same tiles of a last wave.
2375///
2376/// Grouped (`G` 1, 2), the GEMM multiplies an expert mixture's choices: grid layer `z` is expert `z`, its `ecount[z]`
2377/// rows the gathered activation rows from `eoff[z]`, its matrix rows `z·N … z·N + N − 1` of the stacked experts, its
2378/// outputs the same rows of `y` (`yrow` and `ypitch` unread); `G` 2 adds the expert's bias and weighs each row by its
2379/// choice's weight (`wt[list[row]]`), as `lk_moe_down_rows` weighs it. In parts (`G` 4), the GEMM multiplies one
2380/// activation by up to `GEMM_PARTS` matrices side by side (`parts`): its `N` outputs part `p`'s from `end[p − 1]` to
2381/// `end[p]`, each part a whole number of tiles, its matrix `w[p]`, its bias `bias[p]` and its outputs `y[p]` — rows from
2382/// the one-based position `row[p]` names, `pitch[p]` apart, where it names one. Paired
2383/// and dense (`G` 5), it multiplies a gated pair's gate (`w`, `bias`) and up (`w2`, `bias2`) over the activation's rows,
2384/// a tile `LK_BN / 2` of each, and writes each of the `N` hidden values through the gated activation — `ACT` −1 the
2385/// SwiGLU `g·σ(g)·u`, otherwise `u·act(g)` (`lk_act<ACT>`), as `lk_gemv_glu` computes it — into `y` where given and
2386/// quantized (`hq`, `hl`, `hs`) where given. A line of blocks cuts pair tiles `2i` and `2i + 1` as the gate's own
2387/// GEMM cuts its tile `i`.
2388const GEMM_BLK: &str = r#"
2389#define LK_BN 128
2390template<int F> __host__ __device__ constexpr bool lk_halves_apart(){ return F == 10 || F == 11 || F == 14; }
2391// The formats whose sub-blocks carry an offset (a minimum): Q4_1, Q5_1, Q2_K, Q4_K, Q5_K.
2392template<int F> __host__ __device__ constexpr bool lk_has_offset(){ return F == 3 || F == 7 || F == 10 || F == 12 || F == 13; }
2393// A stage's activations, in bytes: the activation tile (and its low words) and each row's scale for each of the
2394// stage's four sub-blocks.
2395template<int Q, int BM> __host__ __device__ constexpr int lk_stage_acts(){ return (Q == 2 ? 2 : 1) * BM * 144 + BM * 4 * 4; }
2396// The rest of a stage, in bytes: the decoded weight tile, each weight sub-block's scales (two halves where they scale
2397// apart) and offsets, and the activation's half sums (16-bit, where the format has offsets).
2398template<int F, int Q, int BM> __host__ __device__ constexpr int lk_stage_rest(){
2399  return LK_BN * 144 + LK_BN * 4 * (lk_halves_apart<F>() ? 2 : 1) * 4
2400       + (lk_has_offset<F>() ? LK_BN * 4 * (lk_halves_apart<F>() ? 2 : 1) * 4 : 0)
2401       + (lk_has_offset<F>() ? (Q == 2 ? 2 : 1) * BM * 4 * 2 * 2 : 0);
2402}
2403// Whether the activations take two buffers — the next stage's landing while this one multiplies — within a block's
2404// 99 KB of shared memory.
2405template<int F, int Q, int BM> __host__ __device__ constexpr bool lk_stage_pipelined(){
2406  return 2 * lk_stage_acts<Q, BM>() + lk_stage_rest<F, Q, BM>() <= 101376;
2407}
2408// One stage's weights: the `SB` sub-blocks from `k0` of the `LK_BN` matrix rows from `wbase + n0`, their levels as int8
2409// words at `Bs` (rows `BP` bytes apart, zero past `N` and `K`) and each sub-block's scales (`DH`) and offsets (`CH`) at
2410// `Bd`, `Bc`: a thread a sub-block, the `U` of each of the `NT` threads from the words `raw` fetched for them.
2411// A paired tile's (`PAIR`) weight rows are its `LK_BN / 2` gate rows, then the same up rows.
2412template<bool PAIR> __device__ __forceinline__ int lk_tile_row(int r){ return PAIR ? r & (LK_BN / 2 - 1) : r; }
2413template<int F, int SB, int BP, int DH, int CH, int NT, int U, bool PAIR>
2414__device__ __forceinline__ void lk_stage_weights(const lk_raw<F> (&raw)[U], int n0, int N, int nb, int k0, unsigned char* Bs,
2415                                                 float* Bd, float* Bc, int tid){
2416  #pragma unroll
2417  for(int u = 0; u < U; ++u){
2418    int c = tid + u * NT, r = c / SB, sb = c % SB, ks = (k0 >> 5) + sb;
2419    int wv[8]; float d[2], o[2];
2420    if(n0 + lk_tile_row<PAIR>(r) < N && ks < nb) lk_unpack<F>(raw[u], ks, wv, d, o);
2421    else { for(int i = 0; i < 8; ++i) wv[i] = 0; d[0] = d[1] = o[0] = o[1] = 0.f; }
2422    uint4* dst = (uint4*)(Bs + r * BP + sb * 32);
2423    dst[0] = make_uint4(wv[0], wv[1], wv[2], wv[3]); dst[1] = make_uint4(wv[4], wv[5], wv[6], wv[7]);
2424    #pragma unroll
2425    for(int h = 0; h < DH; ++h){
2426      Bd[(r * SB + sb) * DH + h] = d[h];
2427      if(CH) Bc[(r * SB + sb) * CH + h] = o[h];
2428    }
2429  }
2430}
2431// The next stage's raw weight words for this thread's `U` sub-blocks: of `w`, or of `w2` in a paired tile's up rows.
2432template<int F, int SB, int NT, int U, bool PAIR>
2433__device__ __forceinline__ void lk_stage_fetch(lk_raw<F> (&raw)[U], lk_w w, lk_w w2, long wbase, int n0, int N, int K, int nb, int k0,
2434                                               int tid){
2435  #pragma unroll
2436  for(int u = 0; u < U; ++u){
2437    int c = tid + u * NT, r = c / SB, ks = (k0 >> 5) + c % SB, row = lk_tile_row<PAIR>(r);
2438    if(n0 + row < N && ks < nb) lk_fetch<F>(raw[u], PAIR && r >= LK_BN / 2 ? w2 : w, wbase + n0 + row, K, nb, ks);
2439  }
2440}
2441// `BM` activation rows a block, `BM / 32 · 4` warps: 128 for a dense product, 64 for an expert's few rows. Paired (`G`
2442// 3), a block takes `LK_BN / 2` hidden columns of an expert's gate (`w`, `bias`) and up (`w2`, `bias2`) projections
2443// together and writes each hidden value through the gated activation `ACT` (`limit`, `slope`), as `lk_moe_glu` computes
2444// it, quantized as `lk_quant_lane` quantizes it (`hq`, `hl`, `hs`). A dense product with `part` given runs on a line
2445// of blocks: block `b < tail` the whole tile `b` (tiles row by row of column tiles), each later block one of `split`
2446// parts of a remaining tile's stages, its sums parked in `part`; the last part of a tile to arrive (`cnt`) sums the
2447// tile's parts in order and writes the tile.
2448#define LK_STREAM_STAGES 4
2449template<int Q, int BM> __host__ __device__ constexpr int lk_q8_stage(){ return (Q == 2 ? 2 : 1) * BM * 32 + LK_BN * 32; }
2450template<int BM> __host__ __device__ constexpr int lk_q8_group(){ return BM * 16 + LK_BN * 8; }
2451// Byte `16·c` of row `r` of a tile of 32-byte rows: the row's halves swapped on every other run of four rows.
2452__device__ __forceinline__ int lk_q8_swz(int r, int c){ return r * 32 + ((c ^ ((r >> 2) & 1)) << 4); }
2453__device__ __forceinline__ void lk_mbar_init(unsigned a, unsigned n){ asm volatile("mbarrier.init.shared.b64 [%0], %1;\n" :: "r"(a), "r"(n) : "memory"); }
2454__device__ __forceinline__ void lk_mbar_arrive(unsigned a){ asm volatile("{\n .reg .b64 st;\n mbarrier.arrive.shared.b64 st, [%0];\n}\n" :: "r"(a) : "memory"); }
2455// The barrier counts this thread's arrival once every `cp.async` it issued before has landed.
2456__device__ __forceinline__ void lk_mbar_copies(unsigned a){ asm volatile("cp.async.mbarrier.arrive.noinc.shared.b64 [%0];\n" :: "r"(a) : "memory"); }
2457__device__ __forceinline__ void lk_mbar_wait(unsigned a, unsigned parity){
2458  asm volatile("{\n .reg .pred p;\n LK_WAIT_%=:\n mbarrier.test_wait.parity.shared.b64 p, [%0], %1;\n @!p bra LK_WAIT_%=;\n}\n" :: "r"(a), "r"(parity) : "memory");
2459}
2460__device__ __forceinline__ void lk_cp16s(unsigned s, const void* g, bool pred){
2461  asm volatile("cp.async.cg.shared.global [%0], [%1], 16, %2;\n" :: "r"(s), "l"(g), "r"(pred ? 16 : 0));
2462}
2463__device__ __forceinline__ void lk_cp8s(unsigned s, const void* g, bool pred){
2464  asm volatile("cp.async.ca.shared.global [%0], [%1], 8, %2;\n" :: "r"(s), "l"(g), "r"(pred ? 8 : 0));
2465}
2466__device__ __forceinline__ void lk_ldsm_s(int* r, unsigned s){
2467  asm volatile("ldmatrix.sync.aligned.m8n8.x4.shared.b16 {%0,%1,%2,%3}, [%4];\n" : "=r"(r[0]), "=r"(r[1]), "=r"(r[2]), "=r"(r[3]) : "r"(s));
2468}
2469// Row `rw` of a tile's matrix rows: paired, row `rw` of warp `rw / 32`'s 32 is gate row `16·(rw / 32) + rw % 16` below
2470// 16 and the same up row above; otherwise row `rw`.
2471template<bool PAIR> __device__ __forceinline__ int lk_q8_row(int rw){ return PAIR ? (rw >> 5) * 16 + (rw & 15) : rw; }
2472// The streamed path of `lk_gemm_blk<8>` over a `K` of whole 128-value scale groups, each warp `WM` rows by 32 outputs
2473// of the tile: `lk_gemm_blk`'s arguments, its block's dynamic shared memory at `lk_sm`.
2474template<int Q, int G, int BM, int ACT, int WM>
2475__device__ __forceinline__ void lk_blk_streamed(unsigned char* lk_sm, lk_w w, const signed char* __restrict__ xq,
2476    const signed char* __restrict__ xl, const float* __restrict__ xs, const float* __restrict__ bias, lk_out y,
2477    const int* __restrict__ yrow, long ypitch, int K, int N, int M, const int* __restrict__ ecount,
2478    const int* __restrict__ eoff, const int* __restrict__ list, const float* __restrict__ wt,
2479    lk_w w2, const float* __restrict__ bias2, signed char* __restrict__ hq,
2480    signed char* __restrict__ hl, float* __restrict__ hs, float limit, float slope,
2481    int tail, int split, float* __restrict__ part, int* __restrict__ cnt, lk_parts parts){
2482  constexpr bool PAIR = G == 3 || G == 5, GROUPED = G >= 1 && G <= 3, DENSE = !GROUPED;
2483  constexpr int TW = PAIR ? LK_BN / 2 : LK_BN;
2484  constexpr int MT = WM / 16, NT = BM / WM * 128, AW = Q == 2 ? 2 : 1;
2485  constexpr int A_BYTES = BM * 32, STAGE = lk_q8_stage<Q, BM>(), GROUP = lk_q8_group<BM>(), RING = LK_STREAM_STAGES * STAGE;
2486  // The grid's blocks in launch order take the row tiles of a column tile one after another, so the blocks a column
2487  // tile's weights serve run together and read them once from memory.
2488  const int lin = blockIdx.x + blockIdx.y * gridDim.x;
2489  int m0 = (lin % gridDim.y) * BM, n0 = (lin / gridDim.y) * TW;
2490  // On a line of blocks: this block's tile, and the scale groups of its part of the tile (all of them for a whole tile).
2491  bool parted = DENSE && part && (int)blockIdx.x >= tail;
2492  if(DENSE && part){
2493    // The whole tiles are the first `tail` of the tiles row by row, and the cut ones the rest, as the block path cuts
2494    // them; the line takes the whole ones a column tile at a time — every column tile `rows` of them, the first `wide`
2495    // one more — so the blocks a column tile's weights serve run together.
2496    int b = blockIdx.x, nbx = (N + TW - 1) / TW, tile;
2497    if(b < tail){
2498      int rows = tail / nbx, wide = tail % nbx, c, r;
2499      if(b < (rows + 1) * wide){ c = b / (rows + 1); r = b % (rows + 1); }
2500      else { int e = b - (rows + 1) * wide; c = wide + e / rows; r = e % rows; }
2501      tile = r * nbx + c;
2502    } else tile = tail + (b - tail) / split;
2503    m0 = (tile / nbx) * BM; n0 = (tile % nbx) * TW;
2504  }
2505  if(G == 4){
2506    int p = 0;
2507    while(p < LK_PARTS - 1 && n0 >= parts.end[p]) ++p;
2508    int start = p ? parts.end[p - 1] : 0;
2509    w = parts.w[p]; y = lk_part_out(parts, p); bias = parts.bias[p]; yrow = parts.row[p]; ypitch = parts.pitch[p];
2510    N = parts.end[p] - start; n0 -= start;
2511  }
2512  long first = 0, wbase = 0;
2513  if(GROUPED){
2514    M = ecount[blockIdx.z];
2515    if(m0 >= M) return;
2516    first = eoff[blockIdx.z];
2517    wbase = (long)blockIdx.z * N;
2518    xq += first * K;
2519    if(Q == 2) xl += first * K;
2520    xs += first * (K >> 5);
2521  }
2522  const int tid = threadIdx.x, lane = tid & 31, warp = tid >> 5;
2523  const int nb = K >> 5;
2524  int g_lo = 0, g_hi = nb >> 2;
2525  if(parted){
2526    int piece = ((int)blockIdx.x - tail) % split, groups = nb >> 2;
2527    g_lo = piece * groups / split; g_hi = (piece + 1) * groups / split;
2528  }
2529  const int kb_lo = 4 * g_lo, n = 4 * (g_hi - g_lo);
2530  const unsigned base = (unsigned)__cvta_generic_to_shared(lk_sm);
2531  const unsigned full = base + RING + 2 * GROUP, empty = full + 8 * LK_STREAM_STAGES;
2532  if(tid == 0) for(int s = 0; s < LK_STREAM_STAGES; ++s){ lk_mbar_init(full + 8 * s, NT); lk_mbar_init(empty + 8 * s, NT / 32); }
2533  __syncthreads();
2534  // Each thread's copies, the same every stage: activation chunks, matrix chunks, and a row's scale group.
2535  constexpr int A_IT = (BM * 2 + NT - 1) / NT;
2536  const signed char* a_src[A_IT]; int a_dst[A_IT]; bool a_ok[A_IT], a_on[A_IT];
2537  #pragma unroll
2538  for(int it = 0; it < A_IT; ++it){
2539    int c = tid + it * NT, r = c >> 1, ch = c & 1;
2540    a_on[it] = c < BM * 2;
2541    a_ok[it] = a_on[it] && m0 + r < M;
2542    a_src[it] = xq + (long)(a_ok[it] ? m0 + r : 0) * K + ch * 16;
2543    a_dst[it] = lk_q8_swz(r, ch);
2544  }
2545  const long a_lo = Q == 2 ? (long)(xl - xq) : 0;
2546  // Two threads a matrix row: 256 copy the tile's rows, any beyond them none.
2547  const int w_r = tid >> 1, w_ch = tid & 1, w_row = lk_q8_row<PAIR>(w_r);
2548  const bool w_on = tid < 2 * LK_BN, w_up = PAIR && (w_r & 31) >= 16, w_ok = w_on && n0 + w_row < N;
2549  const signed char* w_src = (w_up ? w2.q : w.q) + (w_ok ? wbase + n0 + w_row : 0) * (long)K + w_ch * 16;
2550  const int w_dst = AW * A_BYTES + lk_q8_swz(w_r, w_ch);
2551  // Scale groups: threads below `BM` copy their activation row's four scales (16 bytes), the next 128 their matrix row's
2552  // four (8 bytes).
2553  const bool sa_on = tid < BM, s_on = tid < BM + LK_BN;
2554  const int s_r = sa_on ? tid : tid - BM, s_row = sa_on ? s_r : lk_q8_row<PAIR>(s_r);
2555  const bool s_up = PAIR && !sa_on && (s_r & 31) >= 16;
2556  const bool s_ok = s_on && (sa_on ? m0 + s_r < M : n0 + s_row < N);
2557  const char* s_src = sa_on ? (const char*)(xs + (long)(s_ok ? m0 + s_r : 0) * nb)
2558                            : (const char*)((s_up ? w2.s : w.s) + (s_ok ? wbase + n0 + s_row : 0) * (long)nb);
2559  const int s_step = sa_on ? 4 : 2, s_dst = sa_on ? s_r * 16 : BM * 16 + s_r * 8;
2560  // Stage `i` into buffer `b` (`i`'s place in the ring), and with it scale group `i / 4` when `i` starts one.
2561  auto load = [&](int i, int b, bool group){
2562    const int kb = kb_lo + i;
2563    const unsigned st = base + b * STAGE;
2564    #pragma unroll
2565    for(int it = 0; it < A_IT; ++it){
2566      if(!a_on[it]) continue;
2567      lk_cp16s(st + a_dst[it], a_src[it] + kb * 32, a_ok[it]);
2568      if(Q == 2) lk_cp16s(st + A_BYTES + a_dst[it], a_src[it] + a_lo + kb * 32, a_ok[it]);
2569    }
2570    if(w_on) lk_cp16s(st + w_dst, w_src + kb * 32, w_ok);
2571    if(group && s_on){
2572      const unsigned sg = base + RING + ((kb >> 2) & 1) * GROUP + s_dst;
2573      if(sa_on) lk_cp16s(sg, s_src + kb * s_step, s_ok);
2574      else lk_cp8s(sg, s_src + kb * s_step, s_ok);
2575    }
2576    lk_mbar_copies(full + 8 * b);
2577  };
2578  const int wm = (warp >> 2) * WM, wn = (warp & 3) * 32;
2579  const int g = lane >> 2, t4 = lane & 3;
2580  float acc[MT][4][4];
2581  #pragma unroll
2582  for(int i = 0; i < MT; ++i)
2583    #pragma unroll
2584    for(int j = 0; j < 4; ++j)
2585      #pragma unroll
2586      for(int e = 0; e < 4; ++e) acc[i][j][e] = 0.f;
2587  // This lane's `ldmatrix` rows: the activation's 16 by its chunk, and the matrix's for two n-tiles at a time.
2588  const int a_row = wm + (lane & 15), a_ch = lane >> 4;
2589  const int b_row = wn + (lane >> 4) * 8 + (lane & 7), b_ch = (lane >> 3) & 1;
2590  const bool live = m0 + wm < M;
2591  // The stages run four at a time, a scale group each, so every stage's buffer, barrier phase and scale stage is fixed.
2592  if(n > 0){
2593    #pragma unroll
2594    for(int i = 0; i < LK_STREAM_STAGES - 1; ++i) load(i, i, i == 0);
2595  }
2596  for(int q = 0; q < n / 4; ++q){
2597    const unsigned char* ring = lk_sm + RING + ((g_lo + q) & 1) * GROUP;
2598    const float* sa = (const float*)ring;
2599    const __half* sw = (const __half*)(ring + BM * 16);
2600    #pragma unroll
2601    for(int j = 0; j < 4; ++j){
2602      const int i = 4 * q + j;
2603      lk_mbar_wait(full + 8 * j, q & 1);
2604      const unsigned st = base + j * STAGE;
2605      // A warp whose rows all lie past the tile's last row leaves the multiply to the others.
2606      if(live){
2607        int bf[4][2];
2608        #pragma unroll
2609        for(int p = 0; p < 2; ++p){
2610          int r4[4];
2611          lk_ldsm_s(r4, st + AW * A_BYTES + lk_q8_swz(b_row + p * 16, b_ch));
2612          bf[2 * p][0] = r4[0]; bf[2 * p][1] = r4[1]; bf[2 * p + 1][0] = r4[2]; bf[2 * p + 1][1] = r4[3];
2613        }
2614        float dcol[4][2];
2615        #pragma unroll
2616        for(int nt = 0; nt < 4; ++nt)
2617          #pragma unroll
2618          for(int cc = 0; cc < 2; ++cc) dcol[nt][cc] = __half2float(sw[(wn + nt * 8 + t4 * 2 + cc) * 4 + j]);
2619        #pragma unroll
2620        for(int mt = 0; mt < MT; ++mt){
2621          int af[4], al[4];
2622          lk_ldsm_s(af, st + lk_q8_swz(a_row + mt * 16, a_ch));
2623          if(Q == 2) lk_ldsm_s(al, st + A_BYTES + lk_q8_swz(a_row + mt * 16, a_ch));
2624          const float sa0 = sa[(wm + mt * 16 + g) * 4 + j], sa1 = sa[(wm + mt * 16 + g + 8) * 4 + j];
2625          #pragma unroll
2626          for(int nt = 0; nt < 4; ++nt){
2627            int dot[4], dl[4];
2628            lk_mma_s8_from(dot, af, bf[nt], LK_DOT0);
2629            if(Q == 2) lk_mma_s8_from(dl, al, bf[nt], LK_DOT0);
2630            #pragma unroll
2631            for(int e = 0; e < 4; ++e){
2632              const float s0 = e < 2 ? sa0 : sa1;
2633              acc[mt][nt][e] = Q == 2 ? fmaf(s0 * 0.0078125f * dcol[nt][e & 1], fmaf(lk_dot_f(dot[e]), 128.f, lk_dot_f(dl[e])), acc[mt][nt][e])
2634                                      : fmaf(s0 * dcol[nt][e & 1], lk_dot_f(dot[e]), acc[mt][nt][e]);
2635            }
2636          }
2637        }
2638      }
2639      __syncwarp();
2640      if(lane == 0) lk_mbar_arrive(empty + 8 * j);
2641      // The buffer the stage before this one read takes the stage three ahead, once every warp is past it; the stage
2642      // three ahead starts a scale group when this one is a group's second.
2643      if(i + LK_STREAM_STAGES - 1 < n){
2644        if(i >= 1) lk_mbar_wait(empty + 8 * ((j + 3) & 3), j == 0 ? (q - 1) & 1 : q & 1);
2645        load(i + LK_STREAM_STAGES - 1, (j + 3) & 3, j == 1);
2646      }
2647    }
2648  }
2649  asm volatile("cp.async.wait_all;\n" ::: "memory");
2650  __syncthreads();
2651  if(parted){
2652    // A part parks its sums; the tile's last part to arrive sums every part in order, its own read back too.
2653    __shared__ bool lk_last;
2654    int tile = tail + ((int)blockIdx.x - tail) / split;
2655    float4* mine = (float4*)(part + ((long)(blockIdx.x - tail) * NT + tid) * (MT * 16));
2656    #pragma unroll
2657    for(int mt = 0; mt < MT; ++mt)
2658      #pragma unroll
2659      for(int nt = 0; nt < 4; ++nt) mine[mt * 4 + nt] = make_float4(acc[mt][nt][0], acc[mt][nt][1], acc[mt][nt][2], acc[mt][nt][3]);
2660    __threadfence();
2661    __syncthreads();
2662    if(tid == 0) lk_last = atomicAdd(cnt + (tile - tail), 1) == split - 1;
2663    __syncthreads();
2664    if(!lk_last) return;
2665    #pragma unroll
2666    for(int mt = 0; mt < MT; ++mt)
2667      #pragma unroll
2668      for(int nt = 0; nt < 4; ++nt)
2669        #pragma unroll
2670        for(int e = 0; e < 4; ++e) acc[mt][nt][e] = 0.f;
2671    for(int pc = 0; pc < split; ++pc){
2672      const float4* src = (const float4*)(part + ((long)((tile - tail) * split + pc) * NT + tid) * (MT * 16));
2673      #pragma unroll
2674      for(int mt = 0; mt < MT; ++mt)
2675        #pragma unroll
2676        for(int nt = 0; nt < 4; ++nt){
2677          float4 v = __ldcg(src + mt * 4 + nt);
2678          acc[mt][nt][0] += v.x; acc[mt][nt][1] += v.y; acc[mt][nt][2] += v.z; acc[mt][nt][3] += v.w;
2679        }
2680    }
2681    if(tid == 0) cnt[tile - tail] = 0;
2682  }
2683  if(PAIR){
2684    // Each hidden value through the gated activation from its gate and up sums (plus their biases) in this thread,
2685    // staged by row, then quantized a 32-value block a warp at a time.
2686    float* H = (float*)lk_sm;
2687    #pragma unroll
2688    for(int mt = 0; mt < MT; ++mt)
2689      #pragma unroll
2690      for(int nt = 0; nt < 2; ++nt)
2691        #pragma unroll
2692        for(int e = 0; e < 4; ++e){
2693          int r = wm + mt * 16 + g + (e >= 2 ? 8 : 0), h = (wn >> 1) + nt * 8 + t4 * 2 + (e & 1), col = n0 + h;
2694          float gv = acc[mt][nt][e], uv = acc[mt][nt + 2][e];
2695          if(bias && col < N) gv = gv + bias[wbase + col];
2696          if(bias2 && col < N) uv = uv + bias2[wbase + col];
2697          float hv;
2698          if(G == 5) hv = ACT < 0 ? gv / (1.0f + expf(-gv)) * uv : uv * lk_act<(ACT < 0 ? 0 : ACT)>(gv);
2699          else if(ACT == 0) hv = gv / (1.0f + expf(-gv)) * uv;
2700          else { float gc = fminf(gv, limit); hv = gc / (1.0f + expf(-slope * gc)) * (fminf(fmaxf(uv, -limit), limit) + 1.0f); }
2701          H[r * TW + h] = hv;
2702        }
2703    __syncthreads();
2704    for(int r = warp; r < BM; r += NT / 32){
2705      if(m0 + r >= M) break;
2706      #pragma unroll
2707      for(int j = 0; j < TW / 32; ++j){
2708        int c = 32 * j + lane;
2709        if(n0 + 32 * j >= N) break;
2710        float hv = H[r * TW + c];
2711        long i = (first + m0 + r) * N + n0 + c;
2712        if(G == 5 && y) y[i] = hv;
2713        if(G == 3 || hq) lk_quant_lane<Q>(hv, hq, hl, hs, i, i >> 5);
2714      }
2715    }
2716    return;
2717  }
2718  lk_out yo = GROUPED ? y + first * N : LK_ROW(y, yrow, ypitch);
2719  #pragma unroll
2720  for(int mt = 0; mt < MT; ++mt)
2721    #pragma unroll
2722    for(int nt = 0; nt < 4; ++nt)
2723      #pragma unroll
2724      for(int e = 0; e < 4; ++e){
2725        int row = m0 + wm + mt * 16 + g + (e >= 2 ? 8 : 0);
2726        int col = n0 + wn + nt * 8 + t4 * 2 + (e & 1);
2727        if(row >= M || col >= N) continue;
2728        float v = bias ? acc[mt][nt][e] + bias[wbase + col] : acc[mt][nt][e];
2729        // G 2 weighs each choice's result by its weight, as the expert mixture's down projection does.
2730        yo[(long)row * N + col] = G == 2 ? v * wt[list[first + row]] : v;
2731      }
2732}
2733
2734template<int F, int Q, int G = 0, int BM = (G >= 1 && G <= 3 ? 64 : 128), int ACT = 0>
2735__global__ void __launch_bounds__(BM * 4, F == 8 && BM <= 64 ? 2 : 1) lk_gemm_blk(lk_w w, const signed char* __restrict__ xq,
2736    const signed char* __restrict__ xl, const float* __restrict__ xs, const float* __restrict__ bias, lk_out y,
2737    const int* __restrict__ yrow, long ypitch, int K, int N, int M, const int* __restrict__ ecount = nullptr,
2738    const int* __restrict__ eoff = nullptr, const int* __restrict__ list = nullptr, const float* __restrict__ wt = nullptr,
2739    lk_w w2 = {}, const float* __restrict__ bias2 = nullptr, signed char* __restrict__ hq = nullptr,
2740    signed char* __restrict__ hl = nullptr, float* __restrict__ hs = nullptr, float limit = 0.f, float slope = 0.f,
2741    int tail = 0, int split = 1, float* __restrict__ part = nullptr, int* __restrict__ cnt = nullptr, lk_parts parts = {}){
2742  extern __shared__ __align__(128) unsigned char lk_sm[];
2743  if constexpr(F == 8){
2744    if((K & 127) == 0){
2745      // Launched as eight warps over 128 rows, each warp takes 64 of them; otherwise 32.
2746      if constexpr(BM == 128){
2747        if(blockDim.x == 256){
2748          lk_blk_streamed<Q, G, BM, ACT, 64>(lk_sm, w, xq, xl, xs, bias, y, yrow, ypitch, K, N, M, ecount, eoff, list, wt, w2, bias2,
2749                                             hq, hl, hs, limit, slope, tail, split, part, cnt, parts);
2750          return;
2751        }
2752      }
2753      lk_blk_streamed<Q, G, BM, ACT, 32>(lk_sm, w, xq, xl, xs, bias, y, yrow, ypitch, K, N, M, ecount, eoff, list, wt, w2, bias2,
2754                                         hq, hl, hs, limit, slope, tail, split, part, cnt, parts);
2755      return;
2756    }
2757  }
2758  constexpr bool PAIR = G == 3 || G == 5, GROUPED = G >= 1 && G <= 3, DENSE = !GROUPED;
2759  constexpr int TW = PAIR ? LK_BN / 2 : LK_BN;
2760  constexpr int SB = 4, BK = 32 * SB, BP = BK + 16, AW = Q == 2 ? 2 : 1;
2761  constexpr int DH = lk_halves_apart<F>() ? 2 : 1, CH = lk_has_offset<F>() ? DH : 0;
2762  constexpr int A_BYTES = BM * BP;
2763  int m0 = blockIdx.y * BM, n0 = blockIdx.x * (PAIR ? LK_BN / 2 : LK_BN);
2764  // On a line of blocks: this block's tile, and the stages of its part of the tile (all of them for a whole tile).
2765  bool parted = DENSE && part && (int)blockIdx.x >= tail;
2766  if(DENSE && part){
2767    int b = blockIdx.x, nbx = (N + TW - 1) / TW, tile = b < tail ? b : tail + (b - tail) / split;
2768    m0 = (tile / nbx) * BM; n0 = (tile % nbx) * TW;
2769  }
2770  if(G == 4){
2771    // The part whose columns hold the tile: its matrix, outputs and bias, the tile's columns its own.
2772    int p = 0;
2773    while(p < LK_PARTS - 1 && n0 >= parts.end[p]) ++p;
2774    int start = p ? parts.end[p - 1] : 0;
2775    w = parts.w[p]; y = lk_part_out(parts, p); bias = parts.bias[p]; yrow = parts.row[p]; ypitch = parts.pitch[p];
2776    N = parts.end[p] - start; n0 -= start;
2777  }
2778  long first = 0, wbase = 0;
2779  if(GROUPED){
2780    // Grid layer `z` is an expert: its rows the gathered rows of its choices, its matrix rows `z·N …` of the stack.
2781    M = ecount[blockIdx.z];
2782    if(m0 >= M) return;
2783    first = eoff[blockIdx.z];
2784    wbase = (long)blockIdx.z * N;
2785    xq += first * K;
2786    if(Q == 2) xl += first * K;
2787    xs += first * (K >> 5);
2788  }
2789  int tid = threadIdx.x, lane = tid & 31, warp = tid >> 5;
2790  int nb = K >> 5, stages = (K + BK - 1) / BK;
2791  int s_lo = 0, s_hi = stages;
2792  if(parted){
2793    int piece = ((int)blockIdx.x - tail) % split;
2794    s_lo = piece * stages / split; s_hi = (piece + 1) * stages / split;
2795  }
2796  // Each warp multiplies 32 × 32 of the tile.
2797  int wm = (warp >> 2) * 32, wn = (warp & 3) * 32;
2798  int g = lane >> 2, t4 = lane & 3;
2799  float acc[2][4][4];
2800  #pragma unroll
2801  for(int i = 0; i < 2; ++i)
2802    #pragma unroll
2803    for(int j = 0; j < 4; ++j)
2804      #pragma unroll
2805      for(int e = 0; e < 4; ++e) acc[i][j][e] = 0.f;
2806  constexpr bool PIPE = lk_stage_pipelined<F, Q, BM>();
2807  constexpr int ACTS = lk_stage_acts<Q, BM>();
2808  unsigned char* Bs = lk_sm + (PIPE ? 2 : 1) * ACTS;
2809  float* Bd = (float*)(Bs + LK_BN * BP);
2810  float* Bc = Bd + LK_BN * SB * DH;
2811  short* Xs = (short*)(Bc + LK_BN * SB * CH);
2812  // Stage `st`'s activation rows into buffer `b` by `cp.async`, and each row's scales: one 16-byte copy when the
2813  // stage is whole and the row's scales fall on 16 bytes.
2814  auto acts = [&](int st, int b){
2815    int k0 = st * BK;
2816    unsigned char* As = lk_sm + b * ACTS;
2817    float* Sa = (float*)(As + AW * A_BYTES);
2818    for(int c = tid; c < BM * SB * 2; c += (BM * 4)){
2819      int r = c / (SB * 2), h = c % (SB * 2);
2820      bool ok = m0 + r < M && k0 + h * 16 < K;
2821      long off = ok ? (long)(m0 + r) * K + k0 + h * 16 : 0;
2822      lk_cp16(As + r * BP + h * 16, xq + off, ok);
2823      if(Q == 2) lk_cp16(As + A_BYTES + r * BP + h * 16, xl + off, ok);
2824      if(h == 0){
2825        long base = (long)(m0 + r) * nb + (k0 >> 5);
2826        if((nb & 3) == 0 && m0 + r < M && (k0 >> 5) + SB <= nb) lk_cp16(Sa + r * SB, xs + base, true);
2827        else for(int j = 0; j < SB; ++j) Sa[r * SB + j] = m0 + r < M && (k0 >> 5) + j < nb ? xs[base + j] : 0.f;
2828      }
2829    }
2830    asm volatile("cp.async.commit_group;\n");
2831  };
2832  // Each thread's sub-blocks of a stage, their raw words fetched a stage ahead.
2833  constexpr int U = LK_BN * SB / (BM * 4);
2834  lk_raw<F> raw[U];
2835  lk_stage_fetch<F, SB, BM * 4, U, PAIR>(raw, w, w2, wbase, n0, N, K, nb, s_lo * BK, tid);
2836  // The first stage lands in the buffer its parity names, so each stage's buffer is `st & 1` wherever the part starts.
2837  acts(s_lo, PIPE ? s_lo & 1 : 0);
2838  for(int st = s_lo; st < s_hi; ++st){
2839    int k0 = st * BK, b = PIPE ? st & 1 : 0;
2840    const unsigned char* As = lk_sm + b * ACTS;
2841    const float* Sa = (const float*)(As + AW * A_BYTES);
2842    lk_stage_weights<F, SB, BP, DH, CH, BM * 4, U, PAIR>(raw, n0, N, nb, k0, Bs, Bd, Bc, tid);
2843    // The next stage's weights are fetched while this one multiplies.
2844    if(st + 1 < s_hi) lk_stage_fetch<F, SB, BM * 4, U, PAIR>(raw, w, w2, wbase, n0, N, K, nb, k0 + BK, tid);
2845    asm volatile("cp.async.wait_group 0;\n");
2846    __syncthreads();
2847    // The activation's sums over each half of each sub-block, for the offsets.
2848    if(lk_has_offset<F>()) for(int c = tid; c < AW * BM * SB * 2; c += (BM * 4)){
2849      int u = c / (BM * SB * 2), r = (c / (SB * 2)) % BM, h = c % (SB * 2);
2850      const int* a = (const int*)(As + u * A_BYTES + r * BP + h * 16);
2851      int sum = 0;
2852      #pragma unroll
2853      for(int i = 0; i < 4; ++i) sum = __dp4a(0x01010101, a[i], sum);
2854      Xs[(u * BM + r) * SB * 2 + h] = (short)sum;
2855    }
2856    __syncthreads();
2857    // The next stage's activations land in the other buffer while this one multiplies.
2858    if(PIPE && st + 1 < s_hi) acts(st + 1, b ^ 1);
2859    // A warp whose 32 rows all lie past the tile's last row (an expert with few rows) leaves the multiply to the others.
2860    #pragma unroll 1
2861    for(int sb = 0; sb < SB && m0 + wm < M; ++sb){
2862      if((k0 >> 5) + sb >= nb) break;
2863      int ko = sb * 32 + t4 * 4;
2864      int af[2][4], al[2][4], bf[4][2];
2865      // This lane's columns' scales and offsets (two columns an n-tile, a value a half where the halves scale apart),
2866      // and its rows' scales and their sums scaled by them (the low words' at a 128th), read once a sub-block.
2867      constexpr int OH = CH ? CH : 1;
2868      float dcol[4][2][DH], ocol[4][2][OH], sa[2][2], sx[2][2][DH], sxl[2][2][DH];
2869      #pragma unroll
2870      for(int nt = 0; nt < 4; ++nt)
2871        #pragma unroll
2872        for(int cc = 0; cc < 2; ++cc){
2873          int c = wn + nt * 8 + t4 * 2 + cc;
2874          #pragma unroll
2875          for(int h = 0; h < DH; ++h){
2876            dcol[nt][cc][h] = Bd[(c * SB + sb) * DH + h];
2877            if(CH) ocol[nt][cc][h] = Bc[(c * SB + sb) * CH + h];
2878          }
2879        }
2880      #pragma unroll
2881      for(int mt = 0; mt < 2; ++mt)
2882        #pragma unroll
2883        for(int hh = 0; hh < 2; ++hh){
2884          int r = wm + mt * 16 + g + hh * 8;
2885          float s0 = Sa[r * SB + sb];
2886          sa[mt][hh] = s0;
2887          if(lk_has_offset<F>()){
2888            const short* x = Xs + r * SB * 2 + sb * 2;
2889            if(DH == 2){ sx[mt][hh][0] = s0 * (float)x[0]; sx[mt][hh][DH - 1] = s0 * (float)x[1]; }
2890            else sx[mt][hh][0] = s0 * (float)(x[0] + x[1]);
2891            if(Q == 2){
2892              const short* l = Xs + (BM + r) * SB * 2 + sb * 2;
2893              float sl = s0 * 0.0078125f;
2894              if(DH == 2){ sxl[mt][hh][0] = sl * (float)l[0]; sxl[mt][hh][DH - 1] = sl * (float)l[1]; }
2895              else sxl[mt][hh][0] = sl * (float)(l[0] + l[1]);
2896            }
2897          }
2898        }
2899      #pragma unroll
2900      for(int mt = 0; mt < 2; ++mt){
2901        int r = wm + mt * 16 + g;
2902        af[mt][0] = *(const int*)(As + r * BP + ko);
2903        af[mt][1] = *(const int*)(As + (r + 8) * BP + ko);
2904        af[mt][2] = *(const int*)(As + r * BP + ko + 16);
2905        af[mt][3] = *(const int*)(As + (r + 8) * BP + ko + 16);
2906        if(Q == 2){
2907          al[mt][0] = *(const int*)(As + A_BYTES + r * BP + ko);
2908          al[mt][1] = *(const int*)(As + A_BYTES + (r + 8) * BP + ko);
2909          al[mt][2] = *(const int*)(As + A_BYTES + r * BP + ko + 16);
2910          al[mt][3] = *(const int*)(As + A_BYTES + (r + 8) * BP + ko + 16);
2911        }
2912      }
2913      #pragma unroll
2914      for(int nt = 0; nt < 4; ++nt){
2915        int c = wn + nt * 8 + g;
2916        bf[nt][0] = *(const int*)(Bs + c * BP + ko);
2917        bf[nt][1] = *(const int*)(Bs + c * BP + ko + 16);
2918      }
2919      #pragma unroll
2920      for(int mt = 0; mt < 2; ++mt)
2921        #pragma unroll
2922        for(int nt = 0; nt < 4; ++nt){
2923          // The accumulator's elements: rows g, g + 8 of the m-tile by columns 2·t4, 2·t4 + 1 of the n-tile.
2924          int dot[2][4], dl[2][4];
2925          #pragma unroll
2926          for(int h = 0; h < 2; ++h)
2927            #pragma unroll
2928            for(int e = 0; e < 4; ++e){ dot[h][e] = LK_DOT0; dl[h][e] = LK_DOT0; }
2929          if(lk_halves_apart<F>()){
2930            int a0[2] = {af[mt][0], af[mt][1]}, a1[2] = {af[mt][2], af[mt][3]};
2931            lk_mma_s8_k16(dot[0], a0, bf[nt][0]);
2932            lk_mma_s8_k16(dot[1], a1, bf[nt][1]);
2933            if(Q == 2){
2934              int l0[2] = {al[mt][0], al[mt][1]}, l1[2] = {al[mt][2], al[mt][3]};
2935              lk_mma_s8_k16(dl[0], l0, bf[nt][0]);
2936              lk_mma_s8_k16(dl[1], l1, bf[nt][1]);
2937            }
2938          } else {
2939            lk_mma_s8(dot[0], af[mt], bf[nt]);
2940            if(Q == 2) lk_mma_s8(dl[0], al[mt], bf[nt]);
2941          }
2942          #pragma unroll
2943          for(int e = 0; e < 4; ++e){
2944            int hh = e >> 1, cc = e & 1;
2945            float s0 = sa[mt][hh], a = acc[mt][nt][e];
2946            if constexpr(F == 8 && Q == 2){
2947              acc[mt][nt][e] = fmaf(s0 * 0.0078125f * dcol[nt][cc][0], fmaf(lk_dot_f(dot[0][e]), 128.f, lk_dot_f(dl[0][e])), a);
2948              continue;
2949            }
2950            #pragma unroll
2951            for(int h = 0; h < DH; ++h) a = fmaf(s0 * dcol[nt][cc][h], lk_dot_f(dot[h][e]), a);
2952            if(lk_has_offset<F>())
2953              #pragma unroll
2954              for(int h = 0; h < DH; ++h) a = fmaf(ocol[nt][cc][h], sx[mt][hh][h], a);
2955            if(Q == 2){
2956              float sl = s0 * 0.0078125f;
2957              #pragma unroll
2958              for(int h = 0; h < DH; ++h) a = fmaf(sl * dcol[nt][cc][h], lk_dot_f(dl[h][e]), a);
2959              if(lk_has_offset<F>())
2960                #pragma unroll
2961                for(int h = 0; h < DH; ++h) a = fmaf(ocol[nt][cc][h], sxl[mt][hh][h], a);
2962            }
2963            acc[mt][nt][e] = a;
2964          }
2965        }
2966    }
2967    __syncthreads();
2968    if(!PIPE && st + 1 < s_hi) acts(st + 1, 0);
2969  }
2970  if(parted){
2971    // A part parks its sums; the tile's last part to arrive sums every part in order, its own read back too.
2972    __shared__ bool lk_last;
2973    int tile = tail + ((int)blockIdx.x - tail) / split;
2974    float4* mine = (float4*)(part + ((long)(blockIdx.x - tail) * (BM * 4) + tid) * 32);
2975    #pragma unroll
2976    for(int mt = 0; mt < 2; ++mt)
2977      #pragma unroll
2978      for(int nt = 0; nt < 4; ++nt) mine[mt * 4 + nt] = make_float4(acc[mt][nt][0], acc[mt][nt][1], acc[mt][nt][2], acc[mt][nt][3]);
2979    __threadfence();
2980    __syncthreads();
2981    if(tid == 0) lk_last = atomicAdd(cnt + (tile - tail), 1) == split - 1;
2982    __syncthreads();
2983    if(!lk_last) return;
2984    #pragma unroll
2985    for(int mt = 0; mt < 2; ++mt)
2986      #pragma unroll
2987      for(int nt = 0; nt < 4; ++nt)
2988        #pragma unroll
2989        for(int e = 0; e < 4; ++e) acc[mt][nt][e] = 0.f;
2990    for(int pc = 0; pc < split; ++pc){
2991      const float4* src = (const float4*)(part + ((long)((tile - tail) * split + pc) * (BM * 4) + tid) * 32);
2992      #pragma unroll
2993      for(int mt = 0; mt < 2; ++mt)
2994        #pragma unroll
2995        for(int nt = 0; nt < 4; ++nt){
2996          float4 v = __ldcg(src + mt * 4 + nt);
2997          acc[mt][nt][0] += v.x; acc[mt][nt][1] += v.y; acc[mt][nt][2] += v.z; acc[mt][nt][3] += v.w;
2998        }
2999    }
3000    if(tid == 0) cnt[tile - tail] = 0;
3001  }
3002  if(PAIR){
3003    // Each hidden value's gate and up sums (plus their biases) staged by column, then through the gated activation
3004    // and quantized a 32-value block a warp at a time.
3005    float* E = (float*)lk_sm;
3006    #pragma unroll
3007    for(int mt = 0; mt < 2; ++mt)
3008      #pragma unroll
3009      for(int nt = 0; nt < 4; ++nt)
3010        #pragma unroll
3011        for(int e = 0; e < 4; ++e){
3012          int r = wm + mt * 16 + g + (e >= 2 ? 8 : 0), c = wn + nt * 8 + t4 * 2 + (e & 1), col = n0 + lk_tile_row<true>(c);
3013          const float* b = c < LK_BN / 2 ? bias : bias2;
3014          float v = acc[mt][nt][e];
3015          E[r * LK_BN + c] = b && col < N ? v + b[wbase + col] : v;
3016        }
3017    __syncthreads();
3018    for(int r = warp; r < BM; r += BM / 8){
3019      if(m0 + r >= M) break;
3020      #pragma unroll
3021      for(int j = 0; j < LK_BN / 64; ++j){
3022        int c = 32 * j + lane;
3023        if(n0 + 32 * j >= N) break;
3024        float gv = E[r * LK_BN + c], uv = E[r * LK_BN + LK_BN / 2 + c], hv;
3025        if(G == 5) hv = ACT < 0 ? gv / (1.0f + expf(-gv)) * uv : uv * lk_act<(ACT < 0 ? 0 : ACT)>(gv);
3026        else if(ACT == 0) hv = gv / (1.0f + expf(-gv)) * uv;
3027        else { float gc = fminf(gv, limit); hv = gc / (1.0f + expf(-slope * gc)) * (fminf(fmaxf(uv, -limit), limit) + 1.0f); }
3028        long i = (first + m0 + r) * N + n0 + c;
3029        if(G == 5 && y) y[i] = hv;
3030        if(G == 3 || hq) lk_quant_lane<Q>(hv, hq, hl, hs, i, i >> 5);
3031      }
3032    }
3033    return;
3034  }
3035  lk_out yo = GROUPED ? y + first * N : LK_ROW(y, yrow, ypitch);
3036  #pragma unroll
3037  for(int mt = 0; mt < 2; ++mt)
3038    #pragma unroll
3039    for(int nt = 0; nt < 4; ++nt)
3040      #pragma unroll
3041      for(int e = 0; e < 4; ++e){
3042        int row = m0 + wm + mt * 16 + g + (e >= 2 ? 8 : 0);
3043        int col = n0 + wn + nt * 8 + t4 * 2 + (e & 1);
3044        if(row >= M || col >= N) continue;
3045        float v = bias ? acc[mt][nt][e] + bias[wbase + col] : acc[mt][nt][e];
3046        // G 2 weighs each choice's result by its weight, as the expert mixture's down projection does.
3047        yo[(long)row * N + col] = G == 2 ? v * wt[list[first + row]] : v;
3048      }
3049}
3050"#;
3051
3052/// The dynamic shared memory a block-format tensor-core GEMM block in format `f` (its GGUF type id) over `bm` activation
3053/// rows may take, whichever path a launch takes ([`gemm_blk_launch_smem`] over every `k`): what its kernel is allowed.
3054pub fn gemm_blk_smem_bytes(f: u32, two_pass: bool, bm: usize) -> usize {
3055    let block = gemm_blk_block_bytes(f, two_pass, bm);
3056    if f == 8 {
3057        block.max(gemm_blk_stream_bytes(two_pass, bm))
3058    } else {
3059        block
3060    }
3061}
3062
3063/// The dynamic shared memory one launch of the block-format tensor-core GEMM over `k` takes: a Q8_0 matrix's streamed
3064/// path over a `k` of whole 128-value scale groups, the block path otherwise — so the streamed path's blocks are not
3065/// held to the block path's larger stages, and two of them share a multiprocessor where its registers allow.
3066pub fn gemm_blk_launch_smem(f: u32, two_pass: bool, bm: usize, k: usize) -> usize {
3067    if f == 8 && k % 128 == 0 {
3068        gemm_blk_stream_bytes(two_pass, bm)
3069    } else {
3070        gemm_blk_block_bytes(f, two_pass, bm)
3071    }
3072}
3073
3074/// The block path's shared memory over `bm` activation rows in format `f`: its activation tile (twice under two words)
3075/// and each row's scales — two of them where they fit — its decoded weight tile, each weight sub-block's scales (both
3076/// halves where they scale apart) and offsets, and the activation's 16-bit half sums (where the format has offsets), as
3077/// `lk_stage_acts` and `lk_stage_rest` lay them out — and at least the paired epilogue's gate and up sums, a float for
3078/// each of the tile's outputs.
3079fn gemm_blk_block_bytes(f: u32, two_pass: bool, bm: usize) -> usize {
3080    let n = GEMM_TILE_N;
3081    let words = if two_pass { 2 } else { 1 };
3082    let halves = if matches!(f, 10 | 11 | 14) { 2 } else { 1 };
3083    let offset = matches!(f, 3 | 7 | 10 | 12 | 13);
3084    let acts = words * bm * 144 + bm * 4 * 4;
3085    let rest = n * 144
3086        + n * 4 * halves * 4
3087        + if offset { n * 4 * halves * 4 } else { 0 }
3088        + if offset { words * bm * 4 * 2 * 2 } else { 0 };
3089    // Two activation buffers where they fit in a block's 99 KB (`lk_stage_pipelined`).
3090    let stages = if 2 * acts + rest <= 101_376 { 2 * acts + rest } else { acts + rest };
3091    stages.max(bm * n * 4)
3092}
3093
3094/// A Q8_0 matrix's streamed path's shared memory over `bm` activation rows: its `STREAM_STAGES` stages (the activation's
3095/// words, twice under two words, and the matrix's levels, 32 of `k` a row), the two scale groups it holds (four stages'
3096/// scales of each activation row and each matrix row) and its stages' two barriers each — and at least the paired
3097/// epilogue's hidden values, a float for each of the pair tile's `bm` × 64.
3098fn gemm_blk_stream_bytes(two_pass: bool, bm: usize) -> usize {
3099    let n = GEMM_TILE_N;
3100    let words = if two_pass { 2 } else { 1 };
3101    (STREAM_STAGES * (words * bm * 32 + n * 32) + 2 * (bm * 16 + n * 8) + 2 * STREAM_STAGES * 8).max(bm * n / 2 * 4)
3102}
3103
3104/// The stages of `k`, 32 each, a Q8_0 matrix's streamed path keeps in flight (`LK_STREAM_STAGES`).
3105const STREAM_STAGES: usize = 4;
3106
3107/// The activation rows of a grouped GEMM block over an expert mixture's choices: 128 when the average expert has more
3108/// than 64 rows to multiply (`choices / experts`), 64 otherwise — a taller tile reads each expert's decoded weights for
3109/// more rows, a shorter one leaves fewer of its rows empty.
3110pub fn gemm_blk_expert_rows(choices: usize, experts: usize) -> usize {
3111    if choices > 64 * experts {
3112        128
3113    } else {
3114        64
3115    }
3116}
3117
3118/// The parts an `f32` router GEMM (`lk_gemm_f32`) of `tiles` 64 × 64 tiles cuts each tile's `chunks` runs of 32 `k`
3119/// into: as many as give the chip's `sms` two blocks each, whole runs of chunks every one.
3120pub fn gemm_f32_splits(tiles: usize, sms: usize, chunks: usize) -> usize {
3121    (2 * sms / tiles.max(1)).clamp(1, chunks.max(1))
3122}
3123
3124/// How a dense block GEMM of `tiles` tiles and `stages` stages of `k` fills its last wave of `workers` blocks:
3125/// `(whole, split)` — the first `whole` tiles a block each, every later tile cut into `split` parts of its stages, as
3126/// many as fill the wave. `split` 1 when the tiles fill whole waves, or a wave's blocks cannot cut a remaining tile in
3127/// two.
3128pub fn gemm_blk_tail(tiles: usize, workers: usize, stages: usize) -> (usize, usize) {
3129    let rest = tiles % workers;
3130    let split = if rest == 0 { 1 } else { (workers / rest).min(stages) };
3131    if split < 2 {
3132        (tiles, 1)
3133    } else {
3134        (tiles - rest, split)
3135    }
3136}
3137
3138/// The threads of a block-format tensor-core GEMM block over `bm` activation rows: a warp each 32 × 32 of the tile.
3139pub fn gemm_blk_threads(bm: usize) -> usize {
3140    bm * 4
3141}
3142
3143/// The threads one launch of the block-format tensor-core GEMM over `k` takes: a Q8_0 matrix's streamed path over 128
3144/// rows, eight warps of 64 rows by 32 outputs — two blocks of them, their registers and stages, share a multiprocessor —
3145/// and a warp each 32 × 32 of the tile otherwise ([`gemm_blk_threads`]).
3146pub fn gemm_blk_launch_threads(f: u32, bm: usize, k: usize) -> usize {
3147    if f == 8 && k % 128 == 0 && bm == GEMM_BLK_TILE_M {
3148        256
3149    } else {
3150        gemm_blk_threads(bm)
3151    }
3152}
3153
3154/// The activation rows of a dense block-format tensor-core GEMM block's tile (its outputs: `GEMM_TILE_N`).
3155pub const GEMM_BLK_TILE_M: usize = 128;
3156
3157/// The activation rows a dense tensor-core GEMM of a matrix in format `f` (its GGUF type id) takes a block: 64 for a
3158/// Q8_0 matrix under two words, so two blocks of its streamed path, both words of each stage, share a multiprocessor;
3159/// `GEMM_BLK_TILE_M` otherwise.
3160pub fn gemm_blk_rows(f: u32, two_pass: bool) -> usize {
3161    if f == 8 && two_pass {
3162        64
3163    } else {
3164        GEMM_BLK_TILE_M
3165    }
3166}
3167
3168/// The matrices a launch in parts (`lk_parts`: `lk_gemv_parts`, `lk_gemv_mma`, `lk_gemm_blk`'s `G` 4) multiplies one
3169/// activation by at most — the kernels' `LK_PARTS`: six, so a recurrent layer's query, key, value, output gate and two
3170/// gates project its activation in one launch, the gates no launch of their own (at Qwen3.5-0.8B's batch of 64 a
3171/// single block on the 3060, 16.8 µs a layer).
3172pub const GEMM_PARTS: usize = 6;
3173
3174/// The rows of a tiled per-head matmul block (`lk_head_tiled`), each block 64 of a head's outputs.
3175pub const HEAD_TILE_M: usize = 128;
3176
3177/// The outputs a block of the tensor-core block GEMM computes (`lk_gemm_blk`'s tile).
3178pub const GEMM_TILE_N: usize = 128;
3179
3180/// `Y[t,o] = Σ_k X[t,k]·W[o,k]` for the `M` rows of `X` over an `f32` matrix stored a row per output, `f64`
3181/// accumulation: `parts` warps an output row (`gemv_f32_parts`), each summing one run of `k` a lane at a time, the runs'
3182/// sums added in order — a block of eight warps `8 / parts` output rows. A block takes its rows `LK_F32_ROWS` at a time,
3183/// each weight value read once for all of them, every row summed as a row alone sums.
3184const GEMV_F32: &str = r#"
3185#define LK_F32_ROWS 4
3186__global__ void __launch_bounds__(256) lk_gemv_f32(const float* __restrict__ w, const float* __restrict__ x,
3187    const float* __restrict__ bias, lk_out y, const int* __restrict__ yrow, long ypitch, int K, int N, int M,
3188    int parts = 1){
3189  __shared__ double run[LK_F32_ROWS][8];
3190  int warp = threadIdx.x >> 5, lane = threadIdx.x & 31;
3191  int o = blockIdx.x * (8 / parts) + warp / parts, p = warp % parts;
3192  bool live = o < N;
3193  int span = (K + parts - 1) / parts, k0 = p * span, k1 = min(K, k0 + span);
3194  const float* wr = w + (long)(live ? o : 0) * K;
3195  lk_out yo = LK_ROW(y, yrow, ypitch);
3196  int rb = (M + gridDim.y - 1) / gridDim.y, t1 = min(M, (int)(blockIdx.y + 1) * rb);
3197  for(int t0 = blockIdx.y * rb; t0 < t1; t0 += LK_F32_ROWS){
3198    double acc[LK_F32_ROWS];
3199    #pragma unroll
3200    for(int r = 0; r < LK_F32_ROWS; ++r) acc[r] = 0.0;
3201    if(live)
3202      for(int k = k0 + lane; k < k1; k += 32){
3203        const double wv = (double)wr[k];
3204        #pragma unroll
3205        for(int r = 0; r < LK_F32_ROWS; ++r) if(t0 + r < t1) acc[r] += wv * (double)x[(long)(t0 + r) * K + k];
3206      }
3207    #pragma unroll
3208    for(int r = 0; r < LK_F32_ROWS; ++r) acc[r] = lk_warp_sum_d(acc[r]);
3209    if(parts == 1){
3210      #pragma unroll
3211      for(int r = 0; r < LK_F32_ROWS; ++r)
3212        if(live && lane == 0 && t0 + r < t1) yo[(long)(t0 + r) * N + o] = bias ? (float)acc[r] + bias[o] : (float)acc[r];
3213      continue;
3214    }
3215    if(lane == 0)
3216      #pragma unroll
3217      for(int r = 0; r < LK_F32_ROWS; ++r) run[r][warp] = acc[r];
3218    __syncthreads();
3219    if(live && p == 0 && lane == 0)
3220      #pragma unroll
3221      for(int r = 0; r < LK_F32_ROWS; ++r)
3222        if(t0 + r < t1){
3223          double s = 0.0;
3224          for(int i = 0; i < parts; ++i) s += run[r][warp + i];
3225          yo[(long)(t0 + r) * N + o] = bias ? (float)s + bias[o] : (float)s;
3226        }
3227    __syncthreads();
3228  }
3229}
3230"#;
3231
3232/// The warps an `f32` GEMV (`lk_gemv_f32`) cuts each output row's `k` into: the most, to eight, that keep 128 values a
3233/// warp and give its `n` outputs no more than 16 warps a streaming multiprocessor of the chip's `sms`.
3234pub fn gemv_f32_parts(n: usize, k: usize, sms: usize) -> usize {
3235    [8, 4, 2].into_iter().find(|&p| k >= 128 * p && n * p <= 16 * sms).unwrap_or(1)
3236}
3237
3238/// `c = a ⊕ b` elementwise (`OP` 0 add, 1 multiply), `b` passed through the activation `ACT` first when it names one
3239/// (a gate; −1 none); `b` holds `nb` elements read at `i mod nb` — all `n`, or one row combined with every row. `Q`
3240/// quantizes `c` (`n` a multiple of 32) and `OUTF` writes it.
3241/// `Y[m, n] = Σ_k X[m, k]·W[n, k]`, plus `bias[n]` when there is one, in `f32` over a wide chunk's `M` rows: 64 rows by 64
3242/// outputs a block over chunks of 32 `k` staged in shared memory, a thread 4 by 4 — a wide chunk's `f32` router. With
3243/// `split` parts (grid layer `z` a part, [`gemm_f32_splits`]) each tile's `k` is cut into that many runs of whole
3244/// chunks; each part parks its sums in `part`, and the tile's last part to arrive (`cnt`) sums them in order.
3245const GEMM_F32: &str = r#"
3246__global__ void __launch_bounds__(256) lk_gemm_f32(const float* __restrict__ x, const float* __restrict__ w,
3247                                                   const float* __restrict__ bias, lk_out y, int M, int N, int K,
3248                                                   int split = 1, float* __restrict__ part = nullptr, int* __restrict__ cnt = nullptr){
3249  __shared__ __align__(16) float Xs[32][64];
3250  __shared__ __align__(16) float Ws[32][64];
3251  __shared__ bool lk_last;
3252  int m0 = blockIdx.y * 64, n0 = blockIdx.x * 64, tid = threadIdx.x, tr = tid >> 4, tn = tid & 15;
3253  int chunks = (K + 31) / 32, run = (chunks + split - 1) / split, k_lo = blockIdx.z * run * 32, k_hi = min(K, k_lo + run * 32);
3254  float acc[4][4];
3255  #pragma unroll
3256  for(int r = 0; r < 4; ++r)
3257    #pragma unroll
3258    for(int c = 0; c < 4; ++c) acc[r][c] = 0.f;
3259  for(int k0 = k_lo; k0 < k_hi; k0 += 32){
3260    for(int c = tid; c < 64 * 8; c += 256){
3261      int r = c >> 3, k = (c & 7) * 4;
3262      float4 v = m0 + r < M && k0 + k < k_hi ? *(const float4*)(x + (long)(m0 + r) * K + k0 + k) : make_float4(0.f, 0.f, 0.f, 0.f);
3263      Xs[k][r] = v.x; Xs[k + 1][r] = v.y; Xs[k + 2][r] = v.z; Xs[k + 3][r] = v.w;
3264      float4 u = n0 + r < N && k0 + k < k_hi ? *(const float4*)(w + (long)(n0 + r) * K + k0 + k) : make_float4(0.f, 0.f, 0.f, 0.f);
3265      Ws[k][r] = u.x; Ws[k + 1][r] = u.y; Ws[k + 2][r] = u.z; Ws[k + 3][r] = u.w;
3266    }
3267    __syncthreads();
3268    #pragma unroll 8
3269    for(int k = 0; k < 32; ++k){
3270      float4 a = *(const float4*)&Xs[k][4 * tr];
3271      float4 b = *(const float4*)&Ws[k][4 * tn];
3272      float ar[4] = {a.x, a.y, a.z, a.w}, br[4] = {b.x, b.y, b.z, b.w};
3273      #pragma unroll
3274      for(int r = 0; r < 4; ++r)
3275        #pragma unroll
3276        for(int c = 0; c < 4; ++c) acc[r][c] = fmaf(ar[r], br[c], acc[r][c]);
3277    }
3278    __syncthreads();
3279  }
3280  if(split > 1){
3281    int tile = blockIdx.y * gridDim.x + blockIdx.x;
3282    float4* mine = (float4*)(part + ((long)(tile * split + blockIdx.z) * 256 + tid) * 16);
3283    #pragma unroll
3284    for(int r = 0; r < 4; ++r) mine[r] = make_float4(acc[r][0], acc[r][1], acc[r][2], acc[r][3]);
3285    __threadfence();
3286    __syncthreads();
3287    if(tid == 0) lk_last = atomicAdd(cnt + tile, 1) == split - 1;
3288    __syncthreads();
3289    if(!lk_last) return;
3290    #pragma unroll
3291    for(int r = 0; r < 4; ++r)
3292      #pragma unroll
3293      for(int c = 0; c < 4; ++c) acc[r][c] = 0.f;
3294    for(int pc = 0; pc < split; ++pc){
3295      const float4* src = (const float4*)(part + ((long)(tile * split + pc) * 256 + tid) * 16);
3296      #pragma unroll
3297      for(int r = 0; r < 4; ++r){
3298        float4 v = __ldcg(src + r);
3299        acc[r][0] += v.x; acc[r][1] += v.y; acc[r][2] += v.z; acc[r][3] += v.w;
3300      }
3301    }
3302    if(tid == 0) cnt[tile] = 0;
3303  }
3304  #pragma unroll
3305  for(int r = 0; r < 4; ++r){
3306    int m = m0 + 4 * tr + r;
3307    if(m >= M) continue;
3308    #pragma unroll
3309    for(int c = 0; c < 4; ++c){
3310      int n = n0 + 4 * tn + c;
3311      if(n < N) y[(long)m * N + n] = bias ? acc[r][c] + bias[n] : acc[r][c];
3312    }
3313  }
3314}
3315"#;
3316
3317const BINARY: &str = r#"
3318template<int OP, int ACT, bool OUTF, int Q>
3319__global__ void lk_binary(const float* __restrict__ a, const float* __restrict__ b, float* __restrict__ c,
3320                          signed char* __restrict__ cq, signed char* __restrict__ cl, float* __restrict__ cs, long n,
3321                          long nb){
3322  long i = (long)blockIdx.x * blockDim.x + threadIdx.x; if(i >= n) return;
3323  float bv = ACT < 0 ? b[i % nb] : lk_act<ACT>(b[i % nb]);
3324  float v = OP == 0 ? a[i] + bv : a[i] * bv;
3325  if(OUTF) c[i] = v;
3326  if(Q > 0) lk_quant_lane<Q>(v, cq, cl, cs, i, i >> 5);
3327}
3328"#;
3329
3330/// `y = x·c` elementwise.
3331const SCALE: &str = r#"
3332__global__ void lk_scale(const float* __restrict__ x, float* __restrict__ y, long n, float c){
3333  long i = (long)blockIdx.x * blockDim.x + threadIdx.x; if(i >= n) return;
3334  y[i] = x[i] * c;
3335}
3336"#;
3337
3338/// `y = silu(g)·u` elementwise, `silu(g) = g / (1 + e^-g)`; `Q` quantizes `y`, `OUTF` writes it.
3339const SWIGLU: &str = r#"
3340template<bool OUTF, int Q>
3341__global__ void lk_swiglu(const float* __restrict__ g, const float* __restrict__ u, float* __restrict__ y,
3342                          signed char* __restrict__ yq, signed char* __restrict__ yl, float* __restrict__ ys, long n){
3343  long i = (long)blockIdx.x * blockDim.x + threadIdx.x; if(i >= n) return;
3344  float gv = g[i];
3345  float v = gv / (1.0f + expf(-gv)) * u[i];
3346  if(OUTF) y[i] = v;
3347  if(Q > 0) lk_quant_lane<Q>(v, yq, yl, ys, i, i >> 5);
3348}
3349"#;
3350
3351/// An elementwise activation, `lk_act<ACT>`.
3352const UNARY: &str = r#"
3353template<int ACT>
3354__global__ void lk_unary(const float* __restrict__ x, float* __restrict__ y, long n){
3355  long i = (long)blockIdx.x * blockDim.x + threadIdx.x; if(i >= n) return;
3356  y[i] = lk_act<ACT>(x[i]);
3357}
3358"#;
3359
3360/// RoPE-NEOX over one head per block: each of the head's first `half` dims paired with the one `half` after it and
3361/// turned by the angles of one table row, the dims past `2·half` passed through. The heads come `per_row` to a row of
3362/// the input; row `r` reads table row `*pos + r` (1-based; row `r + 1` with no position). `NORM` RMSNorms the head by
3363/// `nw` first (QK-norm). The rows may land in the rows of a cache a position names. Head `h` is read `h·xp + xo` into
3364/// `x` (a part of every head of a wider row) and written `h·yp + yo` into its destination (a part of every head of one).
3365/// A head's work is `lk_rope_head`, which a projection's block that finishes a head also runs (`lk_gemv_parts_rope`), so
3366/// the two turn it alike.
3367const ROPE: &str = r#"
3368// One rotation: the arguments that differ between a layer's query and key rotations.
3369struct lk_rope_side { const float* x; const float* nw; lk_out y; const int* yrow; long ypitch; float eps; long xp, xo, yp, yo; int heads, per_row; long yz; };
3370// Head `h` of side `s`. A normed head's block is at least the head wide, so thread `t` takes its value `t` alone and
3371// the threads past the head add nothing: its sum of squares is the same tree whatever the block's width. `L2` reads the
3372// head past the L1, where other blocks of the launch wrote it. With `seqs`, a side's rows are a batch's sequences: row
3373// `r` turns from its own position, `pos[r]`, into its own table (`yz` values on from the last's) at its own row.
3374template<bool NORM, typename A, bool L2>
3375__device__ __forceinline__ void lk_rope_head(const lk_rope_side& s, int h, const float* __restrict__ cs,
3376                                             const float* __restrict__ sn, const int* __restrict__ pos, int hd, int half,
3377                                             int seqs, A* red, float* hv){
3378  auto ld = [](const float* p){ return L2 ? __ldcg(p) : *p; };
3379  const int r = h / s.per_row, t = threadIdx.x, rt = blockDim.x;
3380  const float* xh = s.x + (long)h * s.xp + s.xo;
3381  lk_out yh = seqs && s.yrow ? s.y + r * s.yz + (long)(s.yrow[r] - 1) * s.ypitch + (long)(h - r * s.per_row) * s.yp + s.yo
3382                             : LK_ROW(s.y, s.yrow, s.ypitch) + (long)h * s.yp + s.yo;
3383  A den = 1;
3384  if(NORM){
3385    A acc = 0;
3386    for(int i = t; i < hd; i += rt) acc += (A)ld(xh + i) * (A)ld(xh + i);
3387    den = sqrt(lk_block_sum(acc, red) / (A)hd + (A)s.eps);
3388  }
3389  for(int i = t; i < hd; i += rt) hv[i] = NORM ? (float)((A)ld(xh + i) / den * (A)s.nw[i]) : ld(xh + i);
3390  __syncthreads();
3391  long row = (pos ? (long)((seqs ? pos[r] : *pos + r) - 1) : (long)r) * half;
3392  for(int i = t; i < half; i += rt){
3393    float c = cs[row + i], sv = sn[row + i], av = hv[i], bv = hv[i + half];
3394    yh[i] = av * c - bv * sv;
3395    yh[i + half] = av * sv + bv * c;
3396  }
3397  for(int i = 2 * half + t; i < hd; i += rt) yh[i] = hv[i];
3398}
3399template<bool NORM, typename A>
3400__global__ void lk_rope(const float* __restrict__ x, const float* __restrict__ nw, const float* __restrict__ cs,
3401                        const float* __restrict__ sn, const int* __restrict__ pos, lk_out y,
3402                        const int* __restrict__ yrow, long ypitch, int hd, int half, int per_row, float eps,
3403                        long xp, long xo, long yp, long yo){
3404  __shared__ A red[32];
3405  __shared__ float hv[1024];
3406  const lk_rope_side s{x, nw, y, yrow, ypitch, eps, xp, xo, yp, yo, (int)gridDim.x, per_row, 0};
3407  lk_rope_head<NORM, A, false>(s, (int)blockIdx.x, cs, sn, pos, hd, half, 0, red, hv);
3408}
3409// Two rotations by one table at one position in one launch, `a`'s heads then `b`'s, each head as `lk_rope<NORM, A>`
3410// computes it.
3411template<bool NORM, typename A>
3412__global__ void lk_rope_parts(lk_rope_side a, lk_rope_side b, const float* __restrict__ cs, const float* __restrict__ sn,
3413                              const int* __restrict__ pos, int hd, int half, int seqs = 0){
3414  __shared__ A red[32];
3415  __shared__ float hv[1024];
3416  // Each side by its own call, as `lk_gemv_parts_rope` turns them: a side chosen at run time puts the by-value
3417  // `lk_rope_side` in a local frame.
3418  if((int)blockIdx.x < a.heads) lk_rope_head<NORM, A, false>(a, (int)blockIdx.x, cs, sn, pos, hd, half, seqs, red, hv);
3419  else lk_rope_head<NORM, A, false>(b, (int)blockIdx.x - a.heads, cs, sn, pos, hd, half, seqs, red, hv);
3420}
3421"#;
3422
3423/// `lk_gemv_parts`, then each head of a rotation that reads one of its parts turned by the block that finishes the head:
3424/// a step's projections of one activation with their heads' norms and rotations in the epilogue (`qkv_head_epilogue`).
3425/// Each warp computes its `W` rows as `lk_gemv_parts` does and writes them; each block then counts in, at the head's
3426/// count in `cnt`, the rows it wrote of each head a rotation reads — side `a` reads part `pa`, `b` part `pb` (−1: no
3427/// side) — and the block whose rows complete a head reads it back through L2 and turns it as `lk_rope_parts` turns it,
3428/// then resets the count. A block is at least a normed head wide, as the rotation's own block is.
3429const GEMV_PARTS_ROPE: &str = r#"
3430template<int F, int Q, int M, int W, bool NORM, typename A>
3431__global__ void __launch_bounds__(1024) lk_gemv_parts_rope(const float* __restrict__ x, const signed char* __restrict__ xq,
3432                              const signed char* __restrict__ xl, const float* __restrict__ xs, int K, int N,
3433                              lk_parts parts, lk_rope_side a, lk_rope_side b, int pa, int pb,
3434                              const float* __restrict__ cs, const float* __restrict__ sn, const int* __restrict__ pos,
3435                              int hd, int half, int* __restrict__ cnt){
3436  __shared__ A red[32];
3437  __shared__ float hv[1024];
3438  __shared__ int done;
3439  const long rows = (long)(blockDim.x >> 5) * W, first = (long)blockIdx.x * rows, last = min(first + rows, (long)N);
3440  const long o = first + (long)(threadIdx.x >> 5) * W;
3441  if(o < N){
3442    int p = 0;
3443    while(p < LK_PARTS - 1 && o >= parts.end[p]) ++p;
3444    long start = p ? parts.end[p - 1] : 0, r = o - start;
3445    long n = parts.end[p] - start;
3446    float d[W * M];
3447    lk_gemv_dot<F, Q, M, W>(parts.w[p], r, K, x, xq, xl, xs, d);
3448    if((threadIdx.x & 31) == 0){
3449      lk_out yo = LK_ROW(lk_part_out(parts, p), parts.row[p], parts.pitch[p]);
3450      const float* b = parts.bias[p];
3451      #pragma unroll
3452      for(int i = 0; i < W; ++i)
3453        #pragma unroll
3454        for(int t = 0; t < M; ++t) yo[(long)t * n + r + i] = b ? d[i * M + t] + b[r + i] : d[i * M + t];
3455    }
3456  }
3457  __threadfence();
3458  __syncthreads();
3459  for(int side = 0; side < 2; ++side){
3460    const int pp = side ? pb : pa;
3461    if(pp < 0) continue;
3462    const long start = pp ? parts.end[pp - 1] : 0, lo = max(first, start), hi = min(last, (long)parts.end[pp]);
3463    for(long at = lo; at < hi;){
3464      const int h = (int)((at - start) / hd);
3465      const long to = min(hi, start + (long)(h + 1) * hd);
3466      const int head = (side ? a.heads : 0) + h, took = (int)(to - at);
3467      if(threadIdx.x == 0) done = atomicAdd(cnt + head, took) + took == hd;
3468      __syncthreads();
3469      if(done){
3470        __threadfence();
3471        // Each side by its own call: a side chosen at run time puts the by-value `lk_rope_side` in a local frame,
3472        // and every field the head's loops read from it goes to local memory.
3473        if(side) lk_rope_head<NORM, A, true>(b, h, cs, sn, pos, hd, half, 0, red, hv);
3474        else lk_rope_head<NORM, A, true>(a, h, cs, sn, pos, hd, half, 0, red, hv);
3475        if(threadIdx.x == 0) cnt[head] = 0;
3476      }
3477      __syncthreads();
3478      at = to;
3479    }
3480  }
3481}
3482"#;
3483
3484/// Rows `*idx … *idx + count − 1` (1-based; from row `fixed` with no index) of a table of rows `cols` wide, overwritten
3485/// by the `count` rows of `src`.
3486const SET_ROW: &str = r#"
3487__global__ void lk_set_row(lk_out t, const int* __restrict__ idx, int fixed, const float* __restrict__ src,
3488                           long n, int cols, long tz = 0){
3489  long c = (long)blockIdx.x * blockDim.x + threadIdx.x; if(c >= n) return;
3490  // A batch's rows (`tz` > 0): row `r` of `src` into its own table, `tz` values on from the last's, at its own index.
3491  if(tz){ long r = c / cols; t[r * tz + (long)(idx[r] - 1) * cols + c % cols] = src[c]; return; }
3492  t[(long)((idx ? *idx : fixed) - 1) * cols + c] = src[c];
3493}
3494// The rows' quantized form, as `lk_set_row` sets their values: each value's words — its low word too under two words —
3495// and each block's scale, from its first value. Rows of whole 32-value blocks, so a block's place is its own.
3496__global__ void lk_set_row_q(signed char* __restrict__ tq, signed char* __restrict__ tl, float* __restrict__ ts,
3497                             const int* __restrict__ idx, int fixed, const signed char* __restrict__ sq,
3498                             const signed char* __restrict__ sl, const float* __restrict__ ss, long n, int cols, long tz = 0){
3499  long c = (long)blockIdx.x * blockDim.x + threadIdx.x; if(c >= n) return;
3500  long d = tz ? (c / cols) * tz + (long)(idx[c / cols] - 1) * cols + c % cols : (long)((idx ? *idx : fixed) - 1) * cols + c;
3501  tq[d] = sq[c];
3502  if(tl) tl[d] = sl[c];
3503  if((c & 31) == 0) ts[d >> 5] = ss[c >> 5];
3504}
3505"#;
3506
3507/// GQA attention split over the attended span. A block takes `G` query heads of one key/value head together (`h0 / group`,
3508/// so every key and value row it reads serves all `G`) and one query row: query row `r` attends the first `*pos + r`
3509/// cached rows (all `len` with no position), or under a window `win` the last `win` of them, cut into `pe` chunks of
3510/// at least `minc` positions and no more than `splits` — a function of the row's span alone, so a row's arithmetic is
3511/// the same in every form. A chunk scores its positions `LK_TILE` at a time, a warp `KB` keys at once (`(q·k)·scale`,
3512/// keys read four values at a time), with a running maximum and sum, each tile's values weighed in: a thread weighs the
3513/// value slots `tid + 256·k` of the block's `G·vd/2` (head `s / (vd/2)`'s pair `s mod (vd/2)` for slot `s`, at most
3514/// `G·VPT` a thread), a head's values read `vw` apart from `voff` — a latent cache's latent where it lies. With a grid
3515/// of `splits` blocks a row (the decode step), each chunk is a block that writes its heads' maxima, sums and weighed
3516/// values to `part`, and the last to arrive (`cnt`, reset by it) folds them (`lk_attn_fold`, then
3517/// `lk_attn_fold_values`, each thread folding the slots it weighed); with one (a batch's sequence or a prefill chunk,
3518/// whose rows already fill the chip), the block takes every chunk of its row and folds them alike — each once, kept in
3519/// its shared memory as a split block keeps it in `part`, when the launch gives it room for them (`held`,
3520/// `attn_holds`); otherwise their maxima and sums first, then their values. One chunk's
3521/// heads are written at once; head `h`'s sink `sinks[h]` joins the maximum and the denominator when there are sinks. A
3522/// key row is `kvw` wide, a head `hd`. Every sum — the scores' dots, the softmax's sums, the weighed values, the chunks' partials and their
3523/// fold — runs in the accumulator type `A`: `double` under the precise numerics, whose contract is `f32` values with
3524/// `f64` sums, `float` otherwise.
3525const ATTENTION: &str = r#"
3526#define LK_TILE 64
3527// The attention's sums in the accumulator type `A`: `float`, or `double` for the precise numerics.
3528template<typename A> struct lk_pair { A x, y; };
3529__device__ __forceinline__ float lk_fma(float a, float b, float c){ return __fmaf_rn(a, b, c); }
3530__device__ __forceinline__ double lk_fma(double a, double b, double c){ return __fma_rn(a, b, c); }
3531__device__ __forceinline__ float lk_add(float a, float b){ return __fadd_rn(a, b); }
3532__device__ __forceinline__ double lk_add(double a, double b){ return __dadd_rn(a, b); }
3533__device__ __forceinline__ float lk_exp(float v){ return expf(v); }
3534__device__ __forceinline__ double lk_exp(double v){ return exp(v); }
3535__device__ __forceinline__ float lk_wsum(float v){ return lk_warp_sum(v); }
3536__device__ __forceinline__ double lk_wsum(double v){ return lk_warp_sum_d(v); }
3537__device__ __forceinline__ float lk_wmax(float v){ return lk_warp_max(v); }
3538__device__ __forceinline__ double lk_wmax(double v){
3539  for(int o = 16; o > 0; o >>= 1) v = fmax(v, __shfl_down_sync(0xffffffffu, v, o));
3540  return __shfl_sync(0xffffffffu, v, 0);
3541}
3542// The `V` values (a power of two) each lane holds, each summed over a run of `D·2` lanes as `lk_wsum` sums a value over
3543// the warp — the lanes paired across `D`, then `D/2`, … then 1: while a lane holds more than one value it keeps one half
3544// (the upper where its bit `D` is set) and sends the other, then the one left is summed with its partner's. Value
3545// `base + i` lands at `v[i]`, `base` the halves a lane kept.
3546template<int D, int V, typename A, int N>
3547__device__ __forceinline__ void lk_tree_halves(A (&v)[N], int lane, int& base){
3548  if constexpr(D >= 1){
3549    if constexpr(V > 1){
3550      const bool up = lane & D;
3551      #pragma unroll
3552      for(int i = 0; i < V / 2; ++i){
3553        const A send = up ? v[i] : v[i + V / 2], keep = up ? v[i + V / 2] : v[i];
3554        v[i] = keep + __shfl_xor_sync(0xffffffffu, send, D);
3555      }
3556      if(up) base += V / 2;
3557      lk_tree_halves<D / 2, V / 2>(v, lane, base);
3558    } else {
3559      v[0] = v[0] + __shfl_xor_sync(0xffffffffu, v[0], D);
3560      lk_tree_halves<D / 2, 1>(v, lane, base);
3561    }
3562  }
3563}
3564template<int V> __host__ __device__ constexpr int lk_pow2_at_least(){ int p = 1; while(p < V) p *= 2; return p; }
3565// A tile's `n` keys scored for a block's `G` heads, run `R` lanes a key: a warp `KB` keys a run at once, `32 / R` runs a
3566// warp. A lane sums its share of the head (fours `lane mod R`, `+ R`, …), the run's lanes past the head zeros; the lanes
3567// past the run add as zeros, then each run sums its keys' dots as `lk_tree_halves` sums them — the operations
3568// `lk_wsum` takes over a key's dot with the head in lanes `0 … R − 1`. Key `j` reads cache row `row(j)` (−1: none); its
3569// head `g`'s sum goes to `emit(j, g, s)`, once. Which of a run's keys read a row is a mask (`ok`): the keys a lane
3570// emits are known only at run time, and an array indexed by them would live in local memory.
3571template<int G, typename A, int R, typename KE, typename Row, typename Emit>
3572__device__ __forceinline__ void lk_attn_scores_in(const float* qs, const KE* __restrict__ kc, int n, int hd, int kvw, long koff,
3573                                                  Row row, Emit emit){
3574  constexpr int KB = G <= 2 ? 4 : (G <= 4 ? 2 : 1), S = KB * (32 / R), NV = KB * G, V = lk_pow2_at_least<NV>();
3575  constexpr int H = V < R ? V : R;
3576  const int lane = threadIdx.x & 31, warp = threadIdx.x >> 5, nw = blockDim.x >> 5, h4 = hd >> 2;
3577  const int run = lane / R, at = lane % R;
3578  const float4* q4 = (const float4*)qs;
3579  for(int i = warp; i < n; i += nw * S){
3580    int rw[KB], ok = 0;
3581    #pragma unroll
3582    for(int b = 0; b < KB; ++b){ rw[b] = row(i + (run * KB + b) * nw); ok |= (rw[b] >= 0) << b; }
3583    A d[V];
3584    #pragma unroll
3585    for(int v = 0; v < V; ++v) d[v] = 0;
3586    for(int e = at; e < h4; e += R){
3587      float4 k[KB];
3588      #pragma unroll
3589      for(int b = 0; b < KB; ++b) k[b] = rw[b] >= 0 ? lk_from4(kc + (long)rw[b] * kvw + koff + 4 * e) : make_float4(0.f, 0.f, 0.f, 0.f);
3590      #pragma unroll
3591      for(int g = 0; g < G; ++g){
3592        float4 a = q4[g * h4 + e];
3593        #pragma unroll
3594        for(int b = 0; b < KB; ++b){
3595          A& s = d[b * G + g];
3596          s = lk_fma((A)a.x, (A)k[b].x, s); s = lk_fma((A)a.y, (A)k[b].y, s);
3597          s = lk_fma((A)a.z, (A)k[b].z, s); s = lk_fma((A)a.w, (A)k[b].w, s);
3598        }
3599      }
3600    }
3601    if constexpr(R < 32){
3602      #pragma unroll
3603      for(int v = 0; v < V; ++v) d[v] = lk_add(d[v], (A)0);
3604    }
3605    int base = 0;
3606    lk_tree_halves<R / 2, V>(d, lane, base);
3607    // A run's lanes below the last distance halved at hold every value; the first of them emits it.
3608    constexpr int LAST = R / H;
3609    if(at % LAST == 0){
3610      #pragma unroll
3611      for(int v = 0; v < V / H; ++v){
3612        const int idx = base + v;
3613        if(idx < NV){
3614          const int b = idx / G, g = idx - b * G;
3615          if(ok >> b & 1) emit(i + (run * KB + b) * nw, g, d[v]);
3616        }
3617      }
3618    }
3619  }
3620}
3621// The lanes a key's dot takes (`lk_attn_scores_in`'s `R`) for a head of `hd`: a half warp for a head of 9 to 16 fours
3622// — two keys a run at once — and the whole warp otherwise. A launch takes it once (`lk_attention`), so each run's body
3623// keeps its registers.
3624__host__ __device__ constexpr int lk_attn_run_width(int hd){ return hd / 4 > 8 && hd / 4 <= 16 ? 16 : 32; }
3625template<int G, typename A, typename KE, typename Row, typename Emit>
3626__device__ __forceinline__ void lk_attn_scores(const float* qs, const KE* __restrict__ kc, int n, int hd, int kvw, long koff,
3627                                               Row row, Emit emit){
3628  if(lk_attn_run_width(hd) == 16) lk_attn_scores_in<G, A, 16>(qs, kc, n, hd, kvw, koff, row, emit);
3629  else lk_attn_scores_in<G, A, 32>(qs, kc, n, hd, kvw, koff, row, emit);
3630}
3631// One chunk `[j0, j1)` of a block's `G` heads: each head's running maximum `mx` and sum `sum`, and with `VALUES` each
3632// thread's value slots weighed in `acc`.
3633template<int G, int VPT, typename A, bool VALUES, int R, typename KE, typename VE>
3634__device__ __forceinline__ void lk_attn_chunk(const float* qs, A* sc, A* mx, A* sum, A* alpha,
3635                                              const KE* __restrict__ kc, const VE* __restrict__ vc, int j0, int j1,
3636                                              int hd, int vd, int kvw, int vw, long koff, long vo, A scale,
3637                                              lk_pair<A> (&acc)[G * VPT]){
3638  int lane = threadIdx.x & 31, warp = threadIdx.x >> 5, nw = blockDim.x >> 5;
3639  if(threadIdx.x < G){ mx[threadIdx.x] = -INFINITY; sum[threadIdx.x] = 0; }
3640  #pragma unroll
3641  for(int k = 0; k < G * VPT; ++k) acc[k] = lk_pair<A>{0, 0};
3642  __syncthreads();
3643  for(int jt = j0; jt < j1; jt += LK_TILE){
3644    int nt = min(LK_TILE, j1 - jt);
3645    lk_attn_scores_in<G, A, R>(qs, kc, nt, hd, kvw, koff, [&](int j){ return j < nt ? jt + j : -1; },
3646                               [&](int j, int g, A s){ sc[g * LK_TILE + j] = s * scale; });
3647    __syncthreads();
3648    for(int g = warp; g < G; g += nw){
3649      A m = mx[g];
3650      for(int j = lane; j < nt; j += 32) m = fmax(m, sc[g * LK_TILE + j]);
3651      m = lk_wmax(m);
3652      A s = 0;
3653      for(int j = lane; j < nt; j += 32){ A p = lk_exp(sc[g * LK_TILE + j] - m); sc[g * LK_TILE + j] = p; s += p; }
3654      s = lk_wsum(s);
3655      if(lane == 0){ A a = lk_exp(mx[g] - m); alpha[g] = a; sum[g] = lk_fma(sum[g], a, s); mx[g] = m; }
3656    }
3657    __syncthreads();
3658    if(VALUES){
3659      const int ph = vd >> 1;
3660      #pragma unroll
3661      for(int k = 0; k < G * VPT; ++k){
3662        const int s = threadIdx.x + k * blockDim.x;
3663        if(s < G * ph){
3664          const int g = s / ph, e = s - g * ph;
3665          const A* w = sc + g * LK_TILE;
3666          lk_pair<A> a{acc[k].x * alpha[g], acc[k].y * alpha[g]};
3667          #pragma unroll 8
3668          for(int j = 0; j < nt; ++j){
3669            float2 v = lk_from2(vc + (long)(jt + j) * vw + vo + 2 * e);
3670            a.x = lk_fma(w[j], (A)v.x, a.x); a.y = lk_fma(w[j], (A)v.y, a.y);
3671          }
3672          acc[k] = a;
3673        }
3674      }
3675    }
3676    __syncthreads();
3677  }
3678}
3679// Chunk `u`'s heads' maxima and sums (thread `g` head `g`'s, the thread that resets them for a next chunk) and weighed
3680// values (each thread its value slots) into the block's partials `p0` — head `g`'s chunk `u` at `(g·splits + u)·stride`
3681// — as every form folds them.
3682template<int G, int VPT, typename A>
3683__device__ __forceinline__ void lk_attn_keep(A* __restrict__ p0, const A* mx, const A* sum, const lk_pair<A> (&acc)[G * VPT],
3684                                             int u, int splits, long stride, int vd){
3685  const int ph = vd >> 1;
3686  if(threadIdx.x < G){ A* p = p0 + (threadIdx.x * splits + u) * stride; p[0] = mx[threadIdx.x]; p[1] = sum[threadIdx.x]; }
3687  #pragma unroll
3688  for(int k = 0; k < G * VPT; ++k){
3689    const int s = threadIdx.x + k * blockDim.x;
3690    if(s < G * ph){
3691      const int g = s / ph, e = s - g * ph;
3692      A* p = p0 + (g * splits + u) * stride;
3693      p[2 + 2 * e] = acc[k].x; p[3 + 2 * e] = acc[k].y;
3694    }
3695  }
3696}
3697// Chunks `u0 … u0 + w − 1` of a row's span `[lo, end)`, cut every `chunk` positions, weighed side by side: step `t0`
3698// takes tile `t0` of every chunk at once — its keys scored, each (head, chunk)'s running maximum and sum taken over it,
3699// its values weighed — each chunk in exactly the operations `lk_attn_chunk` takes it in alone. Head `g`'s chunk `u`
3700// keeps its maximum, sum and last factor at `g·splits + u` of `mx`, `sum` and `alpha`, and its weighed values in the
3701// partials `p0` as `lk_attn_keep` keeps them; a thread's value slots run over the chunks, slot `s` chunk
3702// `s / (G·vd/2)`'s, so `w` chunks' slots fill at most the `G·VPT` a thread holds.
3703template<int G, int VPT, int R, typename A, typename KE, typename VE>
3704__device__ __forceinline__ void lk_attn_side(const float* qs, A* sc, A* mx, A* sum, A* alpha,
3705                                             const KE* __restrict__ kc, const VE* __restrict__ vc, int lo, int chunk,
3706                                             int end, int u0, int w, int splits, int hd, int vd, int kvw, int vw,
3707                                             long koff, long vo, A scale, A* __restrict__ p0, long stride){
3708  int lane = threadIdx.x & 31, warp = threadIdx.x >> 5, nw = blockDim.x >> 5;
3709  const int ph = vd >> 1, slots = G * ph;
3710  // Chunk `u`'s first position and its keys in the tile from `t0`.
3711  auto first = [&](int u){ return min(lo + u * chunk, end); };
3712  auto in_tile = [&](int u, int t0){ int j0 = first(u); return max(0, min(LK_TILE, min(j0 + chunk, end) - j0 - t0)); };
3713  for(int i = threadIdx.x; i < G * w; i += blockDim.x){ int at = (i % G) * splits + u0 + i / G; mx[at] = -INFINITY; sum[at] = 0; }
3714  lk_pair<A> acc[G * VPT];
3715  #pragma unroll
3716  for(int k = 0; k < G * VPT; ++k) acc[k] = lk_pair<A>{0, 0};
3717  __syncthreads();
3718  const int longest = min(first(u0) + chunk, end) - first(u0);
3719  for(int t0 = 0; t0 < longest; t0 += LK_TILE){
3720    // The step's keys of every chunk, `full` a chunk (the last's maybe fewer), each scored as `lk_attn_chunk` scores it.
3721    const int full = min(LK_TILE, longest - t0);
3722    lk_attn_scores_in<G, A, R>(qs, kc, w * full, hd, kvw, koff,
3723                               [&](int idx){ int ul = idx / full, j = idx - ul * full; return ul < w && j < in_tile(u0 + ul, t0) ? first(u0 + ul) + t0 + j : -1; },
3724                               [&](int idx, int g, A s){ int ul = idx / full; sc[(ul * G + g) * LK_TILE + idx - ul * full] = s * scale; });
3725    __syncthreads();
3726    // Each (head, chunk)'s running maximum and sum over the step, a warp a pair.
3727    for(int pi = warp; pi < G * w; pi += nw){
3728      int g = pi % G, ul = pi / G, nt = in_tile(u0 + ul, t0), at = g * splits + u0 + ul;
3729      if(nt == 0) continue;
3730      A* srow = sc + (ul * G + g) * LK_TILE;
3731      A m = mx[at];
3732      for(int j = lane; j < nt; j += 32) m = fmax(m, srow[j]);
3733      m = lk_wmax(m);
3734      A s = 0;
3735      for(int j = lane; j < nt; j += 32){ A p = lk_exp(srow[j] - m); srow[j] = p; s += p; }
3736      s = lk_wsum(s);
3737      if(lane == 0){ A a = lk_exp(mx[at] - m); alpha[at] = a; sum[at] = lk_fma(sum[at], a, s); mx[at] = m; }
3738    }
3739    __syncthreads();
3740    // Every chunk's values weighed in, a thread its slots over the chunks.
3741    #pragma unroll
3742    for(int k = 0; k < G * VPT; ++k){
3743      const int s = threadIdx.x + k * blockDim.x;
3744      if(s < w * slots){
3745        const int ul = s / slots, rest = s - ul * slots, g = rest / ph, e = rest - g * ph, nt = in_tile(u0 + ul, t0);
3746        if(nt > 0){
3747          const A* wt = sc + (ul * G + g) * LK_TILE;
3748          const A al = alpha[g * splits + u0 + ul];
3749          const long j0 = first(u0 + ul) + t0;
3750          lk_pair<A> a{acc[k].x * al, acc[k].y * al};
3751          #pragma unroll 8
3752          for(int j = 0; j < nt; ++j){
3753            float2 v = lk_from2(vc + (j0 + j) * vw + vo + 2 * e);
3754            a.x = lk_fma(wt[j], (A)v.x, a.x); a.y = lk_fma(wt[j], (A)v.y, a.y);
3755          }
3756          acc[k] = a;
3757        }
3758      }
3759    }
3760    __syncthreads();
3761  }
3762  #pragma unroll
3763  for(int k = 0; k < G * VPT; ++k){
3764    const int s = threadIdx.x + k * blockDim.x;
3765    if(s < w * slots){
3766      const int ul = s / slots, rest = s - ul * slots, g = rest / ph, e = rest - g * ph;
3767      A* p = p0 + (g * splits + u0 + ul) * stride;
3768      p[2 + 2 * e] = acc[k].x; p[3 + 2 * e] = acc[k].y;
3769    }
3770  }
3771}
3772// A pair of a chunk's weighed values, read past the cache from the partials the other blocks wrote.
3773__device__ __forceinline__ lk_pair<float> lk_part_pair(const float* p){ float2 v = __ldcg((const float2*)p); return {v.x, v.y}; }
3774__device__ __forceinline__ lk_pair<double> lk_part_pair(const double* p){ double2 v = __ldcg((const double2*)p); return {v.x, v.y}; }
3775// Head `g`'s maximum (with its sink) and denominator over its `pe` chunks' maxima `ms` and sums `ls`, and each chunk's
3776// factor `ff` in the fold — a function of the chunks alone, the same wherever the chunks ran.
3777template<typename A>
3778__device__ __forceinline__ void lk_attn_fold(const A* ms, const A* ls, A* ff, A* fm, A* fl,
3779                                             const float* __restrict__ sinks, int h, int g, int pe, int splits){
3780  A sk = sinks ? (A)sinks[h] : (A)-INFINITY;
3781  A m = sk;
3782  for(int u = 0; u < pe; ++u) m = fmax(m, ms[g * splits + u]);
3783  A l = sinks ? lk_exp(sk - m) : (A)0;
3784  for(int u = 0; u < pe; ++u){
3785    A mu = ms[g * splits + u], f = mu > -INFINITY ? lk_exp(mu - m) : (A)0;
3786    ff[g * splits + u] = f;
3787    if(mu > -INFINITY) l = lk_fma(ls[g * splits + u], f, l);
3788  }
3789  fm[g] = m; fl[g] = l;
3790}
3791// The fold of a block's `G` heads' weighed values over their `pe` chunks' partials `p0` (as `lk_attn_keep` keeps them,
3792// in shared memory under `SHARED`, else read past the cache from what the other blocks wrote): each thread folds the
3793// value slots it weighed, chunk by chunk in order. Each head's values divided by its denominator `fl` into `out`.
3794template<int G, int VPT, typename A, bool SHARED = false, int QO = 0>
3795__device__ __forceinline__ void lk_attn_fold_values(const A* __restrict__ p0, const A* ms, const A* ff, const A* fl,
3796                                                    float* __restrict__ out, long head0, int pe, int splits, long stride, int vd,
3797                                                    lk_qout qo = {}){
3798  const int ph = vd >> 1;
3799  lk_pair<A> a[G * VPT];
3800  #pragma unroll
3801  for(int k = 0; k < G * VPT; ++k) a[k] = lk_pair<A>{0, 0};
3802  #pragma unroll 2
3803  for(int u = 0; u < pe; ++u){
3804    #pragma unroll
3805    for(int k = 0; k < G * VPT; ++k){
3806      const int s = threadIdx.x + k * blockDim.x;
3807      if(s < G * ph){
3808        const int g = s / ph, e = s - g * ph;
3809        if(ms[g * splits + u] > -INFINITY){
3810          const A f = ff[g * splits + u];
3811          const A* p = p0 + (g * splits + u) * stride + 2 + 2 * e;
3812          const lk_pair<A> v = SHARED ? lk_pair<A>{p[0], p[1]} : lk_part_pair(p);
3813          a[k].x = lk_fma(v.x, f, a[k].x); a[k].y = lk_fma(v.y, f, a[k].y);
3814        }
3815      }
3816    }
3817  }
3818  #pragma unroll
3819  for(int k = 0; k < G * VPT; ++k){
3820    const int s = threadIdx.x + k * blockDim.x;
3821    const bool on = s < G * ph;
3822    const int g = on ? s / ph : 0, e = s - g * ph;
3823    lk_attn_store<QO>(out, qo, (head0 + g) * vd + 2 * e, on, on ? (float)(a[k].x / fl[g]) : 0.f, on ? (float)(a[k].y / fl[g]) : 0.f);
3824  }
3825}
3826// The path an attention launch takes past a row of one chunk (`lk_attention`'s `PATH`), fixed where it launches: its
3827// chunks' partials folded by the last split block to arrive, held side by side by the one block of the row, or weighed
3828// one at a time by it; a launch of one chunk a row takes none. `LK_ATTN_ANY` takes whichever its grid and its
3829// arguments name.
3830enum lk_attn_path { LK_ATTN_ANY, LK_ATTN_SPLIT, LK_ATTN_HELD, LK_ATTN_CHUNKS, LK_ATTN_ONE };
3831// The attention's body at a key's run of `R` lanes (`lk_attn_run_width`), on path `PATH`, with the block's heads'
3832// running maxima, sums, factors and folded maxima and denominators, and the flag of the last split block to arrive.
3833template<int R, int G, int VPT, typename A, typename KE, typename VE, int QO, int PATH>
3834__device__ __forceinline__ void lk_attention_run(const float* __restrict__ q, const KE* __restrict__ kc,
3835    const VE* __restrict__ vc, const int* __restrict__ pos, const float* __restrict__ sinks, float* __restrict__ out,
3836    A* __restrict__ part, int* __restrict__ cnt, int len, int win, int hd, int vd, int group, int heads, int kvw,
3837    int vw, int voff, float scale, int minc, int splits, long kz, int held, A* mx, A* sum, A* alpha, A* fm, A* fl,
3838    int& last, lk_qout qo){
3839  extern __shared__ __align__(16) unsigned char lk_smem[];
3840  float* qs = (float*)lk_smem;
3841  A* sc = (A*)(lk_smem + ((G * hd * 4 + 15) & ~15));
3842  A* ms = sc + G * LK_TILE * max(held, 1);
3843  A* ls = ms + G * splits;
3844  A* ff = ls + G * splits;
3845  A* hp = ff + G * splits;
3846  int hb = blockIdx.x, r = blockIdx.y, t = blockIdx.z;
3847  int h0 = hb * G, kvh = h0 / group;
3848  // A batch's rows (`kz` > 0) are its sequences: row `r` attends its own caches, `kz` values on from the last's, up
3849  // to its own position; a chunk's rows share the caches, at consecutive positions.
3850  if(kz){ kc += r * kz; vc += r * kz; }
3851  int end = pos ? (kz ? pos[r] : *pos + r) : len;
3852  int lo = win > 0 && end > win ? end - win : 0, n = end - lo;
3853  int pe = max(1, min(splits, (n + minc - 1) / minc)), chunk = (n + pe - 1) / pe;
3854  if(t >= pe) return;
3855  const float* qb = q + ((long)r * heads + h0) * hd;
3856  for(int i = threadIdx.x; i < G * hd; i += blockDim.x) qs[i] = qb[i];
3857  long koff = (long)kvh * hd, vo = voff + (long)kvh * vd, head0 = (long)r * heads + h0;
3858  const int ph = vd >> 1;
3859  lk_pair<A> acc[G * VPT];
3860  if(PATH == LK_ATTN_ONE || pe == 1){
3861    lk_attn_chunk<G, VPT, A, true, R>(qs, sc, mx, sum, alpha, kc, vc, lo, end, hd, vd, kvw, vw, koff, vo, (A)scale, acc);
3862    #pragma unroll
3863    for(int k = 0; k < G * VPT; ++k){
3864      const int s = threadIdx.x + k * blockDim.x;
3865      const bool on = s < G * ph;
3866      const int g = on ? s / ph : 0, e = s - g * ph;
3867      float x = 0.f, y = 0.f;
3868      if(on){
3869        A sk = sinks ? (A)sinks[h0 + g] : (A)-INFINITY;
3870        A m = fmax(sk, mx[g]), f = lk_exp(mx[g] - m);
3871        A l = lk_fma(sum[g], f, sinks ? lk_exp(sk - m) : (A)0);
3872        x = (float)(acc[k].x * f / l);
3873        y = (float)(acc[k].y * f / l);
3874      }
3875      lk_attn_store<QO>(out, qo, (head0 + g) * vd + 2 * e, on, x, y);
3876    }
3877    return;
3878  }
3879  long stride = (long)vd + 2;
3880  if(PATH == LK_ATTN_ANY ? gridDim.z > 1 : PATH == LK_ATTN_SPLIT){
3881    int j0 = min(lo + t * chunk, end), j1 = min(j0 + chunk, end);
3882    lk_attn_chunk<G, VPT, A, true, R>(qs, sc, mx, sum, alpha, kc, vc, j0, j1, hd, vd, kvw, vw, koff, vo, (A)scale, acc);
3883    lk_attn_keep<G, VPT>(part + head0 * splits * stride, mx, sum, acc, t, splits, stride, vd);
3884    __threadfence();
3885    __syncthreads();
3886    int* c = cnt + (long)r * gridDim.x + hb;
3887    if(threadIdx.x == 0) last = atomicAdd(c, 1) == pe - 1;
3888    __syncthreads();
3889    if(!last) return;
3890    __threadfence();
3891    for(int i = threadIdx.x; i < G * pe; i += blockDim.x){
3892      int g = i / pe, u = i - g * pe;
3893      const A* p = part + ((head0 + g) * splits + u) * stride;
3894      ms[g * splits + u] = __ldcg(p); ls[g * splits + u] = __ldcg(p + 1);
3895    }
3896    __syncthreads();
3897    if(threadIdx.x < G) lk_attn_fold(ms, ls, ff, fm, fl, sinks, h0 + threadIdx.x, threadIdx.x, pe, splits);
3898    __syncthreads();
3899    lk_attn_fold_values<G, VPT, A, false, QO>(part + head0 * splits * stride, ms, ff, fl, out, head0, pe, splits, stride, vd, qo);
3900    if(threadIdx.x == 0) *c = 0;
3901    return;
3902  }
3903  // One block takes every chunk of its row, in the arithmetic the split blocks use. With room for their partials
3904  // (`held`, after the fold's factors), each chunk once, `held` side by side, kept as a split block keeps it, then
3905  // folded alike; otherwise each chunk's maximum and sum first, then each chunk's values weighed in, chunk by chunk.
3906  if(PATH == LK_ATTN_ANY ? held != 0 : PATH == LK_ATTN_HELD){
3907    for(int u0 = 0; u0 < pe; u0 += held)
3908      lk_attn_side<G, VPT, R>(qs, sc, ms, ls, ff, kc, vc, lo, chunk, end, u0, min(held, pe - u0), splits, hd, vd, kvw, vw, koff, vo,
3909                           (A)scale, hp, stride);
3910    __syncthreads();
3911    if(threadIdx.x < G) lk_attn_fold(ms, ls, ff, fm, fl, sinks, h0 + threadIdx.x, threadIdx.x, pe, splits);
3912    __syncthreads();
3913    lk_attn_fold_values<G, VPT, A, true, QO>(hp, ms, ff, fl, out, head0, pe, splits, stride, vd, qo);
3914    return;
3915  }
3916  for(int u = 0; u < pe; ++u){
3917    int j0 = min(lo + u * chunk, end), j1 = min(j0 + chunk, end);
3918    lk_attn_chunk<G, VPT, A, false, R>(qs, sc, mx, sum, alpha, kc, vc, j0, j1, hd, vd, kvw, vw, koff, vo, (A)scale, acc);
3919    if(threadIdx.x < G){ ms[threadIdx.x * splits + u] = mx[threadIdx.x]; ls[threadIdx.x * splits + u] = sum[threadIdx.x]; }
3920  }
3921  __syncthreads();
3922  if(threadIdx.x < G) lk_attn_fold(ms, ls, ff, fm, fl, sinks, h0 + threadIdx.x, threadIdx.x, pe, splits);
3923  lk_pair<A> a[G * VPT];
3924  #pragma unroll
3925  for(int k = 0; k < G * VPT; ++k) a[k] = lk_pair<A>{0, 0};
3926  for(int u = 0; u < pe; ++u){
3927    int j0 = min(lo + u * chunk, end), j1 = min(j0 + chunk, end);
3928    lk_attn_chunk<G, VPT, A, true, R>(qs, sc, mx, sum, alpha, kc, vc, j0, j1, hd, vd, kvw, vw, koff, vo, (A)scale, acc);
3929    #pragma unroll
3930    for(int k = 0; k < G * VPT; ++k){
3931      const int s = threadIdx.x + k * blockDim.x;
3932      if(s < G * ph){
3933        const int g = s / ph;
3934        if(ms[g * splits + u] > -INFINITY){
3935          a[k].x = lk_fma(acc[k].x, ff[g * splits + u], a[k].x);
3936          a[k].y = lk_fma(acc[k].y, ff[g * splits + u], a[k].y);
3937        }
3938      }
3939    }
3940  }
3941  #pragma unroll
3942  for(int k = 0; k < G * VPT; ++k){
3943    const int s = threadIdx.x + k * blockDim.x;
3944    const bool on = s < G * ph;
3945    const int g = on ? s / ph : 0, e = s - g * ph;
3946    lk_attn_store<QO>(out, qo, (head0 + g) * vd + 2 * e, on, on ? (float)(a[k].x / fl[g]) : 0.f, on ? (float)(a[k].y / fl[g]) : 0.f);
3947  }
3948}
3949template<int G, int VPT, typename A, int MB = 2, typename KE = float, typename VE = float, int QO = 0, int PATH = LK_ATTN_ANY,
3950         int RW = 0>
3951__global__ void __launch_bounds__(256, MB) lk_attention(const float* __restrict__ q, const KE* __restrict__ kc,
3952    const VE* __restrict__ vc, const int* __restrict__ pos, const float* __restrict__ sinks, float* __restrict__ out,
3953    A* __restrict__ part, int* __restrict__ cnt, int len, int win, int hd, int vd, int group, int heads, int kvw,
3954    int vw, int voff, float scale, int minc, int splits, long kz = 0, int held = 0, lk_qout qo = {}){
3955  __shared__ A mx[G], sum[G], alpha[G], fm[G], fl[G];
3956  __shared__ int last;
3957  if(RW == 0 ? lk_attn_run_width(hd) == 16 : RW == 16)
3958    lk_attention_run<16, G, VPT, A, KE, VE, QO, PATH>(q, kc, vc, pos, sinks, out, part, cnt, len, win, hd, vd, group, heads, kvw, vw, voff,
3959                                                scale, minc, splits, kz, held, mx, sum, alpha, fm, fl, last, qo);
3960  else
3961    lk_attention_run<32, G, VPT, A, KE, VE, QO, PATH>(q, kc, vc, pos, sinks, out, part, cnt, len, win, hd, vd, group, heads, kvw, vw, voff,
3962                                                scale, minc, splits, kz, held, mx, sum, alpha, fm, fl, last, qo);
3963}
3964"#;
3965
3966/// An attention whose values are its key rows' own part (a latent cache's latent, `voff + vd ≤ hd`), one key/value
3967/// group's `G` heads a block, each cached row read once for every head's score and value — the values read from the
3968/// staged key rows (`VK`), or from rows of their own `vw` apart where a launch sliced them out of the key rows (the
3969/// same values, so the same results bit for bit). A row's span is cut into `pe` chunks
3970/// (`lk_shared_chunks`: at most `splits`, each at least `minc` positions and a whole number of `LK_ST`-row steps but the
3971/// last), a block each. A block holds its heads' queries in registers — a lane `hd / 32` of the width of four heads —
3972/// and stages its chunk's rows `LK_ST` at a time in shared memory by `cp.async`, the next step's rows landing while these
3973/// multiply. A warp scores four heads against `2·⌈G/4⌉` keys over its lanes' parts of the width, the lanes' sums
3974/// exchanged so that each lane ends with one head's score of one key (`lk_lane_sums`); each head keeps a running maximum
3975/// and sum (the online softmax); and a thread weighs `VPT` pairs of every head's values, the step's weights read four
3976/// heads at a time. A row of one chunk writes its outputs; otherwise each chunk writes its heads' maxima, sums and
3977/// weighed values to `part`, and `lk_attention_fold` folds them. Head `h`'s sink `sinks[h]` joins the maximum and the
3978/// denominator when there are sinks. A head is `H4` fours wide, a key row `kvw` wide. Every sum is `f32`.
3979const ATTENTION_SHARED: &str = r#"
3980#define LK_ST 16
3981// The chunks a row's `n` positions are cut into: at most `splits`, each at least `minc` positions, every one but the
3982// last `chunk` positions — a whole number of `LK_ST`-row steps.
3983__device__ __forceinline__ int lk_shared_chunks(int n, int splits, int minc, int& chunk){
3984  int pe = max(1, min(splits, (n + minc - 1) / minc));
3985  chunk = ((n + pe - 1) / pe + LK_ST - 1) / LK_ST * LK_ST;
3986  return max(1, (n + chunk - 1) / chunk);
3987}
3988template<int G, int VPT, int H4, bool VK, typename KE = float, typename VE = float, int QO = 0>
3989__global__ void __launch_bounds__(256) lk_attention_shared(const float* __restrict__ q, const KE* __restrict__ kc,
3990    const VE* __restrict__ vc, const int* __restrict__ pos, const float* __restrict__ sinks, float* __restrict__ out,
3991    float* __restrict__ part, int len, int win, int vd, int heads, int kvw, int vw, int voff, float scale, int minc,
3992    int splits, long kz = 0, lk_qout qo = {}){
3993  constexpr int HD = 4 * H4, HQ = G <= 4 ? 1 : (G <= 8 ? 2 : 4), GP = 4 * HQ, TN = LK_ST * HQ / 8, NV = 4 * TN;
3994  constexpr int M2 = (2 * H4 + 31) / 32, RF = (LK_ST * H4 + 255) / 256;
3995  extern __shared__ __align__(16) float lk_ss[];
3996  float* ks = lk_ss;                          // [2][LK_ST][HD]: two steps' rows
3997  float* sc = ks + 2 * LK_ST * HD;            // [LK_ST][GP]: a step's scores, then weights, a key's heads together
3998  __shared__ float mx[G], sum[G], alpha[G];
3999  int hb = blockIdx.x, r = blockIdx.y, t = blockIdx.z, tid = threadIdx.x, lane = tid & 31, warp = tid >> 5;
4000  // A batch's rows (`kz` > 0) are its sequences, as `lk_attention` takes them.
4001  if(kz){ kc += r * kz; vc += r * kz; }
4002  int end = pos ? (kz ? pos[r] : *pos + r) : len;
4003  int lo = win > 0 && end > win ? end - win : 0, chunk;
4004  int pe = lk_shared_chunks(end - lo, splits, minc, chunk);
4005  if(t >= pe) return;
4006  int j0 = lo + t * chunk, j1 = min(j0 + chunk, end);
4007  const KE* kb = kc + (long)hb * HD;
4008  const VE* vb = vc + (long)hb * vd + voff;
4009  long head0 = (long)r * heads + (long)hb * G;
4010  // A warp's four heads and keys; a lane's part of the width: float pairs `lane + 32·m`.
4011  int hq = warp % HQ, kg = warp / HQ;
4012  float2 qr[4][M2];
4013  #pragma unroll
4014  for(int h = 0; h < 4; ++h)
4015    #pragma unroll
4016    for(int m = 0; m < M2; ++m){
4017      int c = lane + 32 * m, hh = 4 * hq + h;
4018      qr[h][m] = hh < G && c < 2 * H4 ? ((const float2*)(q + (head0 + hh) * HD))[c] : make_float2(0.f, 0.f);
4019    }
4020  if(tid < G){ mx[tid] = -INFINITY; sum[tid] = 0.f; }
4021  float2 acc[G][VPT];
4022  #pragma unroll
4023  for(int g = 0; g < G; ++g)
4024    #pragma unroll
4025    for(int k = 0; k < VPT; ++k) acc[g][k] = make_float2(0.f, 0.f);
4026  // Step `s`'s rows into buffer `s & 1`, the rows past the chunk zero; every step a commit group.
4027  auto issue = [&](int s){
4028    int js = j0 + s * LK_ST;
4029    if(js < j1){
4030      float* dst = ks + (s & 1) * LK_ST * HD;
4031      #pragma unroll
4032      for(int u = 0; u < RF; ++u){
4033        int c = tid + u * 256;
4034        if(c < LK_ST * H4){
4035          int j = c / H4, e = c - j * H4;
4036          bool in = js + j < j1;
4037          lk_stage4(dst + j * HD + 4 * e, kb + (long)(in ? js + j : js) * kvw + 4 * e, in);
4038        }
4039      }
4040    }
4041    asm volatile("cp.async.commit_group;\n");
4042  };
4043  int steps = (j1 - j0 + LK_ST - 1) / LK_ST;
4044  issue(0);
4045  issue(1);
4046  for(int s = 0; s < steps; ++s){
4047    asm volatile("cp.async.wait_group 1;\n");
4048    __syncthreads();
4049    const float* kst = ks + (s & 1) * LK_ST * HD;
4050    int nt = min(LK_ST, j1 - (j0 + s * LK_ST));
4051    float a[NV];
4052    #pragma unroll
4053    for(int i = 0; i < NV; ++i) a[i] = 0.f;
4054    #pragma unroll
4055    for(int m = 0; m < M2; ++m){
4056      int c = lane + 32 * m;
4057      if(c < 2 * H4){
4058        #pragma unroll
4059        for(int n = 0; n < TN; ++n){
4060          float2 k = ((const float2*)(kst + (kg * TN + n) * HD))[c];
4061          #pragma unroll
4062          for(int h = 0; h < 4; ++h){
4063            a[h * TN + n] = fmaf(qr[h][m].x, k.x, a[h * TN + n]);
4064            a[h * TN + n] = fmaf(qr[h][m].y, k.y, a[h * TN + n]);
4065          }
4066        }
4067      }
4068    }
4069    float tot = lk_lane_sums<NV>(a);
4070    {
4071      int i = lane & (NV - 1), hh = 4 * hq + i / TN, j = kg * TN + i % TN;
4072      if(lane < NV && hh < G) sc[j * GP + hh] = j < nt ? tot * scale : -INFINITY;
4073    }
4074    __syncthreads();
4075    // Each head's running maximum and sum over the step: a half-warp a head, a lane a key.
4076    {
4077      int g = warp + 8 * (lane >> 4), j = lane & 15;
4078      bool live = g < G;
4079      float s0 = live ? sc[j * GP + g] : -INFINITY, mo = live ? mx[g] : -INFINITY, m = s0;
4080      #pragma unroll
4081      for(int o = 8; o > 0; o >>= 1) m = fmaxf(m, __shfl_xor_sync(0xffffffffu, m, o));
4082      m = fmaxf(m, mo);
4083      float pv = s0 == -INFINITY ? 0.f : expf(s0 - m), ss = pv;
4084      if(live) sc[j * GP + g] = pv;
4085      #pragma unroll
4086      for(int o = 8; o > 0; o >>= 1) ss += __shfl_xor_sync(0xffffffffu, ss, o);
4087      if(live && j == 0){ float al = mo == -INFINITY ? 0.f : expf(mo - m); alpha[g] = al; sum[g] = fmaf(sum[g], al, ss); mx[g] = m; }
4088    }
4089    __syncthreads();
4090    // Every head's values weighed in, `VPT` pairs a thread, each value read once from the step's rows.
4091    #pragma unroll
4092    for(int k = 0; k < VPT; ++k){
4093      int e = tid + k * 256;
4094      if(2 * e < vd){
4095        #pragma unroll
4096        for(int g = 0; g < G; ++g){ acc[g][k].x *= alpha[g]; acc[g][k].y *= alpha[g]; }
4097        for(int j = 0; j < nt; ++j){
4098          float2 v = VK ? *(const float2*)(kst + j * HD + voff + 2 * e) : lk_from2(vb + (long)(j0 + s * LK_ST + j) * vw + 2 * e);
4099          #pragma unroll
4100          for(int c4 = 0; c4 < HQ; ++c4){
4101            float4 w = ((const float4*)(sc + j * GP))[c4];
4102            float wv[4] = {w.x, w.y, w.z, w.w};
4103            #pragma unroll
4104            for(int i = 0; i < 4; ++i)
4105              if(4 * c4 + i < G){
4106                acc[4 * c4 + i][k].x = fmaf(wv[i], v.x, acc[4 * c4 + i][k].x);
4107                acc[4 * c4 + i][k].y = fmaf(wv[i], v.y, acc[4 * c4 + i][k].y);
4108              }
4109          }
4110        }
4111      }
4112    }
4113    __syncthreads();
4114    issue(s + 2);
4115  }
4116  if(pe == 1){
4117    #pragma unroll
4118    for(int g = 0; g < G; ++g){
4119      float sk = sinks ? sinks[hb * G + g] : -INFINITY, m = fmaxf(sk, mx[g]), f = expf(mx[g] - m);
4120      float l = fmaf(sum[g], f, sinks ? expf(sk - m) : 0.f);
4121      #pragma unroll
4122      for(int k = 0; k < VPT; ++k){
4123        int e = tid + k * 256;
4124        lk_attn_store<QO>(out, qo, (head0 + g) * vd + 2 * e, 2 * e < vd, acc[g][k].x * f / l, acc[g][k].y * f / l);
4125      }
4126    }
4127    return;
4128  }
4129  long stride = (long)vd + 2;
4130  #pragma unroll
4131  for(int g = 0; g < G; ++g){
4132    float* pp = part + ((head0 + g) * splits + t) * stride;
4133    if(tid == 0){ pp[0] = mx[g]; pp[1] = sum[g]; }
4134    #pragma unroll
4135    for(int k = 0; k < VPT; ++k){
4136      int e = tid + k * 256;
4137      if(2 * e < vd) ((float2*)(pp + 2))[e] = acc[g][k];
4138    }
4139  }
4140}
4141// The fold of `lk_attention_shared`'s chunks: a block a head of a row and 128 of its values, each thread's pair of
4142// values summed over the chunks in order, sixteen chunks' pairs read at once — the first sixteen while a warp takes
4143// the chunks' factors (each chunk's maximum against the head's, sink included) and the denominator.
4144template<int QO = 0>
4145__global__ void __launch_bounds__(64) lk_attention_fold(const float* __restrict__ part, const int* __restrict__ pos,
4146    const float* __restrict__ sinks, float* __restrict__ out, int len, int win, int vd, int heads, int minc, int splits,
4147    int seqs = 0, lk_qout qo = {}){
4148  extern __shared__ float lk_ff[];
4149  __shared__ float fl;
4150  int h = blockIdx.x, r = blockIdx.y, tid = threadIdx.x, lane = tid & 31;
4151  int end = pos ? (seqs ? pos[r] : *pos + r) : len;
4152  int lo = win > 0 && end > win ? end - win : 0, chunk;
4153  int pe = lk_shared_chunks(end - lo, splits, minc, chunk);
4154  if(pe == 1) return;
4155  long head = (long)r * heads + h, stride = (long)vd + 2;
4156  const float* hp = part + head * splits * stride;
4157  int e = blockIdx.z * 64 + tid;
4158  bool in = 2 * e < vd;
4159  float2 v[16];
4160  #pragma unroll
4161  for(int i = 0; i < 16; ++i) v[i] = in && i < pe ? __ldcg((const float2*)(hp + i * stride + 2) + e) : make_float2(0.f, 0.f);
4162  if(tid < 32){
4163    float m = sinks ? sinks[h] : -INFINITY;
4164    for(int u = lane; u < pe; u += 32) m = fmaxf(m, __ldcg(hp + u * stride));
4165    m = lk_warp_max(m);
4166    float l = 0.f;
4167    for(int u = lane; u < pe; u += 32){
4168      float mu = __ldcg(hp + u * stride), f = mu > -INFINITY ? expf(mu - m) : 0.f;
4169      lk_ff[u] = f;
4170      l = fmaf(__ldcg(hp + u * stride + 1), f, l);
4171    }
4172    l = lk_warp_sum(l);
4173    if(lane == 0) fl = sinks ? l + expf(sinks[h] - m) : l;
4174  }
4175  __syncthreads();
4176  float2 a = make_float2(0.f, 0.f);
4177  for(int u0 = 0; u0 < pe; u0 += 16){
4178    if(u0 > 0)
4179      #pragma unroll
4180      for(int i = 0; i < 16; ++i) v[i] = in && u0 + i < pe ? __ldcg((const float2*)(hp + (u0 + i) * stride + 2) + e) : make_float2(0.f, 0.f);
4181    #pragma unroll
4182    for(int i = 0; i < 16; ++i)
4183      if(u0 + i < pe){ a.x = fmaf(v[i].x, lk_ff[u0 + i], a.x); a.y = fmaf(v[i].y, lk_ff[u0 + i], a.y); }
4184  }
4185  lk_attn_store<QO>(out, qo, head * vd + 2 * e, in, a.x / fl, a.y / fl);
4186}
4187"#;
4188
4189/// The most query heads `lk_attention_shared` takes in its one block: four warps of four heads.
4190pub const ATTN_SHARED_HEADS: usize = 16;
4191
4192/// The cached rows `lk_attention_shared` stages a step (`LK_ST` in its source).
4193pub const ATTN_SHARED_STEP: usize = 16;
4194
4195/// The value pairs a block of `lk_attention_fold` folds, a thread each.
4196pub const ATTN_FOLD_PAIRS: usize = 64;
4197
4198/// The most chunks `lk_attention_shared` cuts a row's span of `span` positions into, the decode step's in every form:
4199/// one block a streaming multiprocessor (`sms`), its shared memory a block's, and no more than give each chunk
4200/// `ATTN_MIN_SPLIT` positions.
4201pub fn attn_shared_splits(span: usize, sms: usize) -> usize {
4202    sms.clamp(1, span.div_ceil(ATTN_MIN_SPLIT).max(1))
4203}
4204
4205/// The heads `lk_attention_shared` pads its `g` heads to: whole warps of four.
4206pub fn attn_shared_padded_heads(g: usize) -> usize {
4207    4 * if g <= 4 { 1 } else if g <= 8 { 2 } else { 4 }
4208}
4209
4210/// The dynamic shared memory of a block of `lk_attention_shared` over `g` heads of `hd`: two steps' rows, and a step's
4211/// scores of every padded head.
4212pub fn attn_shared_smem_bytes(g: usize, hd: usize) -> usize {
4213    (2 * ATTN_SHARED_STEP * hd + ATTN_SHARED_STEP * attn_shared_padded_heads(g)) * 4
4214}
4215
4216/// Every group of `every` consecutive values of `x`, its `width` from `from`: `y[g·width + i] = x[g·every + from + i]`.
4217/// A wide chunk's attention in tiles: a block takes `ATTN_TILE_Q` query vectors — `HG` heads of one key/value group
4218/// over `ATTN_TILE_Q / HG` consecutive rows — and walks the keys its rows attend 64 at a time. Each tile's scores are
4219/// taken over the head width in chunks of 32 staged in shared memory, a thread 4 queries by 2 keys; then each query's
4220/// running maximum and sum (the online softmax); then the tile's weighed values, eight keys' values staged at a time,
4221/// a thread 4 queries by `VI` groups of 4 values 128 apart. Row `r` attends the keys `lk_attention` gives it — `[lo,
4222/// end)`, `end` its position, `lo` its window's start — and a sink joins each head's denominator. Every sum is `f32`.
4223/// Split at `kh` (when `kt` is given), each query and key is two parts: a query's first `kh` values its own, `qp` apart
4224/// a (row, head) in `q`, the rest `qtp` apart in `qt`; a key's first `kh` its group's own in `kc`, the rest the key
4225/// row's in `kt` from `kto` (rows `ktw` apart), every group's alike — an expanded latent attention's, each head's query
4226/// read in place in the query projection and its rotated part, each head's expanded key and the rotated key the heads
4227/// share, read in place in the cache.
4228const ATTENTION_TILED: &str = r#"
4229#define LK_FQ 32
4230#define LK_FK 64
4231#define LK_FD 32
4232#define LK_FV 8
4233template<int HG, int VI, typename KE = float, typename VE = float, typename TE = float>
4234__global__ void __launch_bounds__(256) lk_attention_tiled(const float* __restrict__ q, const KE* __restrict__ kc,
4235    const VE* __restrict__ vc, const int* __restrict__ pos, const float* __restrict__ sinks, float* __restrict__ out,
4236    int len, int win, int hd, int vd, int group, int heads, int kvw, int vw, int voff, float scale, int rows,
4237    const float* __restrict__ qt = nullptr, long qp = 0, long qtp = 0, const TE* __restrict__ kt = nullptr, long ktw = 0,
4238    long kto = 0, int kh = 0){
4239  constexpr int BR = LK_FQ / HG;
4240  extern __shared__ __align__(16) float lk_fa[];
4241  float* qs = lk_fa;                       // [LK_FD][LK_FQ]: a chunk of the queries
4242  float* ks = qs + LK_FD * LK_FQ;          // [LK_FD][LK_FK]: the same chunk of the tile's keys
4243  float* ps = ks + LK_FD * LK_FK;          // [LK_FK][LK_FQ]: the tile's scores, then its weights
4244  float* vs = ps + LK_FK * LK_FQ;          // [LK_FV][vd]: eight keys' values
4245  __shared__ float mq[LK_FQ], lq[LK_FQ], aq[LK_FQ];
4246  __shared__ int loq[LK_FQ], endq[LK_FQ], span[2];
4247  // Scores: lane `q8` a group of 4 queries, lane `k4` and the warp a pair of keys. Values: lane `q8` the same 4
4248  // queries, lane `k4` and the warp a group of 4 values, `VI` groups 128 apart.
4249  int tid = threadIdx.x, lane = tid & 31, warp = tid >> 5, q8 = lane & 7, k4 = lane >> 3, kp = 4 * warp + k4;
4250  int r0 = blockIdx.x * BR, h0 = blockIdx.y * HG;
4251  long koff = (long)(h0 / group) * (kt ? kh : hd), vo = voff + (long)(h0 / group) * vd;
4252  if(tid < LK_FQ){
4253    int r = r0 + tid / HG;
4254    int end = r < rows ? (pos ? *pos + r : len) : 0;
4255    endq[tid] = end; loq[tid] = win > 0 && end > win ? end - win : 0;
4256    mq[tid] = -INFINITY; lq[tid] = 0.f;
4257  }
4258  __syncthreads();
4259  if(tid == 0){
4260    int lo = 0x7fffffff, hi = 0;
4261    for(int i = 0; i < LK_FQ; ++i) if(endq[i] > 0){ lo = min(lo, loq[i]); hi = max(hi, endq[i]); }
4262    span[0] = hi > 0 ? lo : 0; span[1] = hi;
4263  }
4264  __syncthreads();
4265  int jlo = span[0], jhi = span[1];
4266  float o[4][VI][4];
4267  #pragma unroll
4268  for(int a = 0; a < 4; ++a)
4269    #pragma unroll
4270    for(int i = 0; i < VI; ++i)
4271      #pragma unroll
4272      for(int c = 0; c < 4; ++c) o[a][i][c] = 0.f;
4273  for(int jt = jlo; jt < jhi; jt += LK_FK){
4274    // The tile's scores: queries 4·q8 … 4·q8 + 3 against keys 2·kp, 2·kp + 1.
4275    float s[4][2];
4276    #pragma unroll
4277    for(int a = 0; a < 4; ++a){ s[a][0] = 0.f; s[a][1] = 0.f; }
4278    // A chunk of the queries' and keys' values, four a thread (two fours of keys): fetched a chunk ahead, so their loads
4279    // are in flight while the chunk before multiplies.
4280    auto fetch_q = [&](int d0){
4281      int qi = tid >> 3, dd = (tid & 7) * 4, r = r0 + qi / HG, h = h0 + qi % HG, d = d0 + dd;
4282      long u = (long)r * heads + h;
4283      if(r >= rows || d >= hd) return make_float4(0.f, 0.f, 0.f, 0.f);
4284      return !kt ? *(const float4*)(q + u * hd + d) : d < kh ? *(const float4*)(q + u * qp + d) : *(const float4*)(qt + u * qtp + (d - kh));
4285    };
4286    auto fetch_k = [&](int d0, int part){
4287      int c = tid + part * 256, kj = c >> 3, d = d0 + (c & 7) * 4, j = jt + kj;
4288      if(j >= jhi || d >= hd) return make_float4(0.f, 0.f, 0.f, 0.f);
4289      return kt && d >= kh ? lk_from4(kt + (long)j * ktw + kto + (d - kh)) : lk_from4(kc + (long)j * kvw + koff + d);
4290    };
4291    float4 nq = fetch_q(0), nk0 = fetch_k(0, 0), nk1 = fetch_k(0, 1);
4292    for(int d0 = 0; d0 < hd; d0 += LK_FD){
4293      {
4294        int qi = tid >> 3, dd = (tid & 7) * 4;
4295        qs[(dd + 0) * LK_FQ + qi] = nq.x; qs[(dd + 1) * LK_FQ + qi] = nq.y;
4296        qs[(dd + 2) * LK_FQ + qi] = nq.z; qs[(dd + 3) * LK_FQ + qi] = nq.w;
4297      }
4298      #pragma unroll
4299      for(int u = 0; u < 2; ++u){
4300        int c = tid + u * 256, kj = c >> 3, dd = (c & 7) * 4;
4301        float4 v = u == 0 ? nk0 : nk1;
4302        ks[(dd + 0) * LK_FK + kj] = v.x; ks[(dd + 1) * LK_FK + kj] = v.y;
4303        ks[(dd + 2) * LK_FK + kj] = v.z; ks[(dd + 3) * LK_FK + kj] = v.w;
4304      }
4305      __syncthreads();
4306      if(d0 + LK_FD < hd){ nq = fetch_q(d0 + LK_FD); nk0 = fetch_k(d0 + LK_FD, 0); nk1 = fetch_k(d0 + LK_FD, 1); }
4307      #pragma unroll 8
4308      for(int dd = 0; dd < LK_FD; ++dd){
4309        float4 a4 = *(const float4*)(qs + dd * LK_FQ + 4 * q8);
4310        float2 b2 = *(const float2*)(ks + dd * LK_FK + 2 * kp);
4311        s[0][0] = fmaf(a4.x, b2.x, s[0][0]); s[0][1] = fmaf(a4.x, b2.y, s[0][1]);
4312        s[1][0] = fmaf(a4.y, b2.x, s[1][0]); s[1][1] = fmaf(a4.y, b2.y, s[1][1]);
4313        s[2][0] = fmaf(a4.z, b2.x, s[2][0]); s[2][1] = fmaf(a4.z, b2.y, s[2][1]);
4314        s[3][0] = fmaf(a4.w, b2.x, s[3][0]); s[3][1] = fmaf(a4.w, b2.y, s[3][1]);
4315      }
4316      __syncthreads();
4317    }
4318    #pragma unroll
4319    for(int a = 0; a < 4; ++a)
4320      #pragma unroll
4321      for(int b = 0; b < 2; ++b){
4322        int qi = 4 * q8 + a, j = jt + 2 * kp + b;
4323        ps[(2 * kp + b) * LK_FQ + qi] = j >= loq[qi] && j < endq[qi] ? s[a][b] * scale : -INFINITY;
4324      }
4325    __syncthreads();
4326    // Each query's running maximum and sum, eight threads a query.
4327    {
4328      int qi = tid >> 3, part = tid & 7;
4329      float m = -INFINITY;
4330      #pragma unroll
4331      for(int k = 0; k < 8; ++k) m = fmaxf(m, ps[(part * 8 + k) * LK_FQ + qi]);
4332      #pragma unroll
4333      for(int x = 1; x < 8; x <<= 1) m = fmaxf(m, __shfl_xor_sync(0xffffffffu, m, x));
4334      float mo = mq[qi], mn = fmaxf(mo, m), sum = 0.f;
4335      #pragma unroll
4336      for(int k = 0; k < 8; ++k){
4337        float* sp = ps + (part * 8 + k) * LK_FQ + qi;
4338        float p = *sp == -INFINITY ? 0.f : expf(*sp - mn);
4339        *sp = p; sum += p;
4340      }
4341      #pragma unroll
4342      for(int x = 1; x < 8; x <<= 1) sum += __shfl_xor_sync(0xffffffffu, sum, x);
4343      // Every lane's read of the query's maximum before the first lane writes it.
4344      __syncwarp();
4345      if(part == 0){
4346        float al = mo == -INFINITY ? 0.f : expf(mo - mn);
4347        aq[qi] = al; lq[qi] = fmaf(lq[qi], al, sum); mq[qi] = mn;
4348      }
4349    }
4350    __syncthreads();
4351    // The tile's weighed values: queries 4·q8 … 4·q8 + 3, values 4·kp + 128·i.
4352    #pragma unroll
4353    for(int a = 0; a < 4; ++a){
4354      float al = aq[4 * q8 + a];
4355      #pragma unroll
4356      for(int i = 0; i < VI; ++i)
4357        #pragma unroll
4358        for(int c = 0; c < 4; ++c) o[a][i][c] *= al;
4359    }
4360    int nk = min(LK_FK, jhi - jt), v4 = vd >> 2;
4361    // Eight keys' values, `VI` fours a thread, fetched a group ahead.
4362    float4 nv[VI];
4363    auto fetch_v = [&](int k0){
4364      #pragma unroll
4365      for(int i = 0; i < VI; ++i){
4366        int c = tid + i * 256, kk = c / v4, e = c - kk * v4, j = jt + k0 + kk;
4367        nv[i] = c < LK_FV * v4 && j < jhi ? lk_from4(vc + (long)j * vw + vo + 4 * e) : make_float4(0.f, 0.f, 0.f, 0.f);
4368      }
4369    };
4370    fetch_v(0);
4371    for(int k0 = 0; k0 < nk; k0 += LK_FV){
4372      #pragma unroll
4373      for(int i = 0; i < VI; ++i){
4374        int c = tid + i * 256, kk = c / v4, e = c - kk * v4;
4375        if(c < LK_FV * v4) *(float4*)(vs + kk * vd + 4 * e) = nv[i];
4376      }
4377      __syncthreads();
4378      if(k0 + LK_FV < nk) fetch_v(k0 + LK_FV);
4379      #pragma unroll
4380      for(int kk = 0; kk < LK_FV; ++kk){
4381        float4 p = *(const float4*)(ps + (k0 + kk) * LK_FQ + 4 * q8);
4382        #pragma unroll
4383        for(int i = 0; i < VI; ++i){
4384          int col = 4 * kp + 128 * i;
4385          if(col < vd){
4386            float4 v = *(const float4*)(vs + kk * vd + col);
4387            o[0][i][0] = fmaf(p.x, v.x, o[0][i][0]); o[0][i][1] = fmaf(p.x, v.y, o[0][i][1]); o[0][i][2] = fmaf(p.x, v.z, o[0][i][2]); o[0][i][3] = fmaf(p.x, v.w, o[0][i][3]);
4388            o[1][i][0] = fmaf(p.y, v.x, o[1][i][0]); o[1][i][1] = fmaf(p.y, v.y, o[1][i][1]); o[1][i][2] = fmaf(p.y, v.z, o[1][i][2]); o[1][i][3] = fmaf(p.y, v.w, o[1][i][3]);
4389            o[2][i][0] = fmaf(p.z, v.x, o[2][i][0]); o[2][i][1] = fmaf(p.z, v.y, o[2][i][1]); o[2][i][2] = fmaf(p.z, v.z, o[2][i][2]); o[2][i][3] = fmaf(p.z, v.w, o[2][i][3]);
4390            o[3][i][0] = fmaf(p.w, v.x, o[3][i][0]); o[3][i][1] = fmaf(p.w, v.y, o[3][i][1]); o[3][i][2] = fmaf(p.w, v.z, o[3][i][2]); o[3][i][3] = fmaf(p.w, v.w, o[3][i][3]);
4391          }
4392        }
4393      }
4394      __syncthreads();
4395    }
4396  }
4397  #pragma unroll
4398  for(int a = 0; a < 4; ++a){
4399    int qi = 4 * q8 + a, r = r0 + qi / HG, h = h0 + qi % HG;
4400    if(r >= rows) continue;
4401    float m = mq[qi], sk = sinks ? sinks[h] : -INFINITY, mf = fmaxf(sk, m);
4402    float f = m == -INFINITY ? 0.f : expf(m - mf), l = fmaf(lq[qi], f, sinks ? expf(sk - mf) : 0.f);
4403    float* op = out + ((long)r * heads + h) * vd;
4404    #pragma unroll
4405    for(int i = 0; i < VI; ++i){
4406      int col = 4 * kp + 128 * i;
4407      if(col < vd) *(float4*)(op + col) = make_float4(o[a][i][0] * f / l, o[a][i][1] * f / l, o[a][i][2] * f / l, o[a][i][3] * f / l);
4408    }
4409  }
4410}
4411"#;
4412
4413/// A wide chunk's attention for heads to 256 wide, flash style: a block of 128 threads takes `BQ` query vectors — `HG`
4414/// heads of one key/value group over `BQ / HG` consecutive rows, their queries staged once — and walks the keys its rows
4415/// attend 64 at a time. A tile's keys arrive `LK_KD` values of the head at a time and its values `LK_VK` keys at a time,
4416/// each the next stage's by `cp.async` while this one multiplies. Of `NT` threads, a thread scores queries `tq + TQ·i`
4417/// against keys `tk + 16·j` (`TQ = NT / 16`; a `BQ / TQ` × 4 tile), each query's running maximum and sum taken across
4418/// its 16 lanes; its
4419/// weights land in shared memory a thread's queries together, and it weighs the same queries' values `4·(tv + 16·g)`
4420/// (`VD / 16` values a query). Row `r` attends `lk_attention`'s keys — `[lo, end)` — and a sink joins each head's
4421/// denominator. Split at `kh` (with `kt`), each query and key is two parts as `lk_attention_tiled` reads them. A head is
4422/// `HD` wide, its values `VD`. Every sum is `f32`.
4423const ATTENTION_FLASH: &str = r#"
4424#define LK_FB 64
4425#define LK_KD 32
4426#define LK_VK 16
4427template<int HG, int HD, int VD, int BQ, int NT = 128, typename KE = float, typename VE = float, typename TE = float>
4428__global__ void __launch_bounds__(NT) lk_attention_flash(const float* __restrict__ q, const KE* __restrict__ kc,
4429    const VE* __restrict__ vc, const int* __restrict__ pos, const float* __restrict__ sinks, float* __restrict__ out,
4430    int len, int win, int group, int heads, int kvw, int vw, int voff, float scale, int rows,
4431    const float* __restrict__ qt = nullptr, long qp = 0, long qtp = 0, const TE* __restrict__ kt = nullptr, long ktw = 0,
4432    long kto = 0, int kh = 0){
4433  constexpr int TQ = NT / 16, QI = BQ / TQ, QP = HD + 4, KP = LK_KD + 4, VP = VD + 4, PP = BQ + 4, VG = VD / 64 > 0 ? VD / 64 : 1;
4434  constexpr int BR = BQ / HG;
4435  extern __shared__ __align__(16) float lk_fl[];
4436  float* qs = lk_fl;                       // [BQ][QP]: the block's queries
4437  float* ks = qs + BQ * QP;                // [2][LK_FB][KP]: two stages of a chunk of the tile's keys
4438  float* vs = ks + 2 * LK_FB * KP;         // [2][LK_VK][VP]: two stages of the tile's values
4439  float* ps = vs + 2 * LK_VK * VP;         // [LK_FB][PP]: the tile's weights, a thread's queries together
4440  __shared__ int loq[BQ], endq[BQ], span[2];
4441  int tid = threadIdx.x, tq = tid >> 4, tk = tid & 15;
4442  int r0 = blockIdx.x * BR, h0 = blockIdx.y * HG;
4443  long koff = (long)(h0 / group) * (kt ? kh : HD), vo = voff + (long)(h0 / group) * VD;
4444  // Query `qi` of the block: head `h0 + qi % HG` of row `r0 + qi / HG`.
4445  for(int qi = tid; qi < BQ; qi += NT){
4446    int r = r0 + qi / HG;
4447    int end = r < rows ? (pos ? *pos + r : len) : 0;
4448    endq[qi] = end; loq[qi] = win > 0 && end > win ? end - win : 0;
4449  }
4450  for(int c = tid; c < BQ * (HD / 4); c += NT){
4451    int qi = c / (HD / 4), d = 4 * (c % (HD / 4)), r = r0 + qi / HG, h = h0 + qi % HG;
4452    long u = (long)r * heads + h;
4453    float4 v = make_float4(0.f, 0.f, 0.f, 0.f);
4454    if(r < rows) v = !kt ? *(const float4*)(q + u * HD + d) : d < kh ? *(const float4*)(q + u * qp + d) : *(const float4*)(qt + u * qtp + (d - kh));
4455    *(float4*)(qs + qi * QP + d) = v;
4456  }
4457  __syncthreads();
4458  if(tid == 0){
4459    int lo = 0x7fffffff, hi = 0;
4460    for(int i = 0; i < BQ; ++i) if(endq[i] > 0){ lo = min(lo, loq[i]); hi = max(hi, endq[i]); }
4461    span[0] = hi > 0 ? lo : 0; span[1] = hi;
4462  }
4463  __syncthreads();
4464  int jlo = span[0], jhi = span[1];
4465  float m[QI], l[QI], o[QI][VG][4];
4466  #pragma unroll
4467  for(int i = 0; i < QI; ++i){
4468    m[i] = -INFINITY; l[i] = 0.f;
4469    #pragma unroll
4470    for(int g = 0; g < VG; ++g)
4471      #pragma unroll
4472      for(int c = 0; c < 4; ++c) o[i][g][c] = 0.f;
4473  }
4474  // A chunk `d0` of tile `jt`'s keys into stage `st`; a step `k0` of its values into stage `st`.
4475  auto stage_k = [&](int jt, int d0, int st){
4476    float* dst = ks + st * LK_FB * KP;
4477    for(int c = tid; c < LK_FB * (LK_KD / 4); c += NT){
4478      int kj = c / (LK_KD / 4), d = d0 + 4 * (c % (LK_KD / 4)), j = jt + kj;
4479      bool in = j < jhi && d < HD;
4480      if(kt && d >= kh) lk_stage4(dst + kj * KP + (d - d0), kt + (long)(in ? j : jlo) * ktw + kto + (d - kh), in);
4481      else lk_stage4(dst + kj * KP + (d - d0), kc + (long)(in ? j : jlo) * kvw + koff + (in ? d : 0), in);
4482    }
4483    asm volatile("cp.async.commit_group;\n");
4484  };
4485  auto stage_v = [&](int jt, int k0, int st){
4486    float* dst = vs + st * LK_VK * VP;
4487    for(int c = tid; c < LK_VK * (VD / 4); c += NT){
4488      int kk = c / (VD / 4), e = 4 * (c % (VD / 4)), j = jt + k0 + kk;
4489      bool in = j < jhi;
4490      lk_stage4(dst + kk * VP + e, vc + (long)(in ? j : jlo) * vw + vo + e, in);
4491    }
4492    asm volatile("cp.async.commit_group;\n");
4493  };
4494  constexpr int DS = (HD + LK_KD - 1) / LK_KD, VS = LK_FB / LK_VK;
4495  for(int jt = jlo; jt < jhi; jt += LK_FB){
4496    // The tile's scores: queries tq + 8·i against keys tk + 16·j, over the head a chunk at a time.
4497    float s[QI][4];
4498    #pragma unroll
4499    for(int i = 0; i < QI; ++i)
4500      #pragma unroll
4501      for(int j = 0; j < 4; ++j) s[i][j] = 0.f;
4502    stage_k(jt, 0, 0);
4503    for(int dc = 0; dc < DS; ++dc){
4504      if(dc + 1 < DS){ stage_k(jt, (dc + 1) * LK_KD, (dc + 1) & 1); asm volatile("cp.async.wait_group 1;\n"); }
4505      else asm volatile("cp.async.wait_group 0;\n");
4506      __syncthreads();
4507      const float* kst = ks + (dc & 1) * LK_FB * KP;
4508      #pragma unroll
4509      for(int d4 = 0; d4 < LK_KD; d4 += 4){
4510        if(dc * LK_KD + d4 >= HD) break;
4511        float4 kv[4];
4512        #pragma unroll
4513        for(int j = 0; j < 4; ++j) kv[j] = *(const float4*)(kst + (tk + 16 * j) * KP + d4);
4514        #pragma unroll
4515        for(int i = 0; i < QI; ++i){
4516          float4 qv = *(const float4*)(qs + (tq + TQ * i) * QP + dc * LK_KD + d4);
4517          #pragma unroll
4518          for(int j = 0; j < 4; ++j){
4519            s[i][j] = fmaf(qv.x, kv[j].x, s[i][j]); s[i][j] = fmaf(qv.y, kv[j].y, s[i][j]);
4520            s[i][j] = fmaf(qv.z, kv[j].z, s[i][j]); s[i][j] = fmaf(qv.w, kv[j].w, s[i][j]);
4521          }
4522        }
4523      }
4524      __syncthreads();
4525    }
4526    stage_v(jt, 0, 0);
4527    // Each query's running maximum and sum across its 16 lanes; its weights into shared memory, a thread's together.
4528    #pragma unroll
4529    for(int i = 0; i < QI; ++i){
4530      int qi = tq + TQ * i;
4531      float mt = -INFINITY;
4532      #pragma unroll
4533      for(int j = 0; j < 4; ++j){
4534        int kj = jt + tk + 16 * j;
4535        s[i][j] = kj >= loq[qi] && kj < endq[qi] ? s[i][j] * scale : -INFINITY;
4536        mt = fmaxf(mt, s[i][j]);
4537      }
4538      #pragma unroll
4539      for(int x = 1; x < 16; x <<= 1) mt = fmaxf(mt, __shfl_xor_sync(0xffffffffu, mt, x));
4540      float mn = fmaxf(m[i], mt), sum = 0.f;
4541      #pragma unroll
4542      for(int j = 0; j < 4; ++j){
4543        float pv = s[i][j] == -INFINITY ? 0.f : expf(s[i][j] - mn);
4544        ps[(tk + 16 * j) * PP + QI * tq + i] = pv;
4545        sum += pv;
4546      }
4547      #pragma unroll
4548      for(int x = 1; x < 16; x <<= 1) sum += __shfl_xor_sync(0xffffffffu, sum, x);
4549      float al = m[i] == -INFINITY ? 0.f : expf(m[i] - mn);
4550      l[i] = fmaf(l[i], al, sum); m[i] = mn;
4551      #pragma unroll
4552      for(int g = 0; g < VG; ++g)
4553        #pragma unroll
4554        for(int c = 0; c < 4; ++c) o[i][g][c] *= al;
4555    }
4556    // The tile's weighed values, `LK_VK` keys a step: queries tq + 8·i, values 4·(tk + 16·g).
4557    int nk = min(LK_FB, jhi - jt);
4558    for(int vstep = 0; vstep < VS; ++vstep){
4559      int k0 = vstep * LK_VK;
4560      if(k0 >= nk){ asm volatile("cp.async.wait_group 0;\n"); break; }
4561      if(vstep + 1 < VS && k0 + LK_VK < nk){ stage_v(jt, k0 + LK_VK, (vstep + 1) & 1); asm volatile("cp.async.wait_group 1;\n"); }
4562      else asm volatile("cp.async.wait_group 0;\n");
4563      __syncthreads();
4564      const float* vst = vs + (vstep & 1) * LK_VK * VP;
4565      #pragma unroll 4
4566      for(int kk = 0; kk < LK_VK; ++kk){
4567        const float4* pr = (const float4*)(ps + (k0 + kk) * PP + QI * tq);
4568        float pw[QI];
4569        if constexpr(QI % 4 == 0){
4570          #pragma unroll
4571          for(int i4 = 0; i4 < QI / 4; ++i4){ float4 t = pr[i4]; pw[4 * i4] = t.x; pw[4 * i4 + 1] = t.y; pw[4 * i4 + 2] = t.z; pw[4 * i4 + 3] = t.w; }
4572        } else {
4573          #pragma unroll
4574          for(int i2 = 0; i2 < QI / 2; ++i2){ float2 t = ((const float2*)pr)[i2]; pw[2 * i2] = t.x; pw[2 * i2 + 1] = t.y; }
4575        }
4576        #pragma unroll
4577        for(int g = 0; g < VG; ++g){
4578          int col = 4 * (tk + 16 * g);
4579          if(col < VD){
4580            float4 v = *(const float4*)(vst + kk * VP + col);
4581            #pragma unroll
4582            for(int i = 0; i < QI; ++i){
4583              o[i][g][0] = fmaf(pw[i], v.x, o[i][g][0]); o[i][g][1] = fmaf(pw[i], v.y, o[i][g][1]);
4584              o[i][g][2] = fmaf(pw[i], v.z, o[i][g][2]); o[i][g][3] = fmaf(pw[i], v.w, o[i][g][3]);
4585            }
4586          }
4587        }
4588      }
4589      __syncthreads();
4590    }
4591  }
4592  #pragma unroll
4593  for(int i = 0; i < QI; ++i){
4594    int qi = tq + TQ * i, r = r0 + qi / HG, h = h0 + qi % HG;
4595    if(r >= rows) continue;
4596    float sk = sinks ? sinks[h] : -INFINITY, mf = fmaxf(sk, m[i]);
4597    float f = m[i] == -INFINITY ? 0.f : expf(m[i] - mf), lf = fmaf(l[i], f, sinks ? expf(sk - mf) : 0.f);
4598    float* op = out + ((long)r * heads + h) * VD;
4599    #pragma unroll
4600    for(int g = 0; g < VG; ++g){
4601      int col = 4 * (tk + 16 * g);
4602      if(col < VD) *(float4*)(op + col) = make_float4(o[i][g][0] * f / lf, o[i][g][1] * f / lf, o[i][g][2] * f / lf, o[i][g][3] * f / lf);
4603    }
4604  }
4605}
4606"#;
4607
4608/// A wide chunk's attention on the f16 tensor cores, the one-word numerics' (llama.cpp's precision: f16 queries, keys,
4609/// values and weights, `f32` sums): a block of four warps takes 64 query vectors — `HG` heads of one key/value group
4610/// over `64 / HG` consecutive rows — a warp 16 of them, its queries held in registers as `mma` fragments. Each tile of
4611/// 64 keys (32 where heads or values pass 192 wide, `attn_mma_keys`) is staged in shared memory as f16, keys and values
4612/// rows padded eight values; a warp's scores are
4613/// `m16n8k16` products against the keys (`ldmatrix`), its rows' running maxima and sums taken across the four lanes of
4614/// each row, and its weights — the scores' fragments rounded to f16 — weigh the values (`ldmatrix.trans`) straight from
4615/// registers. Row `r` attends `lk_attention`'s keys — `[lo, end)` — and a sink joins each head's denominator. Split at
4616/// `kh` (with `kt`), each query and key is two parts as `lk_attention_tiled` reads them. A head is `HD` wide, its
4617/// values `VD`, both whole multiples of 16 and at most 256.
4618const ATTENTION_MMA: &str = r#"
4619__device__ __forceinline__ void lk_mma_h16(float* c, const unsigned* a, const unsigned* b){
4620  asm volatile("mma.sync.aligned.m16n8k16.row.col.f32.f16.f16.f32 {%0,%1,%2,%3}, {%4,%5,%6,%7}, {%8,%9}, {%0,%1,%2,%3};\n"
4621               : "+f"(c[0]), "+f"(c[1]), "+f"(c[2]), "+f"(c[3]) : "r"(a[0]), "r"(a[1]), "r"(a[2]), "r"(a[3]), "r"(b[0]), "r"(b[1]));
4622}
4623__device__ __forceinline__ void lk_ldsm4(unsigned* r, const void* p){
4624  unsigned s = (unsigned)__cvta_generic_to_shared(p);
4625  asm volatile("ldmatrix.sync.aligned.m8n8.x4.shared.b16 {%0,%1,%2,%3}, [%4];\n" : "=r"(r[0]), "=r"(r[1]), "=r"(r[2]), "=r"(r[3]) : "r"(s));
4626}
4627__device__ __forceinline__ void lk_ldsm4_t(unsigned* r, const void* p){
4628  unsigned s = (unsigned)__cvta_generic_to_shared(p);
4629  asm volatile("ldmatrix.sync.aligned.m8n8.x4.trans.shared.b16 {%0,%1,%2,%3}, [%4];\n" : "=r"(r[0]), "=r"(r[1]), "=r"(r[2]), "=r"(r[3]) : "r"(s));
4630}
4631__device__ __forceinline__ unsigned lk_h2(float a, float b){
4632  __half2 h = __floats2half2_rn(a, b);
4633  return *(unsigned*)&h;
4634}
4635template<int HG, int HD, int VD, typename KE = float, typename VE = float, typename TE = float>
4636__global__ void __launch_bounds__(128) lk_attention_mma(const float* __restrict__ q, const KE* __restrict__ kc,
4637    const VE* __restrict__ vc, const int* __restrict__ pos, const float* __restrict__ sinks, float* __restrict__ out,
4638    int len, int win, int group, int heads, int kvw, int vw, int voff, float scale, int rows,
4639    const float* __restrict__ qt = nullptr, long qp = 0, long qtp = 0, const TE* __restrict__ kt = nullptr, long ktw = 0,
4640    long kto = 0, int kh = 0){
4641  constexpr int BQ = 64, BR = BQ / HG, KS = HD / 16, NV = VD / 8, KP = HD + 8, VP = VD + 8;
4642  // The keys a tile: 64, or 32 where heads or values pass 192 wide, so the values' sums fit a warp's registers.
4643  constexpr int KT = HD > 192 || VD > 192 ? 32 : 64;
4644  extern __shared__ __align__(16) __half lk_hm[];
4645  __half* ks = lk_hm;                      // [KT][KP]: the tile's keys
4646  __half* vs = ks + KT * KP;               // [KT][VP]: its values
4647  __shared__ int loq[BQ], endq[BQ], span[2];
4648  int tid = threadIdx.x, lane = tid & 31, warp = tid >> 5, g = lane >> 2, t4 = lane & 3;
4649  int r0 = blockIdx.x * BR, h0 = blockIdx.y * HG;
4650  long koff = (long)(h0 / group) * (kt ? kh : HD), vo = voff + (long)(h0 / group) * VD;
4651  if(tid < BQ){
4652    int r = r0 + tid / HG;
4653    int end = r < rows ? (pos ? *pos + r : len) : 0;
4654    endq[tid] = end; loq[tid] = win > 0 && end > win ? end - win : 0;
4655  }
4656  __syncthreads();
4657  if(tid == 0){
4658    int lo = 0x7fffffff, hi = 0;
4659    for(int i = 0; i < BQ; ++i) if(endq[i] > 0){ lo = min(lo, loq[i]); hi = max(hi, endq[i]); }
4660    span[0] = hi > 0 ? lo : 0; span[1] = hi;
4661  }
4662  // The warp's queries: rows g and g + 8 of its 16, as A fragments of every 16 values of the head.
4663  int qa = 16 * warp + g, qb = qa + 8;
4664  auto qrow = [&](int qi, int d) -> const float* {
4665    int r = r0 + qi / HG, h = h0 + qi % HG;
4666    if(r >= rows) return nullptr;
4667    long u = (long)r * heads + h;
4668    return !kt ? q + u * HD + d : d < kh ? q + u * qp + d : qt + u * qtp + (d - kh);
4669  };
4670  unsigned qf[KS][4];
4671  #pragma unroll
4672  for(int k = 0; k < KS; ++k){
4673    int d0 = 16 * k + 2 * t4, d1 = d0 + 8;
4674    const float *a0 = qrow(qa, d0), *a1 = qrow(qb, d0), *a2 = qrow(qa, d1), *a3 = qrow(qb, d1);
4675    float2 v0 = a0 ? *(const float2*)a0 : make_float2(0.f, 0.f), v1 = a1 ? *(const float2*)a1 : make_float2(0.f, 0.f);
4676    float2 v2 = a2 ? *(const float2*)a2 : make_float2(0.f, 0.f), v3 = a3 ? *(const float2*)a3 : make_float2(0.f, 0.f);
4677    qf[k][0] = lk_h2(v0.x, v0.y); qf[k][1] = lk_h2(v1.x, v1.y); qf[k][2] = lk_h2(v2.x, v2.y); qf[k][3] = lk_h2(v3.x, v3.y);
4678  }
4679  __syncthreads();
4680  int jlo = span[0], jhi = span[1];
4681  int loa = loq[qa], enda = endq[qa], lob = loq[qb], endb = endq[qb];
4682  float o[NV][4], ma = -INFINITY, mb = -INFINITY, la = 0.f, lb = 0.f;
4683  #pragma unroll
4684  for(int n = 0; n < NV; ++n)
4685    #pragma unroll
4686    for(int c = 0; c < 4; ++c) o[n][c] = 0.f;
4687  for(int jt = jlo; jt < jhi; jt += KT){
4688    // The tile's keys and values, as f16, rows past the span zero.
4689    for(int c = tid; c < KT * (HD / 4); c += 128){
4690      int kj = c / (HD / 4), d = 4 * (c % (HD / 4)), j = jt + kj;
4691      float4 v = make_float4(0.f, 0.f, 0.f, 0.f);
4692      if(j < jhi) v = kt && d >= kh ? lk_from4(kt + (long)j * ktw + kto + (d - kh)) : lk_from4(kc + (long)j * kvw + koff + d);
4693      unsigned* dst = (unsigned*)(ks + kj * KP + d);
4694      dst[0] = lk_h2(v.x, v.y); dst[1] = lk_h2(v.z, v.w);
4695    }
4696    for(int c = tid; c < KT * (VD / 4); c += 128){
4697      int kj = c / (VD / 4), e = 4 * (c % (VD / 4)), j = jt + kj;
4698      float4 v = j < jhi ? lk_from4(vc + (long)j * vw + vo + e) : make_float4(0.f, 0.f, 0.f, 0.f);
4699      unsigned* dst = (unsigned*)(vs + kj * VP + e);
4700      dst[0] = lk_h2(v.x, v.y); dst[1] = lk_h2(v.z, v.w);
4701    }
4702    __syncthreads();
4703    // Scores: the warp's 16 queries against the tile's keys, tiles of eight.
4704    float s[KT / 8][4];
4705    #pragma unroll
4706    for(int n = 0; n < KT / 8; ++n)
4707      #pragma unroll
4708      for(int c = 0; c < 4; ++c) s[n][c] = 0.f;
4709    int mi = lane >> 3, ri = lane & 7;
4710    #pragma unroll
4711    for(int k = 0; k < KS; ++k)
4712      #pragma unroll
4713      for(int np = 0; np < KT / 16; ++np){
4714        unsigned b[4];
4715        lk_ldsm4(b, ks + (16 * np + (mi >= 2 ? 8 : 0) + ri) * KP + 16 * k + ((mi & 1) ? 8 : 0));
4716        lk_mma_h16(s[2 * np], qf[k], b);
4717        lk_mma_h16(s[2 * np + 1], qf[k], b + 2);
4718      }
4719    // Each row's running maximum and sum across its four lanes; the weights rounded to f16 as A fragments.
4720    float xa = -INFINITY, xb = -INFINITY;
4721    #pragma unroll
4722    for(int n = 0; n < KT / 8; ++n)
4723      #pragma unroll
4724      for(int c = 0; c < 2; ++c){
4725        int j = jt + 8 * n + 2 * t4 + c;
4726        s[n][c] = j >= loa && j < enda ? s[n][c] * scale : -INFINITY;
4727        s[n][c + 2] = j >= lob && j < endb ? s[n][c + 2] * scale : -INFINITY;
4728        xa = fmaxf(xa, s[n][c]); xb = fmaxf(xb, s[n][c + 2]);
4729      }
4730    #pragma unroll
4731    for(int x = 1; x < 4; x <<= 1){ xa = fmaxf(xa, __shfl_xor_sync(0xffffffffu, xa, x)); xb = fmaxf(xb, __shfl_xor_sync(0xffffffffu, xb, x)); }
4732    float na = fmaxf(ma, xa), nb = fmaxf(mb, xb), sa = 0.f, sb = 0.f;
4733    #pragma unroll
4734    for(int n = 0; n < KT / 8; ++n)
4735      #pragma unroll
4736      for(int c = 0; c < 2; ++c){
4737        s[n][c] = s[n][c] == -INFINITY ? 0.f : expf(s[n][c] - na);
4738        s[n][c + 2] = s[n][c + 2] == -INFINITY ? 0.f : expf(s[n][c + 2] - nb);
4739        sa += s[n][c]; sb += s[n][c + 2];
4740      }
4741    #pragma unroll
4742    for(int x = 1; x < 4; x <<= 1){ sa += __shfl_xor_sync(0xffffffffu, sa, x); sb += __shfl_xor_sync(0xffffffffu, sb, x); }
4743    float aa = ma == -INFINITY ? 0.f : expf(ma - na), ab = mb == -INFINITY ? 0.f : expf(mb - nb);
4744    la = fmaf(la, aa, sa); lb = fmaf(lb, ab, sb); ma = na; mb = nb;
4745    #pragma unroll
4746    for(int n = 0; n < NV; ++n){ o[n][0] *= aa; o[n][1] *= aa; o[n][2] *= ab; o[n][3] *= ab; }
4747    // The weighed values: 16 keys a step, two tiles of eight values a load.
4748    #pragma unroll
4749    for(int k = 0; k < KT / 16; ++k){
4750      unsigned pa[4] = {lk_h2(s[2 * k][0], s[2 * k][1]), lk_h2(s[2 * k][2], s[2 * k][3]),
4751                        lk_h2(s[2 * k + 1][0], s[2 * k + 1][1]), lk_h2(s[2 * k + 1][2], s[2 * k + 1][3])};
4752      #pragma unroll
4753      for(int np = 0; np < NV / 2; ++np){
4754        unsigned b[4];
4755        lk_ldsm4_t(b, vs + (16 * k + ((mi & 1) ? 8 : 0) + ri) * VP + 16 * np + (mi >= 2 ? 8 : 0));
4756        lk_mma_h16(o[2 * np], pa, b);
4757        lk_mma_h16(o[2 * np + 1], pa, b + 2);
4758      }
4759    }
4760    __syncthreads();
4761  }
4762  // Each row's outputs, its sink in the denominator.
4763  #pragma unroll
4764  for(int half = 0; half < 2; ++half){
4765    int qi = half ? qb : qa, r = r0 + qi / HG, h = h0 + qi % HG;
4766    if(r >= rows) continue;
4767    float m = half ? mb : ma, l = half ? lb : la;
4768    float sk = sinks ? sinks[h] : -INFINITY, mf = fmaxf(sk, m);
4769    float f = m == -INFINITY ? 0.f : expf(m - mf), lf = fmaf(l, f, sinks ? expf(sk - mf) : 0.f);
4770    float* op = out + ((long)r * heads + h) * VD;
4771    #pragma unroll
4772    for(int n = 0; n < NV; ++n)
4773      *(float2*)(op + 8 * n + 2 * t4) = make_float2(o[n][2 * half] * f / lf, o[n][2 * half + 1] * f / lf);
4774  }
4775}
4776"#;
4777
4778/// The query vectors a block of the f16 tensor-core attention (`lk_attention_mma`) takes, a warp 16 of them.
4779pub const ATTN_MMA_QUERIES: usize = 64;
4780
4781/// The keys a tile of the f16 tensor-core attention takes: 64, or 32 where heads or values pass 192 wide.
4782pub fn attn_mma_keys(hd: usize, vd: usize) -> usize {
4783    if hd > 192 || vd > 192 {
4784        32
4785    } else {
4786        64
4787    }
4788}
4789
4790/// The f16 tensor-core attention block's dynamic shared memory: a tile's keys (`attn_mma_keys`) and their values as
4791/// f16, rows padded eight values.
4792pub fn attn_mma_smem_bytes(hd: usize, vd: usize) -> usize {
4793    attn_mma_keys(hd, vd) * ((hd + 8) * 2 + (vd + 8) * 2)
4794}
4795
4796/// A wide chunk's attention on the int8 tensor cores in two words, the two-word numerics' (`lk_attention_i8`, each
4797/// query, key, value and weight `s·(h + l/128)` under its row's largest magnitude, `≈ 2⁻¹⁵` of it). `lk_kv_two_words`
4798/// takes every key and value row the chunk's rows attend into two words once, a block a run of 32 keys of one key/value
4799/// group: keys `[kv][lpad][HD]`, values a column a row a run at a time `[kv][lpad / 32][VD][32]` with each run's keys in
4800/// the order the weights' A fragments take them — positions `4b … 4b + 3` the keys `2b, 2b + 1, 2b + 8, 2b + 9` (`b < 4`),
4801/// 16 on for `b ≥ 4`, so a score tile's accumulators are the weights' fragments as they lie — and each row's scale
4802/// `[kv][lpad]`; a split key's parts are read as `lk_attention_tiled` reads them. A block of four warps then takes 64 query
4803/// vectors — `HG` heads of one group over `64 / HG` consecutive rows — a warp 16 of them, its queries' two words in
4804/// registers, and walks tiles of 64 keys (32 where heads or values pass 128 wide) from a whole tile below its rows' span,
4805/// each tile's keys, value runs and scales arriving by `cp.async` — the next tile's keys while this one's weights weigh
4806/// its values, the next tile's values while the next scores are taken. A score is `m16n8k32` dots folded into one exact
4807/// integer, `128·qₕ·kₕ + qₕ·kₗ + qₗ·kₕ`, and its low dot `qₗ·kₗ` into another, times both scales — every product of the
4808/// stored words — so the scores are the two-word operands' to `f32` rounding; the running maximum and sum are
4809/// `lk_attention_mma`'s; each
4810/// weight times its value row's scale is taken into three words under its row's largest in the tile, and the weighed
4811/// values fold alike, their next-finest products in a second integer: the attention computes, to `f32` rounding, the
4812/// attention of its queries, keys and values taken into two words. Row `r` attends `lk_attention`'s keys — `[lo, end)` — and a sink joins each head's denominator.
4813/// Split at `kh` (with `qt`), each query is two parts. A head is `HD` wide, its values `VD`, both whole multiples of 32 and
4814/// at most 256.
4815const ATTENTION_I8: &str = r#"
4816template<int HD, int VD, typename KE = float, typename VE = float, typename TE = float>
4817__global__ void __launch_bounds__(256) lk_kv_two_words(const KE* __restrict__ kc, const VE* __restrict__ vc,
4818    const int* __restrict__ pos, int rows, int len, int kvw, int vw, int voff, int lpad,
4819    signed char* __restrict__ k8h, signed char* __restrict__ k8l, float* __restrict__ ksc,
4820    signed char* __restrict__ v8h, signed char* __restrict__ v8l, float* __restrict__ vsc,
4821    const TE* __restrict__ kt = nullptr, long ktw = 0, long kto = 0, int kh = 0){
4822  __shared__ __align__(16) int th[32][VD / 4], tl[32][VD / 4];  // the run's value rows' words, a key a row
4823  int hi = pos ? min(len, *pos + rows - 1) : len;
4824  int j0 = 32 * blockIdx.x, kv = blockIdx.y;
4825  if(j0 >= hi) return;
4826  int lane = threadIdx.x & 31, warp = threadIdx.x >> 5;
4827  long koff = (long)kv * (kt ? kh : HD), vo = voff + (long)kv * VD, row = (long)kv * lpad;
4828  auto amax4 = [](float m, float4 v){ return fmaxf(fmaxf(m, fmaxf(fabsf(v.x), fabsf(v.y))), fmaxf(fabsf(v.z), fabsf(v.w))); };
4829  constexpr int KI = (HD / 4 + 31) / 32, VI = (VD / 4 + 31) / 32;
4830  for(int kk = warp; kk < 32; kk += 8){
4831    int j = j0 + kk;
4832    bool in = j < hi;
4833    float4 v[KI > VI ? KI : VI];
4834    float a = 0.f;
4835    #pragma unroll
4836    for(int i = 0; i < KI; ++i){
4837      int c = lane + 32 * i, d = 4 * c;
4838      v[i] = !(in && c < HD / 4) ? make_float4(0.f, 0.f, 0.f, 0.f)
4839             : kt && d >= kh ? lk_from4(kt + (long)j * ktw + kto + (d - kh)) : lk_from4(kc + (long)j * kvw + koff + d);
4840      a = amax4(a, v[i]);
4841    }
4842    #pragma unroll
4843    for(int x = 16; x > 0; x >>= 1) a = fmaxf(a, __shfl_xor_sync(0xffffffffu, a, x));
4844    float s = lk_two_scale(a), rs = 1.f / s;
4845    #pragma unroll
4846    for(int i = 0; i < KI; ++i){
4847      int c = lane + 32 * i;
4848      if(c >= HD / 4) break;
4849      int h[4], l[4];
4850      lk_two_words_r(v[i].x, s, rs, h[0], l[0]); lk_two_words_r(v[i].y, s, rs, h[1], l[1]); lk_two_words_r(v[i].z, s, rs, h[2], l[2]); lk_two_words_r(v[i].w, s, rs, h[3], l[3]);
4851      *(int*)(k8h + (row + j) * HD + 4 * c) = lk_int8x4(h[0], h[1], h[2], h[3]);
4852      *(int*)(k8l + (row + j) * HD + 4 * c) = lk_int8x4(l[0], l[1], l[2], l[3]);
4853    }
4854    if(lane == 0) ksc[row + j] = in ? s : 0.f;
4855    a = 0.f;
4856    #pragma unroll
4857    for(int i = 0; i < VI; ++i){
4858      int c = lane + 32 * i;
4859      v[i] = in && c < VD / 4 ? lk_from4(vc + (long)j * vw + vo + 4 * c) : make_float4(0.f, 0.f, 0.f, 0.f);
4860      a = amax4(a, v[i]);
4861    }
4862    #pragma unroll
4863    for(int x = 16; x > 0; x >>= 1) a = fmaxf(a, __shfl_xor_sync(0xffffffffu, a, x));
4864    s = lk_two_scale(a); rs = 1.f / s;
4865    #pragma unroll
4866    for(int i = 0; i < VI; ++i){
4867      int c = lane + 32 * i;
4868      if(c >= VD / 4) break;
4869      int h[4], l[4];
4870      lk_two_words_r(v[i].x, s, rs, h[0], l[0]); lk_two_words_r(v[i].y, s, rs, h[1], l[1]); lk_two_words_r(v[i].z, s, rs, h[2], l[2]); lk_two_words_r(v[i].w, s, rs, h[3], l[3]);
4871      th[kk][c] = lk_int8x4(h[0], h[1], h[2], h[3]); tl[kk][c] = lk_int8x4(l[0], l[1], l[2], l[3]);
4872    }
4873    if(lane == 0) vsc[row + j] = in ? s : 0.f;
4874  }
4875  __syncthreads();
4876  long run = ((long)kv * (lpad / 32) + blockIdx.x) * VD * 32;
4877  // Each value column's 32 keys in the weights' order, 16 bytes a thread.
4878  const unsigned char* bh = (const unsigned char*)th;
4879  const unsigned char* bl = (const unsigned char*)tl;
4880  for(int c = threadIdx.x; c < VD * 2; c += 256){
4881    int d = c >> 1, half = c & 1;
4882    unsigned wh[4], wl[4];
4883    #pragma unroll
4884    for(int w = 0; w < 4; ++w){
4885      wh[w] = 0u; wl[w] = 0u;
4886      #pragma unroll
4887      for(int x = 0; x < 4; ++x){
4888        int kk = 16 * half + 2 * w + (x & 1) + 8 * (x >> 1);
4889        wh[w] |= (unsigned)bh[kk * VD + d] << (8 * x); wl[w] |= (unsigned)bl[kk * VD + d] << (8 * x);
4890      }
4891    }
4892    *(int4*)(v8h + run + d * 32 + 16 * half) = make_int4((int)wh[0], (int)wh[1], (int)wh[2], (int)wh[3]);
4893    *(int4*)(v8l + run + d * 32 + 16 * half) = make_int4((int)wl[0], (int)wl[1], (int)wl[2], (int)wl[3]);
4894  }
4895}
4896template<int HG, int HD, int VD>
4897__global__ void __launch_bounds__(128) lk_attention_i8(const float* __restrict__ q, const signed char* __restrict__ k8h,
4898    const signed char* __restrict__ k8l, const float* __restrict__ ksg, const signed char* __restrict__ v8h,
4899    const signed char* __restrict__ v8l, const float* __restrict__ vsg, int lpad, const int* __restrict__ pos,
4900    const float* __restrict__ sinks, float* __restrict__ out, int len, int win, int group, int heads, float scale, int rows,
4901    const float* __restrict__ qt = nullptr, long qp = 0, long qtp = 0, int kh = 0){
4902  constexpr int BQ = 64, BR = BQ / HG, KS = HD / 32;
4903  constexpr int KT = HD > 128 || VD > 128 ? 32 : 64;
4904  constexpr int KP = HD + 16, VP = KT + 16;
4905  extern __shared__ __align__(16) signed char lk_im[];
4906  signed char* kh8 = lk_im;                 // [KT][KP]: the tile's keys, high words
4907  signed char* kl8 = kh8 + KT * KP;         // [KT][KP]: their low words
4908  signed char* vh8 = kl8 + KT * KP;         // [VD][VP]: the tile's values a column a row, the keys in the weights' order
4909  signed char* vl8 = vh8 + VD * VP;         // [VD][VP]: their low words
4910  float* ksc2 = (float*)(vl8 + VD * VP);    // [2][KT]: each key's scale, a buffer a tile's parity
4911  float* vsc2 = ksc2 + 2 * KT;              // [2][KT]: each value row's scale
4912  __shared__ int loq[BQ], endq[BQ], span[2];
4913  int tid = threadIdx.x, lane = tid & 31, warp = tid >> 5, g = lane >> 2, t4 = lane & 3;
4914  int r0 = blockIdx.x * BR, h0 = blockIdx.y * HG;
4915  long row = (long)(h0 / group) * lpad;
4916  if(tid < BQ){
4917    int r = r0 + tid / HG;
4918    int end = r < rows ? (pos ? *pos + r : len) : 0;
4919    endq[tid] = end; loq[tid] = win > 0 && end > win ? end - win : 0;
4920  }
4921  __syncthreads();
4922  if(tid == 0){
4923    int lo = 0x7fffffff, hi = 0;
4924    for(int i = 0; i < BQ; ++i) if(endq[i] > 0){ lo = min(lo, loq[i]); hi = max(hi, endq[i]); }
4925    span[0] = hi > 0 ? lo : 0; span[1] = hi;
4926  }
4927  // The warp's queries: rows g and g + 8 of its 16, each its two words under its largest magnitude's scale, as A
4928  // fragments of every 32 values of the head.
4929  int qa = 16 * warp + g, qb = qa + 8;
4930  auto qload = [&](int qi, int d) -> float4 {
4931    int r = r0 + qi / HG, h = h0 + qi % HG;
4932    if(r >= rows) return make_float4(0.f, 0.f, 0.f, 0.f);
4933    long u = (long)r * heads + h;
4934    return *(const float4*)(!qt ? q + u * HD + d : d < kh ? q + u * qp + d : qt + u * qtp + (d - kh));
4935  };
4936  auto amax4 = [](float m, float4 v){ return fmaxf(fmaxf(m, fmaxf(fabsf(v.x), fabsf(v.y))), fmaxf(fabsf(v.z), fabsf(v.w))); };
4937  float xa = 0.f, xb = 0.f;
4938  #pragma unroll
4939  for(int k = 0; k < KS; ++k)
4940    #pragma unroll
4941    for(int half = 0; half < 2; ++half){
4942      int d = 32 * k + 16 * half + 4 * t4;
4943      xa = amax4(xa, qload(qa, d)); xb = amax4(xb, qload(qb, d));
4944    }
4945  #pragma unroll
4946  for(int x = 1; x < 4; x <<= 1){ xa = fmaxf(xa, __shfl_xor_sync(0xffffffffu, xa, x)); xb = fmaxf(xb, __shfl_xor_sync(0xffffffffu, xb, x)); }
4947  const float sqa = lk_two_scale(xa), sqb = lk_two_scale(xb);
4948  int qh[KS][4], ql[KS][4];
4949  #pragma unroll
4950  for(int k = 0; k < KS; ++k)
4951    #pragma unroll
4952    for(int f = 0; f < 4; ++f){
4953      float4 v = qload(f & 1 ? qb : qa, 32 * k + 16 * (f >> 1) + 4 * t4);
4954      float s = f & 1 ? sqb : sqa;
4955      int h0_, l0_, h1_, l1_, h2_, l2_, h3_, l3_;
4956      lk_two_words(v.x, s, h0_, l0_); lk_two_words(v.y, s, h1_, l1_); lk_two_words(v.z, s, h2_, l2_); lk_two_words(v.w, s, h3_, l3_);
4957      qh[k][f] = lk_int8x4(h0_, h1_, h2_, h3_); ql[k][f] = lk_int8x4(l0_, l1_, l2_, l3_);
4958    }
4959  __syncthreads();
4960  // Tiles from a whole tile below the span's start, so each is whole runs of the values' order and whole scale chunks.
4961  int jlo = span[0] / KT * KT, jhi = span[1];
4962  int loa = loq[qa], enda = endq[qa], lob = loq[qb], endb = endq[qb];
4963  const float fqa = sqa * scale * 0.0078125f, fqb = sqb * scale * 0.0078125f;
4964  float o[VD / 8][4], ma = -INFINITY, mb = -INFINITY, la = 0.f, lb = 0.f;
4965  #pragma unroll
4966  for(int n = 0; n < VD / 8; ++n)
4967    #pragma unroll
4968    for(int c = 0; c < 4; ++c) o[n][c] = 0.f;
4969  // A tile's keys' two words and both its scales, into parity `pb`'s scale buffers; its value runs' two words. Past the
4970  // span zero. Each a `cp.async` group.
4971  auto load_k = [&](int jt){
4972    int pb = ((jt - jlo) / KT) & 1;
4973    for(int c = tid; c < KT * HD / 16; c += 128){
4974      int kj = c / (HD / 16), o16 = 16 * (c % (HD / 16));
4975      bool in = jt + kj < jhi;
4976      long at = (row + (in ? jt + kj : 0)) * HD + o16;
4977      lk_cp16(kh8 + kj * KP + o16, k8h + at, in); lk_cp16(kl8 + kj * KP + o16, k8l + at, in);
4978    }
4979    for(int c = tid; c < KT / 4; c += 128){
4980      bool in = jt + 4 * c < jhi;
4981      lk_cp16(ksc2 + KT * pb + 4 * c, ksg + row + (in ? jt + 4 * c : 0), in); lk_cp16(vsc2 + KT * pb + 4 * c, vsg + row + (in ? jt + 4 * c : 0), in);
4982    }
4983    asm volatile("cp.async.commit_group;\n");
4984  };
4985  auto load_v = [&](int jt){
4986    for(int c = tid; c < VD * KT / 16; c += 128){
4987      int d = c / (KT / 16), o16 = 16 * (c % (KT / 16)), r = (jt + o16) >> 5;
4988      bool in = 32 * r < jhi;
4989      long at = ((row / 32 + (in ? r : 0)) * VD + d) * 32 + (o16 & 31);
4990      lk_cp16(vh8 + d * VP + o16, v8h + at, in); lk_cp16(vl8 + d * VP + o16, v8l + at, in);
4991    }
4992    asm volatile("cp.async.commit_group;\n");
4993  };
4994  if(jlo < jhi){ load_k(jlo); load_v(jlo); }
4995  for(int jt = jlo; jt < jhi; jt += KT){
4996    asm volatile("cp.async.wait_group 1;\n");
4997    __syncthreads();
4998    const float* ksc = ksc2 + KT * (((jt - jlo) / KT) & 1);
4999    const float* vsc = vsc2 + KT * (((jt - jlo) / KT) & 1);
5000    // Scores: the warp's 16 queries against the tile's keys, every tile of eight keys at once; a score's high dot and its
5001    // two cross dots fold into one exact integer, 128·qₕ·kₕ + qₕ·kₗ + qₗ·kₕ, its low dot qₗ·kₗ, 128 times finer, into
5002    // another.
5003    float s[KT / 8][4];
5004    int mi = lane >> 3, ri = lane & 7;
5005    {
5006      int c[KT / 8][4];
5007      #pragma unroll
5008      for(int n = 0; n < KT / 8; ++n)
5009        #pragma unroll
5010        for(int i = 0; i < 4; ++i) c[n][i] = 0;
5011      #pragma unroll
5012      for(int k = 0; k < KS; ++k)
5013        #pragma unroll
5014        for(int np = 0; np < KT / 16; ++np){
5015          int bh[4];
5016          lk_ldsm_s8(bh, kh8 + (16 * np + (mi >= 2 ? 8 : 0) + ri) * KP + 32 * k + ((mi & 1) ? 16 : 0));
5017          lk_mma_s8(c[2 * np], qh[k], bh); lk_mma_s8(c[2 * np + 1], qh[k], bh + 2);
5018        }
5019      #pragma unroll
5020      for(int n = 0; n < KT / 8; ++n)
5021        #pragma unroll
5022        for(int i = 0; i < 4; ++i) c[n][i] *= 128;
5023      #pragma unroll
5024      for(int k = 0; k < KS; ++k){
5025        #pragma unroll
5026        for(int np = 0; np < KT / 16; ++np){
5027          int bl[4];
5028          lk_ldsm_s8(bl, kl8 + (16 * np + (mi >= 2 ? 8 : 0) + ri) * KP + 32 * k + ((mi & 1) ? 16 : 0));
5029          lk_mma_s8(c[2 * np], qh[k], bl); lk_mma_s8(c[2 * np + 1], qh[k], bl + 2);
5030        }
5031        #pragma unroll
5032        for(int np = 0; np < KT / 16; ++np){
5033          int bh[4];
5034          lk_ldsm_s8(bh, kh8 + (16 * np + (mi >= 2 ? 8 : 0) + ri) * KP + 32 * k + ((mi & 1) ? 16 : 0));
5035          lk_mma_s8(c[2 * np], ql[k], bh); lk_mma_s8(c[2 * np + 1], ql[k], bh + 2);
5036        }
5037      }
5038      int cl[KT / 8][4];
5039      #pragma unroll
5040      for(int n = 0; n < KT / 8; ++n)
5041        #pragma unroll
5042        for(int i = 0; i < 4; ++i) cl[n][i] = 0;
5043      #pragma unroll
5044      for(int k = 0; k < KS; ++k)
5045        #pragma unroll
5046        for(int np = 0; np < KT / 16; ++np){
5047          int bl[4];
5048          lk_ldsm_s8(bl, kl8 + (16 * np + (mi >= 2 ? 8 : 0) + ri) * KP + 32 * k + ((mi & 1) ? 16 : 0));
5049          lk_mma_s8(cl[2 * np], ql[k], bl); lk_mma_s8(cl[2 * np + 1], ql[k], bl + 2);
5050        }
5051      #pragma unroll
5052      for(int n = 0; n < KT / 8; ++n)
5053        #pragma unroll
5054        for(int i = 0; i < 4; ++i)
5055          s[n][i] = ((float)c[n][i] + (float)cl[n][i] * 0.0078125f) * (i < 2 ? fqa : fqb) * ksc[8 * n + 2 * t4 + (i & 1)];
5056    }
5057    __syncthreads();
5058    if(jt + KT < jhi) load_k(jt + KT);
5059    else asm volatile("cp.async.commit_group;\n");
5060    // Each row's running maximum and sum across its four lanes.
5061    float ya = -INFINITY, yb = -INFINITY;
5062    #pragma unroll
5063    for(int n = 0; n < KT / 8; ++n)
5064      #pragma unroll
5065      for(int c = 0; c < 2; ++c){
5066        int j = jt + 8 * n + 2 * t4 + c;
5067        if(!(j >= loa && j < enda)) s[n][c] = -INFINITY;
5068        if(!(j >= lob && j < endb)) s[n][c + 2] = -INFINITY;
5069        ya = fmaxf(ya, s[n][c]); yb = fmaxf(yb, s[n][c + 2]);
5070      }
5071    #pragma unroll
5072    for(int x = 1; x < 4; x <<= 1){ ya = fmaxf(ya, __shfl_xor_sync(0xffffffffu, ya, x)); yb = fmaxf(yb, __shfl_xor_sync(0xffffffffu, yb, x)); }
5073    float na = fmaxf(ma, ya), nb = fmaxf(mb, yb), sa = 0.f, sb = 0.f;
5074    #pragma unroll
5075    for(int n = 0; n < KT / 8; ++n)
5076      #pragma unroll
5077      for(int c = 0; c < 2; ++c){
5078        s[n][c] = s[n][c] == -INFINITY ? 0.f : expf(s[n][c] - na);
5079        s[n][c + 2] = s[n][c + 2] == -INFINITY ? 0.f : expf(s[n][c + 2] - nb);
5080        sa += s[n][c]; sb += s[n][c + 2];
5081      }
5082    #pragma unroll
5083    for(int x = 1; x < 4; x <<= 1){ sa += __shfl_xor_sync(0xffffffffu, sa, x); sb += __shfl_xor_sync(0xffffffffu, sb, x); }
5084    float aa = ma == -INFINITY ? 0.f : expf(ma - na), ab = mb == -INFINITY ? 0.f : expf(mb - nb);
5085    la = fmaf(la, aa, sa); lb = fmaf(lb, ab, sb); ma = na; mb = nb;
5086    #pragma unroll
5087    for(int n = 0; n < VD / 8; ++n){ o[n][0] *= aa; o[n][1] *= aa; o[n][2] *= ab; o[n][3] *= ab; }
5088    // The weights times each value row's scale, each row's three words under its largest's scale — so the weights move
5089    // the outputs a hundredth of what the operands' two words do — as A fragments of every 32 keys: positions 4·t4 … of
5090    // a run its tiles 4k and 4k + 1, 16 + 4·t4 … its tiles 4k + 2 and 4k + 3.
5091    float wa = 0.f, wb = 0.f;
5092    #pragma unroll
5093    for(int n = 0; n < KT / 8; ++n)
5094      #pragma unroll
5095      for(int c = 0; c < 2; ++c){
5096        float sv = vsc[8 * n + 2 * t4 + c];
5097        s[n][c] *= sv; s[n][c + 2] *= sv;
5098        wa = fmaxf(wa, s[n][c]); wb = fmaxf(wb, s[n][c + 2]);
5099      }
5100    #pragma unroll
5101    for(int x = 1; x < 4; x <<= 1){ wa = fmaxf(wa, __shfl_xor_sync(0xffffffffu, wa, x)); wb = fmaxf(wb, __shfl_xor_sync(0xffffffffu, wb, x)); }
5102    const float swa = lk_two_scale(wa), swb = lk_two_scale(wb);
5103    const float ra = 1.f / swa, rb = 1.f / swb;
5104    int ah[KT / 32][4], al[KT / 32][4], aq[KT / 32][4];
5105    #pragma unroll
5106    for(int k = 0; k < KT / 32; ++k)
5107      #pragma unroll
5108      for(int f = 0; f < 4; ++f){
5109        int n = 4 * k + 2 * (f >> 1), c = 2 * (f & 1);
5110        float sw = f & 1 ? swb : swa, rw = f & 1 ? rb : ra;
5111        float e[4] = {s[n][c], s[n][c + 1], s[n + 1][c], s[n + 1][c + 1]};
5112        int h[4], l[4], q[4];
5113        #pragma unroll
5114        for(int i = 0; i < 4; ++i){
5115          h[i] = __float2int_rn(e[i] * rw);
5116          float r1 = __fmaf_rn(-(float)h[i], sw, e[i]);
5117          l[i] = __float2int_rn(r1 * rw * 128.f);
5118          q[i] = __float2int_rn(__fmaf_rn(-(float)l[i], sw * 0.0078125f, r1) * rw * 16384.f);
5119        }
5120        ah[k][f] = lk_int8x4(h[0], h[1], h[2], h[3]); al[k][f] = lk_int8x4(l[0], l[1], l[2], l[3]); aq[k][f] = lk_int8x4(q[0], q[1], q[2], q[3]);
5121      }
5122    asm volatile("cp.async.wait_group 1;\n");
5123    __syncthreads();
5124    // The weighed values: four tiles of eight value columns at a time, each sum folded as the scores' are — the weights'
5125    // and values' leading products, 128·wₕ·vₕ + wₕ·vₗ + wₗ·vₕ, in one exact integer, the next, wₗ·vₗ + wₗₗ·vₕ, 128 times
5126    // finer, in another.
5127    const float fwa = swa * 0.0078125f, fwb = swb * 0.0078125f;
5128    constexpr int NG = VD / 32, NPG = VD / 16 / NG;
5129    #pragma unroll
5130    for(int gq = 0; gq < NG; ++gq){
5131      int c[2 * NPG][4];
5132      #pragma unroll
5133      for(int n = 0; n < 2 * NPG; ++n)
5134        #pragma unroll
5135        for(int i = 0; i < 4; ++i) c[n][i] = 0;
5136      #pragma unroll
5137      for(int k = 0; k < KT / 32; ++k)
5138        #pragma unroll
5139        for(int np = 0; np < NPG; ++np){
5140          int bh[4];
5141          lk_ldsm_s8(bh, vh8 + (16 * (gq * NPG + np) + (mi >= 2 ? 8 : 0) + ri) * VP + 32 * k + ((mi & 1) ? 16 : 0));
5142          lk_mma_s8(c[2 * np], ah[k], bh); lk_mma_s8(c[2 * np + 1], ah[k], bh + 2);
5143        }
5144      #pragma unroll
5145      for(int n = 0; n < 2 * NPG; ++n)
5146        #pragma unroll
5147        for(int i = 0; i < 4; ++i) c[n][i] *= 128;
5148      #pragma unroll
5149      for(int k = 0; k < KT / 32; ++k){
5150        #pragma unroll
5151        for(int np = 0; np < NPG; ++np){
5152          int bl[4];
5153          lk_ldsm_s8(bl, vl8 + (16 * (gq * NPG + np) + (mi >= 2 ? 8 : 0) + ri) * VP + 32 * k + ((mi & 1) ? 16 : 0));
5154          lk_mma_s8(c[2 * np], ah[k], bl); lk_mma_s8(c[2 * np + 1], ah[k], bl + 2);
5155        }
5156        #pragma unroll
5157        for(int np = 0; np < NPG; ++np){
5158          int bh[4];
5159          lk_ldsm_s8(bh, vh8 + (16 * (gq * NPG + np) + (mi >= 2 ? 8 : 0) + ri) * VP + 32 * k + ((mi & 1) ? 16 : 0));
5160          lk_mma_s8(c[2 * np], al[k], bh); lk_mma_s8(c[2 * np + 1], al[k], bh + 2);
5161        }
5162      }
5163      int cl[2 * NPG][4];
5164      #pragma unroll
5165      for(int n = 0; n < 2 * NPG; ++n)
5166        #pragma unroll
5167        for(int i = 0; i < 4; ++i) cl[n][i] = 0;
5168      #pragma unroll
5169      for(int k = 0; k < KT / 32; ++k){
5170        #pragma unroll
5171        for(int np = 0; np < NPG; ++np){
5172          int bl[4];
5173          lk_ldsm_s8(bl, vl8 + (16 * (gq * NPG + np) + (mi >= 2 ? 8 : 0) + ri) * VP + 32 * k + ((mi & 1) ? 16 : 0));
5174          lk_mma_s8(cl[2 * np], al[k], bl); lk_mma_s8(cl[2 * np + 1], al[k], bl + 2);
5175        }
5176        #pragma unroll
5177        for(int np = 0; np < NPG; ++np){
5178          int bh[4];
5179          lk_ldsm_s8(bh, vh8 + (16 * (gq * NPG + np) + (mi >= 2 ? 8 : 0) + ri) * VP + 32 * k + ((mi & 1) ? 16 : 0));
5180          lk_mma_s8(cl[2 * np], aq[k], bh); lk_mma_s8(cl[2 * np + 1], aq[k], bh + 2);
5181        }
5182      }
5183      #pragma unroll
5184      for(int n = 0; n < 2 * NPG; ++n)
5185        #pragma unroll
5186        for(int i = 0; i < 4; ++i)
5187          o[2 * gq * NPG + n][i] = fmaf((float)c[n][i] + (float)cl[n][i] * 0.0078125f, i < 2 ? fwa : fwb, o[2 * gq * NPG + n][i]);
5188    }
5189    __syncthreads();
5190    if(jt + KT < jhi) load_v(jt + KT);
5191    else asm volatile("cp.async.commit_group;\n");
5192  }
5193  asm volatile("cp.async.wait_group 0;\n");
5194  // Each row's outputs, its sink in the denominator.
5195  #pragma unroll
5196  for(int half = 0; half < 2; ++half){
5197    int qi = half ? qb : qa, r = r0 + qi / HG, h = h0 + qi % HG;
5198    if(r >= rows) continue;
5199    float m = half ? mb : ma, l = half ? lb : la;
5200    float sk = sinks ? sinks[h] : -INFINITY, mf = fmaxf(sk, m);
5201    float f = m == -INFINITY ? 0.f : expf(m - mf), lf = fmaf(l, f, sinks ? expf(sk - mf) : 0.f);
5202    float* op = out + ((long)r * heads + h) * VD;
5203    #pragma unroll
5204    for(int n = 0; n < VD / 8; ++n)
5205      *(float2*)(op + 8 * n + 2 * t4) = make_float2(o[n][2 * half] * f / lf, o[n][2 * half + 1] * f / lf);
5206  }
5207}
5208"#;
5209
5210/// The query vectors a block of the two-word attention (`lk_attention_i8`) takes, a warp 16 of them.
5211pub const ATTN_I8_QUERIES: usize = 64;
5212
5213/// The keys a tile of the two-word attention takes: 64, or 32 where heads or values pass 128 wide.
5214pub const fn attn_i8_keys(hd: usize, vd: usize) -> usize {
5215    if hd > 128 || vd > 128 {
5216        32
5217    } else {
5218        64
5219    }
5220}
5221
5222/// The two-word attention block's dynamic shared memory: a tile's keys' and values' two words, rows padded 16 bytes, and
5223/// both its scales in two buffers.
5224pub const fn attn_i8_smem_bytes(hd: usize, vd: usize) -> usize {
5225    let kt = attn_i8_keys(hd, vd);
5226    2 * kt * (hd + 16) + 2 * vd * (kt + 16) + 16 * kt
5227}
5228
5229const _: () = assert!(
5230    attn_i8_smem_bytes(128, 128) <= 48 * 1024 && attn_i8_smem_bytes(256, 256) <= 48 * 1024,
5231    "the two-word attention keeps the default shared memory at every width it takes"
5232);
5233
5234/// The key rows a key/value group's two words take for a cache of `len` positions: whole tiles of 64.
5235pub fn attn_i8_rows(len: usize) -> usize {
5236    len.next_multiple_of(64)
5237}
5238
5239/// The two-word attention's scratch for a cache of `len` positions over `groups` key/value groups: the keys' high and
5240/// low words, the values', and each row's two scales — in bytes.
5241pub fn attn_i8_scratch(len: usize, groups: usize, hd: usize, vd: usize) -> [usize; 3] {
5242    let rows = groups * attn_i8_rows(len);
5243    [2 * rows * hd, 2 * rows * vd, 2 * rows * 4]
5244}
5245
5246const SLICE: &str = r#"
5247template<typename XE>
5248__global__ void lk_slice(const XE* __restrict__ x, float* __restrict__ y, long n, int every, int from, int width){
5249  long o = (long)blockIdx.x * blockDim.x + threadIdx.x; if(o >= n) return;
5250  long g = o / width;
5251  y[o] = lk_from(x[g * every + from + (o - g * width)]);
5252}
5253"#;
5254
5255/// Each unit's `ha` values of `a`, then its `hb` values of `b` — into the rows of a table from the row `yrow` names. A
5256/// batch's (`yz` > 0): row `r` of `heads` units into its own table, `yz` values on from the last's, at its own row.
5257const JOIN: &str = r#"
5258__global__ void lk_join(const float* __restrict__ a, const float* __restrict__ b, lk_out y,
5259                        const int* __restrict__ yrow, long ypitch, long n, int ha, int hb, int heads = 1, long yz = 0){
5260  long o = (long)blockIdx.x * blockDim.x + threadIdx.x; if(o >= n) return;
5261  long u = o / (ha + hb); int i = (int)(o - u * (ha + hb));
5262  float v = i < ha ? a[u * ha + i] : b[u * hb + (i - ha)];
5263  if(yz){ long r = u / heads; y[r * yz + (long)(yrow[r] - 1) * ypitch + (o - r * heads * (ha + hb))] = v; return; }
5264  LK_ROW(y, yrow, ypitch)[o] = v;
5265}
5266"#;
5267
5268/// The per-head matmul `Y[t, h·b + r] = Σ_e X[t, h·a + e]·W[h·a + e, r]` over the `M` rows of `X` (`M ≤ 16`) and `H`
5269/// heads, the matrix's rows read in place in format `F`, the activation under numerics `Q` — `f32` with `f64` sums under
5270/// `Q` 0, `f32` with `f32` sums under `Q` 3 (the lane's own, [`head_mode`]), quantized under 1 and 2. `lk_head_gemv`: the rows are
5271/// the heads' outputs (`b` rows of `a` a head), a warp per output row dotting it with its head's part of each activation
5272/// row. `lk_head_axpy`: the rows are the heads' inputs (`a` rows of `b` a head), a block per (32 outputs, head), each
5273/// warp weighing the 32-weight sub-block of its rows by their inputs, a lane decoding its own weight (`lk_level`) — the
5274/// activation's quantized value under `Q` 1 and 2 — and the warps' sums added. Head `h` of row `t` reads its inputs
5275/// `(t·H + h)·xp + xo` into `X` (`xp`, `xo` whole blocks) and writes its outputs `(t·H + h)·yp + yo` into `Y`'s rows,
5276/// from the row `yrow` names. `lk_head_axpy_staged` (under the quantized numerics where [`axpy_staged`] says): a block of
5277/// `R` row groups of `W` warps takes `W` sub-blocks of a head's outputs, the head's rows' units holding them staged in
5278/// shared memory by 16-byte loads from each row's start aligned down (`delta` bytes before it), a tile of rows at a time;
5279/// a lane decodes its rows' sub-block whole (`lk_sub`, or a Q8_0 block's values and scale) and weighs it by the row's
5280/// input into its 32 sums, a transposing butterfly leaves lane `l` its warp's sum for output `l`, and the row groups'
5281/// sums add in group order.
5282const HEADS: &str = r#"
5283template<int F, int Q, int M>
5284__global__ void lk_head_gemv(lk_w w, const float* __restrict__ x, const signed char* __restrict__ xq,
5285                             const signed char* __restrict__ xl, const float* __restrict__ xs, lk_out y,
5286                             int H, int a, int b, long xp, long xo, const int* __restrict__ yrow, long ypitch, long yp, long yo){
5287  int o = (blockIdx.x * blockDim.x + threadIdx.x) >> 5; if(o >= H * b) return;
5288  long off = (long)(o / b) * xp + xo, ld = (long)H * xp;
5289  float v[M];
5290  constexpr bool X = lk_f32_acts<Q>();
5291  lk_dot<F, Q, M>(w, o, a, X ? x + off : nullptr, X ? nullptr : xq + off, Q == 2 ? xl + off : nullptr,
5292                  X ? nullptr : xs + (off >> 5), ld, v);
5293  if((threadIdx.x & 31) == 0){
5294    lk_out yr = LK_ROW(y, yrow, ypitch) + (long)(o / b) * yp + yo + o % b;
5295    #pragma unroll
5296    for(int t = 0; t < M; ++t) yr[(long)t * H * yp] = v[t];
5297  }
5298}
5299// The bytes of a format's smallest unit decoded alone and the sub-blocks it holds: a K-quant super-block (eight), a
5300// legacy block (one); a Q8_0 block is staged as its 32 values and, after a row's values, its scale.
5301template<int F> __host__ __device__ constexpr int lk_unit_bytes(){
5302  return F == 2 ? 18 : F == 3 ? 20 : F == 6 ? 22 : F == 7 ? 24 : F == 39 ? 17 : F == 20 ? 18 : F == 10 ? 84 : F == 11 ? 110 :
5303         F == 12 ? 144 : F == 13 ? 176 : F == 14 ? 210 : F == 23 ? 136 : 34;
5304}
5305template<int F> __host__ __device__ constexpr int lk_unit_subs(){ return F == 10 || F == 11 || F == 12 || F == 13 || F == 14 || F == 23 ? 8 : 1; }
5306// A staged row: the units of `W` sub-blocks (and a unit more, should they straddle two), 15 bytes for the start's
5307// alignment, rounded to an odd number of words so the lanes' rows fall on distinct banks.
5308template<int F, int W> __host__ __device__ constexpr int lk_axpy_pitch(){
5309  return F == 8 ? ((W * 34 + 3) / 4 % 2 == 0 ? (W * 34 + 3) / 4 * 4 + 4 : (W * 34 + 3) / 4 * 4)
5310                : ((((W + lk_unit_subs<F>() - 1) / lk_unit_subs<F>() + 1) * lk_unit_bytes<F>() + 15 + 3) / 4 % 2 == 0
5311                       ? (((W + lk_unit_subs<F>() - 1) / lk_unit_subs<F>() + 1) * lk_unit_bytes<F>() + 15 + 3) / 4 * 4 + 4
5312                       : (((W + lk_unit_subs<F>() - 1) / lk_unit_subs<F>() + 1) * lk_unit_bytes<F>() + 15 + 3) / 4 * 4);
5313}
5314template<int O, typename T>
5315__device__ __forceinline__ void lk_fly_step(T* acc, int lane){
5316  bool up = lane & O;
5317  #pragma unroll
5318  for(int i = 0; i < O; ++i){
5319    T send = up ? acc[i] : acc[i + O];
5320    T keep = up ? acc[i + O] : acc[i];
5321    acc[i] = keep + __shfl_xor_sync(0xffffffffu, send, O);
5322  }
5323}
5324// The sums over a warp's lanes of each lane's 32 values, lane `l` ending with sum `l` in `acc[0]`.
5325template<typename T>
5326__device__ __forceinline__ void lk_fly(T* acc, int lane){
5327  lk_fly_step<16>(acc, lane); lk_fly_step<8>(acc, lane); lk_fly_step<4>(acc, lane); lk_fly_step<2>(acc, lane); lk_fly_step<1>(acc, lane);
5328}
5329template<int F, int Q, int M, int W, int R>
5330__global__ void __launch_bounds__(32 * W * R) lk_head_axpy_staged(lk_w w, const float* __restrict__ x,
5331    const signed char* __restrict__ xq, const signed char* __restrict__ xl, const float* __restrict__ xs,
5332    lk_out y, int H, int a, int b, long xp, long xo, const int* __restrict__ yrow, long ypitch, long yp,
5333    long yo, int tile){
5334  typedef typename lk_acc<Q>::t acc_t;
5335  constexpr int US = lk_unit_subs<F>(), UB = lk_unit_bytes<F>(), PITCH = lk_axpy_pitch<F, W>();
5336  extern __shared__ __align__(16) unsigned char rows[];
5337  __shared__ acc_t red[R][W][32];
5338  int nsb = b >> 5, h = blockIdx.y, s0 = blockIdx.x * W, u0 = s0 / US;
5339  int units = min((s0 + W - 1) / US - u0 + 1, (nsb + US - 1) / US - u0);
5340  int lane = threadIdx.x & 31, warp = threadIdx.x >> 5, wsb = warp % W, grp = warp / W, sb = s0 + wsb;
5341  long ld = (long)H * xp;
5342  for(int t = 0; t < M; ++t){
5343    acc_t acc[32];
5344    #pragma unroll
5345    for(int i = 0; i < 32; ++i) acc[i] = 0;
5346    for(int e0 = 0; e0 < a; e0 += tile){
5347      int here = min(tile, a - e0);
5348      if(t == 0 || tile < a){
5349        __syncthreads();
5350        if(F == 8){
5351          int nb = b >> 5;
5352          for(int c = threadIdx.x; c < here * units * 2; c += blockDim.x){
5353            int e = c / (units * 2), u = (c % (units * 2)) >> 1, half = c & 1;
5354            long row = (long)h * a + e0 + e;
5355            uint4 v = __ldg((const uint4*)(w.q + row * b + (long)(u0 + u) * 32) + half);
5356            unsigned int* d = (unsigned int*)(rows + e * PITCH + u * 32 + half * 16);
5357            d[0] = v.x; d[1] = v.y; d[2] = v.z; d[3] = v.w;
5358            if(half == 0) *(__half*)(rows + e * PITCH + W * 32 + u * 2) = w.s[row * nb + u0 + u];
5359          }
5360        } else {
5361          int chunks = (units * UB + 30) / 16;
5362          for(int c = threadIdx.x; c < here * chunks; c += blockDim.x){
5363            int e = c / chunks, k = c % chunks;
5364            const unsigned char* start = w.b + ((long)h * a + e0 + e) * w.rb + (long)u0 * UB;
5365            uint4 v = __ldg((const uint4*)((unsigned long)start & ~15ul) + k);
5366            unsigned int* d = (unsigned int*)(rows + e * PITCH + k * 16);
5367            d[0] = v.x; d[1] = v.y; d[2] = v.z; d[3] = v.w;
5368          }
5369        }
5370        __syncthreads();
5371      }
5372      if(sb < nsb){
5373        for(int e = grp * 32 + lane; e < here; e += 32 * R){
5374          long k = (long)h * xp + xo + e0 + e;
5375          float xv;
5376          if(lk_f32_acts<Q>()) xv = x[t * ld + k];
5377          else {
5378            float s = xs[t * (ld >> 5) + (k >> 5)];
5379            xv = Q == 1 ? s * (float)xq[t * ld + k] : s * ((float)xq[t * ld + k] + 0.0078125f * (float)xl[t * ld + k]);
5380          }
5381          if(F == 8){
5382            const signed char* q = (const signed char*)(rows + e * PITCH) + (sb - u0) * 32;
5383            float d = __half2float(*(const __half*)(rows + e * PITCH + W * 32 + (sb - u0) * 2));
5384            #pragma unroll
5385            for(int i = 0; i < 32; ++i) acc[i] += (acc_t)(d * (float)q[i]) * (acc_t)xv;
5386          } else {
5387            int delta = (int)(((unsigned long)(w.b + ((long)h * a + e0 + e) * w.rb + (long)u0 * UB)) & 15ul);
5388            signed char v[32]; float d[2], c[2];
5389            lk_sub<F>(rows + e * PITCH + delta, sb - u0 * US, v, d, c);
5390            #pragma unroll
5391            for(int i = 0; i < 32; ++i) acc[i] += (acc_t)__fadd_rn(__fmul_rn(d[i >> 4], (float)v[i]), c[i >> 4]) * (acc_t)xv;
5392          }
5393        }
5394      }
5395    }
5396    lk_fly(acc, lane);
5397    red[grp][wsb][lane] = acc[0];
5398    __syncthreads();
5399    if(grp == 0 && sb < nsb){
5400      acc_t sum = red[0][wsb][lane];
5401      #pragma unroll
5402      for(int r = 1; r < R; ++r) sum += red[r][wsb][lane];
5403      LK_ROW(y, yrow, ypitch)[((long)t * H + h) * yp + yo + sb * 32 + lane] = (float)sum;
5404    }
5405    __syncthreads();
5406  }
5407}
5408template<int F, int Q, int M>
5409__global__ void lk_head_axpy(lk_w w, const float* __restrict__ x, const signed char* __restrict__ xq,
5410                             const signed char* __restrict__ xl, const float* __restrict__ xs, lk_out y,
5411                             int H, int a, int b, long xp, long xo, const int* __restrict__ yrow, long ypitch, long yp, long yo){
5412  typedef typename lk_acc<Q>::t acc_t;
5413  __shared__ acc_t red[8][M][32];
5414  int j = blockIdx.x, h = blockIdx.y, lane = threadIdx.x & 31, warp = threadIdx.x >> 5;
5415  long ld = (long)H * xp;
5416  acc_t acc[M];
5417  #pragma unroll
5418  for(int t = 0; t < M; ++t) acc[t] = 0;
5419  for(int e = warp; e < a; e += 8){
5420    long row = (long)h * a + e, k = (long)h * xp + xo + e;
5421    float wv;
5422    if(F == 8) wv = __half2float(w.s[row * (b >> 5) + j]) * (float)w.q[row * b + j * 32 + lane];
5423    else {
5424      float d, c;
5425      int lv = lk_level<F>(w.b + row * w.rb, j, lane, d, c);
5426      wv = __fadd_rn(__fmul_rn(d, (float)lv), c);
5427    }
5428    #pragma unroll
5429    for(int t = 0; t < M; ++t){
5430      float xv;
5431      if(lk_f32_acts<Q>()) xv = x[t * ld + k];
5432      else {
5433        float s = xs[t * (ld >> 5) + (k >> 5)];
5434        xv = Q == 1 ? s * (float)xq[t * ld + k] : s * ((float)xq[t * ld + k] + 0.0078125f * (float)xl[t * ld + k]);
5435      }
5436      acc[t] += (acc_t)wv * (acc_t)xv;
5437    }
5438  }
5439  #pragma unroll
5440  for(int t = 0; t < M; ++t) red[warp][t][lane] = acc[t];
5441  __syncthreads();
5442  if(warp == 0){
5443    #pragma unroll
5444    for(int t = 0; t < M; ++t){
5445      acc_t sum = 0;
5446      #pragma unroll
5447      for(int u = 0; u < 8; ++u) sum += red[u][t][lane];
5448      LK_ROW(y, yrow, ypitch)[((long)t * H + h) * yp + yo + j * 32 + lane] = (float)sum;
5449    }
5450  }
5451}
5452"#;
5453
5454/// The 1-based index of the first maximal value of `x`, across the grid: each block takes a run of `x` and leaves its
5455/// first maximum in `pv`/`pi`, and the last block to arrive (`cnt`, reset by it) takes the first maximum over the
5456/// blocks in order. `ADV` closes a step of `step` tokens: the token becomes the next step's input, the position moves
5457/// `step` on, and the token is appended to the generated run.
5458/// A wide chunk's per-head matmul in tiles: head `h` (grid layer `z`) multiplies its `M` rows' inputs — the `a` values
5459/// of each row's unit `h`, units `xp` apart from `xo` — by its matrix, whose rows are its `b` outputs (`OUT`) or its
5460/// `a` inputs, `HEAD_TILE_M` rows by 64 outputs a block over chunks of 32 inputs staged in shared memory, a thread 8 rows
5461/// by 4 outputs. Each weight is the dequantizer's `d·level + c` (a Q8_0 one `d·level`) and each input as computed under `Q` 3
5462/// (`x`), or its quantized words times their scale, as `lk_head_axpy` reads them; the sums are `f32`. Rows `xr` apart
5463/// with `xp` 0 give every head the row's one unit (a latent's expansion over the cache's rows); with `upto`, the rows
5464/// multiplied are those before `*upto + after`, at most `M`.
5465const HEAD_TILED: &str = r#"
5466template<int F, int Q, bool OUT, typename XE = float>
5467__global__ void __launch_bounds__(256) lk_head_tiled(lk_w w, const signed char* __restrict__ xq,
5468    const signed char* __restrict__ xl, const float* __restrict__ xs, lk_out y, int H, int a, int b, long xp,
5469    long xo, const int* __restrict__ yrow, long ypitch, long yp, long yo, int M, const XE* __restrict__ x = nullptr,
5470    long xr = 0, const int* __restrict__ upto = nullptr, int after = 0){
5471  __shared__ __align__(16) float Xs[32][128];  // [input][row]
5472  __shared__ __align__(16) float Ws[32][64];   // [input][output]
5473  int h = blockIdx.z, m0 = blockIdx.y * 128, o0 = blockIdx.x * 64, tid = threadIdx.x, tr = tid >> 4, to = tid & 15;
5474  if(upto) M = min(M, *upto + after);
5475  if(m0 >= M) return;
5476  long ld = xr ? xr : (long)H * xp;
5477  // A stage's 32 inputs by the block's 64 outputs are 64 sub-blocks: each output row's sub-block of the stage when the
5478  // rows are the outputs, each input row's two sub-blocks of the outputs otherwise. A thread takes eight values `8·sq`
5479  // … `+ 7` of one, its raw words fetched a stage ahead: a warp's 32 output rows at one `sq` (each store its own bank),
5480  // or eight threads to an input row (two 16-byte stores each, the row's outputs in order).
5481  int sq = OUT ? tid >> 6 : tid & 3;
5482  int srow = OUT ? tid & 63 : tid >> 3, shalf = OUT ? 0 : (tid >> 2) & 1;
5483  int K = OUT ? a : b, nb = K >> 5;
5484  long wrow = OUT ? (long)h * b + o0 + srow : (long)h * a + srow;
5485  bool wout = OUT ? o0 + srow < b : o0 + 32 * shalf < b;
5486  lk_raw<F> raw;
5487  auto fetch = [&](int i0){
5488    int ks = OUT ? i0 >> 5 : (o0 >> 5) + shalf;
5489    if(wout && (OUT || i0 + srow < a)) lk_fetch<F>(raw, w, wrow + (OUT ? 0 : i0), K, nb, ks);
5490  };
5491  float acc[8][4];
5492  #pragma unroll
5493  for(int r = 0; r < 8; ++r)
5494    #pragma unroll
5495    for(int o = 0; o < 4; ++o) acc[r][o] = 0.f;
5496  fetch(0);
5497  for(int i0 = 0; i0 < a; i0 += 32){
5498    // The rows' inputs, four a thread at a time, a warp's 32 rows at one input so each store lands on its own bank: as
5499    // computed under Q 3, as the inputs' quantized blocks hold them otherwise.
5500    #pragma unroll
5501    for(int u2 = 0; u2 < 4; ++u2){
5502      int c = tid + u2 * 256, r = c & 127, i = (c >> 7) * 4, m = m0 + r;
5503      float v[4] = {0.f, 0.f, 0.f, 0.f};
5504      if(m < M && i0 + i < a){
5505        long k = (long)h * xp + xo + i0 + i;
5506        if(Q == 3){
5507          float4 f = lk_from4(x + m * ld + k);
5508          v[0] = f.x; v[1] = f.y; v[2] = f.z; v[3] = f.w;
5509        } else {
5510          float sc = xs[m * (ld >> 5) + (k >> 5)];
5511          int hi = *(const int*)(xq + m * ld + k), lo = Q == 2 ? *(const int*)(xl + m * ld + k) : 0;
5512          #pragma unroll
5513          for(int u = 0; u < 4; ++u){
5514            float qv = (float)(signed char)(hi >> (8 * u));
5515            v[u] = Q == 1 ? sc * qv : sc * (qv + 0.0078125f * (float)(signed char)(lo >> (8 * u)));
5516          }
5517        }
5518      }
5519      #pragma unroll
5520      for(int u = 0; u < 4; ++u) Xs[i + u][r] = v[u];
5521    }
5522    // The stage's weights from their raw words: values 8·sq … 8·sq + 7 of this thread's sub-block, each the
5523    // dequantizer's `d·level + c`.
5524    {
5525      int ks = OUT ? i0 >> 5 : (o0 >> 5) + shalf;
5526      int lv[8]; float d[2], c[2];
5527      bool live = wout && (OUT || i0 + srow < a);
5528      if(live) lk_unpack<F>(raw, ks, lv, d, c);
5529      float wv[8];
5530      #pragma unroll
5531      for(int e = 0; e < 8; ++e){
5532        int l = 8 * sq + e;
5533        wv[e] = live ? __fadd_rn(__fmul_rn(d[l >> 4], (float)(signed char)(lv[l >> 2] >> (8 * (l & 3)))), c[l >> 4]) : 0.f;
5534      }
5535      if(OUT){
5536        #pragma unroll
5537        for(int e = 0; e < 8; ++e) Ws[8 * sq + e][srow] = wv[e];
5538      } else {
5539        float4* dst = (float4*)&Ws[srow][32 * shalf + 8 * sq];
5540        dst[0] = make_float4(wv[0], wv[1], wv[2], wv[3]); dst[1] = make_float4(wv[4], wv[5], wv[6], wv[7]);
5541      }
5542    }
5543    // The next stage's weights are fetched while this one multiplies.
5544    if(i0 + 32 < a) fetch(i0 + 32);
5545    __syncthreads();
5546    #pragma unroll 8
5547    for(int i = 0; i < 32; ++i){
5548      float4 x0 = *(const float4*)&Xs[i][8 * tr], x1 = *(const float4*)&Xs[i][8 * tr + 4];
5549      float4 wv = *(const float4*)&Ws[i][4 * to];
5550      float xa[8] = {x0.x, x0.y, x0.z, x0.w, x1.x, x1.y, x1.z, x1.w}, wa[4] = {wv.x, wv.y, wv.z, wv.w};
5551      #pragma unroll
5552      for(int r = 0; r < 8; ++r)
5553        #pragma unroll
5554        for(int o = 0; o < 4; ++o) acc[r][o] = fmaf(xa[r], wa[o], acc[r][o]);
5555    }
5556    __syncthreads();
5557  }
5558  #pragma unroll
5559  for(int r = 0; r < 8; ++r){
5560    int m = m0 + 8 * tr + r;
5561    if(m >= M) continue;
5562    lk_out yr = LK_ROW(y, yrow, ypitch) + ((long)m * H + h) * yp + yo + o0 + 4 * to;
5563    #pragma unroll
5564    for(int o = 0; o < 4; ++o) if(o0 + 4 * to + o < b) yr[o] = acc[r][o];
5565  }
5566}
5567"#;
5568
5569const ARGMAX: &str = r#"
5570// The first maximum of a block's values (`best`, at `at`; `at` −1 for none), every thread's own first, reduced so the
5571// earlier index wins a tie.
5572__device__ __forceinline__ void lk_first_max(float& best, int& at, float* bv, int* bi){
5573  for(int o = 16; o > 0; o >>= 1){
5574    float ov = __shfl_down_sync(0xffffffffu, best, o); int oi = __shfl_down_sync(0xffffffffu, at, o);
5575    if(oi >= 0 && (at < 0 || ov > best || (ov == best && oi < at))){ best = ov; at = oi; }
5576  }
5577  int lane = threadIdx.x & 31, warp = threadIdx.x >> 5, nw = (blockDim.x + 31) >> 5;
5578  __syncthreads();
5579  if(lane == 0){ bv[warp] = best; bi[warp] = at; }
5580  __syncthreads();
5581  if(threadIdx.x == 0){
5582    for(int w = 1; w < nw; ++w)
5583      if(bi[w] >= 0 && (at < 0 || bv[w] > best || (bv[w] == best && bi[w] < at))){ best = bv[w]; at = bi[w]; }
5584  }
5585}
5586template<bool ADV>
5587__global__ void __launch_bounds__(256) lk_argmax(const float* __restrict__ x, int n, int* __restrict__ out, int* __restrict__ tok,
5588                          int* __restrict__ pos, int step, int* __restrict__ gen, int* __restrict__ count,
5589                          float* __restrict__ pv, int* __restrict__ pi, int* __restrict__ cnt, int seqs = 0, int genz = 0){
5590  __shared__ float bv[32]; __shared__ int bi[32];
5591  __shared__ int last;
5592  // With `seqs`, grid row `y` is a batch's sequence: its logits, result, token, position, count and run its own, the
5593  // run `genz` tokens on from the last sequence's.
5594  if(seqs){
5595    long z = blockIdx.y;
5596    x += z * n; out += z; pv += z * gridDim.x; pi += z * gridDim.x; cnt += z;
5597    if(tok){ tok += z; pos += z; gen += z * genz; count += z; }
5598  }
5599  int run = (n + gridDim.x - 1) / gridDim.x, from = blockIdx.x * run, to = min(n, from + run);
5600  float best = -INFINITY; int at = -1;
5601  for(int i = from + threadIdx.x; i < to; i += blockDim.x){ float v = x[i]; if(at < 0 || v > best){ best = v; at = i; } }
5602  lk_first_max(best, at, bv, bi);
5603  if(threadIdx.x == 0){ pv[blockIdx.x] = best; pi[blockIdx.x] = at; }
5604  __threadfence();
5605  __syncthreads();
5606  if(threadIdx.x == 0) last = atomicAdd(cnt, 1) == gridDim.x - 1;
5607  __syncthreads();
5608  if(!last) return;
5609  __threadfence();
5610  best = -INFINITY; at = -1;
5611  // The blocks' runs are in order: a thread's blocks, then the threads, keep the first maximum.
5612  for(int k = threadIdx.x; k < gridDim.x; k += blockDim.x){
5613    float v = __ldcg(pv + k); int i = __ldcg(pi + k);
5614    if(i >= 0 && (at < 0 || v > best)){ best = v; at = i; }
5615  }
5616  lk_first_max(best, at, bv, bi);
5617  if(threadIdx.x == 0){
5618    *out = at + 1;
5619    if(ADV){ *tok = at + 1; *pos = *pos + step; gen[*count] = at + 1; *count = *count + 1; }
5620    *cnt = 0;
5621  }
5622}
5623"#;
5624
5625
5626/// The depthwise causal conv over `C` channels with a `T`-row ring, fed the `R` rows of `x` one after another from the
5627/// 1-based position `pos` (`*pos + r` row `r`'s): the ring keeps position `p` (from 0) in slot `p mod T` — each row written
5628/// once, where the row `T` positions before it was — and each channel reduces its window, slots oldest to newest, against
5629/// its filter. `SILU` applies silu after; `L2` (one block per head of `blockDim` channels) then normalizes each of the
5630/// first `nl2` heads of every row to unit L2 norm. `lk_conv_rows` takes a block of rows a row at a time — row `r`'s
5631/// window the ring's slots of the positions before the first, then `x`'s rows, in the window's order, so every row
5632/// computes what the rows one after another compute — and `lk_conv_carry` then writes the block's last rows (up to `T`)
5633/// into their slots, leaving the ring as those rows leave it.
5634const CONV: &str = r#"
5635// Position `p`'s slot (from 0, positions before the first too) of a ring of `T` rows.
5636__device__ __forceinline__ int lk_slot(int p, int T){ return ((p % T) + T) % T; }
5637template<bool SILU, bool L2, typename A>
5638__global__ void lk_conv(const float* __restrict__ x, const float* __restrict__ wc, float* __restrict__ cs,
5639                        float* __restrict__ y, int C, int T, int R, int nl2, float eps, const int* __restrict__ pos){
5640  __shared__ A red[32];
5641  int c = blockIdx.x * blockDim.x + threadIdx.x;
5642  const int q0 = *pos - 1;
5643  for(int r = 0; r < R; ++r){
5644    float v = 0.f;
5645    if(c < C){
5646      const int q = q0 + r;
5647      const float cur = x[(long)r * C + c];
5648      cs[(long)lk_slot(q, T) * C + c] = cur;
5649      A sum = 0;
5650      for(int t = 0; t < T - 1; ++t) sum += (A)cs[(long)lk_slot(q - (T - 1) + t, T) * C + c] * (A)wc[(long)t * C + c];
5651      sum += (A)cur * (A)wc[(long)(T - 1) * C + c];
5652      v = (float)sum;
5653      if(SILU) v = v / (1.0f + expf(-v));
5654    }
5655    if(L2 && blockIdx.x < nl2){
5656      A den = sqrt(lk_block_sum(c < C ? (A)v * (A)v : (A)0, red) + (A)eps);
5657      v = (float)((A)v / den);
5658    }
5659    if(c < C) y[(long)r * C + c] = v;
5660  }
5661}
5662template<bool SILU, bool L2, typename A>
5663__global__ void lk_conv_rows(const float* __restrict__ x, const float* __restrict__ wc, const float* __restrict__ cs,
5664                             float* __restrict__ y, int C, int T, int R, int nl2, float eps, const int* __restrict__ pos){
5665  __shared__ A red[32];
5666  int c = blockIdx.x * blockDim.x + threadIdx.x, r = blockIdx.y;
5667  const int q0 = *pos - 1;
5668  float v = 0.f;
5669  if(c < C){
5670    A sum = 0;
5671    for(int t = 0; t < T; ++t){
5672      int j = r - (T - 1) + t;
5673      sum += (A)(j >= 0 ? x[(long)j * C + c] : cs[(long)lk_slot(q0 + j, T) * C + c]) * (A)wc[(long)t * C + c];
5674    }
5675    v = (float)sum;
5676    if(SILU) v = v / (1.0f + expf(-v));
5677  }
5678  if(L2 && blockIdx.x < nl2){
5679    A den = sqrt(lk_block_sum(c < C ? (A)v * (A)v : (A)0, red) + (A)eps);
5680    v = (float)((A)v / den);
5681  }
5682  if(c < C) y[(long)r * C + c] = v;
5683}
5684// One causal convolution of `lk_conv_parts`: its input row, weights, ring and output, its channels `C`, its blocks
5685// `nb`, and whether each head of its output is normed.
5686struct lk_conv_part { const float* x; const float* wc; float* cs; float* y; int C; int nb; int l2; };
5687// With `seqs`, grid row `y` is a batch's sequence: each part's input row, ring and output its part of one array of them,
5688// its position `pos[y]`.
5689struct lk_convs { lk_conv_part p[4]; };
5690// One row of `np` causal convolutions through the SiLU in one launch, their blocks one after another: block `b` the
5691// part whose blocks hold it, each channel's sum — and a normed part's head of `blockDim.x` channels — as `lk_conv<true,
5692// L2>` computes them over one row.
5693template<typename A>
5694__global__ void lk_conv_parts(lk_convs ps, int np, int T, float eps, const int* __restrict__ pos, int seqs = 0){
5695  __shared__ A red[32];
5696  int b = blockIdx.x, p = 0;
5697  while(p + 1 < np && b >= ps.p[p].nb){ b -= ps.p[p].nb; ++p; }
5698  int C = ps.p[p].C, c = b * blockDim.x + threadIdx.x;
5699  long z = seqs ? blockIdx.y : 0;
5700  const int q = pos[z] - 1;
5701  const float* __restrict__ x = ps.p[p].x + z * C;
5702  const float* __restrict__ wc = ps.p[p].wc;
5703  float* __restrict__ cs = ps.p[p].cs + z * T * C;
5704  float* __restrict__ y = ps.p[p].y + z * C;
5705  float v = 0.f;
5706  if(c < C){
5707    const float cur = x[c];
5708    cs[(long)lk_slot(q, T) * C + c] = cur;
5709    A sum = 0;
5710    for(int t = 0; t < T - 1; ++t) sum += (A)cs[(long)lk_slot(q - (T - 1) + t, T) * C + c] * (A)wc[(long)t * C + c];
5711    sum += (A)cur * (A)wc[(long)(T - 1) * C + c];
5712    v = (float)sum;
5713    v = v / (1.0f + expf(-v));
5714  }
5715  if(ps.p[p].l2){
5716    A den = sqrt(lk_block_sum(c < C ? (A)v * (A)v : (A)0, red) + (A)eps);
5717    v = (float)((A)v / den);
5718  }
5719  if(c < C) y[c] = v;
5720}
5721// A block of `R` rows from position `pos`: its last rows, up to `T`, each into its slot.
5722__global__ void lk_conv_carry(const float* __restrict__ x, float* __restrict__ cs, int C, int T, int R, const int* __restrict__ pos){
5723  int c = blockIdx.x * blockDim.x + threadIdx.x; if(c >= C) return;
5724  const int q0 = *pos - 1;
5725  for(int j = max(0, R - T); j < R; ++j) cs[(long)lk_slot(q0 + j, T) * C + c] = x[(long)j * C + c];
5726}
5727"#;
5728
5729/// Per-row L2 normalization `y = x / sqrt(Σx² + eps)`, one block per row.
5730const L2NORM: &str = r#"
5731template<typename A>
5732__global__ void lk_l2norm(const float* __restrict__ x, float* __restrict__ y, int cols, float eps){
5733  __shared__ A red[32];
5734  long base = (long)blockIdx.x * cols;
5735  A acc = 0;
5736  for(int i = threadIdx.x; i < cols; i += blockDim.x) acc += (A)x[base + i] * (A)x[base + i];
5737  A den = sqrt(lk_block_sum(acc, red) + (A)eps);
5738  for(int i = threadIdx.x; i < cols; i += blockDim.x) y[base + i] = (float)((A)x[base + i] / den);
5739}
5740"#;
5741
5742/// Gated DeltaNet's forget gate `(1 + e^(ar + dt))^rate` per head, every row of `ar` by the same `heads` biases and rates.
5743const DECAY: &str = r#"
5744__global__ void lk_decay(const float* __restrict__ ar, const float* __restrict__ dt, const float* __restrict__ al,
5745                         float* __restrict__ y, int n, int heads){
5746  int i = blockIdx.x * blockDim.x + threadIdx.x; if(i >= n) return;
5747  int h = i % heads;
5748  y[i] = powf(1.0f + expf(ar[i] + dt[h]), al[h]);
5749}
5750"#;
5751
5752/// Both Gated DeltaNet gates in one launch: the write strength `sigmoid(br)` and the forget gate. `lk_gate_proj` takes a
5753/// step's one row from its activation: head `o`'s two `f32` dots `x·wb[o]` and `x·wa[o]` each summed as `lk_gemv_f32`
5754/// sums it over `parts` warps (a lane's run of `k` in `f64`, the warp's sum, the runs in order), then both gates as
5755/// `lk_gates` computes them.
5756const GATES: &str = r#"
5757__global__ void lk_gates(const float* __restrict__ br, const float* __restrict__ ar, const float* __restrict__ dt,
5758                         const float* __restrict__ al, float* __restrict__ beta, float* __restrict__ decay, int n, int heads){
5759  int i = blockIdx.x * blockDim.x + threadIdx.x; if(i >= n) return;
5760  int h = i % heads;
5761  beta[i] = 1.0f / (1.0f + expf(-br[i]));
5762  decay[i] = powf(1.0f + expf(ar[i] + dt[h]), al[h]);
5763}
5764__global__ void __launch_bounds__(256) lk_gate_proj(const float* __restrict__ wb, const float* __restrict__ wa,
5765    const float* __restrict__ x, const float* __restrict__ dt, const float* __restrict__ al, float* __restrict__ beta,
5766    float* __restrict__ decay, int K, int H, int parts){
5767  __shared__ double run[2][8];
5768  int warp = threadIdx.x >> 5, lane = threadIdx.x & 31;
5769  int o = blockIdx.x * (8 / parts) + warp / parts, p = warp % parts;
5770  bool live = o < H;
5771  int span = (K + parts - 1) / parts, k0 = p * span, k1 = min(K, k0 + span);
5772  const float* rb = wb + (long)(live ? o : 0) * K;
5773  const float* ra = wa + (long)(live ? o : 0) * K;
5774  double sb = 0.0, sa = 0.0;
5775  if(live) for(int k = k0 + lane; k < k1; k += 32) sb += (double)rb[k] * (double)x[k];
5776  if(live) for(int k = k0 + lane; k < k1; k += 32) sa += (double)ra[k] * (double)x[k];
5777  sb = lk_warp_sum_d(sb);
5778  sa = lk_warp_sum_d(sa);
5779  if(parts > 1){
5780    if(lane == 0){ run[0][warp] = sb; run[1][warp] = sa; }
5781    __syncthreads();
5782    if(p == 0){
5783      sb = 0.0; sa = 0.0;
5784      for(int i = 0; i < parts; ++i){ sb += run[0][warp + i]; sa += run[1][warp + i]; }
5785    }
5786  }
5787  if(live && p == 0 && lane == 0){
5788    float b = (float)sb, a = (float)sa;
5789    beta[o] = 1.0f / (1.0f + expf(-b));
5790    decay[o] = powf(1.0f + expf(a + dt[o]), al[o]);
5791  }
5792}
5793"#;
5794
5795/// The delta-rule step over the `R` rows of a block in turn, one warp per row of a value head's `D×D` memory
5796/// (`grid = (HV, D / warps)`) kept in registers across the block — a lane's `DW` values of the row, `DW` at least
5797/// `D / 32`: value head `h` reads key head `h % NK`; one pass over the row accumulates `S·k`, `S·q` and `k·q`, rewrites
5798/// the row `α·S + β·(v − α·S·k)·kᵀ`, and reads the updated memory as `α·(S·q) + coef·(k·q)`, scaled by `1/√D`.
5799const DELTA_STEP: &str = r#"
5800template<typename A, int DW, typename SS>
5801__device__ __forceinline__ void lk_delta_rows(const float* __restrict__ q, const float* __restrict__ k, const float* __restrict__ v,
5802                              const float* __restrict__ bet, const float* __restrict__ alp, SS* __restrict__ S,
5803                              float* __restrict__ o, int D, int NK, int HV, int R, int seqs){
5804  // With `seqs`, grid layer `z` is a batch's sequence: its one row, its gates and its own memory, each the sequence's
5805  // part of one array of them all.
5806  if(seqs){
5807    long z = blockIdx.z;
5808    q += z * NK * D; k += z * NK * D; v += z * HV * D; bet += z * HV; alp += z * HV; S += z * HV * D * D; o += z * HV * D;
5809  }
5810  int h = blockIdx.x, lane = threadIdx.x & 31, warp = threadIdx.x >> 5;
5811  int a = blockIdx.y * (blockDim.x >> 5) + warp;
5812  if(a >= D) return;
5813  long base = (long)h * D * D + (long)a * D;
5814  float sreg[DW];
5815  #pragma unroll
5816  for(int i = 0; i < DW; ++i) if(lane + 32 * i < D) sreg[i] = lk_from(S[base + lane + 32 * i]);
5817  for(int r = 0; r < R; ++r){
5818    const float* kk = k + ((long)r * NK + h % NK) * D;
5819    const float* qq = q + ((long)r * NK + h % NK) * D;
5820    A su = 0, sw = 0, skq = 0;
5821    #pragma unroll
5822    for(int i = 0; i < DW; ++i){
5823      const int b = lane + 32 * i;
5824      if(b < D){
5825        A sv = sreg[i], kb = kk[b], qb = qq[b];
5826        su += sv * kb; sw += sv * qb; skq += kb * qb;
5827      }
5828    }
5829    float u = (float)lk_warp_sum(su), w = (float)lk_warp_sum(sw), kq = (float)lk_warp_sum(skq);
5830    long hr = (long)r * HV + h;
5831    float alpha = alp[hr], coef = bet[hr] * (v[hr * D + a] - alpha * u);
5832    if(lane == 0) o[hr * D + a] = (alpha * w + coef * kq) * (1.0f / sqrtf((float)D));
5833    #pragma unroll
5834    for(int i = 0; i < DW; ++i) if(lane + 32 * i < D) sreg[i] = lk_kept<SS>(alpha * sreg[i] + coef * kk[lane + 32 * i]);
5835  }
5836  #pragma unroll
5837  for(int i = 0; i < DW; ++i) if(lane + 32 * i < D) S[base + lane + 32 * i] = lk_to<SS>(sreg[i]);
5838}
5839template<typename A, int DW = 32, typename SS = float>
5840__global__ void lk_delta_step(const float* __restrict__ q, const float* __restrict__ k, const float* __restrict__ v,
5841                              const float* __restrict__ bet, const float* __restrict__ alp, SS* __restrict__ S,
5842                              float* __restrict__ o, int D, int NK, int HV, int R, int seqs = 0){
5843  lk_delta_rows<A, DW, SS>(q, k, v, bet, alp, S, o, D, NK, HV, R, seqs);
5844}
5845"#;
5846
5847/// A wide chunk's delta rule a chunk of `LK_DC` rows at a time, the chunkwise form of the recurrence `lk_delta_step`
5848/// walks a row at a time. Within a chunk of value head `h`, with `γ_t` the product of its decays to row `t` (kept as
5849/// cumulative logs, each at least −80) and `G_ts = γ_t / γ_s`, the step's corrections `δ_t = β_t·(v_t − α_t·S_{t−1}k_t)`
5850/// solve `δ_t + Σ_{s<t} β_t·G_ts·(k_t·k_s)·δ_s = β_t·(v_t − γ_t·S₀k_t)` — so, with `T = (I + A)⁻¹` for that strictly lower
5851/// `A`, `Δ = T·diag(β)·(V − diag(γ)·K·S₀ᵀ)` — the outputs are `o_t = (γ_t·S₀q_t + Σ_{s≤t} G_ts·(k_s·q_t)·δ_s) / √D`, and
5852/// the memory leaves the chunk as `γ_n·S₀ + Σ_s G_ns·δ_s·k_sᵀ`. `lk_delta_prep` takes, for every chunk and head at once,
5853/// what the memory does not enter — the decayed keys and queries `diag(γ)·K` and `diag(γ)·Q` (a value of the width at a
5854/// time), `T·diag(β)` (`T` by 16 × 16 blocks, each diagonal block's by forward substitution and the blocks below from
5855/// those), the masked scores `(Q·Kᵀ) ⊙ G` (both a column of the chunk's rows at a time), each row's decay to the chunk's
5856/// end and the chunk's own — its keys and queries a run of 32 values at a time. `lk_delta_state` then walks a head's
5857/// chunks in turn, a block of two warps `RV` (16) of its memory's rows (the rows of a value head's memory are
5858/// independent), held in shared memory a value of the width at a time and each warp's 8 in registers, a lane `D / 32`
5859/// values of their width: a lane one of the chunk's rows across the block's — `diag(γ)·K·S₀ᵀ` and `diag(γ)·Q·S₀ᵀ` over
5860/// the width, the corrections, the outputs — then each warp its rows of the memory the chunk leaves; each warp reads
5861/// half the chunk's decayed keys and queries. Heads `D` wide (at most 128, whole runs of 32), every sum `f32`.
5862const DELTA_CHUNKS: &str = r#"
5863#define LK_DC 64
5864template<int D>
5865__global__ void __launch_bounds__(256) lk_delta_prep(const float* __restrict__ q, const float* __restrict__ k,
5866    const float* __restrict__ bet, const float* __restrict__ alp, float* __restrict__ Kg, float* __restrict__ Qg,
5867    float* __restrict__ Tb, float* __restrict__ P, float* __restrict__ gl, int NK, int HV, int R){
5868  constexpr int CP = LK_DC + 1, KT = 32, KP = KT + 1;
5869  static_assert(D % KT == 0, "the width in whole runs of 32");
5870  extern __shared__ __align__(16) float lk_dp[];
5871  float* kt = lk_dp;                       // [LK_DC][KP]: a run of 32 of the chunk's keys' values
5872  float* qt = kt + LK_DC * KP;             // [LK_DC][KP]: and of its queries'
5873  float* ts = lk_dp;                       // [LK_DC][CP]: T = (I + A)⁻¹, once every run is summed
5874  float* as = lk_dp + 2 * LK_DC * KP;      // [LK_DC][CP]: A below the diagonal
5875  float* xs = as + LK_DC * CP;             // [3][16][16]: the sums T's lower blocks take
5876  __shared__ float lg[LK_DC], bs[LK_DC], eg[LK_DC];
5877  int h = blockIdx.x, c = blockIdx.y, tid = threadIdx.x, kh = h % NK, tq = tid >> 4, tr = tid & 15;
5878  int r0 = c * LK_DC, n = min(LK_DC, R - r0);
5879  long base = (long)h * gridDim.y + c;
5880  if(tid == 0){
5881    float acc = 0.f;
5882    for(int t = 0; t < LK_DC; ++t){
5883      if(t < n) acc += fmaxf(logf(alp[(long)(r0 + t) * HV + h]), -80.f);
5884      lg[t] = acc;
5885    }
5886  }
5887  if(tid < LK_DC) bs[tid] = tid < n ? bet[(long)(r0 + tid) * HV + h] : 0.f;
5888  __syncthreads();
5889  if(tid < LK_DC) eg[tid] = tid < n ? expf(lg[tid]) : 0.f;
5890  // k·k and q·k over rows t = tq + 16·i and s = tr + 16·j, a 4 × 4 tile a thread, the width a run of 32 at a time; and
5891  // the decayed keys and queries diag(γ)·K and diag(γ)·Q, a value of the width at a time.
5892  float kk[4][4], qk[4][4];
5893  #pragma unroll
5894  for(int i = 0; i < 4; ++i)
5895    #pragma unroll
5896    for(int j = 0; j < 4; ++j){ kk[i][j] = 0.f; qk[i][j] = 0.f; }
5897  for(int d0 = 0; d0 < D; d0 += KT){
5898    __syncthreads();
5899    for(int i = tid; i < LK_DC * KT; i += 256){
5900      int t = i / KT, dd = i % KT;
5901      long at = ((long)(r0 + t) * NK + kh) * D + d0 + dd;
5902      kt[t * KP + dd] = t < n ? k[at] : 0.f;
5903      qt[t * KP + dd] = t < n ? q[at] : 0.f;
5904    }
5905    __syncthreads();
5906    for(int i = tid; i < KT * LK_DC; i += 256){
5907      int dd = i / LK_DC, t = i % LK_DC;
5908      long at = (base * D + d0 + dd) * LK_DC + t;
5909      Kg[at] = eg[t] * kt[t * KP + dd];
5910      Qg[at] = eg[t] * qt[t * KP + dd];
5911    }
5912    #pragma unroll 8
5913    for(int dd = 0; dd < KT; ++dd){
5914      float kr[4], qr[4], kc[4];
5915      #pragma unroll
5916      for(int i = 0; i < 4; ++i){ kr[i] = kt[(tq + 16 * i) * KP + dd]; qr[i] = qt[(tq + 16 * i) * KP + dd]; kc[i] = kt[(tr + 16 * i) * KP + dd]; }
5917      #pragma unroll
5918      for(int i = 0; i < 4; ++i)
5919        #pragma unroll
5920        for(int j = 0; j < 4; ++j){ kk[i][j] = fmaf(kr[i], kc[j], kk[i][j]); qk[i][j] = fmaf(qr[i], kc[j], qk[i][j]); }
5921    }
5922  }
5923  // A below the diagonal; the masked scores on and below it, a column of the chunk's rows at a time.
5924  #pragma unroll
5925  for(int i = 0; i < 4; ++i)
5926    #pragma unroll
5927    for(int j = 0; j < 4; ++j){
5928      int t = tq + 16 * i, s = tr + 16 * j;
5929      float g = expf(lg[t] - lg[s]);
5930      as[t * CP + s] = s < t && t < n ? bs[t] * g * kk[i][j] : 0.f;
5931      P[base * LK_DC * LK_DC + s * LK_DC + t] = s <= t && t < n ? g * qk[i][j] : 0.f;
5932    }
5933  __syncthreads();
5934  // T = (I + A)⁻¹ by 16 × 16 blocks: each diagonal block's inverse by forward substitution, a column a thread held in
5935  // registers, the blocks above the diagonal zero; then the blocks below it a diagonal at a time,
5936  // T_ij = −T_ii·Σ_{j≤k<i} A_ik·T_kj — its sums first, then T_ii times them.
5937  if(tid < LK_DC){
5938    int o = 16 * (tid >> 4), jj = tid & 15;
5939    float x[16];
5940    #pragma unroll
5941    for(int tt = 0; tt < 16; ++tt){
5942      float acc = tt == jj ? 1.f : 0.f;
5943      #pragma unroll
5944      for(int s = 0; s < tt; ++s) acc = fmaf(-as[(o + tt) * CP + o + s], x[s], acc);
5945      x[tt] = tt >= jj ? acc : 0.f;
5946    }
5947    #pragma unroll
5948    for(int tt = 0; tt < 16; ++tt) ts[(o + tt) * CP + o + jj] = x[tt];
5949  } else {
5950    for(int i = tid - LK_DC; i < LK_DC * LK_DC; i += 256 - LK_DC)
5951      if((i % LK_DC) >> 4 > (i / LK_DC) >> 4) ts[(i / LK_DC) * CP + i % LK_DC] = 0.f;
5952  }
5953  __syncthreads();
5954  for(int dg = 1; dg < 4; ++dg){
5955    for(int e = tid; e < (4 - dg) * 256; e += 256){
5956      int j = e >> 8, i = j + dg, r = (e >> 4) & 15, cc = e & 15;
5957      float acc = 0.f;
5958      for(int m = 16 * j; m < 16 * i; ++m) acc = fmaf(as[(16 * i + r) * CP + m], ts[m * CP + 16 * j + cc], acc);
5959      xs[e] = acc;
5960    }
5961    __syncthreads();
5962    for(int e = tid; e < (4 - dg) * 256; e += 256){
5963      int j = e >> 8, i = j + dg, r = (e >> 4) & 15, cc = e & 15;
5964      float acc = 0.f;
5965      #pragma unroll
5966      for(int m = 0; m < 16; ++m) acc = fmaf(ts[(16 * i + r) * CP + 16 * i + m], xs[(j << 8) + m * 16 + cc], acc);
5967      ts[(16 * i + r) * CP + 16 * j + cc] = -acc;
5968    }
5969    __syncthreads();
5970  }
5971  // T·diag(β), a column of the chunk's rows at a time; each row's decay to the chunk's end, and the chunk's own.
5972  for(int i = tid; i < LK_DC * LK_DC; i += 256){
5973    int s = i / LK_DC, t = i % LK_DC;
5974    Tb[base * LK_DC * LK_DC + i] = ts[t * CP + s] * bs[s];
5975  }
5976  if(tid <= LK_DC) gl[base * (LK_DC + 1) + tid] = tid < LK_DC ? (tid < n ? expf(lg[n - 1] - lg[tid]) : 0.f) : expf(lg[n - 1]);
5977}
5978// `B` values from `p`, sixteen bytes at a time where `B` is a multiple of four.
5979template<int B>
5980__device__ __forceinline__ void lk_load(const float* __restrict__ p, float (&r)[B]){
5981  if constexpr(B % 4 == 0){
5982    #pragma unroll
5983    for(int i = 0; i < B / 4; ++i){
5984      float4 v = __ldg((const float4*)p + i);
5985      r[4 * i] = v.x; r[4 * i + 1] = v.y; r[4 * i + 2] = v.z; r[4 * i + 3] = v.w;
5986    }
5987  } else {
5988    #pragma unroll
5989    for(int i = 0; i < B; ++i) r[i] = __ldg(p + i);
5990  }
5991}
5992template<int D, int RV, typename SS = float>
5993__global__ void __launch_bounds__(64) lk_delta_state(const float* __restrict__ k, const float* __restrict__ v,
5994    const float* __restrict__ Kg, const float* __restrict__ Qg, const float* __restrict__ Tb, const float* __restrict__ P,
5995    const float* __restrict__ gl, SS* __restrict__ S, float* __restrict__ o, int NK, int HV, int R){
5996  constexpr int RB = RV, B = D / 32;
5997  static_assert(RV == 16 && D % 32 == 0, "two warps, each 32 of the chunk's rows and 8 of the memory's; a lane D / 32 of the width");
5998  __shared__ __align__(16) float sm[D * RB];     // the block's rows of the memory, a value of the width at a time
5999  __shared__ __align__(16) float rd[LK_DC * RB];  // V − diag(γ)·K·S₀ᵀ over them, then the corrections Δ
6000  int h = blockIdx.x, lane = threadIdx.x & 31, warp = threadIdx.x >> 5, kh = h % NK, a0 = blockIdx.y * RB, b0 = lane * B;
6001  int t = 32 * warp + lane, aw = 8 * warp;
6002  int chunks = (R + LK_DC - 1) / LK_DC;
6003  const float sc = rsqrtf((float)D);
6004  float s[8][B];
6005  #pragma unroll
6006  for(int a = 0; a < 8; ++a){
6007    if constexpr(sizeof(SS) == 4) lk_load<B>((const float*)S + ((long)h * D + a0 + aw + a) * D + b0, s[a]);
6008    else
6009      #pragma unroll
6010      for(int i = 0; i < B; ++i) s[a][i] = lk_from(S[((long)h * D + a0 + aw + a) * D + b0 + i]);
6011  }
6012  for(int c = 0; c < chunks; ++c){
6013    int r0 = c * LK_DC, n = min(LK_DC, R - r0);
6014    long base = (long)h * chunks + c;
6015    const float *Kc = Kg + base * LK_DC * D, *Qc = Qg + base * LK_DC * D;
6016    const float *Tc = Tb + base * LK_DC * LK_DC, *Pc = P + base * LK_DC * LK_DC, *g = gl + base * (LK_DC + 1);
6017    #pragma unroll
6018    for(int i = 0; i < B; ++i)
6019      #pragma unroll
6020      for(int a = 0; a < 8; ++a) sm[(b0 + i) * RB + aw + a] = s[a][i];
6021    __syncthreads();
6022    float xr[RB], xo[RB];
6023    #pragma unroll
6024    for(int a = 0; a < RB; ++a){ xr[a] = 0.f; xo[a] = 0.f; }
6025    #pragma unroll 4
6026    for(int b = 0; b < D; ++b){
6027      float kv = __ldg(Kc + b * LK_DC + t), qv = __ldg(Qc + b * LK_DC + t);
6028      const float4* sp = (const float4*)(sm + b * RB);
6029      #pragma unroll
6030      for(int q4 = 0; q4 < RB / 4; ++q4){
6031        float4 sv = sp[q4];
6032        xr[4 * q4] = fmaf(kv, sv.x, xr[4 * q4]); xr[4 * q4 + 1] = fmaf(kv, sv.y, xr[4 * q4 + 1]);
6033        xr[4 * q4 + 2] = fmaf(kv, sv.z, xr[4 * q4 + 2]); xr[4 * q4 + 3] = fmaf(kv, sv.w, xr[4 * q4 + 3]);
6034        xo[4 * q4] = fmaf(qv, sv.x, xo[4 * q4]); xo[4 * q4 + 1] = fmaf(qv, sv.y, xo[4 * q4 + 1]);
6035        xo[4 * q4 + 2] = fmaf(qv, sv.z, xo[4 * q4 + 2]); xo[4 * q4 + 3] = fmaf(qv, sv.w, xo[4 * q4 + 3]);
6036      }
6037    }
6038    {
6039      float vv[RB];
6040      if(t < n) lk_load<RB>(v + ((long)(r0 + t) * HV + h) * D + a0, vv);
6041      else for(int a = 0; a < RB; ++a) vv[a] = 0.f;
6042      #pragma unroll
6043      for(int a = 0; a < RB; ++a) rd[t * RB + a] = vv[a] - xr[a];
6044    }
6045    __syncthreads();
6046    #pragma unroll
6047    for(int a = 0; a < RB; ++a) xr[a] = 0.f;
6048    #pragma unroll 8
6049    for(int sr = 0; sr < LK_DC; ++sr){
6050      float tv = __ldg(Tc + sr * LK_DC + t);
6051      const float4* rp = (const float4*)(rd + sr * RB);
6052      #pragma unroll
6053      for(int q4 = 0; q4 < RB / 4; ++q4){
6054        float4 rv = rp[q4];
6055        xr[4 * q4] = fmaf(tv, rv.x, xr[4 * q4]); xr[4 * q4 + 1] = fmaf(tv, rv.y, xr[4 * q4 + 1]);
6056        xr[4 * q4 + 2] = fmaf(tv, rv.z, xr[4 * q4 + 2]); xr[4 * q4 + 3] = fmaf(tv, rv.w, xr[4 * q4 + 3]);
6057      }
6058    }
6059    __syncthreads();
6060    #pragma unroll
6061    for(int a = 0; a < RB; ++a) rd[t * RB + a] = xr[a];
6062    __syncthreads();
6063    #pragma unroll 8
6064    for(int sr = 0; sr < LK_DC; ++sr){
6065      float pv = __ldg(Pc + sr * LK_DC + t);
6066      const float4* dp = (const float4*)(rd + sr * RB);
6067      #pragma unroll
6068      for(int q4 = 0; q4 < RB / 4; ++q4){
6069        float4 dv = dp[q4];
6070        xo[4 * q4] = fmaf(pv, dv.x, xo[4 * q4]); xo[4 * q4 + 1] = fmaf(pv, dv.y, xo[4 * q4 + 1]);
6071        xo[4 * q4 + 2] = fmaf(pv, dv.z, xo[4 * q4 + 2]); xo[4 * q4 + 3] = fmaf(pv, dv.w, xo[4 * q4 + 3]);
6072      }
6073    }
6074    if(t < n){
6075      float4* op = (float4*)(o + ((long)(r0 + t) * HV + h) * D + a0);
6076      #pragma unroll
6077      for(int q4 = 0; q4 < RB / 4; ++q4) op[q4] = make_float4(xo[4 * q4] * sc, xo[4 * q4 + 1] * sc, xo[4 * q4 + 2] * sc, xo[4 * q4 + 3] * sc);
6078    }
6079    float gn = g[LK_DC];
6080    #pragma unroll
6081    for(int a = 0; a < 8; ++a)
6082      #pragma unroll
6083      for(int i = 0; i < B; ++i) s[a][i] *= gn;
6084    #pragma unroll 8
6085    for(int tt = 0; tt < n; ++tt){
6086      float kv[B];
6087      lk_load<B>(k + ((long)(r0 + tt) * NK + kh) * D + b0, kv);
6088      float gt = g[tt];
6089      float4 d0 = *(const float4*)(rd + tt * RB + aw), d1 = *(const float4*)(rd + tt * RB + aw + 4);
6090      float dv[8] = {d0.x, d0.y, d0.z, d0.w, d1.x, d1.y, d1.z, d1.w};
6091      #pragma unroll
6092      for(int a = 0; a < 8; ++a){
6093        float da = gt * dv[a];
6094        #pragma unroll
6095        for(int i = 0; i < B; ++i) s[a][i] = fmaf(da, kv[i], s[a][i]);
6096      }
6097    }
6098    // The memory as its storage keeps it, at the chunk's end.
6099    #pragma unroll
6100    for(int a = 0; a < 8; ++a)
6101      #pragma unroll
6102      for(int i = 0; i < B; ++i) s[a][i] = lk_kept<SS>(s[a][i]);
6103    __syncthreads();
6104  }
6105  #pragma unroll
6106  for(int a = 0; a < 8; ++a)
6107    #pragma unroll
6108    for(int i = 0; i < B; ++i) S[((long)h * D + a0 + aw + a) * D + b0 + i] = lk_to<SS>(s[a][i]);
6109}
6110"#;
6111
6112/// The rows of a chunk of the chunked delta rule (`LK_DC` in its source), the rows of a value head's memory a block of
6113/// its walk takes, and the threads of that block: two warps.
6114pub const DELTA_CHUNK: usize = 64;
6115pub const DELTA_STATE_ROWS: usize = 16;
6116pub const DELTA_STATE_THREADS: usize = 64;
6117
6118/// The dynamic shared memory of `lk_delta_prep`: a run of 32 of a chunk's keys' and queries' values (then `T`), `A`,
6119/// and the sums `T`'s lower blocks take — rows padded a value.
6120pub const DELTA_PREP_SMEM: usize = (2 * DELTA_CHUNK * 33 + DELTA_CHUNK * (DELTA_CHUNK + 1) + 3 * 256) * 4;
6121
6122const _: () = assert!(DELTA_PREP_SMEM <= 48 * 1024, "the chunked delta rule's preparation keeps the default shared memory");
6123const _: () = assert!(DELTA_CHUNK * 33 * 2 >= DELTA_CHUNK * (DELTA_CHUNK + 1), "T fits where the runs of keys and queries were");
6124
6125/// Whether the chunked delta rule takes heads `d` wide: at most 128, in whole runs of 32 (a lane of the walk's warp
6126/// `d / 32` values of the width, the preparation's runs of 32).
6127pub fn delta_chunks_take(d: usize) -> bool {
6128    d <= 128 && d % 32 == 0
6129}
6130
6131/// The floats of the chunked delta rule's scratch over `chunks` chunks of `hv` value heads `d` wide: each chunk's
6132/// decayed keys and queries (a value of the width at a time), its `T·diag(β)` and masked scores, and its rows' decays
6133/// to its end with its own.
6134pub fn delta_chunk_scratch(chunks: usize, hv: usize, d: usize) -> [usize; 5] {
6135    let per = chunks * hv;
6136    [per * DELTA_CHUNK * d, per * DELTA_CHUNK * d, per * DELTA_CHUNK * DELTA_CHUNK, per * DELTA_CHUNK * DELTA_CHUNK, per * (DELTA_CHUNK + 1)]
6137}
6138
6139/// The delta-rule output's epilogue, one block of `D` threads per value head: RMSNorm the head, scale by `gn`, gate
6140/// by `silu(z)`; `Q` quantizes the result, `OUTF` writes it. The head's work is `lk_delta_norm_row`, which the step's
6141/// last block a head also runs (`DELTA_STEP_NORM`), its warps playing the norm's `D` threads.
6142const DELTA_NORM: &str = r#"
6143// The head of `D` values at `i0`, a value a thread of the norm's own block: warp `w` of the block's plays the norm's
6144// warps `w`, `w + nw`, … (`VW` of them), each value read past the L1 under `L2`.
6145template<bool OUTF, int Q, typename A, int VW, bool L2>
6146__device__ __forceinline__ void lk_delta_norm_row(const float* __restrict__ z, const float* __restrict__ gn, const float* o,
6147                              float* __restrict__ out, signed char* __restrict__ oq, signed char* __restrict__ ol,
6148                              float* __restrict__ os, long i0, int D, float eps, A* red){
6149  const int nw = blockDim.x >> 5, vw = (D + 31) >> 5, warp = threadIdx.x >> 5, lane = threadIdx.x & 31;
6150  float val[VW];
6151  A acc[VW];
6152  #pragma unroll
6153  for(int j = 0; j < VW; ++j){
6154    const int u = (warp + j * nw) * 32 + lane;
6155    val[j] = warp + j * nw < vw && u < D ? (L2 ? __ldcg(o + i0 + u) : o[i0 + u]) : 0.f;
6156    acc[j] = (A)val[j] * (A)val[j];
6157  }
6158  A den = sqrt(lk_warps_sum<VW>(acc, vw, red) / (A)D + (A)eps);
6159  #pragma unroll
6160  for(int j = 0; j < VW; ++j){
6161    const int u = (warp + j * nw) * 32 + lane;
6162    if(warp + j * nw >= vw || u >= D) continue;
6163    const long i = i0 + u;
6164    float zz = z[i];
6165    float r = (float)((A)gn[u] * (A)val[j] / den) * (zz / (1.0f + expf(-zz)));
6166    if(OUTF) out[i] = r;
6167    if(Q > 0) lk_quant_lane<Q>(r, oq, ol, os, i, i >> 5);
6168  }
6169}
6170template<bool OUTF, int Q, typename A>
6171__global__ void lk_delta_norm(const float* __restrict__ z, const float* __restrict__ gn, const float* __restrict__ o,
6172                              float* __restrict__ out, signed char* __restrict__ oq, signed char* __restrict__ ol,
6173                              float* __restrict__ os, int D, float eps){
6174  __shared__ A red[32];
6175  lk_delta_norm_row<OUTF, Q, A, 1, false>(z, gn, o, out, oq, ol, os, (long)blockIdx.x * D, D, eps, red);
6176}
6177"#;
6178
6179/// The delta-rule step a row at a time with its epilogue in its last block a head: `lk_delta_step` given the norm's
6180/// operands (`OUTF`, `Q`, its gate `z` and weight `gn`) and a count a head (a sequence's own, in a batch) — its blocks
6181/// write their rows' outputs and count in; the last reads the head's outputs back through L2 and runs
6182/// `lk_delta_norm_row` over each row's head, its warps playing the norm's `D` threads (`VW` each), then resets the
6183/// count. Every output, memory, norm and quantized word is the one `lk_delta_step` then `lk_delta_norm` compute.
6184const DELTA_STEP_NORM: &str = r#"
6185template<typename A, int DW, bool OUTF, int Q, int VW, typename SS>
6186__global__ void lk_delta_step(const float* __restrict__ q, const float* __restrict__ k, const float* __restrict__ v,
6187                              const float* __restrict__ bet, const float* __restrict__ alp, SS* __restrict__ S,
6188                              float* o, int D, int NK, int HV, int R, int seqs, const float* __restrict__ z,
6189                              const float* __restrict__ gn, float* __restrict__ out, signed char* __restrict__ oq,
6190                              signed char* __restrict__ ol, float* __restrict__ os, float eps, int* __restrict__ cnt){
6191  __shared__ A red[32];
6192  __shared__ int last;
6193  lk_delta_rows<A, DW, SS>(q, k, v, bet, alp, S, o, D, NK, HV, R, seqs);
6194  __threadfence();
6195  __syncthreads();
6196  const long zs = seqs ? blockIdx.z : 0, h = blockIdx.x;
6197  if(threadIdx.x == 0) last = atomicAdd(cnt + zs * HV + h, 1) == gridDim.y - 1;
6198  __syncthreads();
6199  if(!last) return;
6200  __threadfence();
6201  for(int r = 0; r < R; ++r) lk_delta_norm_row<OUTF, Q, A, VW, true>(z, gn, o, out, oq, ol, os, ((zs * R + r) * HV + h) * D, D, eps, red);
6202  if(threadIdx.x == 0) cnt[zs * HV + h] = 0;
6203}
6204"#;
6205
6206/// A mixture of experts for one token: the router's dot products over the `E` experts, a softmax, the top `K` kept
6207/// (and, with `norm`, renormalized to sum to one), then each kept expert's gated FFN and its down projection summed by
6208/// its weight — the experts read by index from the stacked matrices, so only the chosen rows move — and the shared
6209/// experts' SwiGLU FFN (`sdff` wide, 0 without) every token takes, its rows beside the kept experts' and its down row
6210/// added after their sum. `Q` is the numerics: every dot reads the activation quantized (`Q` 1, 2; the hidden rows
6211/// quantized between the two expert launches) or in `f32` with `f64` sums (`Q` 0), each the dot the plain GEMV of its
6212/// format takes (`lk_gemv_dot`). `lk_moe_route` (a warp an expert across the grid; the last block the softmax and the
6213/// top `K`), `lk_moe_up` (a warp per row of every kept expert's gate and up, then the shared expert's), `lk_moe_down`
6214/// (a block per output, a warp per kept expert and one for the shared expert).
6215const MOE: &str = r#"
6216// The router's logits (an expert's row of a router in format `FR`, or with `RF` of an f32 one read against the f32
6217// input, plus the router's bias `rb` when there is one) across the grid's blocks into `logits`: a warp an expert, or an
6218// f32 router's row split over `WPE` warps reading four values a lane at a time, their sums added in order; the last
6219// block to arrive (`cnt`, reset by it) takes their softmax and the top `K` — each pick a warp-wide arg-max, the first
6220// expert of the largest weight winning as a scan in expert order would — renormalized with `norm`, each its softmax
6221// over every expert without. Grid row `y` routes row `y` of the input into its own logits, choices and count.
6222// A row's softmax over its `E` experts' logits and its top `K` — each pick a warp-wide arg-max, the first expert of the
6223// largest weight winning as a scan in expert order would — renormalized with `norm`, each its softmax over every expert
6224// without: a block's threads, `p` `E` floats of shared memory, `red` 32. Lane `r` of the first warp keeps pick `r`'s
6225// weight for the renormalization (`K` at most 32), every lane summing the picks in order.
6226template<int Q>
6227__device__ __forceinline__ void lk_moe_pick_row(const float* logits, float* p, float* red, int E, int K, int norm,
6228                                                int* __restrict__ idx, float* __restrict__ wt){
6229  int lane = threadIdx.x & 31, warp = threadIdx.x >> 5;
6230  for(int i = threadIdx.x; i < E; i += blockDim.x) p[i] = __ldcg(logits + i);
6231  __syncthreads();
6232  float m = -INFINITY;
6233  for(int i = threadIdx.x; i < E; i += blockDim.x) m = fmaxf(m, p[i]);
6234  m = lk_block_max(m, red);
6235  typedef typename lk_acc<Q>::t A;
6236  __shared__ A sums[32];
6237  A s = 0;
6238  for(int i = threadIdx.x; i < E; i += blockDim.x){ float v = expf(p[i] - m); p[i] = v; s += (A)v; }
6239  s = lk_block_sum(s, sums);
6240  __syncthreads();
6241  if(warp == 0){
6242    A total = 0, mine = 0;
6243    for(int r = 0; r < K; ++r){
6244      float bv = -1.0f; int bi = -1;
6245      for(int i = lane; i < E; i += 32) if(p[i] > bv){ bv = p[i]; bi = i; }
6246      for(int o = 16; o > 0; o >>= 1){
6247        float ov = __shfl_down_sync(0xffffffffu, bv, o);
6248        int oi = __shfl_down_sync(0xffffffffu, bi, o);
6249        if(ov > bv || (ov == bv && oi >= 0 && (bi < 0 || oi < bi))){ bv = ov; bi = oi; }
6250      }
6251      bv = __shfl_sync(0xffffffffu, bv, 0);
6252      bi = __shfl_sync(0xffffffffu, bi, 0);
6253      const A pick = (A)bv / s;
6254      if(lane == r) mine = pick;
6255      if(lane == 0){ idx[r] = bi; p[bi] = -2.0f; if(!norm) wt[r] = (float)pick; }
6256      total += pick;
6257      __syncwarp();
6258    }
6259    if(norm && lane < K) wt[lane] = (float)(mine / total);
6260  }
6261}
6262template<int Q, int RF, int FR, int WPE = 1>
6263__global__ void __launch_bounds__(256) lk_moe_route(const float* __restrict__ x, const signed char* __restrict__ xq,
6264                             const signed char* __restrict__ xl, const float* __restrict__ xs, lk_w wr,
6265                             const float* __restrict__ wf, const float* __restrict__ rb, int d, int E, int K, int norm,
6266                             int* __restrict__ idx, float* __restrict__ wt, float* __restrict__ logits, int* __restrict__ cnt){
6267  extern __shared__ float p[];
6268  __shared__ float red[32];
6269  __shared__ double split[8];
6270  __shared__ int last;
6271  int lane = threadIdx.x & 31, warp = threadIdx.x >> 5, nw = blockDim.x >> 5, e = (blockIdx.x * nw + warp) / WPE;
6272  {
6273    long row = blockIdx.y;
6274    if(x) x += row * d;
6275    if(xq) xq += row * d;
6276    if(xl) xl += row * d;
6277    if(xs) xs += row * (d >> 5);
6278    idx += row * K; wt += row * K; logits += row * E; cnt += row;
6279  }
6280  if(RF && WPE > 1){
6281    // Warp `q` of an expert's `WPE` sums its `q`-th part of the row, four values a lane at a time.
6282    int q = warp % WPE, part = d / WPE;
6283    double sum = 0.0;
6284    if(e < E){
6285      const float4* we = (const float4*)(wf + (long)e * d + (long)q * part);
6286      const float4* xv = (const float4*)(x + (long)q * part);
6287      if(Q == 0){
6288        double a = 0.0;
6289        for(int t = lane; t < (part >> 2); t += 32){
6290          float4 w = we[t], v = xv[t];
6291          a += (double)w.x * (double)v.x + (double)w.y * (double)v.y + (double)w.z * (double)v.z + (double)w.w * (double)v.w;
6292        }
6293        sum = lk_warp_sum_d(a);
6294      } else {
6295        float a = 0.f;
6296        for(int t = lane; t < (part >> 2); t += 32){
6297          float4 w = we[t], v = xv[t];
6298          a += w.x * v.x + w.y * v.y + w.z * v.z + w.w * v.w;
6299        }
6300        sum = lk_warp_sum(a);
6301      }
6302    }
6303    if(lane == 0) split[warp] = sum;
6304    __syncthreads();
6305    if(lane == 0 && q == 0 && e < E){
6306      float v;
6307      if(Q == 0){ double t = split[warp]; for(int i = 1; i < WPE; ++i) t += split[warp + i]; v = (float)t; }
6308      else { float t = (float)split[warp]; for(int i = 1; i < WPE; ++i) t += (float)split[warp + i]; v = t; }
6309      logits[e] = rb ? v + rb[e] : v;
6310    }
6311  } else if(e < E){
6312    float v;
6313    if(RF){
6314      const float* we = wf + (long)e * d;
6315      if(Q == 0){ double a = 0.0; for(int t = lane; t < d; t += 32) a += (double)we[t] * (double)x[t]; v = (float)lk_warp_sum_d(a); }
6316      else { float a = 0.f; for(int t = lane; t < d; t += 32) a += we[t] * x[t]; v = lk_warp_sum(a); }
6317    } else {
6318      lk_gemv_dot<FR, Q, 1>(wr, e, d, x, xq, xl, xs, &v);
6319    }
6320    if(lane == 0) logits[e] = rb ? v + rb[e] : v;
6321  }
6322  __threadfence();
6323  __syncthreads();
6324  if(threadIdx.x == 0) last = atomicAdd(cnt, 1) == gridDim.x - 1;
6325  __syncthreads();
6326  if(!last) return;
6327  __threadfence();
6328  lk_moe_pick_row<Q>(logits, p, red, E, K, norm, idx, wt);
6329  if(threadIdx.x == 0) *cnt = 0;
6330}
6331// Row `blockIdx.x`'s choices and weights from its logits (`lk_moe_pick_row`), as `lk_moe_route` takes them: a wide
6332// chunk's router, its logits a GEMM's.
6333template<int Q>
6334__global__ void __launch_bounds__(256) lk_moe_pick(const float* __restrict__ logits, int E, int K, int norm,
6335                                                   int* __restrict__ idx, float* __restrict__ wt){
6336  extern __shared__ float p[];
6337  __shared__ float red[32];
6338  long row = blockIdx.x;
6339  lk_moe_pick_row<Q>(logits + row * E, p, red, E, K, norm, idx + row * K, wt + row * K);
6340}
6341// The rows' choices grouped by expert, in row order then choice order: `ecount[e]` choices of expert `e` from `eoff[e]`
6342// in `list` (each a choice `r·K + k`), and each choice's place in `list` (`pos`). One block: the counts by shared
6343// atomics and their offsets by one thread, then the choices a block-width at a time, each placed after its expert's
6344// choices before it — in earlier block-widths (`run`), in earlier warps of its own (`wc`), in earlier lanes of its
6345// warp (`__match_any_sync`). Shared memory: `run`, then `wc`, (1 + warps) · `E` ints.
6346__global__ void lk_moe_group(const int* __restrict__ idx, int n, int E, int* __restrict__ ecount, int* __restrict__ eoff,
6347                             int* __restrict__ list, int* __restrict__ pos){
6348  extern __shared__ int cur[];
6349  int *run = cur, *wc = cur + E;
6350  int lane = threadIdx.x & 31, warp = threadIdx.x >> 5, nw = blockDim.x >> 5;
6351  for(int e = threadIdx.x; e < E; e += blockDim.x) run[e] = 0;
6352  for(int j = threadIdx.x; j < nw * E; j += blockDim.x) wc[j] = 0;
6353  __syncthreads();
6354  for(int i = threadIdx.x; i < n; i += blockDim.x) atomicAdd(&run[idx[i]], 1);
6355  __syncthreads();
6356  if(threadIdx.x == 0){
6357    int at = 0;
6358    for(int e = 0; e < E; ++e){ int c = run[e]; ecount[e] = c; eoff[e] = at; run[e] = at; at += c; }
6359    eoff[E] = at;
6360  }
6361  __syncthreads();
6362  for(int base = 0; base < n; base += blockDim.x){
6363    int i = base + threadIdx.x, e = i < n ? idx[i] : -1;
6364    unsigned peers = __match_any_sync(0xffffffffu, e);
6365    int rank = __popc(peers & ((1u << lane) - 1u));
6366    if(e >= 0 && rank == 0) wc[warp * E + e] = __popc(peers);
6367    __syncthreads();
6368    if(e >= 0){
6369      int p = run[e] + rank;
6370      for(int u = 0; u < warp; ++u) p += wc[u * E + e];
6371      list[p] = i; pos[i] = p;
6372    }
6373    __syncthreads();
6374    for(int x = threadIdx.x; x < E; x += blockDim.x){
6375      int sum = 0;
6376      for(int u = 0; u < nw; ++u){ sum += wc[u * E + x]; wc[u * E + x] = 0; }
6377      run[x] += sum;
6378    }
6379    __syncthreads();
6380  }
6381}
6382// Each choice's activation row, in `list` order: the row of `x` (f32 under Q 0, its int8 words and scales otherwise)
6383// of the choice's token.
6384template<int Q>
6385__global__ void lk_moe_gather(const float* __restrict__ x, const signed char* __restrict__ xq, const signed char* __restrict__ xl,
6386                              const float* __restrict__ xs, const int* __restrict__ list, int K, int d, float* __restrict__ gx,
6387                              signed char* __restrict__ gq, signed char* __restrict__ gl, float* __restrict__ gs){
6388  long p = blockIdx.x, r = list[p] / K;
6389  for(int i = threadIdx.x; i < d; i += blockDim.x){
6390    if(Q == 0) gx[p * d + i] = x[r * d + i];
6391    else { gq[p * d + i] = xq[r * d + i]; if(Q == 2) gl[p * d + i] = xl[r * d + i]; }
6392  }
6393  if(Q > 0) for(int b = threadIdx.x; b < (d >> 5); b += blockDim.x) gs[p * (d >> 5) + b] = xs[r * (d >> 5) + b];
6394}
6395// A choice count in slabs of 16, then of 8, 4, 2 and 1 rows — every row in exactly one slab, each row's dots those of
6396// one row (`lk_gemv_dot` sums a row alike whatever its slab), `slab<M>(first)` called for each.
6397template<typename S>
6398__device__ __forceinline__ void lk_slabs(int n, S slab){
6399  int s0 = 0;
6400  for(; n - s0 >= 16; s0 += 16) slab.template run<16>(s0);
6401  if(n - s0 >= 8){ slab.template run<8>(s0); s0 += 8; }
6402  if(n - s0 >= 4){ slab.template run<4>(s0); s0 += 4; }
6403  if(n - s0 >= 2){ slab.template run<2>(s0); s0 += 2; }
6404  if(n - s0 >= 1) slab.template run<1>(s0);
6405}
6406template<int Q, int ACT, int FG, int FU>
6407struct lk_up_slab {
6408  const float* x; const signed char* xq; const signed char* xl; const float* xs; lk_w wg, wu;
6409  const float* bg; const float* bu; float* h; long wrow, off, j; int d, dff; float limit, slope;
6410  template<int M> __device__ __forceinline__ void run(int s0) const {
6411    long at = (off + s0) * d;
6412    float g[M], u[M];
6413    lk_gemv_dot<FG, Q, M>(wg, wrow, d, Q ? nullptr : x + at, Q ? xq + at : nullptr, Q == 2 ? xl + at : nullptr,
6414                          Q ? xs + (at >> 5) : nullptr, g);
6415    lk_gemv_dot<FU, Q, M>(wu, wrow, d, Q ? nullptr : x + at, Q ? xq + at : nullptr, Q == 2 ? xl + at : nullptr,
6416                          Q ? xs + (at >> 5) : nullptr, u);
6417    if((threadIdx.x & 31) == 0){
6418      #pragma unroll
6419      for(int t = 0; t < M; ++t){
6420        float gv = bg ? g[t] + bg[wrow] : g[t], uv = bu ? u[t] + bu[wrow] : u[t];
6421        float o;
6422        if(ACT == 0) o = gv / (1.0f + expf(-gv)) * uv;
6423        else { float gc = fminf(gv, limit); o = gc / (1.0f + expf(-slope * gc)) * (fminf(fmaxf(uv, -limit), limit) + 1.0f); }
6424        h[(off + s0 + t) * dff + j] = o;
6425      }
6426    }
6427  }
6428};
6429// Each expert's gate and up rows over the activation rows of the choices of it (`n` from `off` of the gathered rows),
6430// in slabs (`lk_slabs`), each row's dots as one row's (`lk_gemv_dot`), through the gated activation of `lk_moe_up`: a
6431// warp a row of the expert's, a grid row an expert.
6432template<int Q, int ACT, int FG, int FU>
6433__global__ void lk_moe_up_rows(const float* __restrict__ x, const signed char* __restrict__ xq,
6434                               const signed char* __restrict__ xl, const float* __restrict__ xs, lk_w wg, lk_w wu,
6435                               const float* __restrict__ bg, const float* __restrict__ bu, const int* __restrict__ ecount,
6436                               const int* __restrict__ eoff, float* __restrict__ h, int d, int dff, float limit, float slope){
6437  int e = blockIdx.y, n = ecount[e];
6438  long j = ((long)blockIdx.x * blockDim.x + threadIdx.x) >> 5;
6439  if(n == 0 || j >= dff) return;
6440  lk_slabs(n, lk_up_slab<Q, ACT, FG, FU>{x, xq, xl, xs, wg, wu, bg, bu, h, (long)e * dff + j, eoff[e], j, d, dff, limit, slope});
6441}
6442// Each expert's down rows over the hidden rows of the choices of it, in slabs (`lk_slabs`), each choice's result
6443// weighed by its weight into `part` (its place in `list`), as `lk_moe_down` weighs it: a warp an output, a grid row an
6444// expert.
6445template<int Q, int FD>
6446struct lk_down_slab {
6447  const float* h; const signed char* hq; const signed char* hl; const float* hs; lk_w wd; const float* bd;
6448  const int* list; const float* wt; typename lk_acc<Q>::t* part; long wrow, off, o; int d, dff;
6449  template<int M> __device__ __forceinline__ void run(int s0) const {
6450    typedef typename lk_acc<Q>::t A;
6451    long at = (off + s0) * dff;
6452    float v[M];
6453    lk_gemv_dot<FD, Q, M>(wd, wrow, dff, Q ? nullptr : h + at, Q ? hq + at : nullptr, Q == 2 ? hl + at : nullptr,
6454                          Q ? hs + (at >> 5) : nullptr, v);
6455    if((threadIdx.x & 31) == 0){
6456      #pragma unroll
6457      for(int t = 0; t < M; ++t) part[(off + s0 + t) * d + o] = (A)(bd ? v[t] + bd[wrow] : v[t]) * (A)wt[list[off + s0 + t]];
6458    }
6459  }
6460};
6461template<int Q, int FD>
6462__global__ void lk_moe_down_rows(const float* __restrict__ h, const signed char* __restrict__ hq,
6463                                 const signed char* __restrict__ hl, const float* __restrict__ hs, lk_w wd,
6464                                 const float* __restrict__ bd, const int* __restrict__ ecount, const int* __restrict__ eoff,
6465                                 const int* __restrict__ list, const float* __restrict__ wt,
6466                                 typename lk_acc<Q>::t* __restrict__ part, int d, int dff){
6467  int e = blockIdx.y, n = ecount[e];
6468  long o = ((long)blockIdx.x * blockDim.x + threadIdx.x) >> 5;
6469  if(n == 0 || o >= d) return;
6470  lk_slabs(n, lk_down_slab<Q, FD>{h, hq, hl, hs, wd, bd, list, wt, part, (long)e * d + o, eoff[e], o, d, dff});
6471}
6472// Each choice's hidden row from its expert's gate and up rows over it (`g`, `u`, in `list` order), plus the expert's
6473// biases, through the gated activation of `lk_moe_up`.
6474template<int ACT>
6475__global__ void lk_moe_glu(const float* __restrict__ g, const float* __restrict__ u, const float* __restrict__ bg,
6476                           const float* __restrict__ bu, const int* __restrict__ idx, const int* __restrict__ list,
6477                           float* __restrict__ h, long n, int dff, float limit, float slope){
6478  long i = (long)blockIdx.x * blockDim.x + threadIdx.x;
6479  if(i >= n) return;
6480  long wrow = (long)idx[list[i / dff]] * dff + i % dff;
6481  float gv = bg ? g[i] + bg[wrow] : g[i], uv = bu ? u[i] + bu[wrow] : u[i];
6482  if(ACT == 0) h[i] = gv / (1.0f + expf(-gv)) * uv;
6483  else { float gc = fminf(gv, limit); h[i] = gc / (1.0f + expf(-slope * gc)) * (fminf(fmaxf(uv, -limit), limit) + 1.0f); }
6484}
6485// Output `o` of row `r`: its choices' weighed results summed in choice order, as `lk_moe_down` sums them.
6486template<int Q>
6487__device__ __forceinline__ float lk_moe_combined(const typename lk_acc<Q>::t* __restrict__ part, const int* __restrict__ pos,
6488                                                 int K, int d, long r, long o){
6489  typedef typename lk_acc<Q>::t A;
6490  A s = 0;
6491  for(int k = 0; k < K; ++k) s += part[(long)pos[r * K + k] * d + o];
6492  return (float)s;
6493}
6494// Each row's output (`lk_moe_combined`).
6495template<int Q>
6496__global__ void lk_moe_combine(const typename lk_acc<Q>::t* __restrict__ part, const int* __restrict__ pos, int K, int d,
6497                               float* __restrict__ y){
6498  long r = blockIdx.y, o = (long)blockIdx.x * blockDim.x + threadIdx.x;
6499  if(o >= d) return;
6500  y[r * d + o] = lk_moe_combined<Q>(part, pos, K, d, r, o);
6501}
6502// Each chosen expert's gate and up rows (formats `FG`, `FU`, plus their biases `bg`, `bu`) through the gated activation:
6503// SwiGLU, or with `ACT` 1 the gate clamped to at most `limit`, the up to `[−limit, limit]`, the sigmoid sharpened by
6504// `slope`; then the shared expert's (formats `FSG`, `FSU`, `sdff` rows) through SwiGLU, after the kept experts' rows.
6505// A warp takes `W` consecutive rows, all of one expert (`W` divides `dff` and `sdff`).
6506template<int Q, int ACT, int FG, int FU, int FSG, int FSU, int W = 1>
6507__global__ void lk_moe_up(const float* __restrict__ x, const signed char* __restrict__ xq,
6508                          const signed char* __restrict__ xl, const float* __restrict__ xs, lk_w wg, lk_w wu,
6509                          lk_w sg, lk_w su, const float* __restrict__ bg, const float* __restrict__ bu,
6510                          const int* __restrict__ idx, float* __restrict__ h, int d, int dff, int K, int sdff,
6511                          float limit, float slope){
6512  long row = (((long)blockIdx.x * blockDim.x + threadIdx.x) >> 5) * W, routed = (long)K * dff;
6513  if(row >= routed + sdff) return;
6514  float gv[W], uv[W];
6515  if(row < routed){
6516    int r = row / dff, j = row % dff;
6517    long wrow = (long)idx[r] * dff + j;
6518    lk_gemv_dot<FG, Q, 1, W>(wg, wrow, d, x, xq, xl, xs, gv);
6519    lk_gemv_dot<FU, Q, 1, W>(wu, wrow, d, x, xq, xl, xs, uv);
6520    #pragma unroll
6521    for(int i = 0; i < W; ++i){
6522      if(bg) gv[i] += bg[wrow + i];
6523      if(bu) uv[i] += bu[wrow + i];
6524    }
6525  } else {
6526    lk_gemv_dot<FSG, Q, 1, W>(sg, row - routed, d, x, xq, xl, xs, gv);
6527    lk_gemv_dot<FSU, Q, 1, W>(su, row - routed, d, x, xq, xl, xs, uv);
6528  }
6529  if((threadIdx.x & 31) == 0){
6530    #pragma unroll
6531    for(int i = 0; i < W; ++i){
6532      if(ACT == 0 || row >= routed) h[row + i] = gv[i] / (1.0f + expf(-gv[i])) * uv[i];
6533      else {
6534        float gc = fminf(gv[i], limit);
6535        h[row + i] = gc / (1.0f + expf(-slope * gc)) * (fminf(fmaxf(uv[i], -limit), limit) + 1.0f);
6536      }
6537    }
6538  }
6539}
6540// Each chosen expert's down row (format `FD`, plus its bias `bd`), summed by the expert's weight; then the shared
6541// expert's down row (format `FSD`) over the hidden rows past the kept experts', added to the sum. A block takes `W`
6542// consecutive outputs: a warp each kept expert's `W` rows, and `SW` warps (`SW` dividing `W`) the shared expert's, `W /
6543// SW` rows each — every output's dots and sums as a block of one output computes them. `plus`, when given, is added
6544// to each output, as an add of the two arrays adds it.
6545template<int Q, int FD, int FSD, int W, int SW>
6546__device__ __forceinline__ void lk_moe_down_block(const float* __restrict__ h, const signed char* __restrict__ hq,
6547                            const signed char* __restrict__ hl, const float* __restrict__ hs, lk_w wd, lk_w sd,
6548                            const float* __restrict__ bd, const int* __restrict__ idx, const float* __restrict__ wt,
6549                            float* __restrict__ y, int d, int dff, int K, int sdff, const float* __restrict__ plus){
6550  typedef typename lk_acc<Q>::t A;
6551  constexpr int SR = W / SW;
6552  __shared__ A part[32][W];
6553  int o0 = blockIdx.x * W, lane = threadIdx.x & 31, r = threadIdx.x >> 5;
6554  if(r < K){
6555    long wrow = (long)idx[r] * d + o0;
6556    long hoff = (long)r * dff;
6557    float v[W];
6558    lk_gemv_dot<FD, Q, 1, W>(wd, wrow, dff, h + hoff, Q ? hq + hoff : nullptr, Q == 2 ? hl + hoff : nullptr,
6559                             Q ? hs + (hoff >> 5) : nullptr, v);
6560    if(lane == 0)
6561      #pragma unroll
6562      for(int i = 0; i < W; ++i) part[r][i] = (A)(bd ? v[i] + bd[wrow + i] : v[i]) * (A)wt[r];
6563  } else {
6564    int i0 = (r - K) * SR;
6565    long hoff = (long)K * dff;
6566    float v[SR];
6567    lk_gemv_dot<FSD, Q, 1, SR>(sd, o0 + i0, sdff, h + hoff, Q ? hq + hoff : nullptr, Q == 2 ? hl + hoff : nullptr,
6568                               Q ? hs + (hoff >> 5) : nullptr, v);
6569    if(lane == 0)
6570      #pragma unroll
6571      for(int i = 0; i < SR; ++i) part[K][i0 + i] = (A)v[i];
6572  }
6573  __syncthreads();
6574  if(threadIdx.x < W){
6575    int i = threadIdx.x;
6576    A s = 0;
6577    for(int e = 0; e < K; ++e) s += part[e][i];
6578    // The shared expert's row adds to the experts' sum as an `f32` sum of the two results.
6579    float v = sdff ? (float)s + (float)part[K][i] : (float)s;
6580    y[o0 + i] = plus ? v + plus[o0 + i] : v;
6581  }
6582}
6583template<int Q, int FD, int FSD, int W = 1, int SW = 1>
6584__global__ void lk_moe_down(const float* __restrict__ h, const signed char* __restrict__ hq,
6585                            const signed char* __restrict__ hl, const float* __restrict__ hs, lk_w wd, lk_w sd,
6586                            const float* __restrict__ bd, const int* __restrict__ idx, const float* __restrict__ wt,
6587                            float* __restrict__ y, int d, int dff, int K, int sdff){
6588  lk_moe_down_block<Q, FD, FSD, W, SW>(h, hq, hl, hs, wd, sd, bd, idx, wt, y, d, dff, K, sdff, nullptr);
6589}
6590"#;
6591
6592/// A mixture with the residual add and the next norm in its last step (`moe_deferred_finalize`): `lk_moe_down` or a
6593/// chunk's `lk_moe_combine`, each output plus `plus` when the mixture's sum with another array is what the norm adds,
6594/// then `lk_rmsnorm` over the rows it wrote. The decode step's down projection counts its blocks in at `cnt` as they
6595/// write their outputs; the last reads the row back through L2 and norms it, its warps playing the norm's own block of
6596/// `vt` threads (`lk_rmsnorm_row`'s `VW`), then resets the count. A chunk's combine takes a block of the norm's threads a
6597/// row, combining its row before norming it. Either computes each output, sum and norm as the launches apart do.
6598const MOE_NORM: &str = r#"
6599template<int Q, int FD, int FSD, int W, int SW, bool ADD, bool SUM, bool OUTF, int QO, int PER, typename A, bool PRE, int VW>
6600__global__ void lk_moe_down_norm(const float* __restrict__ h, const signed char* __restrict__ hq,
6601                                 const signed char* __restrict__ hl, const float* __restrict__ hs, lk_w wd, lk_w sd,
6602                                 const float* __restrict__ bd, const int* __restrict__ idx, const float* __restrict__ wt,
6603                                 float* y, int d, int dff, int K, int sdff, const float* __restrict__ plus, lk_norm_of nm,
6604                                 int vt, int* __restrict__ cnt){
6605  __shared__ A red[32];
6606  __shared__ int last;
6607  lk_moe_down_block<Q, FD, FSD, W, SW>(h, hq, hl, hs, wd, sd, bd, idx, wt, y, d, dff, K, sdff, plus);
6608  __threadfence();
6609  __syncthreads();
6610  if(threadIdx.x == 0) last = atomicAdd(cnt, 1) == gridDim.x - 1;
6611  __syncthreads();
6612  if(!last) return;
6613  __threadfence();
6614  lk_out yr = nm.y ? LK_ROW(nm.y, nm.yrow, nm.ypitch) : lk_out();
6615  lk_rmsnorm_row<ADD, SUM, OUTF, QO, PER, A, PRE, true, VW>(nm.x, nm.r, nm.s, nm.w, yr, nm.yq, nm.yl, nm.ys, d, nm.eps, 0, 0,
6616                                                            nm.pw, nm.peps, red, vt);
6617  if(threadIdx.x == 0) *cnt = 0;
6618}
6619template<int Q, bool ADD, bool SUM, bool OUTF, int QO, int PER, typename A, bool PRE>
6620__global__ void __launch_bounds__(1024) lk_moe_combine_norm(const typename lk_acc<Q>::t* __restrict__ part,
6621                                 const int* __restrict__ pos, int K, int d, const float* __restrict__ plus, float* y,
6622                                 lk_norm_of nm){
6623  __shared__ A red[32];
6624  long r = blockIdx.x, base = r * d;
6625  for(int o = threadIdx.x; o < d; o += blockDim.x){
6626    float v = lk_moe_combined<Q>(part, pos, K, d, r, o);
6627    y[base + o] = plus ? v + plus[base + o] : v;
6628  }
6629  __syncthreads();
6630  lk_out yr = nm.y ? LK_ROW(nm.y, nm.yrow, nm.ypitch) + base : lk_out();
6631  lk_rmsnorm_row<ADD, SUM, OUTF, QO, PER, A, PRE, false>(nm.x, nm.r, nm.s, nm.w, yr, nm.yq, nm.yl, nm.ys, d, nm.eps, base,
6632                                                         base, nm.pw, nm.peps, red, blockDim.x);
6633}
6634"#;