metrale_model_layers/layers/ops/
fp8_moe_grouped_tc_w8a8.rs1use anyhow::{Result, ensure};
12use metrale_gpu_runtime::gpu::{DevicePtr, GpuBackend, KernelHandle};
13use metrale_gpu_runtime::kernel_args::{KernelLaunch, div_ceil};
14
15use super::{FP8_GROUPED_TC_ROWS_PER_PASS, Fp8GroupedGeometry};
16use crate::weight_map::Fp8Weight;
17
18pub const FP8_GROUPED_GATE_UP_TC_W8A8: Fp8GroupedGeometry = Fp8GroupedGeometry {
21 cols_per_cta: 128,
22 rows_per_pass: FP8_GROUPED_TC_ROWS_PER_PASS,
23 threads: 128,
24};
25
26pub const FP8_GROUPED_DOWN_TC_W8A8: Fp8GroupedGeometry = Fp8GroupedGeometry {
28 cols_per_cta: 256,
29 rows_per_pass: FP8_GROUPED_TC_ROWS_PER_PASS,
30 threads: 128,
31};
32
33fn align16(x: usize) -> usize {
34 x.div_ceil(16) * 16
35}
36
37#[derive(Clone, Copy, Debug, PartialEq, Eq)]
43pub struct Fp8GroupedW8a8Layout {
44 pub act_s: usize,
45 pub xq: usize,
46 pub xs: usize,
47 pub sh_s: usize,
48}
49
50impl Fp8GroupedW8a8Layout {
51 pub fn new(
54 m: usize,
55 top_k: usize,
56 hidden: usize,
57 inter: usize,
58 routed_bytes: usize,
59 shared_bytes: usize,
60 ) -> Result<Self> {
61 ensure!(
62 hidden.is_multiple_of(128) && inter.is_multiple_of(128),
63 "W8A8 grouped decode: hidden {hidden} and inter {inter} must be whole 128 groups"
64 );
65 let te = m * top_k;
66 let act_s = align16(te * inter);
67 let xq = align16(act_s + te * (inter / 128) * 4);
68 let xs = align16(xq + m * hidden);
69 let routed_end = xs + m * (hidden / 128) * 4;
70 let sh_s = align16(m * inter);
71 let shared_end = sh_s + m * (inter / 128) * 4;
72 ensure!(
73 routed_end <= routed_bytes && shared_end <= shared_bytes,
74 "W8A8 grouped decode: needs {routed_end} + {shared_end} bytes, buffers hold {routed_bytes} + {shared_bytes}"
75 );
76 Ok(Self {
77 act_s,
78 xq,
79 xs,
80 sh_s,
81 })
82 }
83}
84
85#[allow(clippy::too_many_arguments)]
87pub fn moe_act_quant_e4m3(
88 gpu: &dyn GpuBackend,
89 kernel: KernelHandle,
90 x: DevicePtr,
91 q: DevicePtr,
92 s: DevicePtr,
93 rows: u32,
94 k: u32,
95 stream: u64,
96) -> Result<()> {
97 KernelLaunch::new(gpu, kernel)
98 .grid([rows, 1, 1])
99 .block([128, 1, 1])
100 .arg_ptr(x)
101 .arg_ptr(q)
102 .arg_ptr(s)
103 .arg_u32(k)
104 .launch(stream)
105}
106
107pub struct Fp8GroupedW8a8Rows {
110 pub expert_offsets: DevicePtr,
111 pub sorted_token_ids: DevicePtr,
112 pub active_experts: DevicePtr,
113 pub active_count: DevicePtr,
114 pub cap: u32,
115 pub num_tokens: u32,
116}
117
118#[allow(clippy::too_many_arguments)]
121pub fn moe_expert_gate_up_act_fp8_grouped_tc_w8a8(
122 gpu: &dyn GpuBackend,
123 kernel: KernelHandle,
124 xq: DevicePtr,
125 xs: DevicePtr,
126 gate: (DevicePtr, DevicePtr),
127 up: (DevicePtr, DevicePtr),
128 act: (DevicePtr, DevicePtr),
129 rows: &Fp8GroupedW8a8Rows,
130 sh_gate: &Fp8Weight,
131 sh_up: &Fp8Weight,
132 sh: (DevicePtr, DevicePtr),
133 n: u32,
134 k: u32,
135 stream: u64,
136) -> Result<()> {
137 let g = FP8_GROUPED_GATE_UP_TC_W8A8;
138 KernelLaunch::new(gpu, kernel)
139 .grid([
140 div_ceil(n, g.cols_per_cta),
141 rows.cap + div_ceil(rows.num_tokens, g.rows_per_pass),
142 1,
143 ])
144 .block([g.threads, 1, 1])
145 .arg_ptr(xq)
146 .arg_ptr(xs)
147 .arg_ptr(gate.0)
148 .arg_ptr(gate.1)
149 .arg_ptr(up.0)
150 .arg_ptr(up.1)
151 .arg_ptr(act.0)
152 .arg_ptr(act.1)
153 .arg_ptr(rows.expert_offsets)
154 .arg_ptr(rows.sorted_token_ids)
155 .arg_ptr(rows.active_experts)
156 .arg_ptr(rows.active_count)
157 .arg_ptr(sh_gate.weight)
158 .arg_ptr(sh_gate.row_scale)
159 .arg_ptr(sh_up.weight)
160 .arg_ptr(sh_up.row_scale)
161 .arg_ptr(sh.0)
162 .arg_ptr(sh.1)
163 .arg_u32(n)
164 .arg_u32(k)
165 .arg_u32(rows.cap)
166 .arg_u32(rows.num_tokens)
167 .launch(stream)
168}
169
170#[allow(clippy::too_many_arguments)]
173pub fn moe_expert_down_act_fp8_grouped_tc_w8a8(
174 gpu: &dyn GpuBackend,
175 kernel: KernelHandle,
176 act: (DevicePtr, DevicePtr),
177 down: (DevicePtr, DevicePtr),
178 output: DevicePtr,
179 rows: &Fp8GroupedW8a8Rows,
180 sh: (DevicePtr, DevicePtr),
181 sh_down: &Fp8Weight,
182 sh_down_out: DevicePtr,
183 n: u32,
184 k: u32,
185 stream: u64,
186) -> Result<()> {
187 let g = FP8_GROUPED_DOWN_TC_W8A8;
188 KernelLaunch::new(gpu, kernel)
189 .grid([
190 div_ceil(n, g.cols_per_cta),
191 rows.cap + div_ceil(rows.num_tokens, g.rows_per_pass),
192 1,
193 ])
194 .block([g.threads, 1, 1])
195 .arg_ptr(act.0)
196 .arg_ptr(act.1)
197 .arg_ptr(down.0)
198 .arg_ptr(down.1)
199 .arg_ptr(output)
200 .arg_ptr(rows.expert_offsets)
201 .arg_ptr(rows.active_experts)
202 .arg_ptr(rows.active_count)
203 .arg_ptr(sh.0)
204 .arg_ptr(sh.1)
205 .arg_ptr(sh_down.weight)
206 .arg_ptr(sh_down.row_scale)
207 .arg_ptr(sh_down_out)
208 .arg_u32(n)
209 .arg_u32(k)
210 .arg_u32(rows.cap)
211 .arg_u32(rows.num_tokens)
212 .launch(stream)
213}