spark_model/layers/qwen3_attention/types.rs
1// SPDX-License-Identifier: AGPL-3.0-only
2
3//! Qwen3 attention struct definitions: `MlaWeights` (latent attention
4//! 2-step decode) and `Qwen3AttentionLayer` (full attention layer).
5
6use spark_runtime::gpu::{DevicePtr, KernelHandle};
7use spark_runtime::kv_cache::KvCacheDtype;
8
9use crate::layers::FfnComponent;
10use crate::layers::fp8_calibration::Fp8KvCalibration;
11use crate::layers::w4a16_gemv_tiers::W4a16BatchmTiers;
12use crate::weight_map::{AttentionWeights, DenseWeight, QuantWeight, QuantizedWeight};
13
14pub use super::types_weights::{HcWeights, MlaWeights};
15
16#[derive(Clone, Copy, Debug, Eq, PartialEq)]
17pub(crate) enum HeadGateActivation {
18 Sigmoid,
19 Softplus,
20}
21
22/// Qwen3-Next full attention layer (12 of 48 layers).
23#[allow(dead_code)]
24pub struct Qwen3AttentionLayer {
25 pub(super) input_norm: DenseWeight,
26 pub(crate) attn: AttentionWeights,
27 pub(super) post_attn_norm: DenseWeight,
28 pub(super) ffn: FfnComponent,
29 pub(super) attn_layer_idx: usize,
30 /// Startup-static LoRA adapter overlay for the K/V/O projections (v0;
31 /// q_proj excluded — gated Q+gate interleave). Installed
32 /// post-construction via `set_lora_weights`; `None` = base-only.
33 /// M0: stored only — the compute-path reads land in M1.
34 pub(super) lora: Option<crate::layers::ops::lora_delta::LoraAttnWeights>,
35 /// Whether Q projection includes an output gate (Q+Gate interleaved).
36 /// When true, q_proj output is 2× q_dim; attn output is gated by sigmoid.
37 /// When false (e.g. Qwen3-VL), q_proj output is q_dim; no gating applied.
38 pub(super) gated: bool,
39 /// Whether this layer should apply MRoPE-interleaved instead of scalar
40 /// RoPE. Set when `config.mrope_interleaved = true` (Qwen3.6).
41 pub(crate) mrope_interleaved: bool,
42 /// Per-layer dimension overrides for heterogeneous models (Gemma-4).
43 pub(crate) head_dim_override: Option<usize>,
44 pub(crate) num_q_heads_override: Option<usize>,
45 pub(crate) num_kv_heads_override: Option<usize>,
46 /// Per-layer sliding-window size for Gemma-4 hybrid attention.
47 pub(crate) sliding_window: Option<u32>,
48 /// Per-layer RoPE overrides for heterogeneous models (Gemma-4).
49 pub(crate) rope_theta_override: Option<f32>,
50 pub(crate) rotary_dim_override: Option<u32>,
51 /// Proportional RoPE (Gemma-4 full-attention).
52 pub(crate) rope_proportional: bool,
53 /// Per-layer attention scale override (Gemma-4: 1.0 because QK-norm
54 /// handles scaling). When None, uses the standard 1/sqrt(head_dim).
55 pub(crate) attn_scale_override: Option<f32>,
56 /// K=V mode: V comes from raw K projection output (no separate v_proj).
57 pub(crate) k_eq_v: bool,
58 /// Ones-filled BF16 weight buffer for the pure-RMSNorm v_norm path.
59 pub(crate) v_norm_weight: Option<DenseWeight>,
60 /// Per-head attention gate weight (Step 3.7 g_proj).
61 /// Shape: [num_q_heads, hidden_size] BF16. Applied as:
62 /// attn_out = attn_out * sigmoid(g_proj @ hidden_states)
63 /// with broadcast over head_dim.
64 pub(crate) head_gate_weight: Option<DenseWeight>,
65 pub(crate) head_gate_activation: HeadGateActivation,
66 /// Kernel handle for per-head sigmoid gate broadcast multiply.
67 pub(super) sigmoid_gate_head_broadcast_k: KernelHandle,
68 pub(super) softplus_gate_head_broadcast_k: KernelHandle,
69 /// Optional YaRN frequencies for standard (non-MLA) attention.
70 pub(crate) yarn_inv_freq: DevicePtr,
71 pub(crate) yarn_attention_factor: f32,
72 /// Post-attention output norm (Gemma-4).
73 pub(crate) post_attn_out_norm: Option<DenseWeight>,
74 /// Post-FFN output norm (Gemma-4).
75 pub(crate) post_ffn_out_norm: Option<DenseWeight>,
76 /// Per-layer scalar (Gemma-4): hidden_states *= layer_scalar at end of forward.
77 pub(crate) layer_scalar: Option<f32>,
78 /// Secondary FFN (Gemma-4 26B MoE): runs in parallel with primary FFN (dense).
79 pub(crate) moe_ffn: Option<FfnComponent>,
80 /// LongCat shortcut-MoE PRODUCER: this sublayer computes `moe_ffn` on its
81 /// post-attention normed input and STASHES the result into the carry
82 /// buffer `(ptr, token_capacity)` instead of adding it — the paired NEXT
83 /// sublayer adds it at its end. Gated separately from the Gemma-4 dual-FFN
84 /// arm (which requires the three Gemma norms, absent here).
85 pub(crate) shortcut_carry_out: Option<(spark_runtime::gpu::DevicePtr, usize)>,
86 /// LongCat shortcut-MoE CONSUMER: after this sublayer's FFN residual add,
87 /// `hidden += carry` (the shortcut MoE output stashed by the previous
88 /// sublayer).
89 pub(crate) shortcut_carry_in: Option<(spark_runtime::gpu::DevicePtr, usize)>,
90 /// Pre-norm for MoE input (pre_feedforward_layernorm_2).
91 pub(crate) pre_moe_norm: Option<DenseWeight>,
92 /// Post-norm for MoE output (post_feedforward_layernorm_2).
93 pub(crate) post_moe_out_norm: Option<DenseWeight>,
94 /// Post-norm for dense FFN output only (post_feedforward_layernorm_1).
95 pub(crate) post_dense_ffn_norm: Option<DenseWeight>,
96 pub(super) kv_dtype: KvCacheDtype,
97 /// Turbo4 sparse-V pruning threshold (0.0 = disabled).
98 pub(super) sparse_v_threshold: f32,
99 // ── Decode weights (QuantWeight enum: Nvfp4 | Fp8 | Dense) ──
100 pub(super) q_weight: Option<QuantWeight>,
101 pub(super) k_weight: Option<QuantWeight>,
102 pub(super) v_weight: Option<QuantWeight>,
103 pub(super) o_weight: Option<QuantWeight>,
104 /// BF16 dense fallback for the output projection. When `Some`, the
105 /// decode/prefill o_proj GEMV uses this BF16 weight instead of the
106 /// NVFP4 path (`attn.o_proj`). Used by Gemma-4 dense which honors
107 /// Nvidia ModelOpt's official ignore list.
108 pub(super) o_dense_bf16: Option<DenseWeight>,
109 // ── MLA (Multi-head Latent Attention) — 2-step decode ──
110 pub(crate) mla: Option<MlaWeights>,
111 // ── Manifold-Constrained Hyper-Connections (mHC) — DeepSeek-V4 ──
112 /// Per-block HC parameters. `Some` only for DeepSeek-V4 (`hc_mult > 0`),
113 /// in which case the attn/ffn residual sites use `hc_pre`/`hc_post`
114 /// against the `hc_streams` buffer instead of the standard residual add.
115 pub(crate) hc: Option<HcWeights>,
116 // ── QSA indexer (Qwen3.8-Flash-Next) ──
117 /// Decode-side sparse-attention selection. `Some` only on the 12
118 /// full-attention layers of qwen4_exp. Presence vetoes decode-graph
119 /// capture (the selection top-k is a host round trip).
120 pub(crate) qsa: Option<crate::layers::qsa::QsaIndexer>,
121 /// HC `hc_pre` kernel handle (NULL when HC disabled).
122 pub(super) hc_pre_k: KernelHandle,
123 /// HC `hc_post` kernel handle (NULL when HC disabled).
124 pub(super) hc_post_k: KernelHandle,
125 /// HC `hc_expand` kernel handle (NULL when HC disabled).
126 pub(super) hc_expand_k: KernelHandle,
127 /// HC `hc_head` kernel handle (NULL when HC disabled).
128 pub(super) hc_head_k: KernelHandle,
129 // ── Transposed weights for prefill GEMM ──
130 /// Fused [q|k|v] transposed twin (N = q_proj_dim + 2*kv_dim). Present only
131 /// when the three projections share one `weight_scale_2` — the GEMM applies
132 /// a single scale2 per launch. `None` => the three separate GEMMs run.
133 pub(super) qkv_nvfp4_t: Option<QuantizedWeight>,
134 pub(super) q_nvfp4_t: Option<QuantizedWeight>,
135 pub(super) k_nvfp4_t: Option<QuantizedWeight>,
136 pub(super) v_nvfp4_t: Option<QuantizedWeight>,
137 pub(super) o_nvfp4_t: Option<QuantizedWeight>,
138 pub(super) q_fp8w_t: Option<crate::weight_map::Fp8WeightTransposed>,
139 pub(super) k_fp8w_t: Option<crate::weight_map::Fp8WeightTransposed>,
140 pub(super) v_fp8w_t: Option<crate::weight_map::Fp8WeightTransposed>,
141 pub(super) o_fp8w_t: Option<crate::weight_map::Fp8WeightTransposed>,
142 pub(super) w8a16_gemm_t_k: KernelHandle,
143 pub(super) w8a16_gemm_t_pipelined_k: KernelHandle,
144 // Fast transposed FP8 prefill GEMM (128x128 / 8-warp / two-level FP32 fold).
145 // Consumes the SAME B_t[K,N] + block_scale_t[K/128,N/128] that
146 // transpose_fp8 / transpose_block_scale already produce. KernelHandle(0) on
147 // miss → fall back to w8a16_gemm_t.
148 pub(super) w8a16_gemm_t_m128_k: KernelHandle,
149 // W8A8 + FP32 epilogue (vLLM-equivalent) — gated by ATLAS_FP8_W8A8=1.
150 pub(super) per_token_group_quant_fp8_k: KernelHandle,
151 pub(super) fp8_gemm_t_blockscaled_k: KernelHandle,
152 // Kernels — decode (GEMV M=1)
153 /// Offset-from-1 `rms_norm` (`out = x * (1 + w) / rms`). Used ONLY for the
154 /// unweighted normalize (`norm_unit_w()` is zero-filled, so `1 + 0 = 1`).
155 pub(super) rms_norm_k: KernelHandle,
156 /// The norm kernel for every weight that comes from the CHECKPOINT.
157 /// Same handle as `rms_norm_k` for offset-from-1 models; `rms_norm_vanilla`
158 /// (`out = x * w / rms`) for models that ship HF-vanilla norm weights.
159 pub(super) rms_norm_w_k: KernelHandle,
160 /// Warp-per-row sibling of `rms_norm_w_k` for short per-head rows; 0 if absent.
161 pub(super) rms_norm_w_warp_row_k: KernelHandle,
162 /// True when `rms_norm_w_k` is the vanilla kernel — i.e. the checkpoint's
163 /// norm weights are loaded exactly, with no `-1` pre-subtraction.
164 pub(super) norm_vanilla: bool,
165 pub(super) rms_norm_residual_k: KernelHandle,
166 /// Gemma-4 FP32-input rms_norm (absolute formula).
167 pub(super) rms_norm_f32_in_k: KernelHandle,
168 pub(super) dense_gemv_k: KernelHandle,
169 /// Load-time packed-Q2 → BF16 dequant (`dequant_gguf_bf16` module). Used by
170 /// the Tier-1c keep-packed attention PREFILL path: dequant q/k/v/o into a
171 /// transient BF16 scratch, run the normal `dense_gemm`, free. Decode uses
172 /// the native `q2_0_gemv_vec` (no dequant). `KernelHandle(0)` when absent.
173 pub(super) dequant_q2_0_gn_k: KernelHandle,
174 /// Native Q2_0 MMQ prefill (Tier-2, `ATLAS_GGUF_NATIVE_Q2_MMQ`): keep-packed
175 /// tensor-core int8 MMA vs a shared q8_1 activation. `KernelHandle(0)` when
176 /// absent → the transient-dequant prefill path is used instead. The q8_1
177 /// activation quantizer is shared with Q4_K (`q4k_quant_act_k`).
178 pub(super) q2_0_mmq_nc_k: KernelHandle,
179 pub(super) q2_0_mmq_wc_k: KernelHandle,
180 pub(super) q4k_quant_act_k: KernelHandle,
181 /// Native `q2_0_gemv_vec` decode kernel for keep-packed q/k/v/o.
182 pub(super) q2_0_gemv_k: KernelHandle,
183 /// Batched BF16 GEMV (M rows, one weight pass). Multi-seq decode q/k/v for
184 /// models whose attention weights are plain BF16 -- the quantized paths have
185 /// w4a16/w8a16 batch tiers, BF16 had none.
186 pub(super) dense_gemv_batchm_k: KernelHandle,
187 pub(super) w4a16_gemv_k: KernelHandle,
188 /// Single-warp `w4a16_gemv_sw`. `KernelHandle(0)` on miss → base GEMV.
189 pub(super) w4a16_gemv_sw_k: KernelHandle,
190 pub(super) w8a16_gemv_k: KernelHandle,
191 pub(super) w8a16_gemm_k: KernelHandle,
192 pub(super) w8a16_gemm_pipelined_k: KernelHandle,
193 pub(super) w4a16_gemv_dual_k: KernelHandle,
194 pub(super) rope_k: KernelHandle,
195 /// Strided sibling: rotates all n sequences in ONE launch. 0 when absent.
196 pub(super) rope_strided_k: KernelHandle,
197 /// Strided sibling of `rms_norm_w_k`: all n sequences in ONE launch. 0 when absent.
198 pub(super) rms_norm_strided_k: KernelHandle,
199 /// MRoPE-interleaved kernel.
200 pub(super) rope_mrope_interleaved_k: KernelHandle,
201 /// K-only MRoPE kernel used when Q RoPE is fused into Q deinterleave/norm.
202 pub(super) rope_mrope_interleaved_k_only_k: KernelHandle,
203 /// YaRN RoPE kernel using pre-computed inv_freq table (Mistral, etc.)
204 pub(super) rope_yarn_k: KernelHandle,
205 pub(super) rope_yarn_scaled_k: KernelHandle,
206 /// Interleaved (GPT-J / is_neox_style=False) YaRN RoPE kernel — DeepSeek MLA.
207 pub(super) rope_yarn_interleaved_k: KernelHandle,
208 /// Conjugate (negated-sin) interleaved YaRN RoPE — DeepSeek-V4 attention
209 /// output de-rotation (eq.26).
210 pub(super) rope_yarn_interleaved_inv_k: KernelHandle,
211 /// Proportional RoPE kernel (Gemma-4 full-attention layers).
212 pub(super) rope_proportional_k: KernelHandle,
213 pub(super) reshape_cache_k: KernelHandle,
214 /// Fused k_norm + RoPE + paged BF16 cache write — eliminates two
215 /// intermediate BF16 rounding steps that cause the documented L35-L39
216 /// cliff in chunked-prefill BF16 KV mode (memory:
217 /// `project_qwen36_phase2b_softmax_expf.md`).
218 pub(super) fused_k_norm_rope_cache_write_bf16_k: KernelHandle,
219 /// MRoPE-interleaved variant of the above. Same precision regime.
220 /// Dispatched when `mrope_interleaved` is true.
221 pub(super) fused_k_norm_rope_mrope_cache_write_bf16_k: KernelHandle,
222 /// V-only paged cache write. Used alongside the fused K-path so the
223 /// K side of the cache stays single-rounded.
224 pub(super) reshape_and_cache_flash_v_only_k: KernelHandle,
225 /// WHT kernel for turbo KV cache.
226 pub(super) wht_bf16_k: KernelHandle,
227 /// Inverse WHT. With TQ_PLUS_SIGNS off this aliases the forward kernel
228 /// (plain WHT is self-inverse); with TQ+ signs the inverse reverses the
229 /// signs1/signs2 order, which is required because (S2·H·S1)·(S2·H·S1) ≠ I.
230 pub(super) wht_bf16_k_inv: KernelHandle,
231 /// InnerQ application kernels (Q pre-WHT scale_inv, K post-WHT scale).
232 /// Returns 0 handle when InnerQ kernel module isn't loaded — caller should
233 /// guard launches with `.0 != 0`.
234 pub(super) innerq_apply_q_k: KernelHandle,
235 pub(super) innerq_apply_k_k: KernelHandle,
236 pub(super) paged_decode_k: KernelHandle,
237 /// HDIM=512 paged decode kernel for Gemma-4 full-attention layers
238 pub(super) paged_decode_512_k: KernelHandle,
239 /// MLA absorbed paged decode kernel (HDIM=320).
240 pub(super) paged_decode_mla_k: KernelHandle,
241 /// MLA paged decode kernel for DeepSeek-V4-Flash (compressed KV cache: 576 dims)
242 pub(super) mla_paged_decode_k: KernelHandle,
243 /// MLA paged decode kernel for DeepSeek-V4-Flash with FP8 KV cache
244 pub(super) mla_paged_decode_fp8_k: KernelHandle,
245 /// MLA batched GEMV for Q absorption and V extraction.
246 pub(super) mla_batched_gemv_k: KernelHandle,
247 /// MLA fused kernels — decode.
248 pub(super) mla_q_rope_scatter_k: KernelHandle,
249 pub(super) mla_q_rope_writeback_k: KernelHandle,
250 pub(super) mla_cache_assemble_k: KernelHandle,
251 /// MLA fused kernels — prefill.
252 pub(super) mla_q_rope_extract_batched_k: KernelHandle,
253 pub(super) mla_q_rope_writeback_batched_k: KernelHandle,
254 pub(super) mla_kv_assemble_batched_k: KernelHandle,
255 pub(super) mla_cache_assemble_batched_k: KernelHandle,
256 /// MLA absorbed prefill flash attention (HDIM=320, GQA 32:1)
257 pub(super) prefill_attn_mla320_k: KernelHandle,
258 /// Grouped GEMM for MLA Q absorption + V extraction.
259 pub(super) grouped_gemm_mla_k: KernelHandle,
260 /// Q_final assembly: [absorbed|rope] per head.
261 pub(super) mla_q_final_assemble_k: KernelHandle,
262 /// Fused MLA prefill: Q_absorb + attention + V_extract in one kernel.
263 pub(super) mla_fused_prefill_k: KernelHandle,
264 /// Split-K GEMM for skinny prefill matrices (M < 64).
265 pub(super) gemm_splitk_partial_k: KernelHandle,
266 pub(super) gemm_splitk_reduce_k: KernelHandle,
267 /// Tensor-core BF16 GEMM (m16n8k16 MMA).
268 pub(super) dense_gemm_tc_k: KernelHandle,
269 pub(super) paged_decode_splitk_k: Option<KernelHandle>,
270 pub(super) paged_decode_reduce_k: Option<KernelHandle>,
271 pub(super) residual_add_k: KernelHandle,
272 pub(super) sigmoid_gate_mul_k: KernelHandle,
273 pub(super) deinterleave_qg_k: KernelHandle,
274 pub(super) w4a16_gemv_qg_k: KernelHandle,
275 pub(super) residual_add_rms_norm_k: KernelHandle,
276 /// Dual-output (bf16 + f32) MoE-input norm for ATLAS_FP32_ROUTING. Zero if absent.
277 pub(super) residual_add_rms_norm_gatef32_k: KernelHandle,
278 // Kernels — batch2 (K=2 verify)
279 pub(super) w4a16_gemv_qg_batch2_k: KernelHandle,
280 pub(super) w4a16_gemv_dual_batch2_k: KernelHandle,
281 pub(super) w4a16_gemv_batch2_k: KernelHandle,
282 // Kernels — batch3 (K=3 verify)
283 pub(super) w4a16_gemv_qg_batch3_k: KernelHandle,
284 pub(super) w4a16_gemv_dual_batch3_k: KernelHandle,
285 pub(super) w4a16_gemv_batch3_k: KernelHandle,
286 /// Narrow `w4a16_gemv_batch{M}` family (M=4..8) for the K=4 verify and the
287 /// K=5..8 chain verify q/k/v/o projections. SSOT for the M -> tier
288 /// decision; individual tiers are 0-handles when the target lacks them.
289 pub(super) w4a16_batchm: W4a16BatchmTiers,
290 // Kernels — prefill (GEMM M=N + Flash Attention)
291 pub(super) w4a16_gemm_k: KernelHandle,
292 pub(super) w4a16_gemm_t_k: KernelHandle,
293 pub(super) w4a16_gemm_t_k64_k: KernelHandle,
294 /// K64 with a 64-wide N tile: same math, 2x the CTAs. `KernelHandle(0)`
295 /// when absent or killed by `ATLAS_NO_K64_N64`.
296 pub(super) w4a16_gemm_t_k64_n64_k: KernelHandle,
297 pub(super) w4a16_gemm_t_m128_k: KernelHandle,
298 /// LOSSLESS BF16-TC variant of t_m128 for QKV/o projection prefill (FP4→BF16
299 /// dequant + BF16 MMA, no FP8 activation crush). Opt-in via ATLAS_BF16_TC_PROJ
300 /// (default off → t_m128 path unchanged). KernelHandle(0) on miss.
301 pub(super) w4a16_gemm_t_m128_bf16_k: KernelHandle,
302 /// MiniMax-only shadow kernel.
303 pub(super) w4a16_gemm_t_m128_v2_k: KernelHandle,
304 /// v3 variant: K_STEP=64.
305 pub(super) w4a16_gemm_t_m128_v3_k: KernelHandle,
306 pub(super) dense_gemm_k: KernelHandle,
307 /// Tensor-core pipelined BF16 GEMM (mma.sync + cp.async, 128×128 tile) —
308 /// ~40× the scalar `dense_gemm_k` on large-M prefill projections, same math
309 /// (cosine 1.0). Used for the BF16-fallback Q/K/V/O projections (Holo's
310 /// native-FP8-dequant-to-BF16 attention path).
311 pub(super) dense_gemm_pipelined_k: KernelHandle,
312 pub(super) prefill_attn_k: KernelHandle,
313 /// HDIM=512 contiguous prefill for Gemma-4 full-attention layers
314 pub(super) prefill_attn_512_k: KernelHandle,
315 /// Did `prefill_attn_512_k` resolve to the TENSOR-CORE instantiation, or the
316 /// scalar reference? Only affects the profile label — but that label has now
317 /// been wrong twice, each time sending an investigation at the wrong kernel,
318 /// so which one ran is recorded rather than assumed.
319 pub(super) prefill_attn_512_is_tc: bool,
320 /// DeepSeek-V4 CSA compressor: window softmax-gated KV compression.
321 pub(super) csa_compress_k: KernelHandle,
322 /// DeepSeek-V4 CSA prefill attention over [raw | compressed] KV + sink.
323 pub(super) prefill_attn_compressed_k: KernelHandle,
324 /// 4b: # compressed blocks prefill wrote to `mla.compressor.pool` for the
325 /// active sequence (= prefill_len / ratio). Decode's compressed arm attends
326 /// blocks `[0, this)`. AtomicU32 for interior mutability under prefill's
327 /// `&self`; V4 serves max_batch=1 so one counter suffices (inc-3: per-seq
328 /// tracking + decode-time append will grow this each boundary crossing).
329 pub(super) v4_comp_pool_filled: std::sync::atomic::AtomicU32,
330 /// 4b inc-3 decode-append state (V4 serves max_batch=1 → scalar per layer).
331 /// `prev_valid`: the CSA `prev_win` ring holds a real previous decode window
332 /// (false until the first decode append, and reset each prefill) — when false
333 /// the CSA append masks Ca (window-0 semantics). `decode_started`/`first_pos`:
334 /// the absolute position of the first decode token this sequence, used to skip
335 /// any prefill/decode straddle window whose ring slots aren't all decode-written
336 /// (that one block is left as prefill/zero — a documented seam, not corruption).
337 pub(super) v4_comp_prev_valid: std::sync::atomic::AtomicBool,
338 pub(super) v4_decode_started: std::sync::atomic::AtomicBool,
339 pub(super) v4_decode_first_pos: std::sync::atomic::AtomicU32,
340 /// HDIM=512 paged prefill (BF16 KV) for Gemma-4 chunked long-context prefill
341 pub(super) prefill_attn_paged_512_k: KernelHandle,
342 pub(super) prefill_attn_64_k: KernelHandle,
343 pub(super) prefill_attn_paged_k: KernelHandle,
344 pub(super) prefill_attn_paged_fp8_k: KernelHandle,
345 pub(super) prefill_attn_paged_nvfp4_k: KernelHandle,
346 pub(super) prefill_attn_paged_turbo4_k: KernelHandle,
347 // BR=64 variants for long-context prefill (q_len >= 256)
348 pub(super) prefill_attn_paged_64_k: KernelHandle,
349 pub(super) prefill_attn_paged_fp8_64_k: KernelHandle,
350 pub(super) prefill_attn_paged_nvfp4_64_k: KernelHandle,
351 pub(super) prefill_attn_paged_turbo2_64_k: KernelHandle,
352 pub(super) prefill_attn_paged_turbo3_64_k: KernelHandle,
353 pub(super) prefill_attn_paged_turbo4_64_k: KernelHandle,
354 pub(super) prefill_attn_paged_turbo8_64_k: KernelHandle,
355 // ── TurboQuant+ asymmetric BR=64 prefill kernels ──
356 // Combined-dtype kernels that read K and V with different on-disk layouts.
357 // Currently: Bf16K + Turbo3V (safer-asym variant — K kept at bf16 precision,
358 // V aggressively compressed to 3-bit Lloyd-Max + FP8 group scale).
359 pub(super) prefill_attn_paged_bf16k_turbo3v_64_k: KernelHandle,
360 pub(super) prefill_attn_paged_bf16k_turbo4v_64_k: KernelHandle,
361 pub(super) prefill_attn_paged_bf16k_turbo2v_64_k: KernelHandle,
362 // Fp8K + TurboNV variants — same shape as bf16k_turbo*v_64 but threads
363 // the FP8 K-side per-tensor `k_scale` through to the dequant in
364 // LOAD_K_TILE. Targets FP8-attention models (Qwen3.6-35B-FP8 etc.).
365 pub(super) prefill_attn_paged_fp8k_turbo3v_64_k: KernelHandle,
366 pub(super) prefill_attn_paged_fp8k_turbo4v_64_k: KernelHandle,
367 pub(super) prefill_attn_paged_fp8k_turbo2v_64_k: KernelHandle,
368 // Both-sides-quantized TurboQuant+ asym (K and V both turbo, separate
369 // pool strides). K-side WHT bookend + Q WHT both fire because K is turbo.
370 pub(super) prefill_attn_paged_turbo4k_turbo3v_64_k: KernelHandle,
371 pub(super) prefill_attn_paged_turbo4k_turbo8v_64_k: KernelHandle,
372 pub(super) prefill_attn_paged_turbo3k_turbo8v_64_k: KernelHandle,
373 // ── Q12 Phase 3: same-chunk-len batched paged-prefill kernels ──
374 // Each takes `const int* const* block_table_ptrs` + per-batch Q/O
375 // offsets. Used by `Qwen3AttentionLayer::prefill_batched` when N≥2
376 // streams share the same chunk_len. Null on targets that don't
377 // carry the corresponding kernel (e.g. CPU backend).
378 pub(super) prefill_attn_paged_batched_k: KernelHandle,
379 pub(super) prefill_attn_paged_fp8_batched_k: KernelHandle,
380 pub(super) prefill_attn_paged_nvfp4_batched_k: KernelHandle,
381 pub(super) prefill_attn_paged_batched_64_k: KernelHandle,
382 pub(super) prefill_attn_paged_fp8_batched_64_k: KernelHandle,
383 pub(super) prefill_attn_paged_nvfp4_batched_64_k: KernelHandle,
384 // Batched prefill kernels
385 pub(super) deinterleave_qg_split_k: KernelHandle,
386 pub(super) deinterleave_qg_split_qnorm_k: KernelHandle,
387 pub(super) deinterleave_qg_split_qnorm_mrope_k: KernelHandle,
388 pub(super) sigmoid_gate_mul_batched_k: KernelHandle,
389 // Pre-dequanted FP8 weights for zero-overhead prefill GEMMs
390 pub(super) q_fp8: Option<DevicePtr>,
391 pub(super) k_fp8: Option<DevicePtr>,
392 pub(super) v_fp8: Option<DevicePtr>,
393 pub(super) o_fp8: Option<DevicePtr>,
394 pub(super) fp8_gemm_k: KernelHandle,
395 // FP8×FP8 GEMM
396 pub(super) bf16_to_fp8_k: KernelHandle,
397 pub(super) fp8_fp8_gemm_k: KernelHandle,
398 // M128 variants
399 pub(super) fp8_gemm_t_m128_k: KernelHandle,
400 pub(super) fp8_fp8_gemm_t_m128_k: KernelHandle,
401 // Native FP4 prefill (mxf4nvf4): present only for models whose kernel dir
402 // ships w4a4_gemm_mfast (try_kernel returns 0 elsewhere).
403 pub(super) w4a4_gemm_k: KernelHandle,
404 pub(super) quantize_nvfp4_k: KernelHandle,
405 /// Online FP8 KV scale calibration.
406 pub(super) fp8_calibration: Option<Fp8KvCalibration>,
407}