Skip to main content

memra_engine/
mla_ffi.rs

1//! FFI declarations + safe Engine wrappers for the MLA CUDA forward (`cu/mla_attn.cu`).
2//!
3//! House pattern (mmq_ffi / dsv4_ffi kind): C-ABI host launchers in the `libmemra_mmq.a`
4//! static lib, returning 0 ok / 10000+cudaError / 40000+contract; the stream rides as
5//! `*mut c_void` (`stream.cu_stream()`).
6//!
7//! The numeric truth for the dense core is `crate::mla` (the CPU f32 oracle), gated in
8//! `tests/mla_gpu_forward.rs`. The truth for the DSA k-pool indexer wrappers at the bottom of
9//! this file is `memra_reference::kpool_allowed_tokens`, gated in
10//! `tests/glm5_kpool_indexer_gpu.rs`.
11
12use crate::Engine;
13use cudarc::driver::{CudaSlice, DevicePtr, DevicePtrMut};
14use std::os::raw::c_void;
15
16/// Engagement counter for the MLA decode-split door (`MEMRA_MLA_DECODE_SPLIT`): counted at
17/// the arm's own call site, announced once per boot — the receipt a box A/B arm must show.
18pub static MLA_DECODE_SPLIT_DISPATCHES: std::sync::atomic::AtomicU64 =
19    std::sync::atomic::AtomicU64::new(0);
20
21/// `MEMRA_MLA_DECODE_SPLIT=1` (default OFF, read per call — rollback seam): the absorb /
22/// decompress launchers split each (token, head) block's output range across several blocks.
23/// PURE LAUNCH GEOMETRY: every output element keeps the same one-thread serial dot, so the
24/// bytes are identical for every split value (asserted in `tests/mla_decode_split_gpu.rs`);
25/// only occupancy changes — 64 blocks at t=1 on the glm5 geometry is single-digit-percent
26/// occupancy on the serving card class, the census's ~211 us/layer absorb+decompress pair.
27/// Engagement counter for the coalesced warp-per-row door (`MEMRA_MLA_COALESCE`).
28pub static MLA_COALESCE_DISPATCHES: std::sync::atomic::AtomicU64 =
29    std::sync::atomic::AtomicU64::new(0);
30
31/// `MEMRA_MLA_COALESCE=1` (default OFF, read per call — the rollback seam is its absence):
32/// dispatch the warp-per-row absorb/decompress kernels instead of the shipped thread-per-row
33/// ones. See `memra_mla_absorb_q_wp_f32` for the defect and the numeric class.
34///
35/// It composes with whichever split door is armed rather than replacing it: the split doors
36/// choose the output-range partition (the GRID), this door chooses how a row is read (the
37/// LOADS), and `split == 1` is simply the unsplit partition. So the dispatch below asks the
38/// existing policy for a split first and passes whatever it returns.
39fn mla_coalesce_on() -> bool {
40    std::env::var("MEMRA_MLA_COALESCE").as_deref() == Ok("1")
41}
42
43/// Announce once per boot, naming the kernel and the split it composed with, because a door
44/// that silently changes which kernel runs is the failure class this lane spent a day on.
45fn mla_coalesce_announce(which: &str, t_q: usize, n_head: usize, split: i32) {
46    use std::sync::atomic::Ordering;
47    if MLA_COALESCE_DISPATCHES.fetch_add(1, Ordering::Relaxed) == 0 {
48        eprintln!(
49            "[mla-coalesce] engaged {which} t_q={t_q} n_head={n_head} split={split} \
50             (warp-per-row coalesced loads + shuffle reduction; numeric class \
51             mla_warp_row_reduce; MEMRA_MLA_COALESCE=1)"
52        );
53    }
54}
55
56fn mla_decode_split_on() -> bool {
57    std::env::var("MEMRA_MLA_DECODE_SPLIT").as_deref() == Ok("1")
58}
59
60/// The split policy: engage only in the block-starved regime (fewer than 1024 (token, head)
61/// blocks — decode and short verify widths; prefill widths already fill the card and the TC
62/// prefill chain owns them anyway), aiming for ~1024 blocks while keeping at least 32 outputs
63/// per block. The OUTPUT BYTES ARE SPLIT-INVARIANT by construction, so this arithmetic is a
64/// throughput policy, never a numerics decision.
65fn mla_decode_split_for(blocks: usize, out_dim: usize) -> Option<i32> {
66    if !mla_decode_split_on() || blocks == 0 || blocks >= 1024 {
67        return None;
68    }
69    let want = 1024usize.div_ceil(blocks);
70    let cap = (out_dim / 32).max(1);
71    let split = want.min(cap);
72    if split <= 1 { None } else { Some(split as i32) }
73}
74
75fn mla_split_announce(kind: &str, t_q: usize, n_head: usize, split: i32) {
76    use std::sync::atomic::Ordering;
77    if MLA_DECODE_SPLIT_DISPATCHES.fetch_add(1, Ordering::Relaxed) == 0 {
78        eprintln!(
79            "[mla-decode-split] engaged {kind} t={t_q} heads={n_head} split={split} \
80             (output-range split of the (token, head) blocks; MEMRA_MLA_DECODE_SPLIT=1)"
81        );
82    }
83}
84
85/// Engagement counter for the B200 decode arm (`MEMRA_B200_MLA_DECODE_ARM`), announced once
86/// per boot: the receipt a B200 box A/B arm must show.
87pub static MLA_B200_DECODE_ARM_DISPATCHES: std::sync::atomic::AtomicU64 =
88    std::sync::atomic::AtomicU64::new(0);
89
90/// `MEMRA_B200_MLA_DECODE_ARM=1` (default OFF, read per call: the rollback seam), compile-time
91/// gated to sm_100a builds (`cfg!(memra_sm100_tcgen05)`, set by build.rs for
92/// `MEMRA_CUDA_ARCH=100a`): on a 120a/90a/89 build this is `false` unconditionally, so naked
93/// non-B200 commands and the flag census see no behavior change from a var they cannot even
94/// engage. The arch guard is a compile-time fact here, not a per-call detection cost.
95///
96/// Owner order 2026-09-02: "hardly improve the decode on these cards, before the full 1M."
97/// This is a genuinely separate door from `MEMRA_MLA_DECODE_SPLIT` (glm5-decode-diet lever 4,
98/// rig-generic, target ~1024 blocks, PRO6000-tuned) rather than a rename of it, per the
99/// per-hardware-arm-selection law in CLAUDE.md: B200 SXM carries more SMs per device than the
100/// PRO6000 pair that door was tuned on, and this arm ALSO covers `attn_gathered`, which the
101/// generic split door never touched (no independent-output split existed for it before this
102/// lane; see `memra_mla_attn_gathered_split_kernel` in cu/mla_attn.cu).
103fn mla_b200_decode_arm_on() -> bool {
104    cfg!(memra_sm100_tcgen05) && std::env::var("MEMRA_B200_MLA_DECODE_ARM").as_deref() == Ok("1")
105}
106
107/// The three kernels the B200 arm covers. The gate bin (`mla_decode_arm_gate.rs`) walks this
108/// same enum and the same table below, so its regression check and the serving policy cannot
109/// disagree about which split a t_q gets.
110#[derive(Clone, Copy, Debug, PartialEq, Eq)]
111pub enum MlaB200Kernel {
112    AbsorbQ,
113    DecompressV,
114    AttnGathered,
115}
116
117impl MlaB200Kernel {
118    pub const ALL: [MlaB200Kernel; 3] = [
119        MlaB200Kernel::AbsorbQ,
120        MlaB200Kernel::DecompressV,
121        MlaB200Kernel::AttnGathered,
122    ];
123
124    pub fn name(self) -> &'static str {
125        match self {
126            MlaB200Kernel::AbsorbQ => "absorb_q",
127            MlaB200Kernel::DecompressV => "decompress_v",
128            MlaB200Kernel::AttnGathered => "attn_gathered",
129        }
130    }
131}
132
133/// Widest query width the B200 arm keys on. Wider widths fall through untouched: the generic
134/// `MEMRA_MLA_DECODE_SPLIT` door if set, else the shipped kernels (t >= 16 reaches
135/// `MEMRA_MLA_TC_PREFILL` before either).
136pub const MLA_B200_ARM_T_MAX: usize = 8;
137
138/// The B200 arm's split tables, keyed on t_q (index = t_q in 1..=MLA_B200_ARM_T_MAX; index 0
139/// is unused and always 1). A cell of 1 means THE SHIPPED KERNEL: the wrapper falls through to
140/// the unsplit launcher and the split twin is never launched with split=1, so "shipped" is the
141/// shipped binary path, not a re-implementation of it. Any other cell is the output-range
142/// split factor handed to the bit-identical split twin.
143///
144/// Why a table and not a block-count target: the first cut of this door aimed at ~2048 blocks
145/// at every t_q <= 8 and the real box refuted that shape. Measured 2026-09-02 on the 2x B200
146/// SXM pair (sm_100a), `mla-decode-arm-gate` device 0, geometry nh=64 kv_rank=512 d_nope=256
147/// d_v=256 d_rope=0 n_slots=2048 pool_rows=32768, N=5, every arm BIT-IDENTICAL to shipped:
148///
149/// | kernel        | t_q | shipped  | arm           | verdict                   |
150/// |---------------|-----|----------|---------------|---------------------------|
151/// | absorb_q      | 1   | 81.8 us  | split=4 49.1  | win                       |
152/// | decompress_v  | 1   | 82.2 us  | split=4 48.0  | win                       |
153/// | attn_gathered | 1   | 564.6 us | split=2 516.4 | win                       |
154/// | absorb_q      | 4   | 150.3 us | split=4 133.2 | win                       |
155/// | decompress_v  | 4   | 150.4 us | split=4 246.6 | REGRESSION, shipped wins  |
156/// | attn_gathered | 4   | 665.3 us | split=2 822.7 | REGRESSION, shipped wins  |
157///
158/// t_q=4..8 is the DFlash2 spec-verify shape the box serves, so a target-driven policy that
159/// splits there costs the spec route. The tables ship exactly what that run showed and nothing
160/// it did not: the measured winner at t_q=1 for all three kernels, absorb_q's measured split=4
161/// win at t_q=4, and the shipped kernel everywhere else (t_q=2,3,5..8 are unmeasured, and
162/// unmeasured behavior does not go on). The gate times every split in {1,2,4,8} at every t_q
163/// in {1,2,4,8} for all three kernels, prints the per-t winner table, and FAILS (`REGRESSION`,
164/// exit 1) when a cell of THESE tables is slower than shipped by more than
165/// `MLA_B200_ARM_REGRESSION_MARGIN`, so a box run either confirms the tables or names the cell
166/// to change. Cite the box run in this comment when editing a cell.
167pub const MLA_B200_ABSORB_Q_SPLIT: [i32; MLA_B200_ARM_T_MAX + 1] = [1, 4, 1, 1, 4, 1, 1, 1, 1];
168pub const MLA_B200_DECOMPRESS_V_SPLIT: [i32; MLA_B200_ARM_T_MAX + 1] = [1, 4, 1, 1, 1, 1, 1, 1, 1];
169pub const MLA_B200_ATTN_GATHERED_SPLIT: [i32; MLA_B200_ARM_T_MAX + 1] = [1, 2, 1, 1, 1, 1, 1, 1, 1];
170
171/// The gate's regression bar: at every measured t_q the table's arm may not be slower than
172/// shipped by more than 5% (arm/shipped above this ratio fails `mla-decode-arm-gate`).
173pub const MLA_B200_ARM_REGRESSION_MARGIN: f64 = 1.05;
174
175/// Table lookup, independent of the door: 1 (shipped) outside 1..=MLA_B200_ARM_T_MAX. Pure,
176/// so the gate bin can read the table on any build, including the 120a builds where the door
177/// itself cannot engage.
178pub fn mla_b200_arm_table_split(kernel: MlaB200Kernel, t_q: usize) -> i32 {
179    if t_q == 0 || t_q > MLA_B200_ARM_T_MAX {
180        return 1;
181    }
182    match kernel {
183        MlaB200Kernel::AbsorbQ => MLA_B200_ABSORB_Q_SPLIT[t_q],
184        MlaB200Kernel::DecompressV => MLA_B200_DECOMPRESS_V_SPLIT[t_q],
185        MlaB200Kernel::AttnGathered => MLA_B200_ATTN_GATHERED_SPLIT[t_q],
186    }
187}
188
189/// The serving policy: door on, table cell above 1, and the cell legal for this geometry (the
190/// split twins need `split <= out_dim`; this keeps at least 32 outputs per block, the same
191/// floor as the generic door). A cell the geometry cannot honour falls through to the shipped
192/// kernel rather than clamping to a split the box never measured. The tables were measured on
193/// the glm5 geometry (kv_rank=512, d_v=256); `None` here means "shipped path", and the caller
194/// falls through in order to the generic split door, then the unsplit launcher.
195fn mla_b200_split_for(kernel: MlaB200Kernel, t_q: usize, out_dim: usize) -> Option<i32> {
196    if !mla_b200_decode_arm_on() {
197        return None;
198    }
199    let split = mla_b200_arm_table_split(kernel, t_q);
200    let cap = (out_dim / 32).max(1) as i32;
201    if split <= 1 || split > cap {
202        None
203    } else {
204        Some(split)
205    }
206}
207
208fn mla_b200_split_announce(kind: &str, t_q: usize, n_head: usize, split: i32) {
209    use std::sync::atomic::Ordering;
210    if MLA_B200_DECODE_ARM_DISPATCHES.fetch_add(1, Ordering::Relaxed) == 0 {
211        eprintln!(
212            "[mla-b200-decode-arm] engaged {kind} t={t_q} heads={n_head} split={split} \
213             (sm_100a output-range split; MEMRA_B200_MLA_DECODE_ARM=1)"
214        );
215    }
216}
217
218/// Engagement counter for the DSA decode door (`MEMRA_B200_DSA_DECODE`), announced once per
219/// boot per arm: the receipt a B200 box A/B has to show.
220pub static MLA_DSA_DECODE_DISPATCHES: std::sync::atomic::AtomicU64 =
221    std::sync::atomic::AtomicU64::new(0);
222
223/// `MEMRA_B200_DSA_DECODE` (default OFF = 0, read per call: the rollback seam), compile-time
224/// gated to sm_100a builds exactly like its sibling `MEMRA_B200_MLA_DECODE_ARM`, so a
225/// 120a/90a/89 build sees no behavior change from a var it cannot engage.
226///
227/// THE DOOR IS A LEVEL, not a boolean, and the level is the numeric-class boundary:
228///
229/// * `0` (default) - nothing engages. Every kernel is the shipped one.
230/// * `1` - the BIT-IDENTICAL arms only: `memra_mla_attn_gathered_dsa_kernel` (same fold, same
231///   lane stride, same shuffle tree; what changes is that each tile's KV rows are staged once
232///   into shared memory with float4 loads and serve BOTH the score dot and the PV accumulate,
233///   and that the 8 tile exponentials are hoisted into registers instead of being recomputed
234///   3x per thread per tile) and `memra_mla_kpool_score_dsa_kernel` (head-blocked decode
235///   scorer; c-ascending dot, h-ascending mix, all six rounding steps spelled with explicit
236///   intrinsics). Both are asserted bytewise by `dsa-decode-gate`, not merely argued.
237/// * `2` - additionally admits the WARP-ONLINE gathered arm
238///   (`memra_mla_dsa_attn_warp_kernel` + `memra_mla_dsa_attn_combine_kernel`), numeric class
239///   **`dsa-warp-online-f32`**: one warp owns one (token, head, slot-chunk) and holds the whole
240///   kv_rank-wide accumulator in registers, so every KV element is read from memory ONCE and
241///   consumed twice from registers, there is not a single `__syncthreads`, and the two `expf`
242///   per slot replace ~196k per warp per layer. It folds PER SLOT and merges `chunks` partials,
243///   where the shipped kernel folds in 8-slot tiles: same sum in real arithmetic, different
244///   rounding, so `dsa-decode-gate` holds it to an ARGMAX gate plus a maxdiff/max-relative bound
245///   on real-shaped inputs and never to bit identity. It exists because at t_q=1 the gathered
246///   attention has exactly 64 independent (token, head) outputs for 148 SMs and the slot axis is
247///   the only one that buys parallelism without duplicating the walk. ADMISSIBLE ONLY AT
248///   `t_q <= MLA_DSA_NAMED_CLASS_T_MAX` = 1 (plain decode): the 2026-09-03 B200 run saw this
249///   class move 1 of 256 latent-row argmaxes at kv=131072 / t_q=4, and t_q=4..8 is the DFlash2
250///   spec-verify shape where a moved argmax is a moved draft acceptance. Enforced by
251///   `mla_dsa_attn_arm_effective`, not by table convention.
252///
253/// Rollback seam: unset the var (or set 0). Both arms are read per call, so a rollback is the
254/// next request, not a restart.
255fn mla_dsa_decode_level() -> u32 {
256    if !cfg!(memra_sm100_tcgen05) {
257        return 0;
258    }
259    match std::env::var("MEMRA_B200_DSA_DECODE").as_deref() {
260        Ok("1") => 1,
261        Ok("2") => 2,
262        _ => 0,
263    }
264}
265
266/// Widest query width the DSA decode door keys on. Wider widths fall through untouched: the
267/// `MEMRA_B200_MLA_DECODE_ARM` split door if set, then the shipped kernels (t >= 16 reaches
268/// `MEMRA_MLA_TC_PREFILL` before either).
269pub const MLA_DSA_ARM_T_MAX: usize = 8;
270
271/// Which gathered-attention arm the door selects, keyed on t_q (index = t_q in
272/// 1..=MLA_DSA_ARM_T_MAX; index 0 unused):
273///
274/// * `0` - the SHIPPED kernel (`memra_mla_attn_gathered_f32`). The door does nothing here.
275/// * `1` - the single-pass BIT-IDENTICAL kernel (`memra_mla_attn_gathered_dsa_f32`).
276/// * `n >= 2` - the WARP-ONLINE arm with `n` slot chunks, numeric class
277///   `dsa-warp-online-f32`. Level 2 only.
278///
279/// B200-MEASURED, 2026-09-03, and the widths are not free: read the width rule below before
280/// editing a cell. `dsa-decode-gate` on the 2x B200 SXM pair (sm_100a), device 0, N=5
281/// interleaved, engine commit f3a0091cd; banked log
282/// `darklanes:research/glm5-b200-20260902/box/gates/gate-dsa-decode.txt`. Means in us, and the
283/// gathered stage is depth-flat so the three contexts agree to a few percent:
284///
285/// | t_q | context | shipped | single-pass (1) | c=4 | c=8 | c=16 | **c=32** |
286/// |---|---|---|---|---|---|---|---|
287/// | 1 | 128k | 556.3 | 573.1 | 272.9 | 136.9 | 80.5 | **57.1** |
288/// | 1 | 256k | 553.3 | 572.4 | 273.3 | 136.7 | 79.7 | **54.8** |
289/// | 1 | 1M | 552.1 | 571.5 | 273.1 | 139.0 | 79.9 | **54.3** |
290/// | 4 | 128k | 641.3 | **618.8** | 276.9 | 156.0 | 159.6 | 131.3 |
291/// | 4 | 256k | 663.1 | **616.6** | 277.1 | 154.7 | 158.9 | 131.8 |
292/// | 4 | 1M | 667.6 | **618.5** | 277.5 | 156.5 | 160.1 | 132.3 |
293///
294/// THE WIDTH RULE, and it is a correctness rule, not a tuning one. The named class
295/// (`dsa-warp-online-f32`, arm >= 2) is admissible ONLY at `t_q <= MLA_DSA_NAMED_CLASS_T_MAX`
296/// = 1, i.e. plain decode. The same box run that produced the table above ALSO recorded the
297/// class moving an argmax: at `kv=131072, t_q=4` every swept chunk count (4, 8, 16, 32) moved
298/// **1 of 256** latent rows, maxdiff ~1.7e-6. It was argmax-clean at t_q=1 in every measured
299/// cell (0 of 64, three contexts on the box plus five on the 5090) and clean at t_q=4 at 256k
300/// and 1M, but "clean in the cells we measured" is not a proof, and t_q=4..8 is the DFlash2
301/// SPEC-VERIFY shape: a moved argmax there is a moved draft acceptance. So the spec-verify
302/// batch never sees the named class. `mla_dsa_attn_arm_effective` enforces this in code, not by
303/// table convention: a cell >= 2 at any width above the rule is demoted to 0 (the shipped
304/// kernel, the always-safe path), never silently run and never quietly promoted to the
305/// single-pass arm at a width where nobody measured it.
306///
307/// The cells therefore ship exactly what the box measured, under that rule:
308///
309/// * `t_q=1` -> **32**. The fastest arm at every context (54.3-57.1 us, a 10.2x on the shipped
310///   552.1 us at 1M) and argmax-clean at every context. 32 beats 16 by ~1.45x here where it lost
311///   to 16 on the 5090 -- 148 SMs want `64 * 32` = 2048 warps, an 82-SM laptop part does not.
312///   That disagreement is the per-hardware-arm-selection law working as intended.
313/// * `t_q=4` -> **1**, the BIT-IDENTICAL single-pass kernel. On the B200 it is a 3.5-7.4% WIN
314///   (618.5 vs 667.6 us at 1M), the opposite sign from the 5090, where it lost by 30% and this
315///   table shipped 0. Same code, different machine: on 148 SMs the shared-memory staging pays
316///   for itself where on 82 it did not. Bit-identical, so this cell carries no numeric risk at
317///   the spec-verify width at all. Banked evidence covers 128k/256k/1M; the two shallow contexts
318///   were not in the log this cell was set from, and the kernel is depth-flat.
319/// * `t_q=2,3,5..8` -> **0** (shipped). Unmeasured, and unmeasured behavior does not go on.
320///
321/// The door is default OFF and arm >= 2 additionally needs level 2, so nothing here reaches a
322/// request without two deliberate acts. `dsa-decode-gate` FAILS with a `REGRESSION` line if a
323/// cell is slower than shipped by more than `MLA_DSA_REGRESSION_MARGIN` on a later run, so the
324/// next box run either confirms these cells or names the one to change. Cite the run here when
325/// a cell moves.
326pub const MLA_DSA_ATTN_ARM: [i32; MLA_DSA_ARM_T_MAX + 1] = [0, 32, 0, 0, 1, 0, 0, 0, 0];
327
328/// Widest query width at which the NAMED numeric class (`dsa-warp-online-f32`, arm >= 2) may be
329/// selected. 1: plain decode only. Above it the door takes a bit-identical arm or the shipped
330/// kernel, so the DFlash2 spec-verify batch (t_q=4..8) never runs a rounding program that could
331/// move a draft acceptance. Set by the 2026-09-03 B200 run, which observed the class move 1 of
332/// 256 latent-row argmaxes at kv=131072 / t_q=4 for every swept chunk count. Raising this needs
333/// its own argmax evidence at the widths it opens, not an inference from t_q=1.
334pub const MLA_DSA_NAMED_CLASS_T_MAX: usize = 1;
335
336/// Chunk counts `dsa-decode-gate` sweeps for the warp-online arm. The warp arm puts
337/// `t_q * n_head * chunks` WARPS on the die, so chunks is the whole occupancy knob at t_q=1
338/// (64 pairs alone is 8 CTAs of 8 warps); 64 is the kernel's ceiling (`MLA_DSA_MAX_CHUNKS`).
339pub const MLA_DSA_ATTN_CHUNK_SWEEP: [i32; 4] = [4, 8, 16, 32];
340
341/// The decode scorer engages only from this pool count up. Below it the block count
342/// (`n_pools / (128 * 2)`) cannot fill the die and the shipped dispatch's own measured
343/// crossover already sends small-pool decode to the reference kernel, which wins there
344/// (cu/mla_attn.cu, MLA_KPOOL_SMALL_TILE_MIN_POOLS note). 4096 pools = 16 blocks = 16k context
345/// at the shipped pool size 4.
346pub const MLA_DSA_SCORE_MIN_POOLS: usize = 4096;
347
348/// The gate's regression bar, shared with the sibling arm's: an arm may not be slower than the
349/// kernel it replaces by more than 5%.
350pub const MLA_DSA_REGRESSION_MARGIN: f64 = 1.05;
351
352/// The gathered-attention arm code at this width (see [`MLA_DSA_ATTN_ARM`]). Pure, so the gate
353/// can read the policy on any build including the 120a ones where the door is dead.
354pub fn mla_dsa_attn_arm(t_q: usize) -> i32 {
355    if t_q == 0 || t_q > MLA_DSA_ARM_T_MAX {
356        return 0;
357    }
358    MLA_DSA_ATTN_ARM[t_q]
359}
360
361/// The arm the door may actually run at this width: the table cell, with the named-class width
362/// rule enforced in CODE rather than by table convention. A cell >= 2 above
363/// `MLA_DSA_NAMED_CLASS_T_MAX` is demoted to 0 (the shipped kernel), not to the single-pass arm
364/// — a width nobody measured gets the path that cannot be wrong, not the path that happens to
365/// be bit-identical. The gate reads this same function, so an edit that violates the rule shows
366/// up as the gate timing a shipped cell, never as a silently-served numeric class.
367pub fn mla_dsa_attn_arm_effective(t_q: usize) -> i32 {
368    let arm = mla_dsa_attn_arm(t_q);
369    if arm >= 2 && t_q > MLA_DSA_NAMED_CLASS_T_MAX {
370        return 0;
371    }
372    arm
373}
374
375/// Geometry refusals from the DSA launchers: the door has nothing for this shape, so the
376/// caller falls through to the shipped kernel instead of failing the request. Every other
377/// non-zero rc (a real cudaError included) still goes through `ck` and surfaces.
378/// Engagement counter for the k-pool SELECT door (`MEMRA_B200_DSA_SELECT`), announced once per
379/// boot: the receipt a B200 A/B has to show.
380pub static MLA_DSA_SELECT_DISPATCHES: std::sync::atomic::AtomicU64 =
381    std::sync::atomic::AtomicU64::new(0);
382
383/// `MEMRA_B200_DSA_SELECT=1` (default OFF, read per call: the rollback seam), compile-time gated
384/// to sm_100a builds exactly like its two siblings, so a 120a/90a/89 build sees no behaviour
385/// change from a var it cannot engage.
386///
387/// WHAT IT REPLACES. `memra_mla_kpool_select_kernel` grids `t_q` blocks, so plain decode runs it
388/// on ONE CTA -- 0.68% of a 148-SM die -- sweeping `n_pools` up to ten times (8 MSB-first radix
389/// passes, an optional unique-resolution scan, then the membership count and the emit). It is
390/// depth-LINEAR in `n_pools = t_kv / pool` and it is what the `MEMRA_B200_DSA_DECODE` lane's
391/// scorer fix stopped hiding.
392///
393/// THE CLASS IS EXACT, not banded, and that is a construction rather than a hope. The emitted
394/// plane is a pure function of ONE 64-bit number: the `select_k`-th smallest order key
395/// `(desc32(score) << 32) | pool_index`. That key is a strictly decreasing injection composed
396/// with a unique index, so keys are DISTINCT and "the k-th smallest" is unambiguous; reproducing
397/// it bit-for-bit reproduces the selection bit-for-bit. The parallel pipeline computes the same
398/// key and runs the same `key(p) <= thr` test, so this is a launch-geometry change with an exact
399/// answer. `dsa-select-gate` asserts the `idx` plane byte-identical to the shipped kernel and
400/// carries a RED ARM that must fail first.
401fn mla_dsa_select_on() -> bool {
402    cfg!(memra_sm100_tcgen05)
403        && mla_dsa_select_on_from(std::env::var("MEMRA_B200_DSA_SELECT").ok().as_deref())
404}
405
406/// The pure parse behind [`mla_dsa_select_on`] (DEFAULT ON since 2026-09-04 on the builds that
407/// carry the kernel at all, which is the `memra_sm100_tcgen05` cfg above): only an explicit `0`
408/// disarms. RECEIPT (darklanes research/glm5-b200-20260902/LANE.md, onemsel 2026-09-04, 2x B200
409/// pair, composed defaults, 1M context, four boots per arm against the banked 46.20-50.24 band):
410/// the door reads outside the band on every armed boot. It stays INERT below its own floors
411/// (`mla_dsa_select_floor`: 65,536 pools = 262,144 tokens at t_q == 1, 262,144 pools = 1,048,576
412/// tokens for the spec widths), so short-context serving is untouched by construction and this
413/// flip changes only the long-context shape it was written for.
414pub fn mla_dsa_select_on_from(v: Option<&str>) -> bool {
415    !matches!(v.map(str::trim), Some("0"))
416}
417
418/// Pool-count floor for PLAIN DECODE (`t_q == 1`). The floor for the spec-verify widths is
419/// separate and much higher: see [`MLA_DSA_SELECT_MIN_POOLS_SPEC`].
420///
421/// **THE FLOOR IN TOKENS IS 262_144 EXACTLY (65536 pools x pool 4), AND A PROMPT CALLED "256k"
422/// IS USUALLY BELOW IT.** Read that before sizing any cell against this door. A 256k serving
423/// rung is ~256_756 tokens, which is 64_189 pools -- 1_347 pools and 5_388 tokens short, 2.06%
424/// under the floor -- so it engages NOTHING and measures noise. This cost a real B200 cell on
425/// 2026-09-03. Every context figure here is an exact token count, never a "k".
426///
427/// MEASURED ON THE TARGET, 2026-09-03 (`dsa-select-gate`, 2x B200 SXM sm_100a, dev 0, N=5
428/// interleaved, binary built from main `3908a431`; receipts
429/// `darklanes:research/glm5-b200-20260902/box/selgate/gate-b200.{txt,full}`, driver
430/// `box/selgate.sh`):
431///
432/// | pools | tokens | t_q=1 | t_q=4 |
433/// |---|---|---|---|
434/// | 4_096 | 16_384 | 0.20x | 0.20x |
435/// | 8_192 | 32_768 | 0.25x | 0.28x |
436/// | 32_768 | 131_072 | 0.67x | 0.35x |
437/// | **65_536** | **262_144** | **1.31x** | **0.94x** |
438/// | 262_144 | 1_048_576 | **2.81x** | **2.06x** |
439///
440/// WHY THIS IS KEYED ON `t_q` AND NOT ONE NUMBER, and it is a policy-CORRECTNESS fix rather
441/// than a tuning one. A single floor of 65536 was chosen from RTX 5090 data, where `t_q=4` at
442/// that point measured 1.07x -- a small win. On the silicon this door is actually gated to it is
443/// **0.94x, a 6.5% LOSS**, and `dsa-select-gate`'s own regression bar caught it
444/// (`REGRESSION kpool_select n_pools=65536 t_q=4: 311.6 us vs shipped 292.7 us (1.064x)`). A
445/// uniform floor therefore ADMITTED A SHAPE THAT REGRESSES ON THE TARGET: the door is
446/// sm_100a-only, and its floor was set by evidence from a card it never runs on. Keying the
447/// floor removes that shape without giving up either measured win.
448///
449/// Both values are measured cells with NO interpolation. `t_q == 1` keeps 65536 (1.31x on the
450/// pair). `t_q >= 2` takes 262144, the ONLY pool count where the spec-verify width was measured
451/// to win (2.06x); everything between 65536 and 262144 at those widths is unswept, and unswept
452/// shapes do not engage.
453pub const MLA_DSA_SELECT_MIN_POOLS: usize = 65_536;
454
455/// Pool-count floor for the DFlash2 spec-verify widths (`t_q >= 2`), where the parallel selector
456/// needs far more pools to pay for its six launches: the shipped kernel already has `t_q` CTAs
457/// of parallelism at those widths, so there is much less to win. B200-measured 0.94x at 65536
458/// pools and 2.06x at 262144, so this is 262144 -- the only measured win. See
459/// [`MLA_DSA_SELECT_MIN_POOLS`] for the full ladder and why the floor is keyed at all.
460pub const MLA_DSA_SELECT_MIN_POOLS_SPEC: usize = 262_144;
461
462/// Widest query width the select door keys on: decode and the spec-verify batch. Wider widths
463/// already have `t_q` CTAs of parallelism and fall through to the shipped kernel untouched.
464pub const MLA_DSA_SELECT_T_MAX: usize = 8;
465
466/// Whether the serving policy engages the parallel selector at this shape. Pure, so the gate
467/// reads the same predicate the wrapper does and the two cannot drift apart.
468pub fn mla_dsa_select_engages(t_q: usize, n_pools: usize) -> bool {
469    if !(1..=MLA_DSA_SELECT_T_MAX).contains(&t_q) {
470        return false;
471    }
472    n_pools >= mla_dsa_select_floor(t_q)
473}
474
475/// The pool-count floor at this width. Keyed because a single floor admitted a shape that
476/// REGRESSES on sm_100a (t_q=4 at 65536 pools, 0.94x on the pair); see
477/// [`MLA_DSA_SELECT_MIN_POOLS`]. Pure, so the gate reads the same floor the wrapper does.
478pub fn mla_dsa_select_floor(t_q: usize) -> usize {
479    if t_q == 1 {
480        MLA_DSA_SELECT_MIN_POOLS
481    } else {
482        MLA_DSA_SELECT_MIN_POOLS_SPEC
483    }
484}
485
486fn mla_dsa_select_announce(t_q: usize, n_pools: usize, n_ctas: i32) {
487    use std::sync::atomic::Ordering;
488    if MLA_DSA_SELECT_DISPATCHES.fetch_add(1, Ordering::Relaxed) == 0 {
489        eprintln!(
490            "[mla-b200-dsa-select] engaged kpool_select t={t_q} pools={n_pools} ctas={n_ctas} \
491             class=exact (sm_100a; MEMRA_B200_DSA_SELECT=1)"
492        );
493    }
494}
495
496fn mla_dsa_geometry_refusal(rc: i32) -> bool {
497    matches!(rc, 40020 | 40021 | 40023)
498}
499
500fn mla_dsa_announce(kind: &str, t_q: usize, detail: &str) {
501    use std::sync::atomic::Ordering;
502    if MLA_DSA_DECODE_DISPATCHES.fetch_add(1, Ordering::Relaxed) == 0 {
503        eprintln!(
504            "[mla-b200-dsa-decode] engaged {kind} t={t_q} {detail} \
505             (sm_100a; MEMRA_B200_DSA_DECODE)"
506        );
507    }
508}
509
510unsafe extern "C" {
511    pub fn memra_mla_rope_interleaved_f32(
512        x: *mut f32,
513        n_pos: i32,
514        n_vec: i32,
515        d_rope: i32,
516        positions: *const i32,
517        base: f32,
518        stream: *mut c_void,
519    ) -> i32;
520    pub fn memra_mla_split_latent_f32(
521        kv: *const f32,
522        c_kv: *mut f32,
523        k_pe: *mut f32,
524        t: i32,
525        kv_rank: i32,
526        d_rope: i32,
527        stream: *mut c_void,
528    ) -> i32;
529    pub fn memra_mla_append_latent_f32(
530        cache: *mut f32,
531        c_kv: *const f32,
532        k_pe: *const f32,
533        slot: i32,
534        t: i32,
535        kv_rank: i32,
536        d_rope: i32,
537        stream: *mut c_void,
538    ) -> i32;
539    pub fn memra_mla_append_latent_live_f32(
540        cache: *mut f32,
541        c_kv: *const f32,
542        k_pe: *const f32,
543        pos_d: *const i32,
544        t: i32,
545        kv_rank: i32,
546        d_rope: i32,
547        stream: *mut c_void,
548    ) -> i32;
549    pub fn memra_mla_absorb_q_f32(
550        q_nope: *const f32,
551        wk_b: *const f32,
552        q_lat: *mut f32,
553        t_q: i32,
554        n_head: i32,
555        d_nope: i32,
556        kv_rank: i32,
557        stream: *mut c_void,
558    ) -> i32;
559    pub fn memra_mla_decompress_v_f32(
560        o_lat: *const f32,
561        wv_b: *const f32,
562        out: *mut f32,
563        t_q: i32,
564        n_head: i32,
565        d_v: i32,
566        kv_rank: i32,
567        stream: *mut c_void,
568    ) -> i32;
569    /// COALESCED warp-per-row twin of `memra_mla_absorb_q_f32` (`MEMRA_MLA_COALESCE`,
570    /// lane/mla-coalesce). The shipped kernel gives output row `l` to THREAD `l`, which then
571    /// walks its row serially, so at step `p` a warp's 32 lanes read addresses `d_nope` floats
572    /// (512 B) apart and pull 32 transactions where one would do. Here a WARP owns a row and
573    /// lane `k` reads `row[k], row[k+32], ...`, which is one 128-byte transaction per step,
574    /// finished by a shuffle reduction. Takes the same `split` output-range partition as the
575    /// decode-split twins, so the two doors COMPOSE: the split fixes the GRID, this fixes the
576    /// LOADS. NAMED NUMERIC CLASS `mla_warp_row_reduce`: the per-output sum becomes 32
577    /// lane-partial sums combined by a shuffle tree instead of one serial ascending dot, so
578    /// this is NOT bit-identical and NOT the split twins' contract.
579    #[allow(clippy::too_many_arguments)]
580    /// BF16-plane twins of the `_wp` decode kernels (lane/mla-absorb-bf16-20260905): the weight
581    /// plane is `u16` BF16 bits, widened per element inside the kernel; same order, same math.
582    pub fn memra_mla_absorb_q_wp_bf16(
583        q_nope: *const f32,
584        wk_b: *const u16,
585        q_lat: *mut f32,
586        t_q: i32,
587        n_head: i32,
588        d_nope: i32,
589        kv_rank: i32,
590        split: i32,
591        stream: *mut c_void,
592    ) -> i32;
593    pub fn memra_mla_decompress_v_wp_bf16(
594        o_lat: *const f32,
595        wv_b: *const u16,
596        out: *mut f32,
597        t_q: i32,
598        n_head: i32,
599        d_v: i32,
600        kv_rank: i32,
601        split: i32,
602        stream: *mut c_void,
603    ) -> i32;
604    pub fn memra_mla_absorb_q_wp_f32(
605        q_nope: *const f32,
606        wk_b: *const f32,
607        q_lat: *mut f32,
608        t_q: i32,
609        n_head: i32,
610        d_nope: i32,
611        kv_rank: i32,
612        split: i32,
613        stream: *mut c_void,
614    ) -> i32;
615    /// COALESCED warp-per-row twin of `memra_mla_decompress_v_f32` (`MEMRA_MLA_COALESCE`).
616    /// Same defect and same fix as `memra_mla_absorb_q_wp_f32`, and worse in the shipped form:
617    /// the lane stride there is `kv_rank` floats (2 KB), and with `d_v` typically 128 against
618    /// `MLA_THREADS` 256 half the block never enters the loop. Numeric class
619    /// `mla_warp_row_reduce`.
620    #[allow(clippy::too_many_arguments)]
621    pub fn memra_mla_decompress_v_wp_f32(
622        o_lat: *const f32,
623        wv_b: *const f32,
624        out: *mut f32,
625        t_q: i32,
626        n_head: i32,
627        d_v: i32,
628        kv_rank: i32,
629        split: i32,
630        stream: *mut c_void,
631    ) -> i32;
632    pub fn memra_mla_decompress_v_wp_zq8_f32(
633        o_lat: *const f32,
634        wv_b: *const f32,
635        out: *mut f32,
636        out_q: *mut i8,
637        out_d: *mut f32,
638        t_q: i32,
639        n_head: i32,
640        d_v: i32,
641        kv_rank: i32,
642        split: i32,
643        stream: *mut c_void,
644    ) -> i32;
645    pub fn memra_mla_decompress_v_wp_bf16_zq8(
646        o_lat: *const f32,
647        wv_b: *const u16,
648        out: *mut f32,
649        out_q: *mut i8,
650        out_d: *mut f32,
651        t_q: i32,
652        n_head: i32,
653        d_v: i32,
654        kv_rank: i32,
655        split: i32,
656        stream: *mut c_void,
657    ) -> i32;
658    /// Decode-split twin of `memra_mla_absorb_q_f32` (MEMRA_MLA_DECODE_SPLIT): the same
659    /// per-output serial dot, its output range split across `split` blocks — bit-identical
660    /// by construction, gated in `tests/mla_decode_split_gpu.rs`.
661    #[allow(clippy::too_many_arguments)]
662    pub fn memra_mla_absorb_q_split_f32(
663        q_nope: *const f32,
664        wk_b: *const f32,
665        q_lat: *mut f32,
666        t_q: i32,
667        n_head: i32,
668        d_nope: i32,
669        kv_rank: i32,
670        split: i32,
671        stream: *mut c_void,
672    ) -> i32;
673    /// Decode-split twin of `memra_mla_decompress_v_f32` (see above).
674    #[allow(clippy::too_many_arguments)]
675    pub fn memra_mla_decompress_v_split_f32(
676        o_lat: *const f32,
677        wv_b: *const f32,
678        out: *mut f32,
679        t_q: i32,
680        n_head: i32,
681        d_v: i32,
682        kv_rank: i32,
683        split: i32,
684        stream: *mut c_void,
685    ) -> i32;
686    pub fn memra_mla_attn_absorbed_f32(
687        q_lat: *const f32,
688        q_pe: *const f32,
689        cache: *const f32,
690        o_lat: *mut f32,
691        n_head: i32,
692        kv_rank: i32,
693        d_rope: i32,
694        t_q: i32,
695        t_kv: i32,
696        scale: f32,
697        stream: *mut c_void,
698    ) -> i32;
699    pub fn memra_mla_attn_absorbed_live_f32(
700        q_lat: *const f32,
701        q_pe: *const f32,
702        cache: *const f32,
703        o_lat: *mut f32,
704        n_head: i32,
705        kv_rank: i32,
706        d_rope: i32,
707        t_q: i32,
708        pos_d: *const i32,
709        scale: f32,
710        stream: *mut c_void,
711    ) -> i32;
712    pub fn memra_mla_index_append_ring_f32(
713        plane: *mut f32,
714        a: *const f32,
715        b: *const f32,
716        slot: i32,
717        t: i32,
718        wa: i32,
719        wb: i32,
720        rows: i32,
721        stream: *mut c_void,
722    ) -> i32;
723    pub fn memra_mla_kpool_pool_keys_f32(
724        state: *const f32,
725        ape: *const f32,
726        pool_keys: *mut f32,
727        pool_begin: i32,
728        n_pools: i32,
729        pool: i32,
730        d: i32,
731        state_rows: i32,
732        stream: *mut c_void,
733    ) -> i32;
734    pub fn memra_mla_kpool_score_f32(
735        q: *const f32,
736        pool_keys: *const f32,
737        hw: *const f32,
738        score: *mut f32,
739        t_q: i32,
740        heads: i32,
741        d: i32,
742        n_pools: i32,
743        pool: i32,
744        first_pos: i32,
745        qk_scale: f32,
746        head_scale: f32,
747        stream: *mut c_void,
748    ) -> i32;
749    pub fn memra_mla_kpool_score_ref_f32(
750        q: *const f32,
751        pool_keys: *const f32,
752        hw: *const f32,
753        score: *mut f32,
754        t_q: i32,
755        heads: i32,
756        d: i32,
757        n_pools: i32,
758        pool: i32,
759        first_pos: i32,
760        qk_scale: f32,
761        head_scale: f32,
762        stream: *mut c_void,
763    ) -> i32;
764    /// Ints of scratch one query needs for the parallel selector, given its CTA count.
765    pub fn memra_mla_kpool_select_ws_ints(n_ctas: i32) -> i64;
766    /// CTA count the parallel selector launches per query. The host sizes the workspace from
767    /// this same entry point, so a mismatch is impossible by construction.
768    pub fn memra_mla_kpool_select_ctas(n_pools: i32) -> i32;
769    /// Exact multi-CTA k-pool selection (`MEMRA_B200_DSA_SELECT`): same threshold key, same
770    /// membership test, same emit order, byte-identical `idx`.
771    #[allow(clippy::too_many_arguments)]
772    pub fn memra_mla_kpool_score_dsa_live_f32(
773        q: *const f32,
774        pool_keys: *const f32,
775        hw: *const f32,
776        score: *mut f32,
777        t_q: i32,
778        heads: i32,
779        d: i32,
780        n_pools_d: *const i32,
781        n_pools_cap: i32,
782        pool: i32,
783        first_pos: i32,
784        qk_scale: f32,
785        head_scale: f32,
786        stream: *mut c_void,
787    ) -> i32;
788    pub fn memra_mla_kpool_select_live_f32(
789        score: *const f32,
790        idx: *mut i32,
791        t_q: i32,
792        n_pools_d: *const i32,
793        pool: i32,
794        select_k: i32,
795        width: i32,
796        first_pos: i32,
797        always_tail: i32,
798        stream: *mut c_void,
799    ) -> i32;
800    pub fn memra_mla_kpool_select_dsa_f32(
801        score: *const f32,
802        idx: *mut i32,
803        ws: *mut i32,
804        t_q: i32,
805        n_pools: i32,
806        pool: i32,
807        select_k: i32,
808        width: i32,
809        first_pos: i32,
810        always_tail: i32,
811        stream: *mut c_void,
812    ) -> i32;
813    /// RED ARM for `dsa-select-gate`, never a serving path: the exact pipeline with the resolved
814    /// threshold deliberately bumped, so the gate can prove its byte comparison actually fails
815    /// on a wrong selection before it is allowed to pass the real kernel.
816    #[allow(clippy::too_many_arguments)]
817    pub fn memra_mla_kpool_select_dsa_redarm_f32(
818        score: *const f32,
819        idx: *mut i32,
820        ws: *mut i32,
821        t_q: i32,
822        n_pools: i32,
823        pool: i32,
824        select_k: i32,
825        width: i32,
826        first_pos: i32,
827        always_tail: i32,
828        bump: i32,
829        stream: *mut c_void,
830    ) -> i32;
831    pub fn memra_mla_kpool_select_f32(
832        score: *const f32,
833        idx: *mut i32,
834        t_q: i32,
835        n_pools: i32,
836        pool: i32,
837        select_k: i32,
838        width: i32,
839        first_pos: i32,
840        always_tail: i32,
841        stream: *mut c_void,
842    ) -> i32;
843    pub fn memra_mla_kpool_select_ref_f32(
844        score: *const f32,
845        idx: *mut i32,
846        t_q: i32,
847        n_pools: i32,
848        pool: i32,
849        select_k: i32,
850        width: i32,
851        first_pos: i32,
852        always_tail: i32,
853        stream: *mut c_void,
854    ) -> i32;
855    pub fn memra_mla_attn_gathered_f32(
856        q_lat: *const f32,
857        q_pe: *const f32,
858        cache: *const f32,
859        idx: *const i32,
860        o_lat: *mut f32,
861        n_head: i32,
862        kv_rank: i32,
863        d_rope: i32,
864        t_q: i32,
865        n_slots: i32,
866        scale: f32,
867        stream: *mut c_void,
868    ) -> i32;
869    /// B200 decode-arm twin of `memra_mla_attn_gathered_f32` (MEMRA_B200_MLA_DECODE_ARM): same
870    /// per-l accumulate chain, its output range [0, kv_rank) split across `split` blocks; the
871    /// shared score/softmax tile walk (m, dsum) is recomputed IN FULL, unchanged, by every
872    /// split block — bit-identical by construction, gated in `mla_decode_arm_gate.rs`.
873    #[allow(clippy::too_many_arguments)]
874    /// Single-pass bit-identical rewrite of `memra_mla_attn_gathered_f32`
875    /// (`MEMRA_B200_DSA_DECODE>=1`): each tile's KV rows staged once into shared memory with
876    /// float4 loads and read back for BOTH the score dot and the PV accumulate, the 8 tile
877    /// exponentials hoisted into registers. Same grid, same fold, same bits. Returns 40020
878    /// (width not a multiple of 4) or 40021 (staging over the smem cap) for a geometry it
879    /// refuses, and the caller falls through to the shipped kernel.
880    pub fn memra_mla_attn_gathered_dsa_f32(
881        q_lat: *const f32,
882        q_pe: *const f32,
883        cache: *const f32,
884        idx: *const i32,
885        o_lat: *mut f32,
886        n_head: i32,
887        kv_rank: i32,
888        d_rope: i32,
889        t_q: i32,
890        n_slots: i32,
891        scale: f32,
892        stream: *mut c_void,
893    ) -> i32;
894    /// Slot-per-chunk span the partial kernel walks. The host MUST size the workspace and
895    /// launch from this, never from its own division, so the two cannot disagree.
896    pub fn memra_mla_dsa_attn_chunk_span(n_slots: i32, chunks: i32) -> i32;
897    /// Warp-online slot-split gathered attention, numeric class `dsa-warp-online-f32`
898    /// (`MEMRA_B200_DSA_DECODE=2`). `part_m` / `part_d` hold `t_q * n_head * chunks` floats
899    /// each; `part_acc` holds `t_q * n_head * chunks * kv_rank`. Returns 40023 for a
900    /// (kv_rank, d_rope) with no template instantiation, and the caller takes the shipped path.
901    pub fn memra_mla_dsa_attn_split_f32(
902        q_lat: *const f32,
903        q_pe: *const f32,
904        cache: *const f32,
905        idx: *const i32,
906        o_lat: *mut f32,
907        part_m: *mut f32,
908        part_d: *mut f32,
909        part_acc: *mut f32,
910        n_head: i32,
911        kv_rank: i32,
912        d_rope: i32,
913        t_q: i32,
914        n_slots: i32,
915        chunks: i32,
916        scale: f32,
917        stream: *mut c_void,
918    ) -> i32;
919    /// Head-blocked decode pool scorer (`MEMRA_B200_DSA_DECODE>=1`), bit-identical to
920    /// `memra_mla_kpool_score_ref_f32`. Returns 40023 when this (heads, d) has no
921    /// instantiation, and the caller falls through to the shipped dispatch.
922    pub fn memra_mla_kpool_score_dsa_f32(
923        q: *const f32,
924        pool_keys: *const f32,
925        hw: *const f32,
926        score: *mut f32,
927        t_q: i32,
928        heads: i32,
929        d: i32,
930        n_pools: i32,
931        pool: i32,
932        first_pos: i32,
933        qk_scale: f32,
934        head_scale: f32,
935        stream: *mut c_void,
936    ) -> i32;
937    pub fn memra_mla_attn_gathered_split_f32(
938        q_lat: *const f32,
939        q_pe: *const f32,
940        cache: *const f32,
941        idx: *const i32,
942        o_lat: *mut f32,
943        n_head: i32,
944        kv_rank: i32,
945        d_rope: i32,
946        t_q: i32,
947        n_slots: i32,
948        scale: f32,
949        split: i32,
950        stream: *mut c_void,
951    ) -> i32;
952    /// Strided-batched BF16 tensor-core GEMM (cu/f16_prefill.cu): per batch b,
953    /// `y_b[m, n] = x_b[m, k] @ w_b[n, k]^T`, f32 accumulate, y f32 or bf16 by flag.
954    /// The MEMRA_MLA_TC_PREFILL absorb/decompress engine (one launch replaces the
955    /// per-position absorb_q / decompress_v kernels at prefill widths).
956    fn memra_bf16_gemm_sb(
957        w_bf16: *const c_void,
958        x_bf16: *const c_void,
959        y: *mut c_void,
960        m: i32,
961        n: i32,
962        k: i32,
963        x_rs: i64,
964        x_bs: i64,
965        y_rs: i64,
966        y_bs: i64,
967        batch: i32,
968        y_is_bf16: i32,
969        ws: *mut c_void,
970        ws_bytes: usize,
971        stream: *mut c_void,
972    ) -> i32;
973}
974
975type Res<T> = Result<T, Box<dyn std::error::Error>>;
976
977/// Turn a launcher's status band into a named error. Every MLA launch goes through this —
978/// a silently-ignored non-zero status is how a contract violation becomes garbage activations.
979fn ck(what: &str, rc: i32) -> Res<()> {
980    if rc == 0 {
981        return Ok(());
982    }
983    let detail = match rc {
984        40001 => " (d_rope must be even — interleaved rope rotates (2j, 2j+1) pairs)",
985        40002 => " (kv_rank exceeds the kernel's MLA_MAX_RANK shared-memory ceiling)",
986        40003 => " (d_rope exceeds the kernel's MLA_MAX_ROPE ceiling)",
987        40004 => " (t_q > t_kv — queries must be a suffix of the latent cache)",
988        40010 => " (k-pool size out of range — 1..=MLA_MAX_POOL)",
989        40011 => " (indexer head count out of range — 1..=1024, one thread per head)",
990        40012 => " (t_q * n_pools exceeds the grid.x contract)",
991        40017 => " (indexer head dim must be positive)",
992        40013 => {
993            " (always_select_tail=false: queries before the first complete pool would have an \
994             empty candidate set, which the memra-reference oracle refuses outright)"
995        }
996        40014 => " (index-list width is narrower than select_k * pool + pool - 1)",
997        40015 => " (empty gathered candidate list — a zero softmax denominator)",
998        40020 => " (latent row width is not a multiple of 4 — the DSA float4 staging needs it)",
999        40021 => " (DSA tile staging exceeds MLA_DSA_KV_SMEM_MAX)",
1000        40022 => " (DSA slot-chunk count out of range — 1..=64)",
1001        40023 => " (no DSA scorer instantiation for this (heads, d))",
1002        r if (10000..20000).contains(&r) => " (cudaError)",
1003        _ => "",
1004    };
1005    Err(format!("mla kernel `{what}` failed: rc {rc}{detail}").into())
1006}
1007
1008impl Engine {
1009    /// Interleaved ("NORM") RoPE in place over `x` laid out [n_pos][n_vec][d_rope].
1010    /// `d_rope == 0` (NoPE, glm5_next) is a no-op — the caller must still not pass an empty
1011    /// slice through a path that dereferences it, which is why the rope plane is skipped
1012    /// entirely in the forward arm rather than launched with a zero extent.
1013    pub fn mla_rope_interleaved(
1014        &self,
1015        x: &mut CudaSlice<f32>,
1016        pos_d: &CudaSlice<i32>,
1017        n_pos: usize,
1018        n_vec: usize,
1019        d_rope: usize,
1020        base: f32,
1021    ) -> Res<()> {
1022        if d_rope == 0 {
1023            return Ok(());
1024        }
1025        let s = self.stream();
1026        unsafe {
1027            ck(
1028                "rope_interleaved",
1029                memra_mla_rope_interleaved_f32(
1030                    x.device_ptr_mut(&s).0 as *mut f32,
1031                    n_pos as i32,
1032                    n_vec as i32,
1033                    d_rope as i32,
1034                    pos_d.device_ptr(&s).0 as *const i32,
1035                    base,
1036                    s.cu_stream() as *mut c_void,
1037                ),
1038            )
1039        }
1040    }
1041
1042    /// Split the `wkv_a` output rows [t][kv_rank + d_rope] into `c_kv` and `k_pe` planes.
1043    pub fn mla_split_latent(
1044        &self,
1045        kv: &CudaSlice<f32>,
1046        c_kv: &mut CudaSlice<f32>,
1047        k_pe: &mut CudaSlice<f32>,
1048        t: usize,
1049        kv_rank: usize,
1050        d_rope: usize,
1051    ) -> Res<()> {
1052        let s = self.stream();
1053        unsafe {
1054            ck(
1055                "split_latent",
1056                memra_mla_split_latent_f32(
1057                    kv.device_ptr(&s).0 as *const f32,
1058                    c_kv.device_ptr_mut(&s).0 as *mut f32,
1059                    k_pe.device_ptr_mut(&s).0 as *mut f32,
1060                    t as i32,
1061                    kv_rank as i32,
1062                    d_rope as i32,
1063                    s.cu_stream() as *mut c_void,
1064                ),
1065            )
1066        }
1067    }
1068
1069    /// Append `t` latent rows `[c_kv | k_pe]` to the cache plane starting at row `slot`.
1070    #[allow(clippy::too_many_arguments)] // allow: the parameter list mirrors the kernel/FFI/call contract; bundling into a struct is a refactor, not a lint fix
1071    pub fn mla_append_latent(
1072        &self,
1073        cache: &mut CudaSlice<f32>,
1074        c_kv: &CudaSlice<f32>,
1075        k_pe: &CudaSlice<f32>,
1076        slot: usize,
1077        t: usize,
1078        kv_rank: usize,
1079        d_rope: usize,
1080    ) -> Res<()> {
1081        let s = self.stream();
1082        unsafe {
1083            ck(
1084                "append_latent",
1085                memra_mla_append_latent_f32(
1086                    cache.device_ptr_mut(&s).0 as *mut f32,
1087                    c_kv.device_ptr(&s).0 as *const f32,
1088                    k_pe.device_ptr(&s).0 as *const f32,
1089                    slot as i32,
1090                    t as i32,
1091                    kv_rank as i32,
1092                    d_rope as i32,
1093                    s.cu_stream() as *mut c_void,
1094                ),
1095            )
1096        }
1097    }
1098
1099    /// Absorb: `q_lat[i][h][:] = w_uk[h]ᵀ · q_nope[i][h][:]` (rank space).
1100    #[allow(clippy::too_many_arguments)]
1101    // allow: the parameter list mirrors the kernel/FFI/call contract; bundling into a struct is a refactor, not a lint fix
1102    /// BENCH-ONLY raw arm dispatch for `mla-coalesce-bench` (structural ncu target): `arm` 0 =
1103    /// shipped thread-per-row, 1 = decode-split twin at `split`, 2 = warp-per-row coalesced twin
1104    /// at `split` (1 = unsplit). Bypasses every door on purpose so one process can be profiled
1105    /// across all three kernels. Not a serving entry point.
1106    #[allow(clippy::too_many_arguments)]
1107    pub fn mla_absorb_q_raw_arm(
1108        &self,
1109        q_nope: &CudaSlice<f32>,
1110        wk_b: &CudaSlice<f32>,
1111        q_lat: &mut CudaSlice<f32>,
1112        t_q: usize,
1113        n_head: usize,
1114        d_nope: usize,
1115        kv_rank: usize,
1116        arm: u8,
1117        split: i32,
1118    ) -> Res<()> {
1119        let s = self.stream();
1120        unsafe {
1121            let (q, w, o) = (
1122                q_nope.device_ptr(&s).0 as *const f32,
1123                wk_b.device_ptr(&s).0 as *const f32,
1124                q_lat.device_ptr_mut(&s).0 as *mut f32,
1125            );
1126            let (t, h, dn, kr) = (t_q as i32, n_head as i32, d_nope as i32, kv_rank as i32);
1127            let st = s.cu_stream() as *mut c_void;
1128            match arm {
1129                0 => ck(
1130                    "absorb_q_raw",
1131                    memra_mla_absorb_q_f32(q, w, o, t, h, dn, kr, st),
1132                ),
1133                1 => ck(
1134                    "absorb_q_split_raw",
1135                    memra_mla_absorb_q_split_f32(q, w, o, t, h, dn, kr, split, st),
1136                ),
1137                _ => ck(
1138                    "absorb_q_wp_raw",
1139                    memra_mla_absorb_q_wp_f32(q, w, o, t, h, dn, kr, split, st),
1140                ),
1141            }
1142        }
1143    }
1144
1145    /// BENCH-ONLY raw arm dispatch, decompress twin of `mla_absorb_q_raw_arm`.
1146    #[allow(clippy::too_many_arguments)]
1147    pub fn mla_decompress_v_raw_arm(
1148        &self,
1149        o_lat: &CudaSlice<f32>,
1150        wv_b: &CudaSlice<f32>,
1151        out: &mut CudaSlice<f32>,
1152        t_q: usize,
1153        n_head: usize,
1154        d_v: usize,
1155        kv_rank: usize,
1156        arm: u8,
1157        split: i32,
1158    ) -> Res<()> {
1159        let s = self.stream();
1160        unsafe {
1161            let (a, w, o) = (
1162                o_lat.device_ptr(&s).0 as *const f32,
1163                wv_b.device_ptr(&s).0 as *const f32,
1164                out.device_ptr_mut(&s).0 as *mut f32,
1165            );
1166            let (t, h, dv, kr) = (t_q as i32, n_head as i32, d_v as i32, kv_rank as i32);
1167            let st = s.cu_stream() as *mut c_void;
1168            match arm {
1169                0 => ck(
1170                    "decompress_v_raw",
1171                    memra_mla_decompress_v_f32(a, w, o, t, h, dv, kr, st),
1172                ),
1173                1 => ck(
1174                    "decompress_v_split_raw",
1175                    memra_mla_decompress_v_split_f32(a, w, o, t, h, dv, kr, split, st),
1176                ),
1177                _ => ck(
1178                    "decompress_v_wp_raw",
1179                    memra_mla_decompress_v_wp_f32(a, w, o, t, h, dv, kr, split, st),
1180                ),
1181            }
1182        }
1183    }
1184
1185    /// BENCH-ONLY raw dispatch of the fused hc pre-chain for `mla-coalesce-bench` (structural
1186    /// ncu target): `arm` 0 = `memra_dsv4_hc_pre_fused_v2` (block 128, the shipped `=2` arm),
1187    /// 1 = `_v3` at `block` with the shared-memory Sinkhorn, 2 = `_v3` at `block` with the
1188    /// register Sinkhorn (`MEMRA_HC_PRE_SINK_REG`). Bypasses the door readers on purpose. The
1189    /// `hc-fused-gate` calls the v1/v2 launchers directly and predates v3, so this is the only
1190    /// way to put the register Sinkhorn under a profiler.
1191    #[allow(clippy::too_many_arguments)]
1192    pub fn hc_pre_raw_arm(
1193        &self,
1194        x: &CudaSlice<f32>,
1195        mixes: &CudaSlice<f32>,
1196        scale: &CudaSlice<f32>,
1197        base: &CudaSlice<f32>,
1198        pre: &mut CudaSlice<f32>,
1199        post: &mut CudaSlice<f32>,
1200        comb: &mut CudaSlice<f32>,
1201        y: &mut CudaSlice<f32>,
1202        s_rows: usize,
1203        hc: usize,
1204        d: usize,
1205        iters: usize,
1206        eps: f32,
1207        arm: u8,
1208        block: i32,
1209        niters: Option<&mut CudaSlice<i32>>,
1210    ) -> Res<()> {
1211        let st = self.stream();
1212        unsafe {
1213            let np: *mut i32 = match niters {
1214                Some(n) => n.device_ptr_mut(&st).0 as *mut i32,
1215                None => std::ptr::null_mut(),
1216            };
1217            let (xp, mp, sp, bp) = (
1218                x.device_ptr(&st).0 as *const f32,
1219                mixes.device_ptr(&st).0 as *const f32,
1220                scale.device_ptr(&st).0 as *const f32,
1221                base.device_ptr(&st).0 as *const f32,
1222            );
1223            let (pp, qp, cp, yp) = (
1224                pre.device_ptr_mut(&st).0 as *mut f32,
1225                post.device_ptr_mut(&st).0 as *mut f32,
1226                comb.device_ptr_mut(&st).0 as *mut f32,
1227                y.device_ptr_mut(&st).0 as *mut f32,
1228            );
1229            let (sr, h, dd, it) = (s_rows as i32, hc as i32, d as i32, iters as i32);
1230            let cs = st.cu_stream() as *mut c_void;
1231            let rc = match arm {
1232                0 => crate::dsv4_ffi::memra_dsv4_hc_pre_fused_v2(
1233                    xp, mp, sp, bp, pp, qp, cp, yp, sr, h, dd, it, eps, np, cs,
1234                ),
1235                1 => crate::dsv4_ffi::memra_dsv4_hc_pre_fused_v3(
1236                    xp, mp, sp, bp, pp, qp, cp, yp, sr, h, dd, it, eps, np, block, 0, cs,
1237                ),
1238                _ => crate::dsv4_ffi::memra_dsv4_hc_pre_fused_v3(
1239                    xp, mp, sp, bp, pp, qp, cp, yp, sr, h, dd, it, eps, np, block, 1, cs,
1240                ),
1241            };
1242            ck("hc_pre_raw", rc)
1243        }
1244    }
1245
1246    #[allow(clippy::too_many_arguments)]
1247    /// The BF16-plane arm of [`Engine::mla_absorb_q`] for the served `_wp` partition (door
1248    /// `MEMRA_MLA_ABSORB_BF16`): the same split the coalesce door chooses, on the BF16 copy of
1249    /// `wk_b`. `Ok(false)` when that partition is not the one in force (the caller runs the f32
1250    /// dispatch unchanged).
1251    #[allow(clippy::too_many_arguments)]
1252    pub fn mla_absorb_q_bf16(
1253        &self,
1254        q_nope: &CudaSlice<f32>,
1255        wk_b16: &CudaSlice<u16>,
1256        q_lat: &mut CudaSlice<f32>,
1257        t_q: usize,
1258        n_head: usize,
1259        d_nope: usize,
1260        kv_rank: usize,
1261    ) -> Res<bool> {
1262        if !mla_coalesce_on() {
1263            return Ok(false);
1264        }
1265        let split = mla_b200_split_for(MlaB200Kernel::AbsorbQ, t_q, kv_rank)
1266            .or_else(|| mla_decode_split_for(t_q * n_head, kv_rank))
1267            .unwrap_or(1);
1268        if split <= 1 {
1269            return Ok(false);
1270        }
1271        let s = self.stream();
1272        unsafe {
1273            ck(
1274                "absorb_q_wp_bf16",
1275                memra_mla_absorb_q_wp_bf16(
1276                    q_nope.device_ptr(&s).0 as *const f32,
1277                    wk_b16.device_ptr(&s).0 as *const u16,
1278                    q_lat.device_ptr_mut(&s).0 as *mut f32,
1279                    t_q as i32,
1280                    n_head as i32,
1281                    d_nope as i32,
1282                    kv_rank as i32,
1283                    split,
1284                    s.cu_stream() as *mut c_void,
1285                ),
1286            )?;
1287        }
1288        Ok(true)
1289    }
1290
1291    /// The BF16-plane arm of [`Engine::mla_decompress_v`]; see [`Engine::mla_absorb_q_bf16`].
1292    #[allow(clippy::too_many_arguments)]
1293    pub fn mla_decompress_v_bf16(
1294        &self,
1295        o_lat: &CudaSlice<f32>,
1296        wv_b16: &CudaSlice<u16>,
1297        out: &mut CudaSlice<f32>,
1298        t_q: usize,
1299        n_head: usize,
1300        d_v: usize,
1301        kv_rank: usize,
1302    ) -> Res<bool> {
1303        if !mla_coalesce_on() {
1304            return Ok(false);
1305        }
1306        let split = mla_b200_split_for(MlaB200Kernel::DecompressV, t_q, d_v)
1307            .or_else(|| mla_decode_split_for(t_q * n_head, d_v))
1308            .unwrap_or(1);
1309        if split <= 1 {
1310            return Ok(false);
1311        }
1312        let s = self.stream();
1313        unsafe {
1314            ck(
1315                "decompress_v_wp_bf16",
1316                memra_mla_decompress_v_wp_bf16(
1317                    o_lat.device_ptr(&s).0 as *const f32,
1318                    wv_b16.device_ptr(&s).0 as *const u16,
1319                    out.device_ptr_mut(&s).0 as *mut f32,
1320                    t_q as i32,
1321                    n_head as i32,
1322                    d_v as i32,
1323                    kv_rank as i32,
1324                    split,
1325                    s.cu_stream() as *mut c_void,
1326                ),
1327            )?;
1328        }
1329        Ok(true)
1330    }
1331
1332    /// The coalesce-arm split the `_wp` decompress launch takes at this shape, when the fused
1333    /// q8_1 epilogue can ride it: `MEMRA_MLA_COALESCE=1`, split > 1, and `d_v / split` a whole
1334    /// number of q8 blocks (<= 256 wide). `None` means the plain kernels run unchanged.
1335    fn mla_decompress_v_zq8_split(&self, t_q: usize, n_head: usize, d_v: usize) -> Option<i32> {
1336        if !mla_coalesce_on() {
1337            return None;
1338        }
1339        let split = mla_b200_split_for(MlaB200Kernel::DecompressV, t_q, d_v)
1340            .or_else(|| mla_decode_split_for(t_q * n_head, d_v))
1341            .unwrap_or(1);
1342        if split <= 1 || !d_v.is_multiple_of(split as usize) {
1343            return None;
1344        }
1345        let per = d_v / split as usize;
1346        (per.is_multiple_of(32) && per <= 256).then_some(split)
1347    }
1348
1349    /// [`Engine::mla_decompress_v`]'s coalesce arm emitting `wo`'s q8_1 pair beside `out`
1350    /// (`memra_mla_decompress_v_wp_zq8_kernel`, MEMRA_MLA_WO_ZQ8): `out` bit-identical to the plain
1351    /// launch, the pair bit-identical to `quantize_q8_1(out, t_q, n_head * d_v)`. `Ok(None)` when
1352    /// the shape or the arm does not fit (the caller then runs the plain sequence).
1353    #[allow(clippy::too_many_arguments)]
1354    pub fn mla_decompress_v_zq8(
1355        &self,
1356        o_lat: &CudaSlice<f32>,
1357        wv_b: &CudaSlice<f32>,
1358        out: &mut CudaSlice<f32>,
1359        t_q: usize,
1360        n_head: usize,
1361        d_v: usize,
1362        kv_rank: usize,
1363    ) -> Res<Option<(CudaSlice<i8>, CudaSlice<f32>)>> {
1364        let Some(split) = self.mla_decompress_v_zq8_split(t_q, n_head, d_v) else {
1365            return Ok(None);
1366        };
1367        let n = t_q * n_head * d_v;
1368        let mut q = self.alloc_i8_uninit(n)?;
1369        let mut d = self.uninit(n / 32)?;
1370        let s = self.stream();
1371        mla_coalesce_announce("decompress_v_zq8", t_q, n_head, split);
1372        unsafe {
1373            ck(
1374                "decompress_v_wp_zq8",
1375                memra_mla_decompress_v_wp_zq8_f32(
1376                    o_lat.device_ptr(&s).0 as *const f32,
1377                    wv_b.device_ptr(&s).0 as *const f32,
1378                    out.device_ptr_mut(&s).0 as *mut f32,
1379                    q.device_ptr_mut(&s).0 as *mut i8,
1380                    d.device_ptr_mut(&s).0 as *mut f32,
1381                    t_q as i32,
1382                    n_head as i32,
1383                    d_v as i32,
1384                    kv_rank as i32,
1385                    split,
1386                    s.cu_stream() as *mut c_void,
1387                ),
1388            )?;
1389        }
1390        Ok(Some((q, d)))
1391    }
1392
1393    /// BF16-plane twin of [`Engine::mla_decompress_v_zq8`] (the `MEMRA_MLA_ABSORB_BF16` arm).
1394    #[allow(clippy::too_many_arguments)]
1395    pub fn mla_decompress_v_bf16_zq8(
1396        &self,
1397        o_lat: &CudaSlice<f32>,
1398        wv_b16: &CudaSlice<u16>,
1399        out: &mut CudaSlice<f32>,
1400        t_q: usize,
1401        n_head: usize,
1402        d_v: usize,
1403        kv_rank: usize,
1404    ) -> Res<Option<(CudaSlice<i8>, CudaSlice<f32>)>> {
1405        let Some(split) = self.mla_decompress_v_zq8_split(t_q, n_head, d_v) else {
1406            return Ok(None);
1407        };
1408        let n = t_q * n_head * d_v;
1409        let mut q = self.alloc_i8_uninit(n)?;
1410        let mut d = self.uninit(n / 32)?;
1411        let s = self.stream();
1412        unsafe {
1413            ck(
1414                "decompress_v_wp_bf16_zq8",
1415                memra_mla_decompress_v_wp_bf16_zq8(
1416                    o_lat.device_ptr(&s).0 as *const f32,
1417                    wv_b16.device_ptr(&s).0 as *const u16,
1418                    out.device_ptr_mut(&s).0 as *mut f32,
1419                    q.device_ptr_mut(&s).0 as *mut i8,
1420                    d.device_ptr_mut(&s).0 as *mut f32,
1421                    t_q as i32,
1422                    n_head as i32,
1423                    d_v as i32,
1424                    kv_rank as i32,
1425                    split,
1426                    s.cu_stream() as *mut c_void,
1427                ),
1428            )?;
1429        }
1430        Ok(Some((q, d)))
1431    }
1432
1433    #[allow(clippy::too_many_arguments)]
1434    pub fn mla_absorb_q(
1435        &self,
1436        q_nope: &CudaSlice<f32>,
1437        wk_b: &CudaSlice<f32>,
1438        q_lat: &mut CudaSlice<f32>,
1439        t_q: usize,
1440        n_head: usize,
1441        d_nope: usize,
1442        kv_rank: usize,
1443    ) -> Res<()> {
1444        let s = self.stream();
1445        // MEMRA_MLA_COALESCE door, checked FIRST because it changes how a row is READ, which
1446        // is orthogonal to every door below (they choose the output-range partition). It reuses
1447        // their policy rather than replacing it: ask the B200 arm, then the generic split, and
1448        // pass whatever split they choose (1 = unsplit). Consulting `mla_decode_split_for` also
1449        // ticks that door's own dispatch counter, which is correct — it WAS consulted and its
1450        // partition IS the one running.
1451        // MEASURED 2026-09-03, 2x B200: at split 1 (64 blocks) warp-per-row REGRESSES -11%
1452        // (51.01 vs 57.34): one row in flight per warp with a serial shuffle reduction after
1453        // each replaces 16,384 threads x 1 row with 512 warps x 1 row, a 32x loss of memory
1454        // parallelism that outweighs the coalescing. At split 16 (1,024 blocks) it is +1.9% on
1455        // top of the split. So the door only engages when a split door gave it a grid to spend
1456        // the coalescing on; at split 1 it falls through to the dispatch below, unchanged.
1457        let coalesce_split = if mla_coalesce_on() {
1458            mla_b200_split_for(MlaB200Kernel::AbsorbQ, t_q, kv_rank)
1459                .or_else(|| mla_decode_split_for(t_q * n_head, kv_rank))
1460                .unwrap_or(1)
1461        } else {
1462            1
1463        };
1464        if coalesce_split > 1 {
1465            let split = coalesce_split;
1466            mla_coalesce_announce("absorb_q", t_q, n_head, split);
1467            return unsafe {
1468                ck(
1469                    "absorb_q_wp",
1470                    memra_mla_absorb_q_wp_f32(
1471                        q_nope.device_ptr(&s).0 as *const f32,
1472                        wk_b.device_ptr(&s).0 as *const f32,
1473                        q_lat.device_ptr_mut(&s).0 as *mut f32,
1474                        t_q as i32,
1475                        n_head as i32,
1476                        d_nope as i32,
1477                        kv_rank as i32,
1478                        split,
1479                        s.cu_stream() as *mut c_void,
1480                    ),
1481                )
1482            };
1483        }
1484        // MEMRA_B200_MLA_DECODE_ARM door (checked first; split from the t_q-keyed table
1485        // MLA_B200_ABSORB_Q_SPLIT, a 1 cell falls through to the doors below; the split twin is
1486        // the same kernel the generic door launches, so this is only a policy pick).
1487        if let Some(split) = mla_b200_split_for(MlaB200Kernel::AbsorbQ, t_q, kv_rank) {
1488            mla_b200_split_announce("absorb_q", t_q, n_head, split);
1489            return unsafe {
1490                ck(
1491                    "absorb_q_split_b200",
1492                    memra_mla_absorb_q_split_f32(
1493                        q_nope.device_ptr(&s).0 as *const f32,
1494                        wk_b.device_ptr(&s).0 as *const f32,
1495                        q_lat.device_ptr_mut(&s).0 as *mut f32,
1496                        t_q as i32,
1497                        n_head as i32,
1498                        d_nope as i32,
1499                        kv_rank as i32,
1500                        split,
1501                        s.cu_stream() as *mut c_void,
1502                    ),
1503                )
1504            };
1505        }
1506        // MEMRA_MLA_DECODE_SPLIT door: same bytes at any split (see mla_decode_split_for).
1507        if let Some(split) = mla_decode_split_for(t_q * n_head, kv_rank) {
1508            mla_split_announce("absorb_q", t_q, n_head, split);
1509            return unsafe {
1510                ck(
1511                    "absorb_q_split",
1512                    memra_mla_absorb_q_split_f32(
1513                        q_nope.device_ptr(&s).0 as *const f32,
1514                        wk_b.device_ptr(&s).0 as *const f32,
1515                        q_lat.device_ptr_mut(&s).0 as *mut f32,
1516                        t_q as i32,
1517                        n_head as i32,
1518                        d_nope as i32,
1519                        kv_rank as i32,
1520                        split,
1521                        s.cu_stream() as *mut c_void,
1522                    ),
1523                )
1524            };
1525        }
1526        unsafe {
1527            ck(
1528                "absorb_q",
1529                memra_mla_absorb_q_f32(
1530                    q_nope.device_ptr(&s).0 as *const f32,
1531                    wk_b.device_ptr(&s).0 as *const f32,
1532                    q_lat.device_ptr_mut(&s).0 as *mut f32,
1533                    t_q as i32,
1534                    n_head as i32,
1535                    d_nope as i32,
1536                    kv_rank as i32,
1537                    s.cu_stream() as *mut c_void,
1538                ),
1539            )
1540        }
1541    }
1542
1543    /// Decompress: `out[i][h][:] = w_uv[h] · o_lat[i][h][:]`.
1544    #[allow(clippy::too_many_arguments)] // allow: the parameter list mirrors the kernel/FFI/call contract; bundling into a struct is a refactor, not a lint fix
1545    pub fn mla_decompress_v(
1546        &self,
1547        o_lat: &CudaSlice<f32>,
1548        wv_b: &CudaSlice<f32>,
1549        out: &mut CudaSlice<f32>,
1550        t_q: usize,
1551        n_head: usize,
1552        d_v: usize,
1553        kv_rank: usize,
1554    ) -> Res<()> {
1555        let s = self.stream();
1556        // MEMRA_MLA_COALESCE door, checked FIRST because it changes how a row is READ, which
1557        // is orthogonal to every door below (they choose the output-range partition). It reuses
1558        // their policy rather than replacing it: ask the B200 arm, then the generic split, and
1559        // pass whatever split they choose (1 = unsplit). Consulting `mla_decode_split_for` also
1560        // ticks that door's own dispatch counter, which is correct — it WAS consulted and its
1561        // partition IS the one running.
1562        // MEASURED 2026-09-03, 2x B200: at split 1 (64 blocks) warp-per-row REGRESSES -11%
1563        // (51.01 vs 57.34): one row in flight per warp with a serial shuffle reduction after
1564        // each replaces 16,384 threads x 1 row with 512 warps x 1 row, a 32x loss of memory
1565        // parallelism that outweighs the coalescing. At split 16 (1,024 blocks) it is +1.9% on
1566        // top of the split. So the door only engages when a split door gave it a grid to spend
1567        // the coalescing on; at split 1 it falls through to the dispatch below, unchanged.
1568        let coalesce_split = if mla_coalesce_on() {
1569            mla_b200_split_for(MlaB200Kernel::DecompressV, t_q, d_v)
1570                .or_else(|| mla_decode_split_for(t_q * n_head, d_v))
1571                .unwrap_or(1)
1572        } else {
1573            1
1574        };
1575        if coalesce_split > 1 {
1576            let split = coalesce_split;
1577            mla_coalesce_announce("decompress_v", t_q, n_head, split);
1578            return unsafe {
1579                ck(
1580                    "decompress_v_wp",
1581                    memra_mla_decompress_v_wp_f32(
1582                        o_lat.device_ptr(&s).0 as *const f32,
1583                        wv_b.device_ptr(&s).0 as *const f32,
1584                        out.device_ptr_mut(&s).0 as *mut f32,
1585                        t_q as i32,
1586                        n_head as i32,
1587                        d_v as i32,
1588                        kv_rank as i32,
1589                        split,
1590                        s.cu_stream() as *mut c_void,
1591                    ),
1592                )
1593            };
1594        }
1595        // MEMRA_B200_MLA_DECODE_ARM door (checked first, table MLA_B200_DECOMPRESS_V_SPLIT; see
1596        // mla_absorb_q above).
1597        if let Some(split) = mla_b200_split_for(MlaB200Kernel::DecompressV, t_q, d_v) {
1598            mla_b200_split_announce("decompress_v", t_q, n_head, split);
1599            return unsafe {
1600                ck(
1601                    "decompress_v_split_b200",
1602                    memra_mla_decompress_v_split_f32(
1603                        o_lat.device_ptr(&s).0 as *const f32,
1604                        wv_b.device_ptr(&s).0 as *const f32,
1605                        out.device_ptr_mut(&s).0 as *mut f32,
1606                        t_q as i32,
1607                        n_head as i32,
1608                        d_v as i32,
1609                        kv_rank as i32,
1610                        split,
1611                        s.cu_stream() as *mut c_void,
1612                    ),
1613                )
1614            };
1615        }
1616        // MEMRA_MLA_DECODE_SPLIT door: same bytes at any split (see mla_decode_split_for).
1617        if let Some(split) = mla_decode_split_for(t_q * n_head, d_v) {
1618            mla_split_announce("decompress_v", t_q, n_head, split);
1619            return unsafe {
1620                ck(
1621                    "decompress_v_split",
1622                    memra_mla_decompress_v_split_f32(
1623                        o_lat.device_ptr(&s).0 as *const f32,
1624                        wv_b.device_ptr(&s).0 as *const f32,
1625                        out.device_ptr_mut(&s).0 as *mut f32,
1626                        t_q as i32,
1627                        n_head as i32,
1628                        d_v as i32,
1629                        kv_rank as i32,
1630                        split,
1631                        s.cu_stream() as *mut c_void,
1632                    ),
1633                )
1634            };
1635        }
1636        unsafe {
1637            ck(
1638                "decompress_v",
1639                memra_mla_decompress_v_f32(
1640                    o_lat.device_ptr(&s).0 as *const f32,
1641                    wv_b.device_ptr(&s).0 as *const f32,
1642                    out.device_ptr_mut(&s).0 as *mut f32,
1643                    t_q as i32,
1644                    n_head as i32,
1645                    d_v as i32,
1646                    kv_rank as i32,
1647                    s.cu_stream() as *mut c_void,
1648                ),
1649            )
1650        }
1651    }
1652
1653    /// Absorbed-form MQA attention over the latent cache. `q_pe` is ignored when
1654    /// `d_rope == 0`; callers on the NoPE path may pass any allocated slice.
1655    #[allow(clippy::too_many_arguments)] // allow: the parameter list mirrors the kernel/FFI/call contract; bundling into a struct is a refactor, not a lint fix
1656    pub fn mla_attn_absorbed(
1657        &self,
1658        q_lat: &CudaSlice<f32>,
1659        q_pe: &CudaSlice<f32>,
1660        cache: &CudaSlice<f32>,
1661        o_lat: &mut CudaSlice<f32>,
1662        n_head: usize,
1663        kv_rank: usize,
1664        d_rope: usize,
1665        t_q: usize,
1666        t_kv: usize,
1667        scale: f32,
1668    ) -> Res<()> {
1669        let s = self.stream();
1670        unsafe {
1671            ck(
1672                "attn_absorbed",
1673                memra_mla_attn_absorbed_f32(
1674                    q_lat.device_ptr(&s).0 as *const f32,
1675                    q_pe.device_ptr(&s).0 as *const f32,
1676                    cache.device_ptr(&s).0 as *const f32,
1677                    o_lat.device_ptr_mut(&s).0 as *mut f32,
1678                    n_head as i32,
1679                    kv_rank as i32,
1680                    d_rope as i32,
1681                    t_q as i32,
1682                    t_kv as i32,
1683                    scale,
1684                    s.cu_stream() as *mut c_void,
1685                ),
1686            )
1687        }
1688    }
1689
1690    /// Live-length twin of [`Engine::mla_attn_absorbed`]: `t_kv = pos_d[0] + t_q` read on the
1691    /// device (the decode-graph door's position word), fixed launch geometry, bit-identical to the
1692    /// scalar launch at the same length (`tests/mla_live_len_gpu.rs`). The caller owns the
1693    /// `t_q <= t_kv` invariant the scalar launcher checks on the host.
1694    #[allow(clippy::too_many_arguments)]
1695    pub fn mla_attn_absorbed_live(
1696        &self,
1697        q_lat: &CudaSlice<f32>,
1698        q_pe: &CudaSlice<f32>,
1699        cache: &CudaSlice<f32>,
1700        o_lat: &mut CudaSlice<f32>,
1701        n_head: usize,
1702        kv_rank: usize,
1703        d_rope: usize,
1704        t_q: usize,
1705        pos_d: &CudaSlice<i32>,
1706        scale: f32,
1707    ) -> Res<()> {
1708        let s = self.stream();
1709        unsafe {
1710            ck(
1711                "attn_absorbed_live",
1712                memra_mla_attn_absorbed_live_f32(
1713                    q_lat.device_ptr(&s).0 as *const f32,
1714                    q_pe.device_ptr(&s).0 as *const f32,
1715                    cache.device_ptr(&s).0 as *const f32,
1716                    o_lat.device_ptr_mut(&s).0 as *mut f32,
1717                    n_head as i32,
1718                    kv_rank as i32,
1719                    d_rope as i32,
1720                    t_q as i32,
1721                    pos_d.device_ptr(&s).0 as *const i32,
1722                    scale,
1723                    s.cu_stream() as *mut c_void,
1724                ),
1725            )
1726        }
1727    }
1728
1729    /// Live-slot twin of [`Engine::mla_append_latent`]: the row offset is `pos_d[0]` on the
1730    /// device. Bit-identical to the scalar launch at `slot == pos_d[0]`.
1731    #[allow(clippy::too_many_arguments)]
1732    pub fn mla_append_latent_live(
1733        &self,
1734        cache: &mut CudaSlice<f32>,
1735        c_kv: &CudaSlice<f32>,
1736        k_pe: &CudaSlice<f32>,
1737        pos_d: &CudaSlice<i32>,
1738        t: usize,
1739        kv_rank: usize,
1740        d_rope: usize,
1741    ) -> Res<()> {
1742        let s = self.stream();
1743        unsafe {
1744            ck(
1745                "append_latent_live",
1746                memra_mla_append_latent_live_f32(
1747                    cache.device_ptr_mut(&s).0 as *mut f32,
1748                    c_kv.device_ptr(&s).0 as *const f32,
1749                    k_pe.device_ptr(&s).0 as *const f32,
1750                    pos_d.device_ptr(&s).0 as *const i32,
1751                    t as i32,
1752                    kv_rank as i32,
1753                    d_rope as i32,
1754                    s.cu_stream() as *mut c_void,
1755                ),
1756            )
1757        }
1758    }
1759}
1760
1761/// Safe wrappers for the DSA k-pool indexer (`cu/mla_attn.cu`, "DSA k-pool indexer" section).
1762/// Numeric truth is `memra_reference::kpool_allowed_tokens`; the gate is
1763/// `tests/glm5_kpool_indexer_gpu.rs`.
1764impl Engine {
1765    /// Collapse pools `[pool_begin, n_pools)` of `pool` cached indexer rows each into one key by a
1766    /// learned per-channel softmax over (gate score + positional embedding).
1767    /// `state` rows are `[k | gate]`, `2 * d` wide; `ape` is `[pool][d]` row-major.
1768    ///
1769    /// `pool_begin` is the RESIDENCY seam: a pool's key depends only on its own `pool` state rows
1770    /// (append-only, never rewritten) and the constant `ape`, so it is final the instant the
1771    /// pool's last row lands. Pools below `pool_begin` are already resident and are left alone —
1772    /// bit-identically to what rebuilding them would produce. Pass 0 for a full rebuild.
1773    ///
1774    /// `state_rows` is the indexer plane's TAIL-RING size in rows (0 = flat, absolute
1775    /// addressing). It is always a multiple of `pool`, so a pool's members stay contiguous
1776    /// across the wrap and the collapse reads the same values in the same order either way.
1777    #[allow(clippy::too_many_arguments)]
1778    pub fn mla_kpool_pool_keys(
1779        &self,
1780        state: &CudaSlice<f32>,
1781        ape: &CudaSlice<f32>,
1782        pool_keys: &mut CudaSlice<f32>,
1783        pool_begin: usize,
1784        n_pools: usize,
1785        pool: usize,
1786        d: usize,
1787        state_rows: usize,
1788    ) -> Res<()> {
1789        let s = self.stream();
1790        unsafe {
1791            ck(
1792                "kpool_pool_keys",
1793                memra_mla_kpool_pool_keys_f32(
1794                    state.device_ptr(&s).0 as *const f32,
1795                    ape.device_ptr(&s).0 as *const f32,
1796                    pool_keys.device_ptr_mut(&s).0 as *mut f32,
1797                    pool_begin as i32,
1798                    n_pools as i32,
1799                    pool as i32,
1800                    d as i32,
1801                    state_rows as i32,
1802                    s.cu_stream() as *mut c_void,
1803                ),
1804            )
1805        }
1806    }
1807
1808    /// Append `t` packed indexer rows `[k_norm | gate]` at absolute row `slot`, wrapping mod
1809    /// `rows` when the plane is a TAIL RING (`rows == 0` is the flat plane).
1810    ///
1811    /// SEPARATE from [`Engine::mla_append_latent`] on purpose: the latent plane is re-read by
1812    /// every later query through the gathered attention walk and is NOT a ring, so the two planes
1813    /// must not share a row-addressing contract even though they share a row shape.
1814    #[allow(clippy::too_many_arguments)]
1815    ///
1816    /// `src_row` is the first SOURCE row of `a`/`b` to append: the call's `k_norm`/`gate` are
1817    /// computed once for the whole call, and the tail-ring drain (`mla_kpool_indices`) walks them
1818    /// in sub-ranges. `src_row` 0 is the whole-call append.
1819    pub fn mla_index_append(
1820        &self,
1821        plane: &mut CudaSlice<f32>,
1822        a: &CudaSlice<f32>,
1823        b: &CudaSlice<f32>,
1824        src_row: usize,
1825        slot: usize,
1826        t: usize,
1827        wa: usize,
1828        wb: usize,
1829        rows: usize,
1830    ) -> Res<()> {
1831        let s = self.stream();
1832        unsafe {
1833            ck(
1834                "index_append_ring",
1835                memra_mla_index_append_ring_f32(
1836                    plane.device_ptr_mut(&s).0 as *mut f32,
1837                    (a.device_ptr(&s).0 as *const f32).add(src_row * wa),
1838                    (b.device_ptr(&s).0 as *const f32).add(src_row * wb),
1839                    slot as i32,
1840                    t as i32,
1841                    wa as i32,
1842                    wb as i32,
1843                    rows as i32,
1844                    s.cu_stream() as *mut c_void,
1845                ),
1846            )
1847        }
1848    }
1849
1850    /// Head-mixed pool scores, `-inf` on pools whose last token is not visible to the query.
1851    /// `first_pos` is the absolute cache row of query 0 (queries are the cache's last `t_q` rows).
1852    ///
1853    /// Register-tiled fused GEMM+head-reduce: the pool-key tile stays resident in shared memory
1854    /// across the head loop, so `pool_keys` is read once per query TILE instead of once per
1855    /// query, and the head mix lands in the accumulator instead of costing a second pass over a
1856    /// `[t_q * heads, n_pools]` plane (17 GB at the shipped 1M/512 shape). BIT-IDENTICAL to
1857    /// [`Engine::mla_kpool_score_ref`] by construction — same six-step rounding sequence, spelled
1858    /// with explicit intrinsics — and gated so
1859    /// (`gpu_kpool_scoring_is_byte_identical_to_the_reference_kernel`). See the scoring section
1860    /// of `cu/mla_attn.cu` for why that identity is the requirement and not a nicety.
1861    #[allow(clippy::too_many_arguments)]
1862    pub fn mla_kpool_score(
1863        &self,
1864        q: &CudaSlice<f32>,
1865        pool_keys: &CudaSlice<f32>,
1866        head_weights: &CudaSlice<f32>,
1867        score: &mut CudaSlice<f32>,
1868        t_q: usize,
1869        heads: usize,
1870        d: usize,
1871        n_pools: usize,
1872        pool: usize,
1873        first_pos: usize,
1874        qk_scale: f32,
1875        head_scale: f32,
1876    ) -> Res<()> {
1877        let s = self.stream();
1878        // MEMRA_B200_DSA_DECODE door (level >= 1): the head-blocked decode scorer. Engages only
1879        // at decode widths and only from MLA_DSA_SCORE_MIN_POOLS up, where the block count can
1880        // fill the die; below that the shipped dispatch's own measured crossover already sends
1881        // decode to the reference kernel, which wins there. Bit-identical, so this is a speed
1882        // choice and nothing else. See research/b200-dsa-decode-20260902/ROOFLINE.md §2.
1883        if mla_dsa_decode_level() >= 1
1884            && (1..=MLA_DSA_ARM_T_MAX).contains(&t_q)
1885            && n_pools >= MLA_DSA_SCORE_MIN_POOLS
1886        {
1887            let rc = unsafe {
1888                memra_mla_kpool_score_dsa_f32(
1889                    q.device_ptr(&s).0 as *const f32,
1890                    pool_keys.device_ptr(&s).0 as *const f32,
1891                    head_weights.device_ptr(&s).0 as *const f32,
1892                    score.device_ptr_mut(&s).0 as *mut f32,
1893                    t_q as i32,
1894                    heads as i32,
1895                    d as i32,
1896                    n_pools as i32,
1897                    pool as i32,
1898                    first_pos as i32,
1899                    qk_scale,
1900                    head_scale,
1901                    s.cu_stream() as *mut c_void,
1902                )
1903            };
1904            if !mla_dsa_geometry_refusal(rc) {
1905                mla_dsa_announce(
1906                    "kpool_score",
1907                    t_q,
1908                    &format!("arm=head-blocked heads={heads} pools={n_pools} class=bit-identical"),
1909                );
1910                return ck("kpool_score_dsa", rc);
1911            }
1912        }
1913        unsafe {
1914            ck(
1915                "kpool_score",
1916                memra_mla_kpool_score_f32(
1917                    q.device_ptr(&s).0 as *const f32,
1918                    pool_keys.device_ptr(&s).0 as *const f32,
1919                    head_weights.device_ptr(&s).0 as *const f32,
1920                    score.device_ptr_mut(&s).0 as *mut f32,
1921                    t_q as i32,
1922                    heads as i32,
1923                    d as i32,
1924                    n_pools as i32,
1925                    pool as i32,
1926                    first_pos as i32,
1927                    qk_scale,
1928                    head_scale,
1929                    s.cu_stream() as *mut c_void,
1930                ),
1931            )
1932        }
1933    }
1934
1935    /// The RETAINED reference scorer: block per (query, pool), one thread per head, head sum
1936    /// walked sequentially by thread 0. It defines the arithmetic [`Engine::mla_kpool_score`]
1937    /// reproduces, and it is the only consumer-visible reason this crate still builds the slow
1938    /// kernel. Not a serving path — `O(t_q * n_pools)` blocks of `heads` threads.
1939    #[allow(clippy::too_many_arguments)]
1940    pub fn mla_kpool_score_ref(
1941        &self,
1942        q: &CudaSlice<f32>,
1943        pool_keys: &CudaSlice<f32>,
1944        head_weights: &CudaSlice<f32>,
1945        score: &mut CudaSlice<f32>,
1946        t_q: usize,
1947        heads: usize,
1948        d: usize,
1949        n_pools: usize,
1950        pool: usize,
1951        first_pos: usize,
1952        qk_scale: f32,
1953        head_scale: f32,
1954    ) -> Res<()> {
1955        let s = self.stream();
1956        unsafe {
1957            ck(
1958                "kpool_score_ref",
1959                memra_mla_kpool_score_ref_f32(
1960                    q.device_ptr(&s).0 as *const f32,
1961                    pool_keys.device_ptr(&s).0 as *const f32,
1962                    head_weights.device_ptr(&s).0 as *const f32,
1963                    score.device_ptr_mut(&s).0 as *mut f32,
1964                    t_q as i32,
1965                    heads as i32,
1966                    d as i32,
1967                    n_pools as i32,
1968                    pool as i32,
1969                    first_pos as i32,
1970                    qk_scale,
1971                    head_scale,
1972                    s.cu_stream() as *mut c_void,
1973                ),
1974            )
1975        }
1976    }
1977
1978    /// Top-`select_k` pools per query expanded to ascending cache rows, tail appended, -1 padded.
1979    ///
1980    /// Radix select on the 64-bit order key `(desc32(score) << 32) | pool_index`, whose ascending
1981    /// order IS the oracle's "score descending, pool index ascending" — see the ORDER contract
1982    /// block in `cu/mla_attn.cu`. `O(8 * n_pools / threads)` per query, independent of `select_k`.
1983    #[allow(clippy::too_many_arguments)]
1984    /// Live-count twin of the DSA decode scorer (`MEMRA_B200_DSA_DECODE` level >= 1): `n_pools`
1985    /// read from the door's device word, launch grid from `n_pools_cap`, t_q must be 1 (one
1986    /// score row, so the row stride does not depend on the count). Bit-identical to
1987    /// `memra_mla_kpool_score_dsa_f32` at the same count (`tests/mla_kpool_live_gpu.rs`).
1988    #[allow(clippy::too_many_arguments)]
1989    pub fn mla_kpool_score_dsa_live(
1990        &self,
1991        q: &CudaSlice<f32>,
1992        pool_keys: &CudaSlice<f32>,
1993        head_weights: &CudaSlice<f32>,
1994        score: &mut CudaSlice<f32>,
1995        heads: usize,
1996        d: usize,
1997        n_pools_d: &CudaSlice<i32>,
1998        n_pools_cap: usize,
1999        pool: usize,
2000        first_pos: usize,
2001        qk_scale: f32,
2002        head_scale: f32,
2003    ) -> Res<()> {
2004        let s = self.stream();
2005        unsafe {
2006            ck(
2007                "kpool_score_dsa_live",
2008                memra_mla_kpool_score_dsa_live_f32(
2009                    q.device_ptr(&s).0 as *const f32,
2010                    pool_keys.device_ptr(&s).0 as *const f32,
2011                    head_weights.device_ptr(&s).0 as *const f32,
2012                    score.device_ptr_mut(&s).0 as *mut f32,
2013                    1,
2014                    heads as i32,
2015                    d as i32,
2016                    n_pools_d.device_ptr(&s).0 as *const i32,
2017                    n_pools_cap as i32,
2018                    pool as i32,
2019                    first_pos as i32,
2020                    qk_scale,
2021                    head_scale,
2022                    s.cu_stream() as *mut c_void,
2023                ),
2024            )
2025        }
2026    }
2027
2028    /// Live-count twin of the single-CTA selector: `n_pools` from the device word, grid t_q.
2029    /// Bit-identical to `memra_mla_kpool_select_f32` at the same count.
2030    #[allow(clippy::too_many_arguments)]
2031    pub fn mla_kpool_select_live(
2032        &self,
2033        score: &CudaSlice<f32>,
2034        idx: &mut CudaSlice<i32>,
2035        t_q: usize,
2036        n_pools_d: &CudaSlice<i32>,
2037        pool: usize,
2038        select_k: usize,
2039        width: usize,
2040        first_pos: usize,
2041        always_tail: bool,
2042    ) -> Res<()> {
2043        let s = self.stream();
2044        unsafe {
2045            ck(
2046                "kpool_select_live",
2047                memra_mla_kpool_select_live_f32(
2048                    score.device_ptr(&s).0 as *const f32,
2049                    idx.device_ptr_mut(&s).0 as *mut i32,
2050                    t_q as i32,
2051                    n_pools_d.device_ptr(&s).0 as *const i32,
2052                    pool as i32,
2053                    select_k as i32,
2054                    width as i32,
2055                    first_pos as i32,
2056                    always_tail as i32,
2057                    s.cu_stream() as *mut c_void,
2058                ),
2059            )
2060        }
2061    }
2062
2063    #[allow(clippy::too_many_arguments)]
2064    pub fn mla_kpool_select(
2065        &self,
2066        score: &CudaSlice<f32>,
2067        idx: &mut CudaSlice<i32>,
2068        t_q: usize,
2069        n_pools: usize,
2070        pool: usize,
2071        select_k: usize,
2072        width: usize,
2073        first_pos: usize,
2074        always_tail: bool,
2075    ) -> Res<()> {
2076        let s = self.stream();
2077        // MEMRA_B200_DSA_SELECT door: the exact multi-CTA selector. Byte-identical output, so
2078        // this is a speed choice and nothing else; it engages only where the single-CTA kernel
2079        // has parallelism to gain (see MLA_DSA_SELECT_MIN_POOLS).
2080        if mla_dsa_select_on() && mla_dsa_select_engages(t_q, n_pools) {
2081            let n_ctas = unsafe { memra_mla_kpool_select_ctas(n_pools as i32) };
2082            let stride = unsafe { memra_mla_kpool_select_ws_ints(n_ctas) };
2083            let mut ws = self.uninit_i32(t_q * stride as usize)?;
2084            mla_dsa_select_announce(t_q, n_pools, n_ctas);
2085            return unsafe {
2086                ck(
2087                    "kpool_select_dsa",
2088                    memra_mla_kpool_select_dsa_f32(
2089                        score.device_ptr(&s).0 as *const f32,
2090                        idx.device_ptr_mut(&s).0 as *mut i32,
2091                        ws.device_ptr_mut(&s).0 as *mut i32,
2092                        t_q as i32,
2093                        n_pools as i32,
2094                        pool as i32,
2095                        select_k as i32,
2096                        width as i32,
2097                        first_pos as i32,
2098                        i32::from(always_tail),
2099                        s.cu_stream() as *mut c_void,
2100                    ),
2101                )
2102            };
2103        }
2104        unsafe {
2105            ck(
2106                "kpool_select",
2107                memra_mla_kpool_select_f32(
2108                    score.device_ptr(&s).0 as *const f32,
2109                    idx.device_ptr_mut(&s).0 as *mut i32,
2110                    t_q as i32,
2111                    n_pools as i32,
2112                    pool as i32,
2113                    select_k as i32,
2114                    width as i32,
2115                    first_pos as i32,
2116                    i32::from(always_tail),
2117                    s.cu_stream() as *mut c_void,
2118                ),
2119            )
2120        }
2121    }
2122
2123    /// The `select_k`-rounds reference selection — the DEFINITION of the order the radix kernel
2124    /// above must reproduce. NOT a serving path: it is `O(select_k * n_pools / threads)` and
2125    /// exists so `gpu_kpool_radix_selection_is_byte_identical_to_the_reference_kernel` can hold
2126    /// the fast kernel to it at shapes the micro fixture cannot reach.
2127    #[allow(clippy::too_many_arguments)]
2128    pub fn mla_kpool_select_ref(
2129        &self,
2130        score: &CudaSlice<f32>,
2131        idx: &mut CudaSlice<i32>,
2132        t_q: usize,
2133        n_pools: usize,
2134        pool: usize,
2135        select_k: usize,
2136        width: usize,
2137        first_pos: usize,
2138        always_tail: bool,
2139    ) -> Res<()> {
2140        let s = self.stream();
2141        unsafe {
2142            ck(
2143                "kpool_select_ref",
2144                memra_mla_kpool_select_ref_f32(
2145                    score.device_ptr(&s).0 as *const f32,
2146                    idx.device_ptr_mut(&s).0 as *mut i32,
2147                    t_q as i32,
2148                    n_pools as i32,
2149                    pool as i32,
2150                    select_k as i32,
2151                    width as i32,
2152                    first_pos as i32,
2153                    i32::from(always_tail),
2154                    s.cu_stream() as *mut c_void,
2155                ),
2156            )
2157        }
2158    }
2159
2160    /// Strided-batched BF16 tensor-core GEMM over per-head planes — the
2161    /// MEMRA_MLA_TC_PREFILL absorb/decompress engine. Per head `b` in `0..batch`:
2162    /// `y_b[m, n] = x_b[m, k] @ w_b[n, k]^T`, f32 accumulate.
2163    ///
2164    /// `w` is the bf16 conversion-split weight plane: per-head `[n, k]` row-major,
2165    /// batch stride `n * k` (baked into the C side). `x` is a bf16 VIEW of a
2166    /// `[m, batch, k]` activation plane: per-head row stride `x_rs`, per-head base
2167    /// offset `x_bs` — for the canonical `[t, n_head, d]` layout that is
2168    /// `x_rs = batch * k`, `x_bs = k`. `y` mirrors that with `y_rs`/`y_bs` over `n`.
2169    ///
2170    /// `y_bf16` selects the output dtype: `true` writes bf16 (feeds the TC attention
2171    /// kernel directly, one fewer convert), `false` writes f32 (re-enters the f32
2172    /// stream). The caller passes `y` as raw bytes either way; an f32 output slice
2173    /// is viewed through its byte layout by the caller (`mla_bf16_gemm_sb_f32out`).
2174    ///
2175    /// rc 2xxxx (no cuBLASLt heuristic for the shape) is a DECLINE class the caller
2176    /// may fall back on; everything else is a hard error.
2177    #[allow(clippy::too_many_arguments)]
2178    pub fn mla_bf16_gemm_sb_raw(
2179        &self,
2180        w_bf16: &CudaSlice<u8>,
2181        x_bf16: &CudaSlice<u8>,
2182        y_ptr: u64,
2183        m: usize,
2184        n: usize,
2185        k: usize,
2186        x_rs: usize,
2187        x_bs: usize,
2188        y_rs: usize,
2189        y_bs: usize,
2190        batch: usize,
2191        y_bf16: bool,
2192    ) -> Res<i32> {
2193        // Workspace from the shared f16/bf16 Lt scratch (bf16_tc_gemm pattern).
2194        let mut guard = self.f16_scratch.lock().unwrap();
2195        if guard.is_none() {
2196            *guard = Some(crate::f16_ffi::F16Scratch::with_capacity(self, 2)?);
2197        }
2198        let s_scr = guard.as_mut().unwrap();
2199        let s = self.stream();
2200        let rc = unsafe {
2201            memra_bf16_gemm_sb(
2202                w_bf16.device_ptr(&s).0 as *const c_void,
2203                x_bf16.device_ptr(&s).0 as *const c_void,
2204                y_ptr as *mut c_void,
2205                m as i32,
2206                n as i32,
2207                k as i32,
2208                x_rs as i64,
2209                x_bs as i64,
2210                y_rs as i64,
2211                y_bs as i64,
2212                batch as i32,
2213                i32::from(y_bf16),
2214                s_scr.ws.device_ptr_mut(&s).0 as *mut c_void,
2215                crate::f16_ffi::F16_WS_BYTES,
2216                s.cu_stream() as *mut c_void,
2217            )
2218        };
2219        Ok(rc)
2220    }
2221
2222    /// [`Engine::mla_bf16_gemm_sb_raw`] with a bf16 output plane (absorb: feeds the TC
2223    /// attention kernel). Non-decline errors are named; a 2xxxx decline is returned as
2224    /// `Ok(false)` so the door can fall back to the per-position kernels.
2225    #[allow(clippy::too_many_arguments)]
2226    pub fn mla_bf16_gemm_sb_bf16out(
2227        &self,
2228        w_bf16: &CudaSlice<u8>,
2229        x_bf16: &CudaSlice<u8>,
2230        y_bf16: &mut CudaSlice<u8>,
2231        m: usize,
2232        n: usize,
2233        k: usize,
2234        x_rs: usize,
2235        x_bs: usize,
2236        y_rs: usize,
2237        y_bs: usize,
2238        batch: usize,
2239    ) -> Res<bool> {
2240        let s = self.stream();
2241        let (y_ptr, _gy) = y_bf16.device_ptr_mut(&s);
2242        let rc = self.mla_bf16_gemm_sb_raw(
2243            w_bf16, x_bf16, y_ptr, m, n, k, x_rs, x_bs, y_rs, y_bs, batch, true,
2244        )?;
2245        match rc {
2246            0 => Ok(true),
2247            r if (20000..30000).contains(&r) => Ok(false),
2248            r => Err(format!(
2249                "mla bf16 strided-batched GEMM (bf16 out) failed: rc {r} \
2250                 (m={m} n={n} k={k} batch={batch})"
2251            )
2252            .into()),
2253        }
2254    }
2255
2256    /// [`Engine::mla_bf16_gemm_sb_raw`] with an f32 output plane (decompress: re-enters
2257    /// the f32 stream). Same decline contract as the bf16-out twin.
2258    #[allow(clippy::too_many_arguments)]
2259    pub fn mla_bf16_gemm_sb_f32out(
2260        &self,
2261        w_bf16: &CudaSlice<u8>,
2262        x_bf16: &CudaSlice<u8>,
2263        y_f32: &mut CudaSlice<f32>,
2264        m: usize,
2265        n: usize,
2266        k: usize,
2267        x_rs: usize,
2268        x_bs: usize,
2269        y_rs: usize,
2270        y_bs: usize,
2271        batch: usize,
2272    ) -> Res<bool> {
2273        let s = self.stream();
2274        let (y_ptr, _gy) = y_f32.device_ptr_mut(&s);
2275        let rc = self.mla_bf16_gemm_sb_raw(
2276            w_bf16, x_bf16, y_ptr, m, n, k, x_rs, x_bs, y_rs, y_bs, batch, false,
2277        )?;
2278        match rc {
2279            0 => Ok(true),
2280            r if (20000..30000).contains(&r) => Ok(false),
2281            r => Err(format!(
2282                "mla bf16 strided-batched GEMM (f32 out) failed: rc {r} \
2283                 (m={m} n={n} k={k} batch={batch})"
2284            )
2285            .into()),
2286        }
2287    }
2288
2289    /// Absorbed-form MQA attention over a GATHERED index list (one list per query, shared across
2290    /// heads). Same body as `mla_attn_absorbed`; only the cache walk differs.
2291    #[allow(clippy::too_many_arguments)]
2292    pub fn mla_attn_gathered(
2293        &self,
2294        q_lat: &CudaSlice<f32>,
2295        q_pe: &CudaSlice<f32>,
2296        cache: &CudaSlice<f32>,
2297        idx: &CudaSlice<i32>,
2298        o_lat: &mut CudaSlice<f32>,
2299        n_head: usize,
2300        kv_rank: usize,
2301        d_rope: usize,
2302        t_q: usize,
2303        n_slots: usize,
2304        scale: f32,
2305    ) -> Res<()> {
2306        let s = self.stream();
2307        // MEMRA_B200_DSA_DECODE door, checked FIRST: its arms fight the same 64-CTA t_q=1
2308        // geometry the output-range split below does, without repeating the slot walk.
2309        // THE TWO LEVELS DIFFER TODAY, and the difference is this PR's headline: the shipped
2310        // table is [0, 32, 0, 0, 1, ...], so at t_q=1 level 1 takes arm 0 (falls through to
2311        // the sibling split door) while level 2 takes warp-online chunks=32 -- +9.7% vs
2312        // +43.1% in the 256k serving A/B. The `a >= 2 && dsa_level < 2` guard below exists
2313        // precisely because they differ, and the level boundary IS the numeric-class
2314        // admission boundary. See research/b200-dsa-decode-20260902/ROOFLINE.md.
2315        let dsa_level = mla_dsa_decode_level();
2316        let dsa_arm = if dsa_level >= 1 && t_q <= MLA_DSA_ARM_T_MAX {
2317            // `_effective` already enforces the named-class width rule (plain decode only, so
2318            // the spec-verify batch never sees `dsa-warp-online-f32`); level 2 is the second,
2319            // independent admission for the same class.
2320            let a = mla_dsa_attn_arm_effective(t_q);
2321            if a >= 2 && dsa_level < 2 { 0 } else { a }
2322        } else {
2323            0
2324        };
2325        if dsa_arm >= 2 {
2326            let cells = t_q * n_head * dsa_arm as usize;
2327            let mut part_m = self.uninit(cells)?;
2328            let mut part_d = self.uninit(cells)?;
2329            let mut part_acc = self.uninit(cells * kv_rank)?;
2330            let rc = unsafe {
2331                memra_mla_dsa_attn_split_f32(
2332                    q_lat.device_ptr(&s).0 as *const f32,
2333                    q_pe.device_ptr(&s).0 as *const f32,
2334                    cache.device_ptr(&s).0 as *const f32,
2335                    idx.device_ptr(&s).0 as *const i32,
2336                    o_lat.device_ptr_mut(&s).0 as *mut f32,
2337                    part_m.device_ptr_mut(&s).0 as *mut f32,
2338                    part_d.device_ptr_mut(&s).0 as *mut f32,
2339                    part_acc.device_ptr_mut(&s).0 as *mut f32,
2340                    n_head as i32,
2341                    kv_rank as i32,
2342                    d_rope as i32,
2343                    t_q as i32,
2344                    n_slots as i32,
2345                    dsa_arm,
2346                    scale,
2347                    s.cu_stream() as *mut c_void,
2348                )
2349            };
2350            if !mla_dsa_geometry_refusal(rc) {
2351                mla_dsa_announce(
2352                    "attn_gathered",
2353                    t_q,
2354                    &format!("arm=warp-online chunks={dsa_arm} class=dsa-warp-online-f32"),
2355                );
2356                return ck("attn_gathered_dsa_warp", rc);
2357            }
2358        } else if dsa_arm == 1 {
2359            let rc = unsafe {
2360                memra_mla_attn_gathered_dsa_f32(
2361                    q_lat.device_ptr(&s).0 as *const f32,
2362                    q_pe.device_ptr(&s).0 as *const f32,
2363                    cache.device_ptr(&s).0 as *const f32,
2364                    idx.device_ptr(&s).0 as *const i32,
2365                    o_lat.device_ptr_mut(&s).0 as *mut f32,
2366                    n_head as i32,
2367                    kv_rank as i32,
2368                    d_rope as i32,
2369                    t_q as i32,
2370                    n_slots as i32,
2371                    scale,
2372                    s.cu_stream() as *mut c_void,
2373                )
2374            };
2375            if !mla_dsa_geometry_refusal(rc) {
2376                mla_dsa_announce("attn_gathered", t_q, "arm=single-pass class=bit-identical");
2377                return ck("attn_gathered_dsa", rc);
2378            }
2379        }
2380        // MEMRA_B200_MLA_DECODE_ARM door: output-range split from the t_q-keyed table
2381        // MLA_B200_ATTN_GATHERED_SPLIT. This twin repeats the score/softmax walk per split
2382        // block, unlike the absorb/decompress splits, which is why the B200 run found it a win
2383        // at t_q=1 only (see the table comment); every other cell is the shipped kernel.
2384        if let Some(split) = mla_b200_split_for(MlaB200Kernel::AttnGathered, t_q, kv_rank) {
2385            mla_b200_split_announce("attn_gathered", t_q, n_head, split);
2386            return unsafe {
2387                ck(
2388                    "attn_gathered_split_b200",
2389                    memra_mla_attn_gathered_split_f32(
2390                        q_lat.device_ptr(&s).0 as *const f32,
2391                        q_pe.device_ptr(&s).0 as *const f32,
2392                        cache.device_ptr(&s).0 as *const f32,
2393                        idx.device_ptr(&s).0 as *const i32,
2394                        o_lat.device_ptr_mut(&s).0 as *mut f32,
2395                        n_head as i32,
2396                        kv_rank as i32,
2397                        d_rope as i32,
2398                        t_q as i32,
2399                        n_slots as i32,
2400                        scale,
2401                        split,
2402                        s.cu_stream() as *mut c_void,
2403                    ),
2404                )
2405            };
2406        }
2407        unsafe {
2408            ck(
2409                "attn_gathered",
2410                memra_mla_attn_gathered_f32(
2411                    q_lat.device_ptr(&s).0 as *const f32,
2412                    q_pe.device_ptr(&s).0 as *const f32,
2413                    cache.device_ptr(&s).0 as *const f32,
2414                    idx.device_ptr(&s).0 as *const i32,
2415                    o_lat.device_ptr_mut(&s).0 as *mut f32,
2416                    n_head as i32,
2417                    kv_rank as i32,
2418                    d_rope as i32,
2419                    t_q as i32,
2420                    n_slots as i32,
2421                    scale,
2422                    s.cu_stream() as *mut c_void,
2423                ),
2424            )
2425        }
2426    }
2427}
2428
2429#[cfg(test)]
2430mod dsa_select_default_tests {
2431    use super::{mla_dsa_select_engages, mla_dsa_select_on_from};
2432
2433    #[test]
2434    fn default_on_only_zero_disarms_and_the_floors_still_gate() {
2435        assert!(mla_dsa_select_on_from(None));
2436        assert!(mla_dsa_select_on_from(Some("1")));
2437        assert!(!mla_dsa_select_on_from(Some("0")));
2438        assert!(!mla_dsa_select_on_from(Some(" 0 ")));
2439        // The flip does not reach short context: the floors are unchanged.
2440        assert!(!mla_dsa_select_engages(1, 65_535));
2441        assert!(mla_dsa_select_engages(1, 65_536));
2442        assert!(!mla_dsa_select_engages(2, 65_536));
2443        assert!(mla_dsa_select_engages(2, 262_144));
2444        assert!(!mla_dsa_select_engages(9, 1_000_000));
2445    }
2446}