1#![allow(non_snake_case)]
18
19use teeny_macros::kernel;
20use teeny_triton::triton::{
21 types::{AddOffsets, Comparison},
22 *,
23};
24
25#[kernel]
35pub fn muon_frob_norm_sq<T: Triton, const BLOCK_SIZE: i32>(
36 x_ptr: T::Pointer<f32>,
37 out_ptr: T::Pointer<f32>,
38 n_elements: i32,
39) where
40 T::I32Tensor: types::Tensor<i32, 1>,
41 T::I32Tensor: Comparison<i32, BoolTensor = T::BoolTensor>,
42 T::Pointer<f32>: AddOffsets<i32, 1, T::I32Tensor, Output = T::Tensor<T::Pointer<f32>>>,
43{
44 let pid = T::program_id(Axis::X);
45 let offsets = T::arange(0, BLOCK_SIZE) + pid * BLOCK_SIZE;
46 let mask = offsets.lt(n_elements);
47
48 let x = T::load(
49 x_ptr.add_offsets(offsets),
50 Some(mask),
51 Some(T::zeros::<f32>(&[BLOCK_SIZE])),
52 &[],
53 None,
54 None,
55 None,
56 false,
57 );
58 let partial = T::expand_dims(T::sum(x * x, Some(0), false), 0);
60
61 let out_off: T::I32Tensor = T::arange(0, 1);
63 let _ = T::atomic_add(out_ptr.add_offsets(out_off), partial, None, None, None);
64}
65
66#[kernel]
78pub fn muon_ns_xtx<
79 T: Triton,
80 const TRANSPOSE: bool,
81 const BLOCK_R: i32,
82 const BLOCK_K: i32,
83 const GROUP_R: i32,
84>(
85 x_ptr: T::Pointer<f32>,
86 t_ptr: T::Pointer<f32>,
87 M: i32,
88 N: i32,
89 stride_xm: i32,
90) {
91 let R = if TRANSPOSE { N } else { M };
95 let K = if TRANSPOSE { M } else { N };
96 let a_stride_row = if TRANSPOSE { 1 } else { stride_xm };
97 let a_stride_col = if TRANSPOSE { stride_xm } else { 1 };
98
99 let pid = T::program_id(Axis::X);
100 let num_pid_r = T::cdiv(R, BLOCK_R);
101 let num_pid_in_group = GROUP_R * num_pid_r;
102 let group_id = pid / num_pid_in_group;
103 let first_pid_r = group_id * GROUP_R;
104 let remaining = num_pid_r - first_pid_r;
105 let group_size = if remaining < GROUP_R {
106 remaining
107 } else {
108 GROUP_R
109 };
110 let pid_in_group = pid % num_pid_in_group;
111 let pid_rm = first_pid_r + (pid_in_group % group_size);
112 let pid_rn = pid_in_group / group_size;
113
114 let a_desc = T::make_tensor_descriptor(
116 x_ptr,
117 &[R, K],
118 &[a_stride_row, a_stride_col],
119 &[BLOCK_R, BLOCK_K],
120 Some(PaddingOption::Zero),
121 );
122 let b_desc = T::make_tensor_descriptor(
123 x_ptr,
124 &[R, K],
125 &[a_stride_row, a_stride_col],
126 &[BLOCK_R, BLOCK_K],
127 Some(PaddingOption::Zero),
128 );
129
130 let mut acc = T::zeros::<f32>(&[BLOCK_R, BLOCK_R]);
131 let k_tiles = T::cdiv(K, BLOCK_K);
132 for k in 0..k_tiles {
133 let a = T::load_tensor_descriptor(a_desc, &[pid_rm * BLOCK_R, k * BLOCK_K]);
134 let b = T::load_tensor_descriptor(b_desc, &[pid_rn * BLOCK_R, k * BLOCK_K]);
135 let b_t = T::trans(b, &[1, 0]);
136 acc = T::dot::<f32, f32>(a, b_t, Some(acc), InputPrecision::IEEE, None);
140 }
141
142 let t_desc = T::make_tensor_descriptor(
144 t_ptr,
145 &[R, R],
146 &[R, 1],
147 &[BLOCK_R, BLOCK_R],
148 Some(PaddingOption::Zero),
149 );
150 T::store_tensor_descriptor(t_desc, &[pid_rm * BLOCK_R, pid_rn * BLOCK_R], acc);
151}
152
153#[kernel]
170pub fn muon_ns_step<
171 T: Triton,
172 const TRANSPOSE: bool,
173 const BLOCK_M: i32,
174 const BLOCK_N: i32,
175 const BLOCK_K: i32,
176 const GROUP_M: i32,
177>(
178 t_ptr: T::Pointer<f32>,
179 x_ptr: T::Pointer<f32>,
180 M: i32,
181 N: i32,
182 stride_tm: i32,
183 stride_xm: i32,
184 a: f32,
185 b: f32,
186) {
187 let K = if TRANSPOSE { N } else { M };
189
190 let pid = T::program_id(Axis::X);
191 let num_pid_m = T::cdiv(M, BLOCK_M);
192 let num_pid_n = T::cdiv(N, BLOCK_N);
193 let num_pid_in_group = GROUP_M * num_pid_n;
194 let group_id = pid / num_pid_in_group;
195 let first_pid_m = group_id * GROUP_M;
196 let remaining = num_pid_m - first_pid_m;
197 let group_size = if remaining < GROUP_M {
198 remaining
199 } else {
200 GROUP_M
201 };
202 let pid_in_group = pid % num_pid_in_group;
203 let pid_m = first_pid_m + (pid_in_group % group_size);
204 let pid_n = pid_in_group / group_size;
205
206 let (a_desc, b_desc) = if TRANSPOSE {
210 let ad = T::make_tensor_descriptor(
211 x_ptr,
212 &[M, K],
213 &[stride_xm, 1],
214 &[BLOCK_M, BLOCK_K],
215 Some(PaddingOption::Zero),
216 );
217 let bd = T::make_tensor_descriptor(
218 t_ptr,
219 &[K, N],
220 &[stride_tm, 1],
221 &[BLOCK_K, BLOCK_N],
222 Some(PaddingOption::Zero),
223 );
224 (ad, bd)
225 } else {
226 let ad = T::make_tensor_descriptor(
227 t_ptr,
228 &[M, K],
229 &[stride_tm, 1],
230 &[BLOCK_M, BLOCK_K],
231 Some(PaddingOption::Zero),
232 );
233 let bd = T::make_tensor_descriptor(
234 x_ptr,
235 &[K, N],
236 &[stride_xm, 1],
237 &[BLOCK_K, BLOCK_N],
238 Some(PaddingOption::Zero),
239 );
240 (ad, bd)
241 };
242
243 let mut acc = T::zeros::<f32>(&[BLOCK_M, BLOCK_N]);
244 let k_tiles = T::cdiv(K, BLOCK_K);
245 for k in 0..k_tiles {
246 let av = T::load_tensor_descriptor(a_desc, &[pid_m * BLOCK_M, k * BLOCK_K]);
247 let bv = T::load_tensor_descriptor(b_desc, &[k * BLOCK_K, pid_n * BLOCK_N]);
248 acc = T::dot::<f32, f32>(av, bv, Some(acc), InputPrecision::IEEE, None);
251 }
252
253 let x_desc = T::make_tensor_descriptor(
255 x_ptr,
256 &[M, N],
257 &[stride_xm, 1],
258 &[BLOCK_M, BLOCK_N],
259 Some(PaddingOption::Zero),
260 );
261 let x_tile = T::load_tensor_descriptor(x_desc, &[pid_m * BLOCK_M, pid_n * BLOCK_N]);
262
263 let a_t = T::full::<f32>(&[BLOCK_M, BLOCK_N], a);
264 let b_t = T::full::<f32>(&[BLOCK_M, BLOCK_N], b);
265 let result = a_t * x_tile + b_t * acc;
266 T::store_tensor_descriptor(x_desc, &[pid_m * BLOCK_M, pid_n * BLOCK_N], result);
267}
268
269#[kernel]
275pub fn muon_update<T: Triton, const BLOCK_SIZE: i32>(
276 params_ptr: T::Pointer<f32>,
277 grad_ptr: T::Pointer<f32>,
278 n_elements: i32,
279 lr: f32,
280) where
281 T::I32Tensor: types::Tensor<i32, 1>,
282 T::I32Tensor: Comparison<i32, BoolTensor = T::BoolTensor>,
283 T::Pointer<f32>: AddOffsets<i32, 1, T::I32Tensor, Output = T::Tensor<T::Pointer<f32>>>,
284{
285 let pid = T::program_id(Axis::X);
286 let offsets = T::arange(0, BLOCK_SIZE) + pid * BLOCK_SIZE;
287 let mask = offsets.lt(n_elements);
288
289 let p = T::load(
290 params_ptr.add_offsets(offsets),
291 Some(mask),
292 None,
293 &[],
294 None,
295 None,
296 None,
297 false,
298 );
299 let g = T::load(
300 grad_ptr.add_offsets(offsets),
301 Some(mask),
302 None,
303 &[],
304 None,
305 None,
306 None,
307 false,
308 );
309 let lr_t = T::full::<f32>(&[BLOCK_SIZE], lr);
310
311 T::store(
312 params_ptr.add_offsets(offsets),
313 p - lr_t * g,
314 Some(mask),
315 &[],
316 None,
317 None,
318 );
319}