1#![allow(unused_imports)]
6
7use anyhow::Result;
8use spark_runtime::gpu::{DevicePtr, GpuBackend, KernelHandle};
9use spark_runtime::kernel_args::{KernelLaunch, div_ceil};
10
11use crate::weight_map::{DenseWeight, Fp8DenseWeight, Fp8Weight, QuantizedWeight};
12
13use super::*;
14
15#[path = "moe_grouped_a/topk.rs"]
18mod topk;
19pub use topk::{moe_topk_sigmoid_batched, moe_topk_softmax_batched, moe_topk_sqrtsoftplus_batched};
22
23pub fn moe_w4a16_grouped_gemm(
25 gpu: &dyn GpuBackend,
26 kernel: KernelHandle,
27 a: DevicePtr,
28 b_packed: DevicePtr,
29 b_scale: DevicePtr,
30 scale2: f32,
31 c: DevicePtr,
32 expert_offsets: DevicePtr,
33 num_experts: u32,
34 n: u32,
35 k: u32,
36 stream: u64,
37) -> Result<()> {
38 KernelLaunch::new(gpu, kernel)
39 .grid([num_experts, 1, 1])
40 .block([256, 1, 1])
41 .arg_ptr(a)
42 .arg_ptr(b_packed)
43 .arg_ptr(b_scale)
44 .arg_f32(scale2)
45 .arg_ptr(c)
46 .arg_ptr(expert_offsets)
47 .arg_u32(num_experts)
48 .arg_u32(n)
49 .arg_u32(k)
50 .launch(stream)
51}
52
53const PTRTABLE_LEGACY_N_TILE: u32 = 64;
54
55fn ptrtable_legacy_grid_x(n_out: u32) -> u32 {
56 div_ceil(n_out, PTRTABLE_LEGACY_N_TILE)
57}
58
59#[allow(clippy::too_many_arguments)]
67pub fn moe_w4a16_grouped_gemm_ptrtable_m256(
68 gpu: &dyn GpuBackend,
69 kernel: KernelHandle,
70 a: DevicePtr,
71 b_packed_ptrs: DevicePtr,
72 b_scale_ptrs: DevicePtr,
73 scale2_vals: DevicePtr,
74 c: DevicePtr,
75 expert_offsets: DevicePtr,
76 sorted_token_ids: DevicePtr,
77 num_experts: u32,
78 n_out: u32,
79 k: u32,
80 max_m_tiles: u32,
81 stream: u64,
82) -> Result<()> {
83 KernelLaunch::new(gpu, kernel)
84 .grid([ptrtable_legacy_grid_x(n_out), max_m_tiles, num_experts])
85 .block([512, 1, 1])
86 .arg_ptr(a)
87 .arg_ptr(b_packed_ptrs)
88 .arg_ptr(b_scale_ptrs)
89 .arg_ptr(scale2_vals)
90 .arg_ptr(c)
91 .arg_ptr(expert_offsets)
92 .arg_ptr(sorted_token_ids)
93 .arg_u32(num_experts)
94 .arg_u32(n_out)
95 .arg_u32(k)
96 .launch(stream)
97}
98
99#[allow(clippy::too_many_arguments)]
103pub fn moe_w4a16_grouped_gemm_ptrtable(
104 gpu: &dyn GpuBackend,
105 kernel: KernelHandle,
106 a: DevicePtr,
107 b_packed_ptrs: DevicePtr,
108 b_scale_ptrs: DevicePtr,
109 scale2_vals: DevicePtr,
110 c: DevicePtr,
111 expert_offsets: DevicePtr,
112 sorted_token_ids: DevicePtr,
113 num_experts: u32,
114 n_out: u32,
115 k: u32,
116 max_m_tiles: u32,
117 stream: u64,
118) -> Result<()> {
119 KernelLaunch::new(gpu, kernel)
120 .grid([ptrtable_legacy_grid_x(n_out), max_m_tiles, num_experts])
121 .block([128, 1, 1])
122 .arg_ptr(a)
123 .arg_ptr(b_packed_ptrs)
124 .arg_ptr(b_scale_ptrs)
125 .arg_ptr(scale2_vals)
126 .arg_ptr(c)
127 .arg_ptr(expert_offsets)
128 .arg_ptr(sorted_token_ids)
129 .arg_u32(num_experts)
130 .arg_u32(n_out)
131 .arg_u32(k)
132 .launch(stream)
133}
134
135#[allow(clippy::too_many_arguments)]
139pub fn moe_w4a16_grouped_gemm_ptrtable_n128(
140 gpu: &dyn GpuBackend,
141 kernel: KernelHandle,
142 a: DevicePtr,
143 b_packed_ptrs: DevicePtr,
144 b_scale_ptrs: DevicePtr,
145 scale2_vals: DevicePtr,
146 c: DevicePtr,
147 expert_offsets: DevicePtr,
148 sorted_token_ids: DevicePtr,
149 num_experts: u32,
150 n_out: u32,
151 k: u32,
152 max_m_tiles: u32,
153 stream: u64,
154) -> Result<()> {
155 KernelLaunch::new(gpu, kernel)
156 .grid([div_ceil(n_out, 128), max_m_tiles, num_experts])
157 .block([128, 1, 1])
158 .arg_ptr(a)
159 .arg_ptr(b_packed_ptrs)
160 .arg_ptr(b_scale_ptrs)
161 .arg_ptr(scale2_vals)
162 .arg_ptr(c)
163 .arg_ptr(expert_offsets)
164 .arg_ptr(sorted_token_ids)
165 .arg_u32(num_experts)
166 .arg_u32(n_out)
167 .arg_u32(k)
168 .launch(stream)
169}
170
171#[allow(clippy::too_many_arguments)]
176pub fn moe_fp8_grouped_gemm_ptrtable_n128(
177 gpu: &dyn GpuBackend,
178 kernel: KernelHandle,
179 a_fp8: DevicePtr,
180 b_packed_ptrs: DevicePtr,
181 b_scale_ptrs: DevicePtr,
182 scale2_vals: DevicePtr,
183 c: DevicePtr,
184 expert_offsets: DevicePtr,
185 sorted_token_ids: DevicePtr,
186 num_experts: u32,
187 n_out: u32,
188 k: u32,
189 max_m_tiles: u32,
190 stream: u64,
191) -> Result<()> {
192 KernelLaunch::new(gpu, kernel)
193 .grid([div_ceil(n_out, 128), max_m_tiles, num_experts])
194 .block([128, 1, 1])
195 .arg_ptr(a_fp8)
196 .arg_ptr(b_packed_ptrs)
197 .arg_ptr(b_scale_ptrs)
198 .arg_ptr(scale2_vals)
199 .arg_ptr(c)
200 .arg_ptr(expert_offsets)
201 .arg_ptr(sorted_token_ids)
202 .arg_u32(num_experts)
203 .arg_u32(n_out)
204 .arg_u32(k)
205 .launch(stream)
206}
207
208#[allow(clippy::too_many_arguments)]
213pub fn moe_w4a16_grouped_gemm_ptrtable_k64_n128(
214 gpu: &dyn GpuBackend,
215 kernel: KernelHandle,
216 a: DevicePtr,
217 b_packed_ptrs: DevicePtr,
218 b_scale_ptrs: DevicePtr,
219 scale2_vals: DevicePtr,
220 c: DevicePtr,
221 expert_offsets: DevicePtr,
222 sorted_token_ids: DevicePtr,
223 num_experts: u32,
224 n_out: u32,
225 k: u32,
226 max_m_tiles: u32,
227 stream: u64,
228) -> Result<()> {
229 KernelLaunch::new(gpu, kernel)
230 .grid([div_ceil(n_out, 128), max_m_tiles, num_experts])
231 .block([128, 1, 1])
232 .arg_ptr(a)
233 .arg_ptr(b_packed_ptrs)
234 .arg_ptr(b_scale_ptrs)
235 .arg_ptr(scale2_vals)
236 .arg_ptr(c)
237 .arg_ptr(expert_offsets)
238 .arg_ptr(sorted_token_ids)
239 .arg_u32(num_experts)
240 .arg_u32(n_out)
241 .arg_u32(k)
242 .launch(stream)
243}
244
245#[allow(clippy::too_many_arguments)]
249pub fn moe_w4a16_fused_gate_up_k64_n128(
250 gpu: &dyn GpuBackend,
251 kernel: KernelHandle,
252 a: DevicePtr,
253 gate_packed_ptrs: DevicePtr,
254 gate_scale_ptrs: DevicePtr,
255 gate_scale2_vals: DevicePtr,
256 up_packed_ptrs: DevicePtr,
257 up_scale_ptrs: DevicePtr,
258 up_scale2_vals: DevicePtr,
259 c_gate: DevicePtr,
260 c_up: DevicePtr,
261 expert_offsets: DevicePtr,
262 sorted_token_ids: DevicePtr,
263 num_experts: u32,
264 n_out: u32,
265 k: u32,
266 max_m_tiles: u32,
267 stream: u64,
268) -> Result<()> {
269 KernelLaunch::new(gpu, kernel)
270 .grid([div_ceil(2 * n_out, 128), max_m_tiles, num_experts])
271 .block([128, 1, 1])
272 .arg_ptr(a)
273 .arg_ptr(gate_packed_ptrs)
274 .arg_ptr(gate_scale_ptrs)
275 .arg_ptr(gate_scale2_vals)
276 .arg_ptr(up_packed_ptrs)
277 .arg_ptr(up_scale_ptrs)
278 .arg_ptr(up_scale2_vals)
279 .arg_ptr(c_gate)
280 .arg_ptr(c_up)
281 .arg_ptr(expert_offsets)
282 .arg_ptr(sorted_token_ids)
283 .arg_u32(num_experts)
284 .arg_u32(n_out)
285 .arg_u32(k)
286 .launch(stream)
287}
288
289#[allow(clippy::too_many_arguments, dead_code)]
299pub fn moe_permute_tokens(
300 gpu: &dyn GpuBackend,
301 kernel: KernelHandle,
302 hidden_states: DevicePtr,
303 permuted: DevicePtr,
304 sorted_token_ids: DevicePtr,
305 hidden: u32,
306 total_expanded: u32,
307 stream: u64,
308) -> Result<()> {
309 let threads = hidden.clamp(1, 256);
310 KernelLaunch::new(gpu, kernel)
311 .grid([total_expanded, 1, 1])
312 .block([threads, 1, 1])
313 .arg_ptr(hidden_states)
314 .arg_ptr(permuted)
315 .arg_ptr(sorted_token_ids)
316 .arg_u32(hidden)
317 .arg_u32(total_expanded)
318 .launch(stream)
319}
320
321#[allow(clippy::too_many_arguments)]
329pub fn moe_w4a16_fused_gate_up_k64_m128(
330 gpu: &dyn GpuBackend,
331 kernel: KernelHandle,
332 a: DevicePtr,
333 gate_packed_ptrs: DevicePtr,
334 gate_scale_ptrs: DevicePtr,
335 gate_scale2_vals: DevicePtr,
336 up_packed_ptrs: DevicePtr,
337 up_scale_ptrs: DevicePtr,
338 up_scale2_vals: DevicePtr,
339 c_gate: DevicePtr,
340 c_up: DevicePtr,
341 expert_offsets: DevicePtr,
342 sorted_token_ids: DevicePtr,
343 num_experts: u32,
344 n_out: u32,
345 k: u32,
346 max_m_tiles_m128: u32,
347 stream: u64,
348) -> Result<()> {
349 KernelLaunch::new(gpu, kernel)
350 .grid([div_ceil(2 * n_out, 128), max_m_tiles_m128, num_experts])
351 .block([256, 1, 1])
352 .arg_ptr(a)
353 .arg_ptr(gate_packed_ptrs)
354 .arg_ptr(gate_scale_ptrs)
355 .arg_ptr(gate_scale2_vals)
356 .arg_ptr(up_packed_ptrs)
357 .arg_ptr(up_scale_ptrs)
358 .arg_ptr(up_scale2_vals)
359 .arg_ptr(c_gate)
360 .arg_ptr(c_up)
361 .arg_ptr(expert_offsets)
362 .arg_ptr(sorted_token_ids)
363 .arg_u32(num_experts)
364 .arg_u32(n_out)
365 .arg_u32(k)
366 .launch(stream)
367}
368
369#[allow(clippy::too_many_arguments)]
374pub fn moe_w4a16_fused_gate_up_n128(
375 gpu: &dyn GpuBackend,
376 kernel: KernelHandle,
377 a: DevicePtr,
378 gate_packed_ptrs: DevicePtr,
379 gate_scale_ptrs: DevicePtr,
380 gate_scale2_vals: DevicePtr,
381 up_packed_ptrs: DevicePtr,
382 up_scale_ptrs: DevicePtr,
383 up_scale2_vals: DevicePtr,
384 c_gate: DevicePtr,
385 c_up: DevicePtr,
386 expert_offsets: DevicePtr,
387 sorted_token_ids: DevicePtr,
388 num_experts: u32,
389 n_out: u32,
390 k: u32,
391 max_m_tiles: u32,
392 stream: u64,
393) -> Result<()> {
394 KernelLaunch::new(gpu, kernel)
395 .grid([div_ceil(2 * n_out, 128), max_m_tiles, num_experts])
396 .block([128, 1, 1])
397 .arg_ptr(a)
398 .arg_ptr(gate_packed_ptrs)
399 .arg_ptr(gate_scale_ptrs)
400 .arg_ptr(gate_scale2_vals)
401 .arg_ptr(up_packed_ptrs)
402 .arg_ptr(up_scale_ptrs)
403 .arg_ptr(up_scale2_vals)
404 .arg_ptr(c_gate)
405 .arg_ptr(c_up)
406 .arg_ptr(expert_offsets)
407 .arg_ptr(sorted_token_ids)
408 .arg_u32(num_experts)
409 .arg_u32(n_out)
410 .arg_u32(k)
411 .launch(stream)
412}
413
414pub fn moe_silu_mul(
418 gpu: &dyn GpuBackend,
419 kernel: KernelHandle,
420 gate: DevicePtr,
421 up: DevicePtr,
422 output: DevicePtr,
423 total_elements: u32,
424 stream: u64,
425) -> Result<()> {
426 KernelLaunch::new(gpu, kernel)
427 .grid([div_ceil(total_elements, 256), 1, 1])
428 .block([256, 1, 1])
429 .arg_ptr(gate)
430 .arg_ptr(up)
431 .arg_ptr(output)
432 .arg_u32(total_elements)
433 .launch(stream)
434}
435
436#[cfg(test)]
437mod tests {
438 use super::ptrtable_legacy_grid_x;
439
440 #[test]
441 fn legacy_ptrtable_grid_covers_every_64_column_tile() {
442 assert_eq!(ptrtable_legacy_grid_x(1), 1);
443 assert_eq!(ptrtable_legacy_grid_x(64), 1);
444 assert_eq!(ptrtable_legacy_grid_x(65), 2);
445 assert_eq!(ptrtable_legacy_grid_x(1024), 16);
446 assert_eq!(ptrtable_legacy_grid_x(3072), 48);
447 }
448}