use crate::Engine;
use cudarc::driver::{CudaSlice, DevicePtr, DevicePtrMut};
use std::os::raw::c_void;
pub static MLA_DECODE_SPLIT_DISPATCHES: std::sync::atomic::AtomicU64 =
std::sync::atomic::AtomicU64::new(0);
pub static MLA_COALESCE_DISPATCHES: std::sync::atomic::AtomicU64 =
std::sync::atomic::AtomicU64::new(0);
fn mla_coalesce_on() -> bool {
std::env::var("MEMRA_MLA_COALESCE").as_deref() == Ok("1")
}
fn mla_coalesce_announce(which: &str, t_q: usize, n_head: usize, split: i32) {
use std::sync::atomic::Ordering;
if MLA_COALESCE_DISPATCHES.fetch_add(1, Ordering::Relaxed) == 0 {
eprintln!(
"[mla-coalesce] engaged {which} t_q={t_q} n_head={n_head} split={split} \
(warp-per-row coalesced loads + shuffle reduction; numeric class \
mla_warp_row_reduce; MEMRA_MLA_COALESCE=1)"
);
}
}
fn mla_decode_split_on() -> bool {
std::env::var("MEMRA_MLA_DECODE_SPLIT").as_deref() == Ok("1")
}
fn mla_decode_split_for(blocks: usize, out_dim: usize) -> Option<i32> {
if !mla_decode_split_on() || blocks == 0 || blocks >= 1024 {
return None;
}
let want = 1024usize.div_ceil(blocks);
let cap = (out_dim / 32).max(1);
let split = want.min(cap);
if split <= 1 { None } else { Some(split as i32) }
}
fn mla_split_announce(kind: &str, t_q: usize, n_head: usize, split: i32) {
use std::sync::atomic::Ordering;
if MLA_DECODE_SPLIT_DISPATCHES.fetch_add(1, Ordering::Relaxed) == 0 {
eprintln!(
"[mla-decode-split] engaged {kind} t={t_q} heads={n_head} split={split} \
(output-range split of the (token, head) blocks; MEMRA_MLA_DECODE_SPLIT=1)"
);
}
}
pub static MLA_B200_DECODE_ARM_DISPATCHES: std::sync::atomic::AtomicU64 =
std::sync::atomic::AtomicU64::new(0);
fn mla_b200_decode_arm_on() -> bool {
cfg!(memra_sm100_tcgen05) && std::env::var("MEMRA_B200_MLA_DECODE_ARM").as_deref() == Ok("1")
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum MlaB200Kernel {
AbsorbQ,
DecompressV,
AttnGathered,
}
impl MlaB200Kernel {
pub const ALL: [MlaB200Kernel; 3] = [
MlaB200Kernel::AbsorbQ,
MlaB200Kernel::DecompressV,
MlaB200Kernel::AttnGathered,
];
pub fn name(self) -> &'static str {
match self {
MlaB200Kernel::AbsorbQ => "absorb_q",
MlaB200Kernel::DecompressV => "decompress_v",
MlaB200Kernel::AttnGathered => "attn_gathered",
}
}
}
pub const MLA_B200_ARM_T_MAX: usize = 8;
pub const MLA_B200_ABSORB_Q_SPLIT: [i32; MLA_B200_ARM_T_MAX + 1] = [1, 4, 1, 1, 4, 1, 1, 1, 1];
pub const MLA_B200_DECOMPRESS_V_SPLIT: [i32; MLA_B200_ARM_T_MAX + 1] = [1, 4, 1, 1, 1, 1, 1, 1, 1];
pub const MLA_B200_ATTN_GATHERED_SPLIT: [i32; MLA_B200_ARM_T_MAX + 1] = [1, 2, 1, 1, 1, 1, 1, 1, 1];
pub const MLA_B200_ARM_REGRESSION_MARGIN: f64 = 1.05;
pub fn mla_b200_arm_table_split(kernel: MlaB200Kernel, t_q: usize) -> i32 {
if t_q == 0 || t_q > MLA_B200_ARM_T_MAX {
return 1;
}
match kernel {
MlaB200Kernel::AbsorbQ => MLA_B200_ABSORB_Q_SPLIT[t_q],
MlaB200Kernel::DecompressV => MLA_B200_DECOMPRESS_V_SPLIT[t_q],
MlaB200Kernel::AttnGathered => MLA_B200_ATTN_GATHERED_SPLIT[t_q],
}
}
fn mla_b200_split_for(kernel: MlaB200Kernel, t_q: usize, out_dim: usize) -> Option<i32> {
if !mla_b200_decode_arm_on() {
return None;
}
let split = mla_b200_arm_table_split(kernel, t_q);
let cap = (out_dim / 32).max(1) as i32;
if split <= 1 || split > cap {
None
} else {
Some(split)
}
}
fn mla_b200_split_announce(kind: &str, t_q: usize, n_head: usize, split: i32) {
use std::sync::atomic::Ordering;
if MLA_B200_DECODE_ARM_DISPATCHES.fetch_add(1, Ordering::Relaxed) == 0 {
eprintln!(
"[mla-b200-decode-arm] engaged {kind} t={t_q} heads={n_head} split={split} \
(sm_100a output-range split; MEMRA_B200_MLA_DECODE_ARM=1)"
);
}
}
pub static MLA_DSA_DECODE_DISPATCHES: std::sync::atomic::AtomicU64 =
std::sync::atomic::AtomicU64::new(0);
fn mla_dsa_decode_level() -> u32 {
if !cfg!(memra_sm100_tcgen05) {
return 0;
}
match std::env::var("MEMRA_B200_DSA_DECODE").as_deref() {
Ok("1") => 1,
Ok("2") => 2,
_ => 0,
}
}
pub const MLA_DSA_ARM_T_MAX: usize = 8;
pub const MLA_DSA_ATTN_ARM: [i32; MLA_DSA_ARM_T_MAX + 1] = [0, 32, 0, 0, 1, 0, 0, 0, 0];
pub const MLA_DSA_NAMED_CLASS_T_MAX: usize = 1;
pub const MLA_DSA_ATTN_CHUNK_SWEEP: [i32; 4] = [4, 8, 16, 32];
pub const MLA_DSA_SCORE_MIN_POOLS: usize = 4096;
pub const MLA_DSA_REGRESSION_MARGIN: f64 = 1.05;
pub fn mla_dsa_attn_arm(t_q: usize) -> i32 {
if t_q == 0 || t_q > MLA_DSA_ARM_T_MAX {
return 0;
}
MLA_DSA_ATTN_ARM[t_q]
}
pub fn mla_dsa_attn_arm_effective(t_q: usize) -> i32 {
let arm = mla_dsa_attn_arm(t_q);
if arm >= 2 && t_q > MLA_DSA_NAMED_CLASS_T_MAX {
return 0;
}
arm
}
pub static MLA_DSA_SELECT_DISPATCHES: std::sync::atomic::AtomicU64 =
std::sync::atomic::AtomicU64::new(0);
fn mla_dsa_select_on() -> bool {
cfg!(memra_sm100_tcgen05)
&& mla_dsa_select_on_from(std::env::var("MEMRA_B200_DSA_SELECT").ok().as_deref())
}
pub fn mla_dsa_select_on_from(v: Option<&str>) -> bool {
!matches!(v.map(str::trim), Some("0"))
}
pub const MLA_DSA_SELECT_MIN_POOLS: usize = 65_536;
pub const MLA_DSA_SELECT_MIN_POOLS_SPEC: usize = 262_144;
pub const MLA_DSA_SELECT_T_MAX: usize = 8;
pub fn mla_dsa_select_engages(t_q: usize, n_pools: usize) -> bool {
if !(1..=MLA_DSA_SELECT_T_MAX).contains(&t_q) {
return false;
}
n_pools >= mla_dsa_select_floor(t_q)
}
pub fn mla_dsa_select_floor(t_q: usize) -> usize {
if t_q == 1 {
MLA_DSA_SELECT_MIN_POOLS
} else {
MLA_DSA_SELECT_MIN_POOLS_SPEC
}
}
fn mla_dsa_select_announce(t_q: usize, n_pools: usize, n_ctas: i32) {
use std::sync::atomic::Ordering;
if MLA_DSA_SELECT_DISPATCHES.fetch_add(1, Ordering::Relaxed) == 0 {
eprintln!(
"[mla-b200-dsa-select] engaged kpool_select t={t_q} pools={n_pools} ctas={n_ctas} \
class=exact (sm_100a; MEMRA_B200_DSA_SELECT=1)"
);
}
}
fn mla_dsa_geometry_refusal(rc: i32) -> bool {
matches!(rc, 40020 | 40021 | 40023)
}
fn mla_dsa_announce(kind: &str, t_q: usize, detail: &str) {
use std::sync::atomic::Ordering;
if MLA_DSA_DECODE_DISPATCHES.fetch_add(1, Ordering::Relaxed) == 0 {
eprintln!(
"[mla-b200-dsa-decode] engaged {kind} t={t_q} {detail} \
(sm_100a; MEMRA_B200_DSA_DECODE)"
);
}
}
unsafe extern "C" {
pub fn memra_mla_rope_interleaved_f32(
x: *mut f32,
n_pos: i32,
n_vec: i32,
d_rope: i32,
positions: *const i32,
base: f32,
stream: *mut c_void,
) -> i32;
pub fn memra_mla_split_latent_f32(
kv: *const f32,
c_kv: *mut f32,
k_pe: *mut f32,
t: i32,
kv_rank: i32,
d_rope: i32,
stream: *mut c_void,
) -> i32;
pub fn memra_mla_append_latent_f32(
cache: *mut f32,
c_kv: *const f32,
k_pe: *const f32,
slot: i32,
t: i32,
kv_rank: i32,
d_rope: i32,
stream: *mut c_void,
) -> i32;
pub fn memra_mla_absorb_q_f32(
q_nope: *const f32,
wk_b: *const f32,
q_lat: *mut f32,
t_q: i32,
n_head: i32,
d_nope: i32,
kv_rank: i32,
stream: *mut c_void,
) -> i32;
pub fn memra_mla_decompress_v_f32(
o_lat: *const f32,
wv_b: *const f32,
out: *mut f32,
t_q: i32,
n_head: i32,
d_v: i32,
kv_rank: i32,
stream: *mut c_void,
) -> i32;
#[allow(clippy::too_many_arguments)]
pub fn memra_mla_absorb_q_wp_f32(
q_nope: *const f32,
wk_b: *const f32,
q_lat: *mut f32,
t_q: i32,
n_head: i32,
d_nope: i32,
kv_rank: i32,
split: i32,
stream: *mut c_void,
) -> i32;
#[allow(clippy::too_many_arguments)]
pub fn memra_mla_decompress_v_wp_f32(
o_lat: *const f32,
wv_b: *const f32,
out: *mut f32,
t_q: i32,
n_head: i32,
d_v: i32,
kv_rank: i32,
split: i32,
stream: *mut c_void,
) -> i32;
#[allow(clippy::too_many_arguments)]
pub fn memra_mla_absorb_q_split_f32(
q_nope: *const f32,
wk_b: *const f32,
q_lat: *mut f32,
t_q: i32,
n_head: i32,
d_nope: i32,
kv_rank: i32,
split: i32,
stream: *mut c_void,
) -> i32;
#[allow(clippy::too_many_arguments)]
pub fn memra_mla_decompress_v_split_f32(
o_lat: *const f32,
wv_b: *const f32,
out: *mut f32,
t_q: i32,
n_head: i32,
d_v: i32,
kv_rank: i32,
split: i32,
stream: *mut c_void,
) -> i32;
pub fn memra_mla_attn_absorbed_f32(
q_lat: *const f32,
q_pe: *const f32,
cache: *const f32,
o_lat: *mut f32,
n_head: i32,
kv_rank: i32,
d_rope: i32,
t_q: i32,
t_kv: i32,
scale: f32,
stream: *mut c_void,
) -> i32;
pub fn memra_mla_index_append_ring_f32(
plane: *mut f32,
a: *const f32,
b: *const f32,
slot: i32,
t: i32,
wa: i32,
wb: i32,
rows: i32,
stream: *mut c_void,
) -> i32;
pub fn memra_mla_kpool_pool_keys_f32(
state: *const f32,
ape: *const f32,
pool_keys: *mut f32,
pool_begin: i32,
n_pools: i32,
pool: i32,
d: i32,
state_rows: i32,
stream: *mut c_void,
) -> i32;
pub fn memra_mla_kpool_score_f32(
q: *const f32,
pool_keys: *const f32,
hw: *const f32,
score: *mut f32,
t_q: i32,
heads: i32,
d: i32,
n_pools: i32,
pool: i32,
first_pos: i32,
qk_scale: f32,
head_scale: f32,
stream: *mut c_void,
) -> i32;
pub fn memra_mla_kpool_score_ref_f32(
q: *const f32,
pool_keys: *const f32,
hw: *const f32,
score: *mut f32,
t_q: i32,
heads: i32,
d: i32,
n_pools: i32,
pool: i32,
first_pos: i32,
qk_scale: f32,
head_scale: f32,
stream: *mut c_void,
) -> i32;
pub fn memra_mla_kpool_select_ws_ints(n_ctas: i32) -> i64;
pub fn memra_mla_kpool_select_ctas(n_pools: i32) -> i32;
#[allow(clippy::too_many_arguments)]
pub fn memra_mla_kpool_select_dsa_f32(
score: *const f32,
idx: *mut i32,
ws: *mut i32,
t_q: i32,
n_pools: i32,
pool: i32,
select_k: i32,
width: i32,
first_pos: i32,
always_tail: i32,
stream: *mut c_void,
) -> i32;
#[allow(clippy::too_many_arguments)]
pub fn memra_mla_kpool_select_dsa_redarm_f32(
score: *const f32,
idx: *mut i32,
ws: *mut i32,
t_q: i32,
n_pools: i32,
pool: i32,
select_k: i32,
width: i32,
first_pos: i32,
always_tail: i32,
bump: i32,
stream: *mut c_void,
) -> i32;
pub fn memra_mla_kpool_select_f32(
score: *const f32,
idx: *mut i32,
t_q: i32,
n_pools: i32,
pool: i32,
select_k: i32,
width: i32,
first_pos: i32,
always_tail: i32,
stream: *mut c_void,
) -> i32;
pub fn memra_mla_kpool_select_ref_f32(
score: *const f32,
idx: *mut i32,
t_q: i32,
n_pools: i32,
pool: i32,
select_k: i32,
width: i32,
first_pos: i32,
always_tail: i32,
stream: *mut c_void,
) -> i32;
pub fn memra_mla_attn_gathered_f32(
q_lat: *const f32,
q_pe: *const f32,
cache: *const f32,
idx: *const i32,
o_lat: *mut f32,
n_head: i32,
kv_rank: i32,
d_rope: i32,
t_q: i32,
n_slots: i32,
scale: f32,
stream: *mut c_void,
) -> i32;
#[allow(clippy::too_many_arguments)]
pub fn memra_mla_attn_gathered_dsa_f32(
q_lat: *const f32,
q_pe: *const f32,
cache: *const f32,
idx: *const i32,
o_lat: *mut f32,
n_head: i32,
kv_rank: i32,
d_rope: i32,
t_q: i32,
n_slots: i32,
scale: f32,
stream: *mut c_void,
) -> i32;
pub fn memra_mla_dsa_attn_chunk_span(n_slots: i32, chunks: i32) -> i32;
pub fn memra_mla_dsa_attn_split_f32(
q_lat: *const f32,
q_pe: *const f32,
cache: *const f32,
idx: *const i32,
o_lat: *mut f32,
part_m: *mut f32,
part_d: *mut f32,
part_acc: *mut f32,
n_head: i32,
kv_rank: i32,
d_rope: i32,
t_q: i32,
n_slots: i32,
chunks: i32,
scale: f32,
stream: *mut c_void,
) -> i32;
pub fn memra_mla_kpool_score_dsa_f32(
q: *const f32,
pool_keys: *const f32,
hw: *const f32,
score: *mut f32,
t_q: i32,
heads: i32,
d: i32,
n_pools: i32,
pool: i32,
first_pos: i32,
qk_scale: f32,
head_scale: f32,
stream: *mut c_void,
) -> i32;
pub fn memra_mla_attn_gathered_split_f32(
q_lat: *const f32,
q_pe: *const f32,
cache: *const f32,
idx: *const i32,
o_lat: *mut f32,
n_head: i32,
kv_rank: i32,
d_rope: i32,
t_q: i32,
n_slots: i32,
scale: f32,
split: i32,
stream: *mut c_void,
) -> i32;
fn memra_bf16_gemm_sb(
w_bf16: *const c_void,
x_bf16: *const c_void,
y: *mut c_void,
m: i32,
n: i32,
k: i32,
x_rs: i64,
x_bs: i64,
y_rs: i64,
y_bs: i64,
batch: i32,
y_is_bf16: i32,
ws: *mut c_void,
ws_bytes: usize,
stream: *mut c_void,
) -> i32;
}
type Res<T> = Result<T, Box<dyn std::error::Error>>;
fn ck(what: &str, rc: i32) -> Res<()> {
if rc == 0 {
return Ok(());
}
let detail = match rc {
40001 => " (d_rope must be even — interleaved rope rotates (2j, 2j+1) pairs)",
40002 => " (kv_rank exceeds the kernel's MLA_MAX_RANK shared-memory ceiling)",
40003 => " (d_rope exceeds the kernel's MLA_MAX_ROPE ceiling)",
40004 => " (t_q > t_kv — queries must be a suffix of the latent cache)",
40010 => " (k-pool size out of range — 1..=MLA_MAX_POOL)",
40011 => " (indexer head count out of range — 1..=1024, one thread per head)",
40012 => " (t_q * n_pools exceeds the grid.x contract)",
40017 => " (indexer head dim must be positive)",
40013 => {
" (always_select_tail=false: queries before the first complete pool would have an \
empty candidate set, which the memra-reference oracle refuses outright)"
}
40014 => " (index-list width is narrower than select_k * pool + pool - 1)",
40015 => " (empty gathered candidate list — a zero softmax denominator)",
40020 => " (latent row width is not a multiple of 4 — the DSA float4 staging needs it)",
40021 => " (DSA tile staging exceeds MLA_DSA_KV_SMEM_MAX)",
40022 => " (DSA slot-chunk count out of range — 1..=64)",
40023 => " (no DSA scorer instantiation for this (heads, d))",
r if (10000..20000).contains(&r) => " (cudaError)",
_ => "",
};
Err(format!("mla kernel `{what}` failed: rc {rc}{detail}").into())
}
impl Engine {
pub fn mla_rope_interleaved(
&self,
x: &mut CudaSlice<f32>,
pos_d: &CudaSlice<i32>,
n_pos: usize,
n_vec: usize,
d_rope: usize,
base: f32,
) -> Res<()> {
if d_rope == 0 {
return Ok(());
}
let s = self.stream();
unsafe {
ck(
"rope_interleaved",
memra_mla_rope_interleaved_f32(
x.device_ptr_mut(&s).0 as *mut f32,
n_pos as i32,
n_vec as i32,
d_rope as i32,
pos_d.device_ptr(&s).0 as *const i32,
base,
s.cu_stream() as *mut c_void,
),
)
}
}
pub fn mla_split_latent(
&self,
kv: &CudaSlice<f32>,
c_kv: &mut CudaSlice<f32>,
k_pe: &mut CudaSlice<f32>,
t: usize,
kv_rank: usize,
d_rope: usize,
) -> Res<()> {
let s = self.stream();
unsafe {
ck(
"split_latent",
memra_mla_split_latent_f32(
kv.device_ptr(&s).0 as *const f32,
c_kv.device_ptr_mut(&s).0 as *mut f32,
k_pe.device_ptr_mut(&s).0 as *mut f32,
t as i32,
kv_rank as i32,
d_rope as i32,
s.cu_stream() as *mut c_void,
),
)
}
}
#[allow(clippy::too_many_arguments)] pub fn mla_append_latent(
&self,
cache: &mut CudaSlice<f32>,
c_kv: &CudaSlice<f32>,
k_pe: &CudaSlice<f32>,
slot: usize,
t: usize,
kv_rank: usize,
d_rope: usize,
) -> Res<()> {
let s = self.stream();
unsafe {
ck(
"append_latent",
memra_mla_append_latent_f32(
cache.device_ptr_mut(&s).0 as *mut f32,
c_kv.device_ptr(&s).0 as *const f32,
k_pe.device_ptr(&s).0 as *const f32,
slot as i32,
t as i32,
kv_rank as i32,
d_rope as i32,
s.cu_stream() as *mut c_void,
),
)
}
}
#[allow(clippy::too_many_arguments)]
#[allow(clippy::too_many_arguments)]
pub fn mla_absorb_q_raw_arm(
&self,
q_nope: &CudaSlice<f32>,
wk_b: &CudaSlice<f32>,
q_lat: &mut CudaSlice<f32>,
t_q: usize,
n_head: usize,
d_nope: usize,
kv_rank: usize,
arm: u8,
split: i32,
) -> Res<()> {
let s = self.stream();
unsafe {
let (q, w, o) = (
q_nope.device_ptr(&s).0 as *const f32,
wk_b.device_ptr(&s).0 as *const f32,
q_lat.device_ptr_mut(&s).0 as *mut f32,
);
let (t, h, dn, kr) = (t_q as i32, n_head as i32, d_nope as i32, kv_rank as i32);
let st = s.cu_stream() as *mut c_void;
match arm {
0 => ck(
"absorb_q_raw",
memra_mla_absorb_q_f32(q, w, o, t, h, dn, kr, st),
),
1 => ck(
"absorb_q_split_raw",
memra_mla_absorb_q_split_f32(q, w, o, t, h, dn, kr, split, st),
),
_ => ck(
"absorb_q_wp_raw",
memra_mla_absorb_q_wp_f32(q, w, o, t, h, dn, kr, split, st),
),
}
}
}
#[allow(clippy::too_many_arguments)]
pub fn mla_decompress_v_raw_arm(
&self,
o_lat: &CudaSlice<f32>,
wv_b: &CudaSlice<f32>,
out: &mut CudaSlice<f32>,
t_q: usize,
n_head: usize,
d_v: usize,
kv_rank: usize,
arm: u8,
split: i32,
) -> Res<()> {
let s = self.stream();
unsafe {
let (a, w, o) = (
o_lat.device_ptr(&s).0 as *const f32,
wv_b.device_ptr(&s).0 as *const f32,
out.device_ptr_mut(&s).0 as *mut f32,
);
let (t, h, dv, kr) = (t_q as i32, n_head as i32, d_v as i32, kv_rank as i32);
let st = s.cu_stream() as *mut c_void;
match arm {
0 => ck(
"decompress_v_raw",
memra_mla_decompress_v_f32(a, w, o, t, h, dv, kr, st),
),
1 => ck(
"decompress_v_split_raw",
memra_mla_decompress_v_split_f32(a, w, o, t, h, dv, kr, split, st),
),
_ => ck(
"decompress_v_wp_raw",
memra_mla_decompress_v_wp_f32(a, w, o, t, h, dv, kr, split, st),
),
}
}
}
#[allow(clippy::too_many_arguments)]
pub fn hc_pre_raw_arm(
&self,
x: &CudaSlice<f32>,
mixes: &CudaSlice<f32>,
scale: &CudaSlice<f32>,
base: &CudaSlice<f32>,
pre: &mut CudaSlice<f32>,
post: &mut CudaSlice<f32>,
comb: &mut CudaSlice<f32>,
y: &mut CudaSlice<f32>,
s_rows: usize,
hc: usize,
d: usize,
iters: usize,
eps: f32,
arm: u8,
block: i32,
niters: Option<&mut CudaSlice<i32>>,
) -> Res<()> {
let st = self.stream();
unsafe {
let np: *mut i32 = match niters {
Some(n) => n.device_ptr_mut(&st).0 as *mut i32,
None => std::ptr::null_mut(),
};
let (xp, mp, sp, bp) = (
x.device_ptr(&st).0 as *const f32,
mixes.device_ptr(&st).0 as *const f32,
scale.device_ptr(&st).0 as *const f32,
base.device_ptr(&st).0 as *const f32,
);
let (pp, qp, cp, yp) = (
pre.device_ptr_mut(&st).0 as *mut f32,
post.device_ptr_mut(&st).0 as *mut f32,
comb.device_ptr_mut(&st).0 as *mut f32,
y.device_ptr_mut(&st).0 as *mut f32,
);
let (sr, h, dd, it) = (s_rows as i32, hc as i32, d as i32, iters as i32);
let cs = st.cu_stream() as *mut c_void;
let rc = match arm {
0 => crate::dsv4_ffi::memra_dsv4_hc_pre_fused_v2(
xp, mp, sp, bp, pp, qp, cp, yp, sr, h, dd, it, eps, np, cs,
),
1 => crate::dsv4_ffi::memra_dsv4_hc_pre_fused_v3(
xp, mp, sp, bp, pp, qp, cp, yp, sr, h, dd, it, eps, np, block, 0, 0, cs,
),
_ => crate::dsv4_ffi::memra_dsv4_hc_pre_fused_v3(
xp, mp, sp, bp, pp, qp, cp, yp, sr, h, dd, it, eps, np, block, 1, 0, cs,
),
};
ck("hc_pre_raw", rc)
}
}
#[allow(clippy::too_many_arguments)]
pub fn mla_absorb_q(
&self,
q_nope: &CudaSlice<f32>,
wk_b: &CudaSlice<f32>,
q_lat: &mut CudaSlice<f32>,
t_q: usize,
n_head: usize,
d_nope: usize,
kv_rank: usize,
) -> Res<()> {
let s = self.stream();
let coalesce_split = if mla_coalesce_on() {
mla_b200_split_for(MlaB200Kernel::AbsorbQ, t_q, kv_rank)
.or_else(|| mla_decode_split_for(t_q * n_head, kv_rank))
.unwrap_or(1)
} else {
1
};
if coalesce_split > 1 {
let split = coalesce_split;
mla_coalesce_announce("absorb_q", t_q, n_head, split);
return unsafe {
ck(
"absorb_q_wp",
memra_mla_absorb_q_wp_f32(
q_nope.device_ptr(&s).0 as *const f32,
wk_b.device_ptr(&s).0 as *const f32,
q_lat.device_ptr_mut(&s).0 as *mut f32,
t_q as i32,
n_head as i32,
d_nope as i32,
kv_rank as i32,
split,
s.cu_stream() as *mut c_void,
),
)
};
}
if let Some(split) = mla_b200_split_for(MlaB200Kernel::AbsorbQ, t_q, kv_rank) {
mla_b200_split_announce("absorb_q", t_q, n_head, split);
return unsafe {
ck(
"absorb_q_split_b200",
memra_mla_absorb_q_split_f32(
q_nope.device_ptr(&s).0 as *const f32,
wk_b.device_ptr(&s).0 as *const f32,
q_lat.device_ptr_mut(&s).0 as *mut f32,
t_q as i32,
n_head as i32,
d_nope as i32,
kv_rank as i32,
split,
s.cu_stream() as *mut c_void,
),
)
};
}
if let Some(split) = mla_decode_split_for(t_q * n_head, kv_rank) {
mla_split_announce("absorb_q", t_q, n_head, split);
return unsafe {
ck(
"absorb_q_split",
memra_mla_absorb_q_split_f32(
q_nope.device_ptr(&s).0 as *const f32,
wk_b.device_ptr(&s).0 as *const f32,
q_lat.device_ptr_mut(&s).0 as *mut f32,
t_q as i32,
n_head as i32,
d_nope as i32,
kv_rank as i32,
split,
s.cu_stream() as *mut c_void,
),
)
};
}
unsafe {
ck(
"absorb_q",
memra_mla_absorb_q_f32(
q_nope.device_ptr(&s).0 as *const f32,
wk_b.device_ptr(&s).0 as *const f32,
q_lat.device_ptr_mut(&s).0 as *mut f32,
t_q as i32,
n_head as i32,
d_nope as i32,
kv_rank as i32,
s.cu_stream() as *mut c_void,
),
)
}
}
#[allow(clippy::too_many_arguments)] pub fn mla_decompress_v(
&self,
o_lat: &CudaSlice<f32>,
wv_b: &CudaSlice<f32>,
out: &mut CudaSlice<f32>,
t_q: usize,
n_head: usize,
d_v: usize,
kv_rank: usize,
) -> Res<()> {
let s = self.stream();
let coalesce_split = if mla_coalesce_on() {
mla_b200_split_for(MlaB200Kernel::DecompressV, t_q, d_v)
.or_else(|| mla_decode_split_for(t_q * n_head, d_v))
.unwrap_or(1)
} else {
1
};
if coalesce_split > 1 {
let split = coalesce_split;
mla_coalesce_announce("decompress_v", t_q, n_head, split);
return unsafe {
ck(
"decompress_v_wp",
memra_mla_decompress_v_wp_f32(
o_lat.device_ptr(&s).0 as *const f32,
wv_b.device_ptr(&s).0 as *const f32,
out.device_ptr_mut(&s).0 as *mut f32,
t_q as i32,
n_head as i32,
d_v as i32,
kv_rank as i32,
split,
s.cu_stream() as *mut c_void,
),
)
};
}
if let Some(split) = mla_b200_split_for(MlaB200Kernel::DecompressV, t_q, d_v) {
mla_b200_split_announce("decompress_v", t_q, n_head, split);
return unsafe {
ck(
"decompress_v_split_b200",
memra_mla_decompress_v_split_f32(
o_lat.device_ptr(&s).0 as *const f32,
wv_b.device_ptr(&s).0 as *const f32,
out.device_ptr_mut(&s).0 as *mut f32,
t_q as i32,
n_head as i32,
d_v as i32,
kv_rank as i32,
split,
s.cu_stream() as *mut c_void,
),
)
};
}
if let Some(split) = mla_decode_split_for(t_q * n_head, d_v) {
mla_split_announce("decompress_v", t_q, n_head, split);
return unsafe {
ck(
"decompress_v_split",
memra_mla_decompress_v_split_f32(
o_lat.device_ptr(&s).0 as *const f32,
wv_b.device_ptr(&s).0 as *const f32,
out.device_ptr_mut(&s).0 as *mut f32,
t_q as i32,
n_head as i32,
d_v as i32,
kv_rank as i32,
split,
s.cu_stream() as *mut c_void,
),
)
};
}
unsafe {
ck(
"decompress_v",
memra_mla_decompress_v_f32(
o_lat.device_ptr(&s).0 as *const f32,
wv_b.device_ptr(&s).0 as *const f32,
out.device_ptr_mut(&s).0 as *mut f32,
t_q as i32,
n_head as i32,
d_v as i32,
kv_rank as i32,
s.cu_stream() as *mut c_void,
),
)
}
}
#[allow(clippy::too_many_arguments)] pub fn mla_attn_absorbed(
&self,
q_lat: &CudaSlice<f32>,
q_pe: &CudaSlice<f32>,
cache: &CudaSlice<f32>,
o_lat: &mut CudaSlice<f32>,
n_head: usize,
kv_rank: usize,
d_rope: usize,
t_q: usize,
t_kv: usize,
scale: f32,
) -> Res<()> {
let s = self.stream();
unsafe {
ck(
"attn_absorbed",
memra_mla_attn_absorbed_f32(
q_lat.device_ptr(&s).0 as *const f32,
q_pe.device_ptr(&s).0 as *const f32,
cache.device_ptr(&s).0 as *const f32,
o_lat.device_ptr_mut(&s).0 as *mut f32,
n_head as i32,
kv_rank as i32,
d_rope as i32,
t_q as i32,
t_kv as i32,
scale,
s.cu_stream() as *mut c_void,
),
)
}
}
}
impl Engine {
#[allow(clippy::too_many_arguments)]
pub fn mla_kpool_pool_keys(
&self,
state: &CudaSlice<f32>,
ape: &CudaSlice<f32>,
pool_keys: &mut CudaSlice<f32>,
pool_begin: usize,
n_pools: usize,
pool: usize,
d: usize,
state_rows: usize,
) -> Res<()> {
let s = self.stream();
unsafe {
ck(
"kpool_pool_keys",
memra_mla_kpool_pool_keys_f32(
state.device_ptr(&s).0 as *const f32,
ape.device_ptr(&s).0 as *const f32,
pool_keys.device_ptr_mut(&s).0 as *mut f32,
pool_begin as i32,
n_pools as i32,
pool as i32,
d as i32,
state_rows as i32,
s.cu_stream() as *mut c_void,
),
)
}
}
#[allow(clippy::too_many_arguments)]
pub fn mla_index_append(
&self,
plane: &mut CudaSlice<f32>,
a: &CudaSlice<f32>,
b: &CudaSlice<f32>,
src_row: usize,
slot: usize,
t: usize,
wa: usize,
wb: usize,
rows: usize,
) -> Res<()> {
let s = self.stream();
unsafe {
ck(
"index_append_ring",
memra_mla_index_append_ring_f32(
plane.device_ptr_mut(&s).0 as *mut f32,
(a.device_ptr(&s).0 as *const f32).add(src_row * wa),
(b.device_ptr(&s).0 as *const f32).add(src_row * wb),
slot as i32,
t as i32,
wa as i32,
wb as i32,
rows as i32,
s.cu_stream() as *mut c_void,
),
)
}
}
#[allow(clippy::too_many_arguments)]
pub fn mla_kpool_score(
&self,
q: &CudaSlice<f32>,
pool_keys: &CudaSlice<f32>,
head_weights: &CudaSlice<f32>,
score: &mut CudaSlice<f32>,
t_q: usize,
heads: usize,
d: usize,
n_pools: usize,
pool: usize,
first_pos: usize,
qk_scale: f32,
head_scale: f32,
) -> Res<()> {
let s = self.stream();
if mla_dsa_decode_level() >= 1
&& (1..=MLA_DSA_ARM_T_MAX).contains(&t_q)
&& n_pools >= MLA_DSA_SCORE_MIN_POOLS
{
let rc = unsafe {
memra_mla_kpool_score_dsa_f32(
q.device_ptr(&s).0 as *const f32,
pool_keys.device_ptr(&s).0 as *const f32,
head_weights.device_ptr(&s).0 as *const f32,
score.device_ptr_mut(&s).0 as *mut f32,
t_q as i32,
heads as i32,
d as i32,
n_pools as i32,
pool as i32,
first_pos as i32,
qk_scale,
head_scale,
s.cu_stream() as *mut c_void,
)
};
if !mla_dsa_geometry_refusal(rc) {
mla_dsa_announce(
"kpool_score",
t_q,
&format!("arm=head-blocked heads={heads} pools={n_pools} class=bit-identical"),
);
return ck("kpool_score_dsa", rc);
}
}
unsafe {
ck(
"kpool_score",
memra_mla_kpool_score_f32(
q.device_ptr(&s).0 as *const f32,
pool_keys.device_ptr(&s).0 as *const f32,
head_weights.device_ptr(&s).0 as *const f32,
score.device_ptr_mut(&s).0 as *mut f32,
t_q as i32,
heads as i32,
d as i32,
n_pools as i32,
pool as i32,
first_pos as i32,
qk_scale,
head_scale,
s.cu_stream() as *mut c_void,
),
)
}
}
#[allow(clippy::too_many_arguments)]
pub fn mla_kpool_score_ref(
&self,
q: &CudaSlice<f32>,
pool_keys: &CudaSlice<f32>,
head_weights: &CudaSlice<f32>,
score: &mut CudaSlice<f32>,
t_q: usize,
heads: usize,
d: usize,
n_pools: usize,
pool: usize,
first_pos: usize,
qk_scale: f32,
head_scale: f32,
) -> Res<()> {
let s = self.stream();
unsafe {
ck(
"kpool_score_ref",
memra_mla_kpool_score_ref_f32(
q.device_ptr(&s).0 as *const f32,
pool_keys.device_ptr(&s).0 as *const f32,
head_weights.device_ptr(&s).0 as *const f32,
score.device_ptr_mut(&s).0 as *mut f32,
t_q as i32,
heads as i32,
d as i32,
n_pools as i32,
pool as i32,
first_pos as i32,
qk_scale,
head_scale,
s.cu_stream() as *mut c_void,
),
)
}
}
#[allow(clippy::too_many_arguments)]
pub fn mla_kpool_select(
&self,
score: &CudaSlice<f32>,
idx: &mut CudaSlice<i32>,
t_q: usize,
n_pools: usize,
pool: usize,
select_k: usize,
width: usize,
first_pos: usize,
always_tail: bool,
) -> Res<()> {
let s = self.stream();
if mla_dsa_select_on() && mla_dsa_select_engages(t_q, n_pools) {
let n_ctas = unsafe { memra_mla_kpool_select_ctas(n_pools as i32) };
let stride = unsafe { memra_mla_kpool_select_ws_ints(n_ctas) };
let mut ws = self.uninit_i32(t_q * stride as usize)?;
mla_dsa_select_announce(t_q, n_pools, n_ctas);
return unsafe {
ck(
"kpool_select_dsa",
memra_mla_kpool_select_dsa_f32(
score.device_ptr(&s).0 as *const f32,
idx.device_ptr_mut(&s).0 as *mut i32,
ws.device_ptr_mut(&s).0 as *mut i32,
t_q as i32,
n_pools as i32,
pool as i32,
select_k as i32,
width as i32,
first_pos as i32,
i32::from(always_tail),
s.cu_stream() as *mut c_void,
),
)
};
}
unsafe {
ck(
"kpool_select",
memra_mla_kpool_select_f32(
score.device_ptr(&s).0 as *const f32,
idx.device_ptr_mut(&s).0 as *mut i32,
t_q as i32,
n_pools as i32,
pool as i32,
select_k as i32,
width as i32,
first_pos as i32,
i32::from(always_tail),
s.cu_stream() as *mut c_void,
),
)
}
}
#[allow(clippy::too_many_arguments)]
pub fn mla_kpool_select_ref(
&self,
score: &CudaSlice<f32>,
idx: &mut CudaSlice<i32>,
t_q: usize,
n_pools: usize,
pool: usize,
select_k: usize,
width: usize,
first_pos: usize,
always_tail: bool,
) -> Res<()> {
let s = self.stream();
unsafe {
ck(
"kpool_select_ref",
memra_mla_kpool_select_ref_f32(
score.device_ptr(&s).0 as *const f32,
idx.device_ptr_mut(&s).0 as *mut i32,
t_q as i32,
n_pools as i32,
pool as i32,
select_k as i32,
width as i32,
first_pos as i32,
i32::from(always_tail),
s.cu_stream() as *mut c_void,
),
)
}
}
#[allow(clippy::too_many_arguments)]
pub fn mla_bf16_gemm_sb_raw(
&self,
w_bf16: &CudaSlice<u8>,
x_bf16: &CudaSlice<u8>,
y_ptr: u64,
m: usize,
n: usize,
k: usize,
x_rs: usize,
x_bs: usize,
y_rs: usize,
y_bs: usize,
batch: usize,
y_bf16: bool,
) -> Res<i32> {
let mut guard = self.f16_scratch.lock().unwrap();
if guard.is_none() {
*guard = Some(crate::f16_ffi::F16Scratch::with_capacity(self, 2)?);
}
let s_scr = guard.as_mut().unwrap();
let s = self.stream();
let rc = unsafe {
memra_bf16_gemm_sb(
w_bf16.device_ptr(&s).0 as *const c_void,
x_bf16.device_ptr(&s).0 as *const c_void,
y_ptr as *mut c_void,
m as i32,
n as i32,
k as i32,
x_rs as i64,
x_bs as i64,
y_rs as i64,
y_bs as i64,
batch as i32,
i32::from(y_bf16),
s_scr.ws.device_ptr_mut(&s).0 as *mut c_void,
crate::f16_ffi::F16_WS_BYTES,
s.cu_stream() as *mut c_void,
)
};
Ok(rc)
}
#[allow(clippy::too_many_arguments)]
pub fn mla_bf16_gemm_sb_bf16out(
&self,
w_bf16: &CudaSlice<u8>,
x_bf16: &CudaSlice<u8>,
y_bf16: &mut CudaSlice<u8>,
m: usize,
n: usize,
k: usize,
x_rs: usize,
x_bs: usize,
y_rs: usize,
y_bs: usize,
batch: usize,
) -> Res<bool> {
let s = self.stream();
let (y_ptr, _gy) = y_bf16.device_ptr_mut(&s);
let rc = self.mla_bf16_gemm_sb_raw(
w_bf16, x_bf16, y_ptr, m, n, k, x_rs, x_bs, y_rs, y_bs, batch, true,
)?;
match rc {
0 => Ok(true),
r if (20000..30000).contains(&r) => Ok(false),
r => Err(format!(
"mla bf16 strided-batched GEMM (bf16 out) failed: rc {r} \
(m={m} n={n} k={k} batch={batch})"
)
.into()),
}
}
#[allow(clippy::too_many_arguments)]
pub fn mla_bf16_gemm_sb_f32out(
&self,
w_bf16: &CudaSlice<u8>,
x_bf16: &CudaSlice<u8>,
y_f32: &mut CudaSlice<f32>,
m: usize,
n: usize,
k: usize,
x_rs: usize,
x_bs: usize,
y_rs: usize,
y_bs: usize,
batch: usize,
) -> Res<bool> {
let s = self.stream();
let (y_ptr, _gy) = y_f32.device_ptr_mut(&s);
let rc = self.mla_bf16_gemm_sb_raw(
w_bf16, x_bf16, y_ptr, m, n, k, x_rs, x_bs, y_rs, y_bs, batch, false,
)?;
match rc {
0 => Ok(true),
r if (20000..30000).contains(&r) => Ok(false),
r => Err(format!(
"mla bf16 strided-batched GEMM (f32 out) failed: rc {r} \
(m={m} n={n} k={k} batch={batch})"
)
.into()),
}
}
#[allow(clippy::too_many_arguments)]
pub fn mla_attn_gathered(
&self,
q_lat: &CudaSlice<f32>,
q_pe: &CudaSlice<f32>,
cache: &CudaSlice<f32>,
idx: &CudaSlice<i32>,
o_lat: &mut CudaSlice<f32>,
n_head: usize,
kv_rank: usize,
d_rope: usize,
t_q: usize,
n_slots: usize,
scale: f32,
) -> Res<()> {
let s = self.stream();
let dsa_level = mla_dsa_decode_level();
let dsa_arm = if dsa_level >= 1 && t_q <= MLA_DSA_ARM_T_MAX {
let a = mla_dsa_attn_arm_effective(t_q);
if a >= 2 && dsa_level < 2 { 0 } else { a }
} else {
0
};
if dsa_arm >= 2 {
let cells = t_q * n_head * dsa_arm as usize;
let mut part_m = self.uninit(cells)?;
let mut part_d = self.uninit(cells)?;
let mut part_acc = self.uninit(cells * kv_rank)?;
let rc = unsafe {
memra_mla_dsa_attn_split_f32(
q_lat.device_ptr(&s).0 as *const f32,
q_pe.device_ptr(&s).0 as *const f32,
cache.device_ptr(&s).0 as *const f32,
idx.device_ptr(&s).0 as *const i32,
o_lat.device_ptr_mut(&s).0 as *mut f32,
part_m.device_ptr_mut(&s).0 as *mut f32,
part_d.device_ptr_mut(&s).0 as *mut f32,
part_acc.device_ptr_mut(&s).0 as *mut f32,
n_head as i32,
kv_rank as i32,
d_rope as i32,
t_q as i32,
n_slots as i32,
dsa_arm,
scale,
s.cu_stream() as *mut c_void,
)
};
if !mla_dsa_geometry_refusal(rc) {
mla_dsa_announce(
"attn_gathered",
t_q,
&format!("arm=warp-online chunks={dsa_arm} class=dsa-warp-online-f32"),
);
return ck("attn_gathered_dsa_warp", rc);
}
} else if dsa_arm == 1 {
let rc = unsafe {
memra_mla_attn_gathered_dsa_f32(
q_lat.device_ptr(&s).0 as *const f32,
q_pe.device_ptr(&s).0 as *const f32,
cache.device_ptr(&s).0 as *const f32,
idx.device_ptr(&s).0 as *const i32,
o_lat.device_ptr_mut(&s).0 as *mut f32,
n_head as i32,
kv_rank as i32,
d_rope as i32,
t_q as i32,
n_slots as i32,
scale,
s.cu_stream() as *mut c_void,
)
};
if !mla_dsa_geometry_refusal(rc) {
mla_dsa_announce("attn_gathered", t_q, "arm=single-pass class=bit-identical");
return ck("attn_gathered_dsa", rc);
}
}
if let Some(split) = mla_b200_split_for(MlaB200Kernel::AttnGathered, t_q, kv_rank) {
mla_b200_split_announce("attn_gathered", t_q, n_head, split);
return unsafe {
ck(
"attn_gathered_split_b200",
memra_mla_attn_gathered_split_f32(
q_lat.device_ptr(&s).0 as *const f32,
q_pe.device_ptr(&s).0 as *const f32,
cache.device_ptr(&s).0 as *const f32,
idx.device_ptr(&s).0 as *const i32,
o_lat.device_ptr_mut(&s).0 as *mut f32,
n_head as i32,
kv_rank as i32,
d_rope as i32,
t_q as i32,
n_slots as i32,
scale,
split,
s.cu_stream() as *mut c_void,
),
)
};
}
unsafe {
ck(
"attn_gathered",
memra_mla_attn_gathered_f32(
q_lat.device_ptr(&s).0 as *const f32,
q_pe.device_ptr(&s).0 as *const f32,
cache.device_ptr(&s).0 as *const f32,
idx.device_ptr(&s).0 as *const i32,
o_lat.device_ptr_mut(&s).0 as *mut f32,
n_head as i32,
kv_rank as i32,
d_rope as i32,
t_q as i32,
n_slots as i32,
scale,
s.cu_stream() as *mut c_void,
),
)
}
}
}
#[cfg(test)]
mod dsa_select_default_tests {
use super::{mla_dsa_select_engages, mla_dsa_select_on_from};
#[test]
fn default_on_only_zero_disarms_and_the_floors_still_gate() {
assert!(mla_dsa_select_on_from(None));
assert!(mla_dsa_select_on_from(Some("1")));
assert!(!mla_dsa_select_on_from(Some("0")));
assert!(!mla_dsa_select_on_from(Some(" 0 ")));
assert!(!mla_dsa_select_engages(1, 65_535));
assert!(mla_dsa_select_engages(1, 65_536));
assert!(!mla_dsa_select_engages(2, 65_536));
assert!(mla_dsa_select_engages(2, 262_144));
assert!(!mla_dsa_select_engages(9, 1_000_000));
}
}