1#![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
21#[allow(clippy::too_many_arguments)]
27pub fn gdn_decode_f16_strided_norm(
28 gpu: &dyn GpuBackend,
29 kernel: KernelHandle,
30 h_state: DevicePtr,
31 query: DevicePtr,
32 key: DevicePtr,
33 value: DevicePtr,
34 gate: DevicePtr,
35 beta: DevicePtr,
36 z_gate: DevicePtr,
37 norm_weight: DevicePtr,
38 output: DevicePtr,
39 batch_size: u32,
40 num_k_heads: u32,
41 num_v_heads: u32,
42 k_dim: u32,
43 v_dim: u32,
44 qk_stride: u32,
45 v_stride: u32,
46 gb_stride: u32,
47 z_stride: u32,
48 out_stride: u32,
49 h_seq_stride: u64,
50 eps: f32,
51 stream: u64,
52) -> Result<()> {
53 KernelLaunch::new(gpu, kernel)
54 .grid([num_v_heads, batch_size, 1])
55 .block([128, 1, 1])
56 .arg_ptr(h_state)
57 .arg_ptr(query)
58 .arg_ptr(key)
59 .arg_ptr(value)
60 .arg_ptr(gate)
61 .arg_ptr(beta)
62 .arg_ptr(z_gate)
63 .arg_ptr(norm_weight)
64 .arg_ptr(output)
65 .arg_u32(batch_size)
66 .arg_u32(num_k_heads)
67 .arg_u32(num_v_heads)
68 .arg_u32(k_dim)
69 .arg_u32(v_dim)
70 .arg_u32(qk_stride)
71 .arg_u32(v_stride)
72 .arg_u32(gb_stride)
73 .arg_u32(z_stride)
74 .arg_u32(out_stride)
75 .arg_u64(h_seq_stride)
76 .arg_f32(eps)
77 .launch(stream)
78}
79
80pub fn ssm_h_state_f32_to_f16(
85 gpu: &dyn GpuBackend,
86 kernel: KernelHandle,
87 src: DevicePtr,
88 dst: DevicePtr,
89 n: u64,
90 stream: u64,
91) -> Result<()> {
92 const BLOCK: u32 = 256;
93 let blocks = div_ceil(n as u32, BLOCK).clamp(1, 4096);
94 KernelLaunch::new(gpu, kernel)
95 .grid([blocks, 1, 1])
96 .block([BLOCK, 1, 1])
97 .arg_ptr(src)
98 .arg_ptr(dst)
99 .arg_u64(n)
100 .launch(stream)
101}
102
103pub fn ssm_h_state_f16_to_f32(
106 gpu: &dyn GpuBackend,
107 kernel: KernelHandle,
108 src: DevicePtr,
109 dst: DevicePtr,
110 n: u64,
111 stream: u64,
112) -> Result<()> {
113 const BLOCK: u32 = 256;
114 let blocks = div_ceil(n as u32, BLOCK).clamp(1, 4096);
115 KernelLaunch::new(gpu, kernel)
116 .grid([blocks, 1, 1])
117 .block([BLOCK, 1, 1])
118 .arg_ptr(src)
119 .arg_ptr(dst)
120 .arg_u64(n)
121 .launch(stream)
122}
123
124pub fn gdn_decode(
128 gpu: &dyn GpuBackend,
129 kernel: KernelHandle,
130 h_state: DevicePtr,
131 query: DevicePtr,
132 key: DevicePtr,
133 value: DevicePtr,
134 gate: DevicePtr,
135 beta: DevicePtr,
136 output: DevicePtr,
137 batch_size: u32,
138 num_k_heads: u32,
139 num_v_heads: u32,
140 k_dim: u32,
141 v_dim: u32,
142 stream: u64,
143) -> Result<()> {
144 KernelLaunch::new(gpu, kernel)
145 .grid([num_v_heads, batch_size, 1])
146 .block([128, 1, 1])
147 .arg_ptr(h_state)
148 .arg_ptr(query)
149 .arg_ptr(key)
150 .arg_ptr(value)
151 .arg_ptr(gate)
152 .arg_ptr(beta)
153 .arg_ptr(output)
154 .arg_u32(batch_size)
155 .arg_u32(num_k_heads)
156 .arg_u32(num_v_heads)
157 .arg_u32(k_dim)
158 .arg_u32(v_dim)
159 .launch(stream)
160}
161
162#[allow(clippy::too_many_arguments)]
166pub fn gdn_decode_f32_norm(
167 gpu: &dyn GpuBackend,
168 kernel: KernelHandle,
169 h_state: DevicePtr,
170 query: DevicePtr,
171 key: DevicePtr,
172 value: DevicePtr,
173 gate: DevicePtr,
174 beta: DevicePtr,
175 z_gate: DevicePtr,
176 norm_weight: DevicePtr,
177 output: DevicePtr,
178 batch_size: u32,
179 num_k_heads: u32,
180 num_v_heads: u32,
181 k_dim: u32,
182 v_dim: u32,
183 eps: f32,
184 stream: u64,
185) -> Result<()> {
186 KernelLaunch::new(gpu, kernel)
187 .grid([num_v_heads, batch_size, 1])
188 .block([128, 1, 1])
189 .arg_ptr(h_state)
190 .arg_ptr(query)
191 .arg_ptr(key)
192 .arg_ptr(value)
193 .arg_ptr(gate)
194 .arg_ptr(beta)
195 .arg_ptr(z_gate)
196 .arg_ptr(norm_weight)
197 .arg_ptr(output)
198 .arg_u32(batch_size)
199 .arg_u32(num_k_heads)
200 .arg_u32(num_v_heads)
201 .arg_u32(k_dim)
202 .arg_u32(v_dim)
203 .arg_f32(eps)
204 .launch(stream)
205}
206
207#[allow(clippy::too_many_arguments)]
212pub fn gdn_prefill_regresident(
213 gpu: &dyn GpuBackend,
214 kernel: KernelHandle,
215 h_state: DevicePtr,
216 query: DevicePtr,
217 key: DevicePtr,
218 value: DevicePtr,
219 gate: DevicePtr,
220 beta: DevicePtr,
221 output: DevicePtr,
222 batch_size: u32,
223 seq_len: u32,
224 num_k_heads: u32,
225 num_v_heads: u32,
226 k_dim: u32,
227 v_dim: u32,
228 qk_stride: u32,
229 v_stride: u32,
230 gb_stride: u32,
231 stream: u64,
232) -> Result<()> {
233 KernelLaunch::new(gpu, kernel)
234 .grid([num_v_heads, batch_size, v_dim / 4])
235 .block([128, 1, 1])
236 .arg_ptr(h_state)
237 .arg_ptr(query)
238 .arg_ptr(key)
239 .arg_ptr(value)
240 .arg_ptr(gate)
241 .arg_ptr(beta)
242 .arg_ptr(output)
243 .arg_u32(batch_size)
244 .arg_u32(seq_len)
245 .arg_u32(num_k_heads)
246 .arg_u32(num_v_heads)
247 .arg_u32(k_dim)
248 .arg_u32(v_dim)
249 .arg_u32(qk_stride)
250 .arg_u32(v_stride)
251 .arg_u32(gb_stride)
252 .launch(stream)
253}
254
255#[allow(clippy::too_many_arguments)]
263pub fn gdn_decode_f32_conv_norm(
264 gpu: &dyn GpuBackend,
265 kernel: KernelHandle,
266 h_state: DevicePtr,
267 conv_state: DevicePtr,
268 new_input: DevicePtr,
269 conv_weight: DevicePtr,
270 gate: DevicePtr,
271 beta: DevicePtr,
272 z_gate: DevicePtr,
273 norm_weight: DevicePtr,
274 output: DevicePtr,
275 batch_size: u32,
276 num_k_heads: u32,
277 num_v_heads: u32,
278 k_dim: u32,
279 v_dim: u32,
280 conv_dim: u32,
281 d_conv: u32,
282 l2_eps: f32,
283 eps: f32,
284 stream: u64,
285) -> Result<()> {
286 let head_repeat = num_v_heads / num_k_heads;
287 KernelLaunch::new(gpu, kernel)
288 .grid([num_k_heads, batch_size, 1])
289 .block([head_repeat * v_dim, 1, 1])
290 .arg_ptr(h_state)
291 .arg_ptr(conv_state)
292 .arg_ptr(new_input)
293 .arg_ptr(conv_weight)
294 .arg_ptr(DevicePtr::NULL)
295 .arg_ptr(gate)
296 .arg_ptr(beta)
297 .arg_ptr(z_gate)
298 .arg_ptr(norm_weight)
299 .arg_ptr(output)
300 .arg_u32(batch_size)
301 .arg_u32(num_k_heads)
302 .arg_u32(num_v_heads)
303 .arg_u32(k_dim)
304 .arg_u32(v_dim)
305 .arg_u32(conv_dim)
306 .arg_u32(d_conv)
307 .arg_f32(l2_eps)
308 .arg_f32(eps)
309 .launch(stream)
310}
311
312pub const GDN_DECODE_STRIDED_SMEM_CAP_BYTES: u32 = 32 << 10;
321
322pub const GDN_DECODE_STRIDED_SMEM_CAP_MIN_BATCH: u32 = 16;
325
326pub fn gdn_decode_strided_smem(batch_size: u32) -> u32 {
328 if batch_size >= GDN_DECODE_STRIDED_SMEM_CAP_MIN_BATCH {
329 GDN_DECODE_STRIDED_SMEM_CAP_BYTES
330 } else {
331 0
332 }
333}
334
335#[allow(clippy::too_many_arguments)]
339pub fn gdn_decode_f32_strided(
340 gpu: &dyn GpuBackend,
341 kernel: KernelHandle,
342 h_state: DevicePtr,
343 query: DevicePtr,
344 key: DevicePtr,
345 value: DevicePtr,
346 gate: DevicePtr,
347 beta: DevicePtr,
348 output: DevicePtr,
349 batch_size: u32,
350 num_k_heads: u32,
351 num_v_heads: u32,
352 k_dim: u32,
353 v_dim: u32,
354 qk_stride: u32,
355 v_stride: u32,
356 gb_stride: u32,
357 out_stride: u32,
358 stream: u64,
359) -> Result<()> {
360 KernelLaunch::new(gpu, kernel)
361 .grid([num_v_heads, batch_size, 1])
362 .block([128, 1, 1])
363 .shared_mem(gdn_decode_strided_smem(batch_size))
364 .arg_ptr(h_state)
365 .arg_ptr(query)
366 .arg_ptr(key)
367 .arg_ptr(value)
368 .arg_ptr(gate)
369 .arg_ptr(beta)
370 .arg_ptr(output)
371 .arg_u32(batch_size)
372 .arg_u32(num_k_heads)
373 .arg_u32(num_v_heads)
374 .arg_u32(k_dim)
375 .arg_u32(v_dim)
376 .arg_u32(qk_stride)
377 .arg_u32(v_stride)
378 .arg_u32(gb_stride)
379 .arg_u32(out_stride)
380 .launch(stream)
381}
382
383#[allow(clippy::too_many_arguments)]
386pub fn gdn_decode_f32_strided_norm(
387 gpu: &dyn GpuBackend,
388 kernel: KernelHandle,
389 h_state: DevicePtr,
390 query: DevicePtr,
391 key: DevicePtr,
392 value: DevicePtr,
393 gate: DevicePtr,
394 beta: DevicePtr,
395 z_gate: DevicePtr,
396 norm_weight: DevicePtr,
397 output: DevicePtr,
398 batch_size: u32,
399 num_k_heads: u32,
400 num_v_heads: u32,
401 k_dim: u32,
402 v_dim: u32,
403 qk_stride: u32,
404 v_stride: u32,
405 gb_stride: u32,
406 z_stride: u32,
407 out_stride: u32,
408 eps: f32,
409 stream: u64,
410) -> Result<()> {
411 KernelLaunch::new(gpu, kernel)
412 .grid([num_v_heads, batch_size, 1])
413 .block([128, 1, 1])
414 .arg_ptr(h_state)
415 .arg_ptr(query)
416 .arg_ptr(key)
417 .arg_ptr(value)
418 .arg_ptr(gate)
419 .arg_ptr(beta)
420 .arg_ptr(z_gate)
421 .arg_ptr(norm_weight)
422 .arg_ptr(output)
423 .arg_u32(batch_size)
424 .arg_u32(num_k_heads)
425 .arg_u32(num_v_heads)
426 .arg_u32(k_dim)
427 .arg_u32(v_dim)
428 .arg_u32(qk_stride)
429 .arg_u32(v_stride)
430 .arg_u32(gb_stride)
431 .arg_u32(z_stride)
432 .arg_u32(out_stride)
433 .arg_f32(eps)
434 .launch(stream)
435}
436
437#[allow(clippy::too_many_arguments)]
442pub fn gdn_decode_chunk2(
443 gpu: &dyn GpuBackend,
444 kernel: KernelHandle,
445 h_state: DevicePtr,
446 query: DevicePtr,
447 key: DevicePtr,
448 value: DevicePtr,
449 gate: DevicePtr,
450 beta: DevicePtr,
451 output: DevicePtr,
452 h_state_intermediate: DevicePtr,
453 batch_size: u32,
454 num_k_heads: u32,
455 num_v_heads: u32,
456 k_dim: u32,
457 v_dim: u32,
458 qk_stride: u32,
459 v_stride: u32,
460 gb_stride: u32,
461 stream: u64,
462) -> Result<()> {
463 KernelLaunch::new(gpu, kernel)
464 .grid([num_v_heads, batch_size, 1])
465 .block([128, 1, 1])
466 .arg_ptr(h_state)
467 .arg_ptr(query)
468 .arg_ptr(key)
469 .arg_ptr(value)
470 .arg_ptr(gate)
471 .arg_ptr(beta)
472 .arg_ptr(output)
473 .arg_ptr(h_state_intermediate)
474 .arg_u32(batch_size)
475 .arg_u32(num_k_heads)
476 .arg_u32(num_v_heads)
477 .arg_u32(k_dim)
478 .arg_u32(v_dim)
479 .arg_u32(qk_stride)
480 .arg_u32(v_stride)
481 .arg_u32(gb_stride)
482 .launch(stream)
483}