metrale_model_layers/layers/ops/
gemm_dense_bf16.rs1use super::*;
11
12pub fn dense_gemm_tc(
15 gpu: &dyn GpuBackend,
16 kernel: KernelHandle,
17 input: DevicePtr,
18 weight: &DenseWeight,
19 output: DevicePtr,
20 m: u32,
21 n: u32,
22 k: u32,
23 stream: u64,
24) -> Result<()> {
25 KernelLaunch::new(gpu, kernel)
26 .grid([div_ceil(n, 64), div_ceil(m, 16), 1])
27 .block([128, 1, 1])
28 .arg_ptr(input)
29 .arg_ptr(weight.weight)
30 .arg_ptr(output)
31 .arg_u32(m)
32 .arg_u32(n)
33 .arg_u32(k)
34 .launch(stream)
35}
36
37#[allow(clippy::too_many_arguments)]
46pub fn dense_gemm_tc_scaled_acc(
47 gpu: &dyn GpuBackend,
48 kernel: KernelHandle,
49 input: DevicePtr,
50 weight: &DenseWeight,
51 output: DevicePtr,
52 m: u32,
53 n: u32,
54 k: u32,
55 scale: f32,
56 stream: u64,
57) -> Result<()> {
58 KernelLaunch::new(gpu, kernel)
59 .grid([div_ceil(n, 64), div_ceil(m, 16), 1])
60 .block([128, 1, 1])
61 .arg_ptr(input)
62 .arg_ptr(weight.weight)
63 .arg_ptr(output)
64 .arg_u32(m)
65 .arg_u32(n)
66 .arg_u32(k)
67 .arg_f32(scale)
68 .launch(stream)
69}
70
71#[allow(clippy::too_many_arguments)]
75pub fn dense_gemm_splitk(
76 gpu: &dyn GpuBackend,
77 partial_kernel: KernelHandle,
78 reduce_kernel: KernelHandle,
79 input: DevicePtr,
80 weight: &DenseWeight,
81 output: DevicePtr,
82 workspace: DevicePtr,
83 m: u32,
84 n: u32,
85 k: u32,
86 k_splits: u32,
87 stream: u64,
88) -> Result<()> {
89 KernelLaunch::new(gpu, partial_kernel)
90 .grid([div_ceil(n, 16), div_ceil(m, 16), k_splits])
91 .block([16, 16, 1])
92 .arg_ptr(input)
93 .arg_ptr(weight.weight)
94 .arg_ptr(workspace)
95 .arg_u32(m)
96 .arg_u32(n)
97 .arg_u32(k)
98 .arg_u32(k_splits)
99 .launch(stream)?;
100 KernelLaunch::new(gpu, reduce_kernel)
101 .grid([div_ceil(n, 256), m, 1])
102 .block([256, 1, 1])
103 .arg_ptr(workspace)
104 .arg_ptr(output)
105 .arg_u32(m)
106 .arg_u32(n)
107 .arg_u32(k_splits)
108 .launch(stream)
109}
110
111pub fn dense_gemm(
115 gpu: &dyn GpuBackend,
116 kernel: KernelHandle,
117 input: DevicePtr,
118 weight: &DenseWeight,
119 output: DevicePtr,
120 m: u32,
121 n: u32,
122 k: u32,
123 stream: u64,
124) -> Result<()> {
125 KernelLaunch::new(gpu, kernel)
126 .grid([div_ceil(n, 16), div_ceil(m, 16), 1])
127 .block([16, 16, 1])
128 .arg_ptr(input)
129 .arg_ptr(weight.weight)
130 .arg_ptr(output)
131 .arg_u32(m)
132 .arg_u32(n)
133 .arg_u32(k)
134 .launch(stream)
135}
136
137pub const MOE_ROUTER_GEMM_COLS: u32 = 4;
140pub const MOE_ROUTER_GEMM_ROWS: u32 = 16;
142
143#[allow(clippy::too_many_arguments)]
150pub fn moe_router_gemm(
151 gpu: &dyn GpuBackend,
152 kernel: KernelHandle,
153 input: DevicePtr,
154 weight: &DenseWeight,
155 output: DevicePtr,
156 m: u32,
157 n: u32,
158 k: u32,
159 stream: u64,
160) -> Result<()> {
161 anyhow::ensure!(
162 k.is_multiple_of(16),
163 "moe_router_gemm: k={k} is not a multiple of 16"
164 );
165 KernelLaunch::new(gpu, kernel)
166 .grid([
167 div_ceil(n, MOE_ROUTER_GEMM_COLS),
168 div_ceil(m, MOE_ROUTER_GEMM_ROWS),
169 1,
170 ])
171 .block([256, 1, 1])
172 .arg_ptr(input)
173 .arg_ptr(weight.weight)
174 .arg_ptr(output)
175 .arg_u32(m)
176 .arg_u32(n)
177 .arg_u32(k)
178 .launch(stream)
179}
180
181pub fn dense_gemm_router(
187 gpu: &dyn GpuBackend,
188 kernel: KernelHandle,
189 input: DevicePtr,
190 weight: &DenseWeight,
191 output: DevicePtr,
192 m: u32,
193 n: u32,
194 k: u32,
195 stream: u64,
196) -> Result<()> {
197 KernelLaunch::new(gpu, kernel)
198 .grid([div_ceil(n, 64), div_ceil(m, 16), 1])
199 .block([16, 16, 1])
200 .arg_ptr(input)
201 .arg_ptr(weight.weight)
202 .arg_ptr(output)
203 .arg_u32(m)
204 .arg_u32(n)
205 .arg_u32(k)
206 .launch(stream)
207}
208
209pub const MOE_ROUTER_GEMM_MAX_PREFILL_ROWS: u32 = 64;
213
214pub const MOE_ROUTER_RT_MIN_ROWS: u32 = 1024;
217
218#[allow(clippy::too_many_arguments)]
222pub fn moe_router_gemm_rt(
223 gpu: &dyn GpuBackend,
224 kernel: KernelHandle,
225 input: DevicePtr,
226 weight: &DenseWeight,
227 output: DevicePtr,
228 m: u32,
229 n: u32,
230 k: u32,
231 stream: u64,
232) -> Result<()> {
233 anyhow::ensure!(
234 k.is_multiple_of(16),
235 "moe_router_gemm_rt: K={k} is not a multiple of 16"
236 );
237 KernelLaunch::new(gpu, kernel)
238 .grid([div_ceil(n, 128), div_ceil(m, 64), 1])
239 .block([256, 1, 1])
240 .arg_ptr(input)
241 .arg_ptr(weight.weight)
242 .arg_ptr(output)
243 .arg_u32(m)
244 .arg_u32(n)
245 .arg_u32(k)
246 .launch(stream)
247}
248
249#[allow(clippy::too_many_arguments)]
253pub fn dense_gemm_bf16_pipelined(
254 gpu: &dyn GpuBackend,
255 kernel: KernelHandle,
256 input: DevicePtr,
257 weight: &DenseWeight,
258 output: DevicePtr,
259 m: u32,
260 n: u32,
261 k: u32,
262 stream: u64,
263) -> Result<()> {
264 KernelLaunch::new(gpu, kernel)
265 .grid([div_ceil(n, 128), div_ceil(m, 128), 1])
266 .block([256, 1, 1])
267 .arg_ptr(input)
268 .arg_ptr(weight.weight)
269 .arg_ptr(output)
270 .arg_u32(m)
271 .arg_u32(n)
272 .arg_u32(k)
273 .launch(stream)
274}
275
276#[allow(clippy::too_many_arguments)]
280pub fn dense_gemm_prefill(
281 gpu: &dyn GpuBackend,
282 fallback_kernel: KernelHandle,
283 pipelined_kernel: KernelHandle,
284 input: DevicePtr,
285 weight: &DenseWeight,
286 output: DevicePtr,
287 m: u32,
288 n: u32,
289 k: u32,
290 stream: u64,
291) -> Result<()> {
292 if pipelined_kernel.0 != 0 {
293 dense_gemm_bf16_pipelined(
294 gpu,
295 pipelined_kernel,
296 input,
297 weight,
298 output,
299 m,
300 n,
301 k,
302 stream,
303 )
304 } else {
305 dense_gemm(gpu, fallback_kernel, input, weight, output, m, n, k, stream)
306 }
307}