metrale_model_layers/layers/ops/
ssm_mamba.rs1#![allow(unused_imports)]
11
12use anyhow::Result;
13use metrale_gpu_runtime::gpu::{DevicePtr, GpuBackend, KernelHandle};
14use metrale_gpu_runtime::kernel_args::{KernelLaunch, div_ceil};
15
16use crate::layers::moe;
17use crate::weight_map::{DenseWeight, Fp8DenseWeight, Fp8Weight, QuantizedWeight};
18
19use super::*;
20#[path = "ssm_mamba_gdn_verify.rs"]
21mod gdn_verify;
22pub use gdn_verify::{
23 gdn_verify_fused_conv_k2, gdn_verify_fused_conv_kn, gdn_verify_fused_conv_kn_batched,
24 gdn_verify_fused_norm_k2,
25};
26
27pub fn conv1d_update(
32 gpu: &dyn GpuBackend,
33 kernel: KernelHandle,
34 conv_state: DevicePtr,
35 input: DevicePtr,
36 weight: &DenseWeight,
37 output: DevicePtr,
38 d_inner: u32,
39 d_conv: u32,
40 batch_size: u32,
41 stream: u64,
42) -> Result<()> {
43 let bias_ptr = DevicePtr::NULL;
44 KernelLaunch::new(gpu, kernel)
45 .grid([div_ceil(d_inner, 256), batch_size, 1])
46 .block([256, 1, 1])
47 .arg_ptr(conv_state)
48 .arg_ptr(input)
49 .arg_ptr(weight.weight)
50 .arg_ptr(bias_ptr)
51 .arg_ptr(output)
52 .arg_u32(batch_size)
53 .arg_u32(d_inner)
54 .arg_u32(d_conv)
55 .launch(stream)
56}
57
58#[allow(clippy::too_many_arguments)]
62pub fn conv1d_update_l2norm(
63 gpu: &dyn GpuBackend,
64 kernel: KernelHandle,
65 conv_state: DevicePtr,
66 input: DevicePtr,
67 weight: &DenseWeight,
68 output: DevicePtr,
69 d_inner: u32,
70 d_conv: u32,
71 batch_size: u32,
72 qk_channels: u32,
73 head_dim: u32,
74 l2_eps: f32,
75 stream: u64,
76) -> Result<()> {
77 let bias_ptr = DevicePtr::NULL;
78 KernelLaunch::new(gpu, kernel)
79 .grid([div_ceil(d_inner, 256), batch_size, 1])
80 .block([256, 1, 1])
81 .arg_ptr(conv_state)
82 .arg_ptr(input)
83 .arg_ptr(weight.weight)
84 .arg_ptr(bias_ptr)
85 .arg_ptr(output)
86 .arg_u32(batch_size)
87 .arg_u32(d_inner)
88 .arg_u32(d_conv)
89 .arg_u32(qk_channels)
90 .arg_u32(head_dim)
91 .arg_f32(l2_eps)
92 .launch(stream)
93}
94
95#[allow(clippy::too_many_arguments)]
106pub fn conv1d_update_l2norm_strided(
107 gpu: &dyn GpuBackend,
108 kernel: KernelHandle,
109 conv_state: DevicePtr,
110 input: DevicePtr,
111 weight: &DenseWeight,
112 output: DevicePtr,
113 d_inner: u32,
114 d_conv: u32,
115 batch_size: u32,
116 qk_channels: u32,
117 head_dim: u32,
118 l2_eps: f32,
119 input_stride: u32,
120 output_stride: u32,
121 stream: u64,
122) -> Result<()> {
123 let bias_ptr = DevicePtr::NULL;
124 KernelLaunch::new(gpu, kernel)
125 .grid([div_ceil(d_inner, 256), batch_size, 1])
126 .block([256, 1, 1])
127 .arg_ptr(conv_state)
128 .arg_ptr(input)
129 .arg_ptr(weight.weight)
130 .arg_ptr(bias_ptr)
131 .arg_ptr(output)
132 .arg_u32(batch_size)
133 .arg_u32(d_inner)
134 .arg_u32(d_conv)
135 .arg_u32(qk_channels)
136 .arg_u32(head_dim)
137 .arg_f32(l2_eps)
138 .arg_u32(input_stride)
139 .arg_u32(output_stride)
140 .launch(stream)
141}
142
143#[allow(clippy::too_many_arguments)]
149pub fn conv1d_update_prefill(
150 gpu: &dyn GpuBackend,
151 kernel: KernelHandle,
152 conv1d_prefill_tp_k: KernelHandle,
153 conv_state: DevicePtr,
154 input: DevicePtr,
155 weight: &DenseWeight,
156 bias: DevicePtr,
157 output: DevicePtr,
158 d_inner: u32,
159 d_conv: u32,
160 seq_len: u32,
161 input_stride: u32,
162 output_stride: u32,
163 stream: u64,
164) -> Result<()> {
165 let tp = std::env::var("METRALE_CONV1D_TP").ok().as_deref() != Some("0")
171 && conv1d_prefill_tp_k.0 != 0;
172 let (k, grid, block) = if tp {
173 (
174 conv1d_prefill_tp_k,
175 [div_ceil(d_inner, 32), div_ceil(seq_len, 64), 1],
176 [32u32, 8u32, 1u32],
177 )
178 } else {
179 (kernel, [div_ceil(d_inner, 256), 1, 1], [256u32, 1u32, 1u32])
180 };
181 KernelLaunch::new(gpu, k)
182 .grid(grid)
183 .block(block)
184 .arg_ptr(conv_state)
185 .arg_ptr(input)
186 .arg_ptr(weight.weight)
187 .arg_ptr(bias)
188 .arg_ptr(output)
189 .arg_u32(d_inner)
190 .arg_u32(d_conv)
191 .arg_u32(seq_len)
192 .arg_u32(input_stride)
193 .arg_u32(output_stride)
194 .launch(stream)?;
195 if tp {
200 let state_k = gpu
201 .op_cache()
202 .kernel(gpu, "causal_conv1d", "causal_conv1d_prefill_state")?;
203 KernelLaunch::new(gpu, state_k)
204 .grid([div_ceil(d_inner, 256), 1, 1])
205 .block([256, 1, 1])
206 .arg_ptr(conv_state)
207 .arg_ptr(input)
208 .arg_u32(d_inner)
209 .arg_u32(d_conv)
210 .arg_u32(seq_len)
211 .arg_u32(input_stride)
212 .launch(stream)?;
213 }
214 Ok(())
215}
216
217#[allow(clippy::too_many_arguments)]
221pub fn mamba2_ssm_prefill(
222 gpu: &dyn GpuBackend,
223 kernel: KernelHandle,
224 h_state: DevicePtr,
225 x: DevicePtr,
226 b_proj: DevicePtr,
227 c_proj: DevicePtr,
228 dt_raw: DevicePtr,
229 a_log: DevicePtr,
230 d_param: DevicePtr,
231 dt_bias: DevicePtr,
232 output: DevicePtr,
233 batch_size: u32,
234 seq_len: u32,
235 num_heads: u32,
236 head_dim: u32,
237 state_size: u32,
238 n_groups: u32,
239 dt_min: f32,
240 dt_max: f32,
241 x_stride: u32,
242 bc_stride: u32,
243 dt_stride: u32,
244 y_stride: u32,
245 stream: u64,
246) -> Result<()> {
247 KernelLaunch::new(gpu, kernel)
248 .grid([num_heads, batch_size, 1])
249 .block([state_size, 1, 1])
250 .arg_ptr(h_state)
251 .arg_ptr(x)
252 .arg_ptr(b_proj)
253 .arg_ptr(c_proj)
254 .arg_ptr(dt_raw)
255 .arg_ptr(a_log)
256 .arg_ptr(d_param)
257 .arg_ptr(dt_bias)
258 .arg_ptr(output)
259 .arg_u32(batch_size)
260 .arg_u32(seq_len)
261 .arg_u32(num_heads)
262 .arg_u32(head_dim)
263 .arg_u32(state_size)
264 .arg_u32(n_groups)
265 .arg_f32(dt_min)
266 .arg_f32(dt_max)
267 .arg_u32(x_stride)
268 .arg_u32(bc_stride)
269 .arg_u32(dt_stride)
270 .arg_u32(y_stride)
271 .launch(stream)
272}
273
274#[allow(clippy::too_many_arguments)]
279pub fn mamba2_ssm_prefill_persistent(
280 gpu: &dyn GpuBackend,
281 kernel: KernelHandle,
282 h_state: DevicePtr,
283 x: DevicePtr,
284 b_proj: DevicePtr,
285 c_proj: DevicePtr,
286 dt_raw: DevicePtr,
287 a_log: DevicePtr,
288 d_param: DevicePtr,
289 dt_bias: DevicePtr,
290 output: DevicePtr,
291 batch_size: u32,
292 seq_len: u32,
293 num_heads: u32,
294 head_dim: u32,
295 state_size: u32,
296 n_groups: u32,
297 dt_min: f32,
298 dt_max: f32,
299 x_stride: u32,
300 bc_stride: u32,
301 dt_stride: u32,
302 y_stride: u32,
303 stream: u64,
304) -> Result<()> {
305 let smem = head_dim * (state_size + 1) * 4 + head_dim * 4 + state_size * 4 + state_size * 4;
311 const SUB: u32 = 4;
314 KernelLaunch::new(gpu, kernel)
315 .grid([num_heads, batch_size, 1])
316 .block([head_dim * SUB, 1, 1])
317 .shared_mem(smem)
318 .arg_ptr(h_state)
319 .arg_ptr(x)
320 .arg_ptr(b_proj)
321 .arg_ptr(c_proj)
322 .arg_ptr(dt_raw)
323 .arg_ptr(a_log)
324 .arg_ptr(d_param)
325 .arg_ptr(dt_bias)
326 .arg_ptr(output)
327 .arg_u32(batch_size)
328 .arg_u32(seq_len)
329 .arg_u32(num_heads)
330 .arg_u32(head_dim)
331 .arg_u32(state_size)
332 .arg_u32(n_groups)
333 .arg_f32(dt_min)
334 .arg_f32(dt_max)
335 .arg_u32(x_stride)
336 .arg_u32(bc_stride)
337 .arg_u32(dt_stride)
338 .arg_u32(y_stride)
339 .launch(stream)
340}