1#![allow(unused_imports)]
10
11use anyhow::Result;
12use metrale_gpu_runtime::gpu::{DevicePtr, GpuBackend, KernelHandle};
13use metrale_gpu_runtime::kernel_args::{KernelLaunch, div_ceil};
14
15use crate::layers::moe;
16use crate::weight_map::{DenseWeight, Fp8DenseWeight, Fp8Weight, QuantizedWeight};
17
18use super::*;
19
20#[allow(clippy::too_many_arguments)]
28pub fn rms_norm_strided(
29 gpu: &dyn GpuBackend,
30 kernel: KernelHandle,
31 input: DevicePtr,
32 weight: &DenseWeight,
33 output: DevicePtr,
34 rows_per_group: u32,
35 num_groups: u32,
36 hidden_size: u32,
37 eps: f32,
38 row_stride: u32,
39 stream: u64,
40) -> Result<()> {
41 KernelLaunch::new(gpu, kernel)
42 .grid([rows_per_group, num_groups, 1])
43 .block([hidden_size.min(1024), 1, 1])
44 .arg_ptr(input)
45 .arg_ptr(weight.weight)
46 .arg_ptr(output)
47 .arg_u32(hidden_size)
48 .arg_f32(eps)
49 .arg_u32(row_stride)
50 .launch(stream)
51}
52
53pub fn rms_norm(
58 gpu: &dyn GpuBackend,
59 kernel: KernelHandle,
60 input: DevicePtr,
61 weight: &DenseWeight,
62 output: DevicePtr,
63 num_tokens: u32,
64 hidden_size: u32,
65 eps: f32,
66 stream: u64,
67) -> Result<()> {
68 KernelLaunch::new(gpu, kernel)
69 .grid([num_tokens, 1, 1])
70 .block([hidden_size.min(1024), 1, 1])
71 .arg_ptr(input)
72 .arg_ptr(weight.weight)
73 .arg_ptr(output)
74 .arg_u32(hidden_size)
75 .arg_f32(eps)
76 .launch(stream)
77}
78
79pub fn rms_norm_warp_row(
84 gpu: &dyn GpuBackend,
85 kernel: KernelHandle,
86 input: DevicePtr,
87 weight: &DenseWeight,
88 output: DevicePtr,
89 num_rows: u32,
90 hidden_size: u32,
91 eps: f32,
92 stream: u64,
93) -> Result<()> {
94 const ROWS_PER_BLOCK: u32 = 8;
95 KernelLaunch::new(gpu, kernel)
96 .grid([num_rows.div_ceil(ROWS_PER_BLOCK), 1, 1])
97 .block([32 * ROWS_PER_BLOCK, 1, 1])
98 .arg_ptr(input)
99 .arg_ptr(weight.weight)
100 .arg_ptr(output)
101 .arg_u32(num_rows)
102 .arg_u32(hidden_size)
103 .arg_f32(eps)
104 .launch(stream)
105}
106
107pub fn rms_norm_short_row_eligible(num_rows: u32, hidden_size: u32) -> bool {
111 use std::sync::OnceLock;
112 static ON: OnceLock<bool> = OnceLock::new();
113 let on = *ON.get_or_init(|| std::env::var("METRALE_RMS_NORM_WARP_ROW").as_deref() != Ok("0"));
114 on && hidden_size <= 256 && hidden_size.is_multiple_of(2) && num_rows >= 1024
115}
116
117pub fn rms_norm_residual(
120 gpu: &dyn GpuBackend,
121 kernel: KernelHandle,
122 input: DevicePtr,
123 weight: &DenseWeight,
124 output: DevicePtr,
125 residual: DevicePtr,
126 num_tokens: u32,
127 hidden_size: u32,
128 eps: f32,
129 stream: u64,
130) -> Result<()> {
131 KernelLaunch::new(gpu, kernel)
132 .grid([num_tokens, 1, 1])
133 .block([hidden_size.min(1024), 1, 1])
134 .arg_ptr(input)
135 .arg_ptr(weight.weight)
136 .arg_ptr(output)
137 .arg_ptr(residual)
138 .arg_u32(hidden_size)
139 .arg_f32(eps)
140 .launch(stream)
141}
142
143#[allow(clippy::too_many_arguments)]
146pub fn residual_add_rms_norm(
147 gpu: &dyn GpuBackend,
148 kernel: KernelHandle,
149 hidden: DevicePtr,
150 src: DevicePtr,
151 weight: &DenseWeight,
152 output: DevicePtr,
153 residual: DevicePtr,
154 num_tokens: u32,
155 hidden_size: u32,
156 eps: f32,
157 stream: u64,
158) -> Result<()> {
159 KernelLaunch::new(gpu, kernel)
160 .grid([num_tokens, 1, 1])
161 .block([hidden_size.min(1024), 1, 1])
162 .arg_ptr(hidden)
163 .arg_ptr(src)
164 .arg_ptr(weight.weight)
165 .arg_ptr(output)
166 .arg_ptr(residual)
167 .arg_u32(hidden_size)
168 .arg_f32(eps)
169 .launch(stream)
170}
171
172#[allow(clippy::too_many_arguments)]
177pub fn residual_add_rms_norm_exact(
178 gpu: &dyn GpuBackend,
179 kernel: KernelHandle,
180 hidden: DevicePtr,
181 src: DevicePtr,
182 weight: &DenseWeight,
183 output: DevicePtr,
184 residual: DevicePtr,
185 num_tokens: u32,
186 hidden_size: u32,
187 eps: f32,
188 stream: u64,
189) -> Result<()> {
190 residual_add_rms_norm(
191 gpu,
192 kernel,
193 hidden,
194 src,
195 weight,
196 output,
197 residual,
198 num_tokens,
199 hidden_size,
200 eps,
201 stream,
202 )
203}
204
205#[allow(clippy::too_many_arguments)]
210pub fn residual_add_rms_norm_gatef32(
211 gpu: &dyn GpuBackend,
212 kernel: KernelHandle,
213 hidden: DevicePtr,
214 src: DevicePtr,
215 weight: &DenseWeight,
216 output: DevicePtr,
217 output_f32: DevicePtr,
218 residual: DevicePtr,
219 num_tokens: u32,
220 hidden_size: u32,
221 eps: f32,
222 stream: u64,
223) -> Result<()> {
224 KernelLaunch::new(gpu, kernel)
225 .grid([num_tokens, 1, 1])
226 .block([hidden_size.min(1024), 1, 1])
227 .arg_ptr(hidden)
228 .arg_ptr(src)
229 .arg_ptr(weight.weight)
230 .arg_ptr(output)
231 .arg_ptr(output_f32)
232 .arg_ptr(residual)
233 .arg_u32(hidden_size)
234 .arg_f32(eps)
235 .launch(stream)
236}
237
238pub fn gated_rms_norm(
246 gpu: &dyn GpuBackend,
247 kernel: KernelHandle,
248 input: DevicePtr,
249 gate: DevicePtr,
250 weight: &DenseWeight,
251 output: DevicePtr,
252 num_tokens: u32,
253 hidden_size: u32,
254 gate_stride: u32,
255 eps: f32,
256 group_size: u32,
257 stream: u64,
258) -> Result<()> {
259 KernelLaunch::new(gpu, kernel)
260 .grid([num_tokens, 1, 1])
261 .block([hidden_size.min(1024), 1, 1])
262 .arg_ptr(input)
263 .arg_ptr(gate)
264 .arg_ptr(weight.weight)
265 .arg_ptr(output)
266 .arg_u32(hidden_size)
267 .arg_f32(eps)
268 .arg_u32(gate_stride)
269 .arg_u32(group_size)
270 .launch(stream)
271}
272
273#[allow(clippy::too_many_arguments)]
282pub fn gated_rms_norm_strided(
283 gpu: &dyn GpuBackend,
284 kernel: KernelHandle,
285 input: DevicePtr,
286 gate: DevicePtr,
287 weight: &DenseWeight,
288 output: DevicePtr,
289 heads_per_seq: u32,
290 num_seqs: u32,
291 hidden_size: u32,
292 gate_stride: u32,
293 eps: f32,
294 group_size: u32,
295 input_seq_stride: u32,
296 gate_seq_stride: u32,
297 output_seq_stride: u32,
298 stream: u64,
299) -> Result<()> {
300 KernelLaunch::new(gpu, kernel)
301 .grid([heads_per_seq, num_seqs, 1])
302 .block([hidden_size.min(1024), 1, 1])
303 .arg_ptr(input)
304 .arg_ptr(gate)
305 .arg_ptr(weight.weight)
306 .arg_ptr(output)
307 .arg_u32(hidden_size)
308 .arg_f32(eps)
309 .arg_u32(gate_stride)
310 .arg_u32(group_size)
311 .arg_u32(input_seq_stride)
312 .arg_u32(gate_seq_stride)
313 .arg_u32(output_seq_stride)
314 .launch(stream)
315}
316
317#[allow(clippy::too_many_arguments)]
322pub fn gated_rms_norm_prefill(
323 gpu: &dyn GpuBackend,
324 kernel: KernelHandle,
325 input: DevicePtr,
326 gate: DevicePtr,
327 weight: &DenseWeight,
328 output: DevicePtr,
329 heads_per_token: u32,
330 head_dim: u32,
331 eps: f32,
332 num_actual_tokens: u32,
333 input_token_stride: u32,
334 gate_token_stride: u32,
335 stream: u64,
336) -> Result<()> {
337 KernelLaunch::new(gpu, kernel)
338 .grid([heads_per_token, num_actual_tokens, 1])
339 .block([head_dim.min(1024), 1, 1])
340 .arg_ptr(input)
341 .arg_ptr(gate)
342 .arg_ptr(weight.weight)
343 .arg_ptr(output)
344 .arg_u32(head_dim)
345 .arg_f32(eps)
346 .arg_u32(input_token_stride)
347 .arg_u32(gate_token_stride)
348 .launch(stream)
349}