metrale_model_layers/layers/qwen3_ssm/
init.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! 2026-09-25: `Qwen3SsmLayer::new`, which looks up the layer's kernel handles
4//! and sizes its per-sequence state.
5//!
6//! Owner: model-layers (qwen3_ssm).
7//! Invariants: none beyond the types.
8
9use super::*;
10
11impl Qwen3SsmLayer {
12    pub fn new(
13        input_norm: DenseWeight,
14        ssm: SsmWeights,
15        post_attn_norm: DenseWeight,
16        ffn: FfnComponent,
17        qkvz_nvfp4: Option<QuantizedWeight>,
18        config: &metrale_config::ModelConfig,
19        gpu: &dyn GpuBackend,
20    ) -> Result<Self> {
21        let nv = config.linear_num_value_heads;
22        let vd = config.linear_value_head_dim;
23        let nk = config.linear_num_key_heads;
24        let kd = config.linear_key_head_dim;
25        let d_conv = config.linear_conv_kernel_dim;
26
27        let conv_dim = nk * kd * 2 + nv * vd;
28
29        // 2026-09-25: Looked up before the struct literal because two fields use
30        // it: `gdn_prefill_fla_chunk_delta_h_tcfuse_k` itself, and
31        // `fused_spine_kernel`, whose route line names the tensor-core spine
32        // when this handle is non-zero.
33        let gdn_tc_spine = gdn_prefill_tc_kernel(gpu);
34        let woa = super::woa::woa_kernels(gpu);
35
36        Ok(Self {
37            // 2026-09-25: The mHC weights arrive later through `set_hc_weights`;
38            // `hc_kernel` looks the handles up only when `config.hc_mult > 0`.
39            hc: None,
40            ple: None,
41            hc_pre_k: hc_kernel(config, gpu, "hc_pre"),
42            hc_post_k: hc_kernel(config, gpu, "hc_post"),
43            hc_expand_k: hc_kernel(config, gpu, "hc_expand"),
44            input_norm,
45            ssm,
46            post_attn_norm,
47            ffn,
48            lora_out_proj: None,
49            w8a8: None,
50            qkvz_nvfp4,
51            qkvz_nvfp4_t: None,
52            out_proj_nvfp4_t: None,
53            out_proj_dense: None,
54            qkvz_fp8w: None,
55            out_proj_fp8w: None,
56            qkvz_fp8w_rowwise: None,
57            out_proj_fp8w_rowwise: None,
58            qkvz_rowwise_bf16: std::sync::atomic::AtomicU64::new(0),
59            out_proj_rowwise_bf16: std::sync::atomic::AtomicU64::new(0),
60            qkvz_q2: None,
61            q2_0_gemv_k: super::super::try_kernel(gpu, "q2_0_gemv_vec", "q2_0_gemv_vec"),
62            dequant_q2_0_gn_k: super::super::try_kernel(
63                gpu,
64                "dequant_gguf_bf16",
65                "dequant_q2_0_gn_to_bf16",
66            ),
67            // 2026-09-25: Looked up by `set_packed_q2_qkvz`, so a layer without a
68            // packed weight issues no lookup for them.
69            q2_0_mmq_nc_k: KernelHandle(0),
70            q2_0_mmq_wc_k: KernelHandle(0),
71            q4k_quant_act_k: KernelHandle(0),
72            sequential_qkvz: false,
73            // 2026-09-25: Read once from the driver; `ms_proj_gemm` compares grid
74            // widths with it.
75            sm_count: gpu.sm_count()?,
76            rms_norm_residual_k: gpu.kernel("norm", "rms_norm_residual")?,
77            // 2026-09-25: `config.gdn_norm_sigmoid` selects the sigmoid gated-norm
78            // kernels here; no forward call site reads the flag.
79            gated_rms_norm_k: if config.gdn_norm_sigmoid {
80                gpu.kernel("gated_norm_sigmoid", "gated_rms_norm_sigmoid")?
81            } else {
82                gpu.kernel("norm", "gated_rms_norm")?
83            },
84            gated_rms_norm_f32_k: if config.gdn_norm_sigmoid {
85                super::super::try_kernel(
86                    gpu,
87                    "gated_norm_sigmoid",
88                    "gated_rms_norm_f32_input_sigmoid",
89                )
90            } else {
91                super::super::try_kernel(gpu, "norm", "gated_rms_norm_f32_input")
92            },
93            // 2026-09-25: No sigmoid strided variant is looked up. With 0,
94            // `trait_decode_multi_seq/ssm_batched_recurrent.rs` runs the gated
95            // norm once per sequence.
96            gated_rms_norm_f32_strided_k: if config.gdn_norm_sigmoid {
97                KernelHandle(0)
98            } else {
99                super::super::try_kernel(gpu, "norm", "gated_rms_norm_f32_input_strided")
100            },
101            dense_gemv_k: gpu.kernel("gemv", "dense_gemv_bf16")?,
102            dense_gemv_batch2_k: gpu.kernel("dense_gemv_bf16_batch2", "dense_gemv_bf16_batch2")?,
103            w4a16_gemv_k: gpu.kernel("w4a16_gemv", "w4a16_gemv")?,
104            w4a16_gemv_sw_k: super::super::try_kernel(gpu, "w4a16_gemv", "w4a16_gemv_sw"),
105            w8a16_gemv_k: gpu.kernel("w8a16_gemv", "w8a16_gemv")?,
106            w4a16_gemv_qkvz_k: gpu.kernel("w4a16_gemv", "w4a16_gemv_qkvz")?,
107            deinterleave_k: gpu.kernel("ssm_preprocess", "deinterleave_qkvz")?,
108            conv1d_k: gpu.kernel("causal_conv1d", "causal_conv1d_update")?,
109            conv1d_l2norm_k: gpu.kernel("causal_conv1d", "causal_conv1d_update_l2norm")?,
110            // 2026-09-25: With 0, `trait_decode_multi_seq/ssm_batched_recurrent.rs`
111            // runs the conv once per sequence.
112            conv1d_l2norm_f32_strided_k: super::super::try_kernel(
113                gpu,
114                "causal_conv1d",
115                "causal_conv1d_update_l2norm_f32_strided",
116            ),
117            conv1d_l2norm_f32_k: {
118                let h = super::super::try_kernel(
119                    gpu,
120                    "causal_conv1d",
121                    "causal_conv1d_update_l2norm_f32",
122                );
123                if h.0 == 0 {
124                    tracing::warn!(
125                        "FP32 conv1d kernel not loaded; SSM uses BF16 conv \
126                         output. Expect long-context coherence drift past ~8k \
127                         tokens on this backend."
128                    );
129                }
130                h
131            },
132            gdn_k: gpu.kernel("gated_delta_rule", "gated_delta_rule_decode")?,
133            gdn_f32_k: super::super::try_kernel(
134                gpu,
135                "gated_delta_rule",
136                "gated_delta_rule_decode_f32",
137            ),
138            gdn_f32_norm_k: super::super::try_kernel(
139                gpu,
140                "gated_delta_rule",
141                "gated_delta_rule_decode_f32_norm",
142            ),
143            gdn_f32_conv_norm_k: super::super::try_kernel(
144                gpu,
145                "gated_delta_rule",
146                "gated_delta_rule_decode_f32_conv_norm",
147            ),
148            gdn_f32_strided_k: super::super::try_kernel(
149                gpu,
150                "gated_delta_rule",
151                "gated_delta_rule_decode_f32_strided",
152            ),
153            gdn_f32_strided_norm_k: super::super::try_kernel(
154                gpu,
155                "gated_delta_rule",
156                "gated_delta_rule_decode_f32_strided_norm",
157            ),
158            gdn_f32_strided_norm_half_k: super::super::try_kernel(
159                gpu,
160                "gated_delta_rule",
161                "gated_delta_rule_decode_f32_strided_norm_half",
162            ),
163            gdn_f32_strided_norm_smem_k: super::super::try_kernel(
164                gpu,
165                "gated_delta_rule",
166                "gated_delta_rule_decode_f32_strided_norm_smem",
167            ),
168            gdn_f16_strided_norm_half_k: super::super::try_kernel(
169                gpu,
170                "gated_delta_rule",
171                "gated_delta_rule_decode_f16_strided_norm_half",
172            ),
173            gdn_f16_norm_k: super::super::try_kernel(
174                gpu,
175                "gated_delta_rule",
176                "gated_delta_rule_decode_f16_norm",
177            ),
178            ssm_h_f16_to_f32_k: super::super::try_kernel(
179                gpu,
180                "ssm_h_dtype",
181                "ssm_h_state_f16_to_f32",
182            ),
183            ssm_h_f32_to_f16_k: super::super::try_kernel(
184                gpu,
185                "ssm_h_dtype",
186                "ssm_h_state_f32_to_f16",
187            ),
188            ba_gates_k: gpu.kernel("ssm_preprocess", "dense_gemv_ba_gates")?,
189            residual_add_k: gpu.kernel("residual_add", "bf16_residual_add")?,
190            l2_norm_k: gpu.kernel("norm", "l2_norm_bf16")?,
191            residual_add_rms_norm_k: gpu.kernel("norm", "residual_add_rms_norm")?,
192            residual_add_rms_norm_gatef32_k: crate::layers::try_kernel(
193                gpu,
194                "norm",
195                "residual_add_rms_norm_gatef32",
196            ),
197            gated_rms_norm_prefill_k: if config.gdn_norm_sigmoid {
198                gpu.kernel("gated_norm_sigmoid", "gated_rms_norm_prefill_sigmoid")?
199            } else {
200                gpu.kernel("norm", "gated_rms_norm_prefill")?
201            },
202            w4a16_gemm_k: gpu.kernel("w4a16", "w4a16_gemm")?,
203            w4a16_gemm_t_k: crate::layers::tgemm_kernel(gpu),
204            w4a16_gemm_t_k64_k: crate::layers::k64_kernel(gpu)?,
205            w4a16_gemm_t_k64_n64_k: crate::layers::k64_n64_kernel(gpu),
206            w4a16_gemm_t_m128_k: gpu.kernel("w4a16", "w4a16_gemm_t_m128")?,
207            // 2026-09-25: 0 unless `METRALE_W4A16_VARIANT` is `v2` or `v3`; then
208            // `w4a16_v2_kernel` panics if the kernel is absent.
209            w4a16_gemm_t_m128_v2_k: super::super::w4a16_v2_kernel(gpu),
210            w4a16_gemv_batch2_k: gpu.kernel("w4a16_gemv", "w4a16_gemv_batch2")?,
211            dense_gemm_k: gpu.kernel("gemm", "dense_gemm_bf16")?,
212            dense_gemm_pipelined_k: super::super::try_kernel(
213                gpu,
214                "gemm",
215                "dense_gemm_bf16_pipelined",
216            ),
217            gdn_prefill_k: gpu.kernel("gated_delta_rule", "gated_delta_rule_prefill")?,
218            gdn_prefill_split_k: gpu
219                .kernel("gated_delta_rule", "gated_delta_rule_prefill_split")?,
220            gdn_prefill_split4_k: gpu
221                .kernel("gated_delta_rule", "gated_delta_rule_prefill_split4")?,
222            gdn_prefill_persistent_k: super::super::try_kernel(
223                gpu,
224                "gated_delta_rule_persistent",
225                "gated_delta_rule_prefill_persistent",
226            ),
227            gdn_prefill_persistent_wy4_k: super::super::try_kernel(
228                gpu,
229                "gated_delta_rule_persistent",
230                "gated_delta_rule_prefill_persistent_wy4",
231            ),
232            gdn_prefill_regresident_k: super::super::try_kernel(
233                gpu,
234                "gated_delta_rule_regresident",
235                "gated_delta_rule_prefill_regresident",
236            ),
237            gdn_prefill_fla_recompute_wu_k: super::super::try_kernel(
238                gpu,
239                "gated_delta_rule_fla",
240                "gated_delta_rule_recompute_wu",
241            ),
242            gdn_prefill_fla_recompute_wu_hopper_k: init_kernels::prefill_wu_hopper_k(gpu),
243            gdn_prefill_fla_chunk_fwd_o_hopper_k: init_kernels::prefill_fwd_o_hopper_k(gpu),
244            gdn_prefill_fla_chunk_delta_h_k: super::super::try_kernel(
245                gpu,
246                "gated_delta_rule_fla",
247                "gated_delta_rule_chunk_delta_h_ksplit",
248            ),
249            gdn_prefill_fla_chunk_delta_h_tc_vblock_k: super::super::try_kernel(
250                gpu,
251                "gated_delta_rule_fla",
252                "gated_delta_rule_chunk_delta_h_tc_vblock",
253            ),
254            gdn_prefill_fla_chunk_delta_h_tcfuse_k: gdn_tc_spine,
255            gdn_prefill_fla_chunk_delta_h_fused_k: fused_spine_kernel(gpu, gdn_tc_spine),
256            gdn_prefill_fla_chunk_delta_h_tma_k: super::super::try_kernel(
257                gpu,
258                "gated_delta_rule_fla",
259                "gated_delta_rule_chunk_delta_h_tma",
260            ),
261            gdn_prefill_fla_chunk_fwd_o_k: super::super::try_kernel(
262                gpu,
263                "gated_delta_rule_fla",
264                "gated_delta_rule_chunk_fwd_o",
265            ),
266            gdn_prefill_wy32_k: super::super::try_kernel(
267                gpu,
268                "gated_delta_rule_wy64_prefill",
269                "gated_delta_rule_prefill_wy64",
270            ),
271            gdn_prefill_wy32_batched_k: super::super::try_kernel(
272                gpu,
273                "gated_delta_rule_wy64_prefill",
274                "gated_delta_rule_prefill_wy64_batched",
275            ),
276            gdn_prefill_persistent_batched_k: super::super::try_kernel(
277                gpu,
278                "gated_delta_rule_persistent",
279                "gated_delta_rule_prefill_persistent_batched",
280            ),
281            gdn_prefill_persistent_wy4_batched_k: super::super::try_kernel(
282                gpu,
283                "gated_delta_rule_persistent",
284                "gated_delta_rule_prefill_persistent_wy4_batched",
285            ),
286            gdn_prefill_split4_batched_k: super::super::try_kernel(
287                gpu,
288                "gated_delta_rule",
289                "gated_delta_rule_prefill_split4_batched",
290            ),
291            compute_gdn_gates_k: gpu.kernel("ssm_preprocess", "compute_gdn_gates")?,
292            ba_gates_prefill_k: gpu.kernel("ssm_preprocess", "dense_gemm_ba_gates_prefill")?,
293            ba_gates_prefill_hopper_k: init_kernels::ba_gates_hopper_k(gpu),
294            conv1d_prefill_k: gpu.kernel("causal_conv1d", "causal_conv1d_update_prefill")?,
295            conv1d_prefill_tp_k: super::super::try_kernel(
296                gpu,
297                "causal_conv1d",
298                "causal_conv1d_update_prefill_tp",
299            ),
300            gdn_chunk2_k: gpu.kernel("gated_delta_rule", "gated_delta_rule_chunk2")?,
301            conv1d_chunk2_k: gpu.kernel("causal_conv1d", "causal_conv1d_update_chunk2")?,
302            gdn_chunk3_k: gpu.kernel("gated_delta_rule", "gated_delta_rule_chunk3")?,
303            w4a16_gemv_batch3_k: gpu.kernel("w4a16_gemv", "w4a16_gemv_batch3")?,
304            gdn_wy2_k: gpu.kernel("gated_delta_rule_wy", "gated_delta_rule_wy2")?,
305            gdn_wy2_resident_k: super::super::try_kernel(
306                gpu,
307                "gated_delta_rule_wy2_resident",
308                "gated_delta_rule_wy2_resident",
309            ),
310            gdn_wy3_k: gpu.kernel("gated_delta_rule_wy3", "gated_delta_rule_wy3")?,
311            gdn_wy3_resident_k: super::super::try_kernel(
312                gpu,
313                "gated_delta_rule_wy3_resident",
314                "gated_delta_rule_wy3_resident",
315            ),
316            gdn_wy4_k: gpu.kernel("gated_delta_rule_wy4", "gated_delta_rule_wy4")?,
317            gdn_wy4_woa_k: woa.woa_k,
318            gdn_wy4_fold_k: woa.fold_k,
319            gdn_wy4_clear_k: woa.clear_k,
320            woa_flag: std::sync::atomic::AtomicU64::new(0),
321            woa_stash: std::sync::atomic::AtomicU64::new(0),
322            woa_seqs: std::sync::atomic::AtomicUsize::new(0),
323            woa_dims: [nk, nv, kd, vd],
324            carry: super::carry::CarryState::new(gpu, [nk, nv, kd, vd]),
325            gdn_wy2_f16_k: super::super::try_kernel(
326                gpu,
327                "gated_delta_rule_wy_f16",
328                "gated_delta_rule_wy2_f16",
329            ),
330            gdn_wy2_resident_f16_k: super::super::try_kernel(
331                gpu,
332                "gated_delta_rule_wy2_resident_f16",
333                "gated_delta_rule_wy2_resident_f16",
334            ),
335            gdn_wy3_f16_k: super::super::try_kernel(
336                gpu,
337                "gated_delta_rule_wy3_f16",
338                "gated_delta_rule_wy3_f16",
339            ),
340            gdn_wy3_resident_f16_k: super::super::try_kernel(
341                gpu,
342                "gated_delta_rule_wy3_resident_f16",
343                "gated_delta_rule_wy3_resident_f16",
344            ),
345            gdn_wy4_f16_k: super::super::try_kernel(
346                gpu,
347                "gated_delta_rule_wy4_f16",
348                "gated_delta_rule_wy4_f16",
349            ),
350            gdn_verify_fused_conv_k2_k: super::super::try_kernel(
351                gpu,
352                "gdn_verify_fused_k2",
353                "gdn_verify_fused_conv_k2",
354            ),
355            gdn_verify_fused_norm_k2_k: super::super::try_kernel(
356                gpu,
357                "gdn_verify_fused_k2",
358                "gdn_verify_fused_norm_k2",
359            ),
360            gdn_verify_fused_conv_kn_k: super::super::try_kernel(
361                gpu,
362                "gdn_verify_fused_conv_kn",
363                "gdn_verify_fused_conv_kn",
364            ),
365            gdn_verify_fused_conv_kn_batched_k: super::super::try_kernel(
366                gpu,
367                "gdn_verify_fused_conv_kn",
368                "gdn_verify_fused_conv_kn_batched",
369            ),
370            gdn_f32_norm_snap_k: super::super::try_kernel(
371                gpu,
372                "gated_delta_rule_snap",
373                "gated_delta_rule_decode_f32_norm_snap",
374            ),
375            gdn_f32_strided_norm_snap_k: super::super::try_kernel(
376                gpu,
377                "gated_delta_rule_snap",
378                "gated_delta_rule_decode_f32_strided_norm_snap",
379            ),
380            gdn_verify_fused_conv_kn_f32_k: super::super::try_kernel(
381                gpu,
382                "gdn_verify_fused_conv_kn_f32",
383                "gdn_verify_fused_conv_kn_f32",
384            ),
385            gdn_wy17_k: super::super::try_kernel(
386                gpu,
387                "gated_delta_rule_wy17",
388                "gated_delta_rule_wy17",
389            ),
390            gdn_wyn_k: init_kernels::wyn_kernels(gpu),
391            gdn_wyn_f16_k: init_kernels::wyn_f16_kernels(gpu),
392            // 2026-09-25: Pointer-table twins for the cross-sequence batched verify.
393            // provenance-id: 526f6e616c6420522e205374657369616b
394            gdn_wyn_table_k: init_kernels::wyn_table_kernels(gpu),
395            gdn_wyn_f16_table_k: init_kernels::wyn_f16_table_kernels(gpu),
396            h_state_bytes: nv * vd * kd * 4,
397            conv_state_bytes: conv_dim * d_conv * 4,
398            qkvz_fp8: None,
399            out_proj_fp8: None,
400            fp8_gemm_k: gpu.kernel("w4a16", "fp8_gemm_t")?,
401            fp8_gemm_t_m128_k: gpu.kernel("w4a16", "fp8_gemm_t_m128")?,
402            w8a16_gemm_k: super::super::try_kernel(gpu, "w8a16_gemm", "w8a16_gemm"),
403            w8a16_gemm_pipelined_k: super::super::try_kernel(
404                gpu,
405                "w8a16_gemm_pipelined",
406                "w8a16_gemm_pipelined",
407            ),
408            w8a16_gemm_pipelined_m32_k: super::super::try_target_kernel(
409                gpu,
410                "w8a16_gemm_pipelined_m32",
411                "w8a16_gemm_pipelined_m32",
412            ),
413            w8a16_gemm_pipelined_m64_k: super::super::try_target_kernel(
414                gpu,
415                "w8a16_gemm_pipelined_m32",
416                "w8a16_gemm_pipelined_m64",
417            ),
418            w8a16_gemv_batch4_k: super::super::try_kernel(
419                gpu,
420                "w8a16_gemv_batch4",
421                "w8a16_gemv_batch4",
422            ),
423            w8a16_gemv_batch16_k: super::super::try_kernel(
424                gpu,
425                "w8a16_gemv_batch4",
426                "w8a16_gemv_batch16",
427            ),
428            w4a16_batchm: crate::layers::w4a16_gemv_tiers::W4a16BatchmTiers::resolve(gpu),
429            w4a16_gemv_batch16_k: super::super::try_kernel(gpu, "w4a16_gemv", "w4a16_gemv_batch16"),
430            w8a16_gemm_t_k: super::super::try_kernel(gpu, "w8a16_gemm_t", "w8a16_gemm_t"),
431            per_token_group_quant_fp8_k: ops::Fp8ActQuant::resolve(gpu),
432            fp8_gemm_t_blockscaled_k: super::super::try_kernel(
433                gpu,
434                "fp8_gemm_t_blockscaled",
435                "fp8_gemm_t_blockscaled",
436            ),
437            fp8_act_scale_kmajor_k: super::super::try_kernel(
438                gpu,
439                "fp8_scale_transpose",
440                "fp8_act_scale_to_kmajor",
441            ),
442        })
443    }
444}
445
446#[path = "init_kernels.rs"]
447mod init_kernels;
448use init_kernels::{fused_spine_kernel, gdn_prefill_tc_kernel, hc_kernel};
449
450#[path = "init_sequential.rs"]
451mod init_sequential;