1use std::marker::PhantomData;
2
3use cubecl::prelude::*;
4use cubecl::std::tensor::{
5 View, ViewMut,
6 launch::ViewArg,
7 layout::{Coords1d, VirtualLayout, VirtualLayoutLaunch},
8};
9use cubecl::unexpanded;
10use cubek_std::launch::tma::tma_operand;
11use cubek_std::{InputBinding, MatrixLayout, stage::SwizzleMode};
12
13use crate::components::global::memory::{
14 BatchLayout, BatchLayoutLaunch, GlobalLayout, GlobalLayoutConfig, GlobalLayoutLaunch,
15 GlobalScaleLayout, NoopLayout, NoopLayoutLaunch, SimpleTmaGlobalLayout,
16 SimpleTmaGlobalLayoutLaunch,
17};
18use crate::{
19 definition::{Blueprint as _, MatmulElems, MatmulProblem, MatmulVectorSizes},
20 routines::BatchMatmulRoutine,
21};
22
23define_scalar!(pub Lhs);
24define_scalar!(pub Rhs);
25define_scalar!(pub Acc);
26
27define_size!(pub LhsSize);
28define_size!(pub RhsSize);
29define_size!(pub AccSize);
30
31pub type InputArg<MA> =
33 <MA as MatmulArgs>::Input<Vector<Lhs, LhsSize>, Vector<Rhs, RhsSize>, Vector<Acc, AccSize>>;
34
35pub type OutputArg<MA> = <MA as MatmulArgs>::Output<Vector<Acc, AccSize>>;
37
38pub type ConfigArg<MA> = <MA as MatmulArgs>::Config;
40
41pub type InputRuntimeArg<MA, R> = <InputArg<MA> as LaunchArg>::RuntimeArg<R>;
43
44pub type ConfigRuntimeArg<MA, R> = <ConfigArg<MA> as LaunchArg>::RuntimeArg<R>;
46
47pub type OutputRuntimeArg<MA, R> = <OutputArg<MA> as LaunchArg>::RuntimeArg<R>;
49
50pub type BatchedCoords = (usize, u32, u32);
51
52pub trait ConcreteInputsFactory<A: BatchMatmulRoutine<()>>: LaunchArg {
55 #[allow(clippy::too_many_arguments)]
56 fn create<R: Runtime>(
57 lhs: InputBinding<R>,
58 rhs: InputBinding<R>,
59 blueprint: &A::Blueprint,
60 problem: &MatmulProblem,
61 vector_sizes: &MatmulVectorSizes,
62 dtypes: &MatmulElems,
63 ) -> Self::RuntimeArg<R>;
64}
65
66pub trait ConcreteOutputFactory<A: BatchMatmulRoutine<()>>: LaunchArg {
69 #[allow(clippy::too_many_arguments)]
70 fn create<R: Runtime>(
71 out: TensorBinding<R>,
72 blueprint: &A::Blueprint,
73 problem: &MatmulProblem,
74 vector_sizes: &MatmulVectorSizes,
75 dtypes: &MatmulElems,
76 ) -> Self::RuntimeArg<R>;
77}
78
79pub trait RuntimeConfig: LaunchArg + CubeType<ExpandType: Clone> + Clone + Send + Sync {}
80impl<T: LaunchArg + CubeType<ExpandType: Clone> + Clone + Send + Sync> RuntimeConfig for T {}
81
82#[cube]
83pub trait MatmulArgs: Send + Sync + 'static + Clone {
85 type Input<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>: LaunchArg + CubeType;
87
88 type Output<EO: CubePrimitive>: LaunchArg + CubeType;
90
91 type Config: RuntimeConfig;
93
94 type State<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>: CubeType;
97
98 fn init_state<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
100 input: &Self::Input<Lhs, Rhs, EO>,
101 output: &mut Self::Output<EO>,
102 config: Self::Config,
103 #[comptime] lhs_layout_config: GlobalLayoutConfig,
104 #[comptime] rhs_layout_config: GlobalLayoutConfig,
105 #[comptime] out_layout_config: GlobalLayoutConfig,
106 ) -> Self::State<Lhs, Rhs, EO>;
107
108 fn view_lhs<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
109 _state: &Self::State<Lhs, Rhs, EO>,
110 ) -> View<'_, Lhs, BatchedCoords> {
111 unexpanded!()
112 }
113 fn batch_lhs<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
114 _state: &Self::State<Lhs, Rhs, EO>,
115 _batch: usize,
116 ) -> usize {
117 unexpanded!()
118 }
119 fn view_rhs<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
120 _state: &Self::State<Lhs, Rhs, EO>,
121 ) -> View<'_, Rhs, BatchedCoords> {
122 unexpanded!()
123 }
124 fn batch_rhs<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
125 _state: &Self::State<Lhs, Rhs, EO>,
126 _batch: usize,
127 ) -> usize {
128 unexpanded!()
129 }
130 fn view_acc<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
131 _state: &Self::State<Lhs, Rhs, EO>,
132 ) -> ComptimeOption<View<'_, EO, BatchedCoords>> {
133 unexpanded!()
134 }
135 fn batch_acc<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
136 _state: &Self::State<Lhs, Rhs, EO>,
137 _batch: usize,
138 ) -> usize {
139 unexpanded!()
140 }
141 fn view_out<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
142 _state: &Self::State<Lhs, Rhs, EO>,
143 ) -> ViewMut<'_, EO, BatchedCoords> {
144 unexpanded!()
145 }
146 fn batch_out<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
147 _state: &Self::State<Lhs, Rhs, EO>,
148 _batch: usize,
149 ) -> usize {
150 unexpanded!()
151 }
152
153 fn runtime_config<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
154 _state: &Self::State<Lhs, Rhs, EO>,
155 ) -> Self::Config {
156 unexpanded!()
157 }
158}
159
160#[derive(Clone, Copy)]
161pub enum TensorInputIdent {
163 Lhs,
164 Rhs,
165}
166
167#[derive(Clone)]
168pub struct TensorArgs<Config: RuntimeConfig = ()> {
172 _config: PhantomData<Config>,
173}
174
175#[derive(CubeLaunch, CubeType, Clone)]
176#[expand(derive(Clone))]
177pub struct TensorInputs<Lhs: CubePrimitive, Rhs: CubePrimitive, Acc: CubePrimitive> {
179 lhs_batch: VirtualLayout<Coords1d, Coords1d>,
181 lhs: View<'static, Lhs, BatchedCoords>,
182 rhs_batch: VirtualLayout<Coords1d, Coords1d>,
184 rhs: View<'static, Rhs, BatchedCoords>,
185 acc_batch: ComptimeOption<VirtualLayout<Coords1d, Coords1d>>,
187 acc: ComptimeOption<View<'static, Acc, BatchedCoords>>,
188}
189
190impl<Lhs: CubePrimitive, Rhs: CubePrimitive, Acc: CubePrimitive, A: BatchMatmulRoutine<()>>
191 ConcreteInputsFactory<A> for TensorInputs<Lhs, Rhs, Acc>
192{
193 fn create<R: Runtime>(
194 lhs: InputBinding<R>,
195 rhs: InputBinding<R>,
196 blueprint: &A::Blueprint,
197 problem: &MatmulProblem,
198 vector_sizes: &MatmulVectorSizes,
199 _dtypes: &MatmulElems,
200 ) -> Self::RuntimeArg<R> {
201 let view = |handle: InputBinding<R>, config: GlobalLayoutConfig, vector_size| match handle {
202 InputBinding::Normal(handle, _dtype) => {
203 let layout = GlobalLayoutLaunch::from_handle(&handle, vector_size, config);
204 ViewArg::new_tensor::<GlobalLayout>(handle.into_tensor_arg(), layout)
205 }
206 InputBinding::Quantized {
207 data,
208 scale,
209 shape,
210 scheme,
211 ..
212 } => {
213 let (data_layout, scales_layout) = GlobalLayoutLaunch::from_quantized_handle(
214 &data,
215 &scale,
216 &shape,
217 problem,
218 scheme,
219 vector_size,
220 config,
221 );
222 let data_view =
223 ViewArg::new_tensor::<GlobalLayout>(data.into_tensor_arg(), data_layout);
224 let scales_view = ViewArg::new_tensor::<GlobalScaleLayout>(
225 scale.into_tensor_arg(),
226 scales_layout,
227 );
228 ViewArg::new_quantized(data_view, scales_view, scheme)
229 }
230 };
231 let batch_layout = |handle: &InputBinding<R>| match handle {
232 InputBinding::Normal(handle, _dtype) => {
233 let layout = BatchLayoutLaunch::from_handle(handle, problem);
234 VirtualLayoutLaunch::new::<BatchLayout>(layout)
235 }
236 InputBinding::Quantized { .. } => {
237 VirtualLayoutLaunch::new::<NoopLayout>(NoopLayoutLaunch::new())
238 }
239 };
240
241 TensorInputsLaunch::new(
242 batch_layout(&lhs),
243 view(lhs, blueprint.lhs_global_layout_config(), vector_sizes.lhs),
244 batch_layout(&rhs),
245 view(rhs, blueprint.rhs_global_layout_config(), vector_sizes.rhs),
246 ComptimeOptionArgs::None,
247 ComptimeOptionArgs::None,
248 )
249 }
250}
251
252#[derive(CubeType, CubeLaunch, Clone)]
253#[expand(derive(Clone))]
254pub struct TensorOutput<EG: CubePrimitive> {
255 view: ViewMut<'static, EG, BatchedCoords>,
256 batch: VirtualLayout<Coords1d, Coords1d>,
257}
258
259impl<EG: CubePrimitive, A: BatchMatmulRoutine<()>> ConcreteOutputFactory<A> for TensorOutput<EG> {
260 fn create<R: Runtime>(
261 out: TensorBinding<R>,
262 blueprint: &A::Blueprint,
263 problem: &MatmulProblem,
264 vector_sizes: &MatmulVectorSizes,
265 _dtypes: &MatmulElems,
266 ) -> Self::RuntimeArg<R> {
267 let layout = GlobalLayoutLaunch::from_handle(
268 &out,
269 vector_sizes.out,
270 blueprint.out_global_layout_config(),
271 );
272 let batch = BatchLayoutLaunch::from_handle(&out, problem);
273 let view = ViewArg::new_tensor::<GlobalLayout>(out.into_tensor_arg(), layout);
274 TensorOutputLaunch::new(view, VirtualLayoutLaunch::new::<BatchLayout>(batch))
275 }
276}
277
278#[cube]
279impl<Config: RuntimeConfig> MatmulArgs for TensorArgs<Config> {
280 type Output<EO: CubePrimitive> = TensorOutput<EO>;
281 type Input<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive> =
282 TensorInputs<Lhs, Rhs, EO>;
283 type Config = Config;
284 type State<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive> =
285 (TensorInputs<Lhs, Rhs, EO>, TensorOutput<EO>, Config);
286
287 fn init_state<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
288 input: &Self::Input<Lhs, Rhs, EO>,
289 output: &mut Self::Output<EO>,
290 config: Self::Config,
291 #[comptime] _lhs_layout_config: GlobalLayoutConfig,
292 #[comptime] _rhs_layout_config: GlobalLayoutConfig,
293 #[comptime] _out_layout_config: GlobalLayoutConfig,
294 ) -> Self::State<Lhs, Rhs, EO> {
295 (input.clone(), output.clone(), config)
296 }
297
298 fn view_lhs<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
299 state: &Self::State<Lhs, Rhs, EO>,
300 ) -> View<'_, Lhs, BatchedCoords> {
301 state.0.lhs
302 }
303
304 fn batch_lhs<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
305 state: &Self::State<Lhs, Rhs, EO>,
306 batch: usize,
307 ) -> usize {
308 state.0.lhs_batch.to_source_pos(batch)
309 }
310
311 fn view_rhs<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
312 state: &Self::State<Lhs, Rhs, EO>,
313 ) -> View<'_, Rhs, BatchedCoords> {
314 state.0.rhs
315 }
316
317 fn batch_rhs<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
318 state: &Self::State<Lhs, Rhs, EO>,
319 batch: usize,
320 ) -> usize {
321 state.0.rhs_batch.to_source_pos(batch)
322 }
323
324 fn view_acc<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
325 state: &Self::State<Lhs, Rhs, EO>,
326 ) -> ComptimeOption<View<'_, EO, BatchedCoords>> {
327 state.0.acc.map(|view| view) }
329
330 fn batch_acc<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
331 state: &Self::State<Lhs, Rhs, EO>,
332 batch: usize,
333 ) -> usize {
334 #[comptime]
335 match &state.0.acc_batch {
336 ComptimeOption::Some(layout) => layout.to_source_pos(batch),
337 ComptimeOption::None => batch,
338 }
339 }
340
341 fn view_out<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
342 state: &Self::State<Lhs, Rhs, EO>,
343 ) -> ViewMut<'_, EO, BatchedCoords> {
344 state.1.view
345 }
346
347 fn batch_out<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
348 state: &Self::State<Lhs, Rhs, EO>,
349 batch: usize,
350 ) -> usize {
351 state.1.batch.to_source_pos(batch)
352 }
353
354 fn runtime_config<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
355 state: &Self::State<Lhs, Rhs, EO>,
356 ) -> Self::Config {
357 state.2.clone()
358 }
359}
360
361#[derive(Clone)]
362pub struct TensorMapArgs<Config: RuntimeConfig = ()> {
366 _config: PhantomData<Config>,
367}
368
369#[derive(CubeLaunch, CubeType, Clone)]
370#[expand(derive(Clone))]
371pub struct TensorMapInputs<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive> {
373 pub lhs: View<'static, Lhs, BatchedCoords>,
375 pub rhs: View<'static, Rhs, BatchedCoords>,
377 pub acc: ComptimeOption<View<'static, EO, BatchedCoords>>,
379 pub acc_batch: ComptimeOption<VirtualLayout<Coords1d, Coords1d>>,
381}
382
383impl<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive, A: BatchMatmulRoutine<()>>
384 ConcreteInputsFactory<A> for TensorMapInputs<Lhs, Rhs, EO>
385{
386 fn create<R: Runtime>(
387 lhs_handle: InputBinding<R>,
388 rhs_handle: InputBinding<R>,
389 blueprint: &A::Blueprint,
390 problem: &MatmulProblem,
391 _vector_sizes: &MatmulVectorSizes,
392 dtypes: &MatmulElems,
393 ) -> Self::RuntimeArg<R> {
394 let lhs = lhs_handle.into_data();
395 let rhs = rhs_handle.into_data();
396
397 let tiling_scheme = blueprint.tiling_scheme();
398 let stage_m = tiling_scheme.elements_per_stage_along_m() as usize;
399 let stage_n = tiling_scheme.elements_per_stage_along_n() as usize;
400 let stage_k = tiling_scheme.elements_per_stage_along_k() as usize;
401 let (tile_m, tile_n, tile_k) = (
402 tiling_scheme.tile_size.m as usize,
403 tiling_scheme.tile_size.n as usize,
404 tiling_scheme.tile_size.k as usize,
405 );
406
407 let box_lhs = match blueprint.swizzle_modes().lhs {
411 SwizzleMode::None => match problem.lhs_layout {
412 MatrixLayout::RowMajor => (stage_m, tile_k),
413 MatrixLayout::ColMajor => (tile_m, stage_k),
414 },
415 _ => (stage_m, stage_k),
416 };
417 let box_rhs = match blueprint.swizzle_modes().rhs {
418 SwizzleMode::None => match problem.rhs_layout {
419 MatrixLayout::RowMajor => (stage_k, tile_n),
420 MatrixLayout::ColMajor => (tile_k, stage_n),
421 },
422 _ => (stage_k, stage_n),
423 };
424
425 let dims = |binding: &TensorBinding<R>, batches: &[usize]| {
427 let rank = binding.shape.len();
428 (
429 batches.iter().product::<usize>(),
430 binding.shape[rank - 2] as u32,
431 binding.shape[rank - 1] as u32,
432 )
433 };
434 let lhs_dims = dims(&lhs, &problem.lhs_batches);
435 let rhs_dims = dims(&rhs, &problem.rhs_batches);
436
437 let (lhs, lhs_transposed) = tma_operand(
438 lhs,
439 lhs_dims.0,
440 problem.lhs_layout,
441 box_lhs,
442 dtypes.lhs_stage,
443 blueprint.swizzle_modes().lhs.into(),
444 );
445 let (rhs, rhs_transposed) = tma_operand(
446 rhs,
447 rhs_dims.0,
448 problem.rhs_layout,
449 box_rhs,
450 dtypes.rhs_stage,
451 blueprint.swizzle_modes().rhs.into(),
452 );
453
454 let view = |buffer, shape: (usize, u32, u32), transposed| {
455 let layout = SimpleTmaGlobalLayoutLaunch::new(transposed, shape);
456 ViewArg::new_tensor_map_tiled::<SimpleTmaGlobalLayout>(buffer, layout)
457 };
458
459 TensorMapInputsLaunch::new(
460 view(lhs, lhs_dims, lhs_transposed),
461 view(rhs, rhs_dims, rhs_transposed),
462 ComptimeOptionArgs::None,
463 ComptimeOptionArgs::None,
464 )
465 }
466}
467
468#[cube]
469impl<Config: RuntimeConfig> MatmulArgs for TensorMapArgs<Config> {
470 type Input<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive> =
471 TensorMapInputs<Lhs, Rhs, EO>;
472 type Output<EO: CubePrimitive> = TensorOutput<EO>;
473 type Config = Config;
474 type State<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive> =
475 (TensorMapInputs<Lhs, Rhs, EO>, TensorOutput<EO>, Config);
476
477 fn init_state<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
478 input: &Self::Input<Lhs, Rhs, EO>,
479 output: &mut Self::Output<EO>,
480 config: Self::Config,
481 #[comptime] _lhs_layout_config: GlobalLayoutConfig,
482 #[comptime] _rhs_layout_config: GlobalLayoutConfig,
483 #[comptime] _out_layout_config: GlobalLayoutConfig,
484 ) -> Self::State<Lhs, Rhs, EO> {
485 (input.clone(), output.clone(), config)
486 }
487
488 fn view_lhs<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
489 state: &Self::State<Lhs, Rhs, EO>,
490 ) -> View<'_, Lhs, BatchedCoords> {
491 state.0.lhs
492 }
493
494 fn batch_lhs<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
495 _state: &Self::State<Lhs, Rhs, EO>,
496 batch: usize,
497 ) -> usize {
498 batch
499 }
500
501 fn view_rhs<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
502 state: &Self::State<Lhs, Rhs, EO>,
503 ) -> View<'_, Rhs, BatchedCoords> {
504 state.0.rhs
505 }
506
507 fn batch_rhs<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
508 _state: &Self::State<Lhs, Rhs, EO>,
509 batch: usize,
510 ) -> usize {
511 batch
512 }
513
514 fn view_acc<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
515 state: &Self::State<Lhs, Rhs, EO>,
516 ) -> ComptimeOption<View<'_, EO, BatchedCoords>> {
517 state.0.acc.map(|view| view) }
519
520 fn batch_acc<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
521 state: &Self::State<Lhs, Rhs, EO>,
522 batch: usize,
523 ) -> usize {
524 #[comptime]
525 #[comptime]
526 match &state.0.acc_batch {
527 ComptimeOption::Some(layout) => layout.to_source_pos(batch),
528 ComptimeOption::None => batch,
529 }
530 }
531
532 fn view_out<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
533 state: &Self::State<Lhs, Rhs, EO>,
534 ) -> ViewMut<'_, EO, BatchedCoords> {
535 state.1.view
536 }
537
538 fn batch_out<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
539 state: &Self::State<Lhs, Rhs, EO>,
540 batch: usize,
541 ) -> usize {
542 state.1.batch.to_source_pos(batch)
543 }
544
545 fn runtime_config<Lhs: CubePrimitive, Rhs: CubePrimitive, EO: CubePrimitive>(
546 state: &Self::State<Lhs, Rhs, EO>,
547 ) -> Self::Config {
548 state.2.clone()
549 }
550}