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
21pub fn deinterleave_qkvz(
31 gpu: &dyn GpuBackend,
32 kernel: KernelHandle,
33 interleaved: DevicePtr,
34 output: DevicePtr,
35 num_tokens: u32,
36 num_groups: u32,
37 head_k_dim: u32,
38 vheads_per_group: u32,
39 head_v_dim: u32,
40 stream: u64,
41) -> Result<()> {
42 let group_dim = 2 * head_k_dim + 2 * vheads_per_group * head_v_dim;
43 let total = num_groups * group_dim;
44 KernelLaunch::new(gpu, kernel)
45 .grid([num_tokens, div_ceil(total, 256), 1])
46 .block([256, 1, 1])
47 .arg_ptr(interleaved)
48 .arg_ptr(output)
49 .arg_u32(num_groups)
50 .arg_u32(head_k_dim)
51 .arg_u32(vheads_per_group)
52 .arg_u32(head_v_dim)
53 .launch(stream)
54}
55
56pub fn deinterleave_qg(
66 gpu: &dyn GpuBackend,
67 kernel: KernelHandle,
68 data: DevicePtr,
69 num_tokens: u32,
70 num_heads: u32,
71 head_dim: u32,
72 stride: u32,
73 stream: u64,
74) -> Result<()> {
75 let shared_bytes = num_heads * head_dim * 2 * 2;
76 KernelLaunch::new(gpu, kernel)
77 .grid([num_tokens, 1, 1])
78 .block([256, 1, 1])
79 .shared_mem(shared_bytes)
80 .arg_ptr(data)
81 .arg_u32(num_heads)
82 .arg_u32(head_dim)
83 .arg_u32(stride)
84 .launch(stream)
85}
86
87pub fn deinterleave_qg_split(
91 gpu: &dyn GpuBackend,
92 kernel: KernelHandle,
93 data: DevicePtr,
94 q_out: DevicePtr,
95 num_tokens: u32,
96 num_heads: u32,
97 head_dim: u32,
98 stride: u32,
99 stream: u64,
100) -> Result<()> {
101 let shared_bytes = num_heads * head_dim * 2 * 2;
102 KernelLaunch::new(gpu, kernel)
103 .grid([num_tokens, 1, 1])
104 .block([256, 1, 1])
105 .shared_mem(shared_bytes)
106 .arg_ptr(data)
107 .arg_ptr(q_out)
108 .arg_u32(num_heads)
109 .arg_u32(head_dim)
110 .arg_u32(stride)
111 .launch(stream)
112}
113
114pub fn deinterleave_qg_split_qnorm(
120 gpu: &dyn GpuBackend,
121 kernel: KernelHandle,
122 data: DevicePtr,
123 q_out: DevicePtr,
124 q_norm_weight: DevicePtr,
125 num_tokens: u32,
126 num_heads: u32,
127 head_dim: u32,
128 stride: u32,
129 eps: f32,
130 stream: u64,
131) -> Result<()> {
132 let shared_bytes = num_heads * head_dim * 2 * 2;
133 KernelLaunch::new(gpu, kernel)
134 .grid([num_tokens, 1, 1])
135 .block([256, 1, 1])
136 .shared_mem(shared_bytes)
137 .arg_ptr(data)
138 .arg_ptr(q_out)
139 .arg_ptr(q_norm_weight)
140 .arg_u32(num_heads)
141 .arg_u32(head_dim)
142 .arg_u32(stride)
143 .arg_f32(eps)
144 .launch(stream)
145}
146
147#[allow(clippy::too_many_arguments)]
155pub fn deinterleave_qg_split_qnorm_mrope(
156 gpu: &dyn GpuBackend,
157 kernel: KernelHandle,
158 data: DevicePtr,
159 q_out: DevicePtr,
160 q_norm_weight: DevicePtr,
161 pos_t: DevicePtr,
162 pos_h: DevicePtr,
163 pos_w: DevicePtr,
164 num_tokens: u32,
165 num_heads: u32,
166 head_dim: u32,
167 stride: u32,
168 rotary_dim: u32,
169 eps: f32,
170 theta: f32,
171 stream: u64,
172) -> Result<()> {
173 let raw_shared = num_heads * head_dim * 2 * 2;
174 let norm_shared = num_heads * head_dim * 2;
175 KernelLaunch::new(gpu, kernel)
176 .grid([num_tokens, 1, 1])
177 .block([256, 1, 1])
178 .shared_mem(raw_shared + norm_shared)
179 .arg_ptr(data)
180 .arg_ptr(q_out)
181 .arg_ptr(q_norm_weight)
182 .arg_ptr(pos_t)
183 .arg_ptr(pos_h)
184 .arg_ptr(pos_w)
185 .arg_u32(num_heads)
186 .arg_u32(head_dim)
187 .arg_u32(stride)
188 .arg_u32(rotary_dim)
189 .arg_f32(eps)
190 .arg_f32(theta)
191 .launch(stream)
192}
193
194pub fn sigmoid_gate_mul_batched(
198 gpu: &dyn GpuBackend,
199 kernel: KernelHandle,
200 input: DevicePtr,
201 gate: DevicePtr,
202 output: DevicePtr,
203 dim: u32,
204 gate_stride: u32,
205 num_tokens: u32,
206 stream: u64,
207) -> Result<()> {
208 let total = num_tokens * dim;
209 KernelLaunch::new(gpu, kernel)
210 .grid([div_ceil(total, 256), 1, 1])
211 .block([256, 1, 1])
212 .arg_ptr(input)
213 .arg_ptr(gate)
214 .arg_ptr(output)
215 .arg_u32(dim)
216 .arg_u32(gate_stride)
217 .arg_u32(total)
218 .launch(stream)
219}
220
221pub fn compute_gdn_gates(
232 gpu: &dyn GpuBackend,
233 kernel: KernelHandle,
234 ba_interleaved: DevicePtr,
235 a_log: DevicePtr,
236 dt_bias: DevicePtr,
237 gate_out: DevicePtr,
238 beta_out: DevicePtr,
239 num_tokens: u32,
240 num_v_heads: u32,
241 num_groups: u32,
242 vheads_per_group: u32,
243 ba_stride: u32,
244 stream: u64,
245) -> Result<()> {
246 KernelLaunch::new(gpu, kernel)
247 .grid([num_tokens, 1, 1])
248 .block([num_v_heads, 1, 1])
249 .arg_ptr(ba_interleaved)
250 .arg_ptr(a_log)
251 .arg_ptr(dt_bias)
252 .arg_ptr(gate_out)
253 .arg_ptr(beta_out)
254 .arg_u32(num_v_heads)
255 .arg_u32(num_groups)
256 .arg_u32(vheads_per_group)
257 .arg_u32(ba_stride)
258 .launch(stream)
259}
260
261#[allow(clippy::too_many_arguments)]
267pub fn dense_gemv_ba_gates(
268 gpu: &dyn GpuBackend,
269 kernel: KernelHandle,
270 input: DevicePtr,
271 ba_weight: &DenseWeight,
272 a_log: DevicePtr,
273 dt_bias: DevicePtr,
274 gate_out: DevicePtr,
275 beta_out: DevicePtr,
276 n: u32,
277 k: u32,
278 vheads_per_group: u32,
279 stream: u64,
280) -> Result<()> {
281 KernelLaunch::new(gpu, kernel)
282 .grid([div_ceil(n, 4), 1, 1])
283 .block([256, 1, 1])
284 .arg_ptr(input)
285 .arg_ptr(ba_weight.weight)
286 .arg_ptr(a_log)
287 .arg_ptr(dt_bias)
288 .arg_ptr(gate_out)
289 .arg_ptr(beta_out)
290 .arg_u32(n)
291 .arg_u32(k)
292 .arg_u32(vheads_per_group)
293 .launch(stream)
294}
295
296#[allow(clippy::too_many_arguments)]
315pub fn dense_gemm_ba_gates_prefill(
316 gpu: &dyn GpuBackend,
317 kernel: KernelHandle,
318 twin: KernelHandle,
319 input: DevicePtr,
320 ba_weight: &DenseWeight,
321 a_log: DevicePtr,
322 dt_bias: DevicePtr,
323 gate_out: DevicePtr,
324 m: u32,
325 n: u32,
326 k: u32,
327 k_stride: u32,
328 gate_stride: u32,
329 nv: u32,
330 vheads_per_group: u32,
331 stream: u64,
332) -> Result<()> {
333 let requested = ssm_ba_gates_hopper_enabled();
334 let pick = ba_gates_pick(
335 requested,
336 kernel,
337 twin,
338 m,
339 n,
340 k,
341 k_stride,
342 ba_gates_sm_count(gpu),
343 );
344 ba_gates_log(&pick, requested, m);
345 if pick.twin {
346 return dense_gemm_ba_gates_prefill_hopper(
347 gpu,
348 pick.kernel,
349 input,
350 ba_weight,
351 a_log,
352 dt_bias,
353 gate_out,
354 m,
355 n,
356 k,
357 k_stride,
358 gate_stride,
359 nv,
360 vheads_per_group,
361 stream,
362 );
363 }
364 KernelLaunch::new(gpu, pick.kernel)
365 .grid([div_ceil(n, 4), m, 1])
366 .block([256, 1, 1])
367 .arg_ptr(input)
368 .arg_ptr(ba_weight.weight)
369 .arg_ptr(a_log)
370 .arg_ptr(dt_bias)
371 .arg_ptr(gate_out)
372 .arg_u32(m)
373 .arg_u32(n)
374 .arg_u32(k)
375 .arg_u32(k_stride)
376 .arg_u32(gate_stride)
377 .arg_u32(nv)
378 .arg_u32(vheads_per_group)
379 .launch(stream)
380}