Skip to main content

rublas/kernel_ir/launch/
args.rs

1use ruda_kernel::dsl as kernel_dsl;
2use std::marker::PhantomData;
3
4use ruda_kernel::library::tensor::View;
5use ruda_kernel::library::tensor::launch::ViewArg;
6use ruda_kernel::library::tensor::layout::Coords1d;
7use ruda_kernel::library::tensor::layout::VirtualLayout;
8use ruda_kernel::library::tensor::layout::VirtualLayoutLaunch;
9use ruda_kernel::dsl::unexpanded;
10use ruda_kernel::dsl::prelude::*;
11use ruda_kernel::dsl::zspace::metadata::Metadata;
12use ruda_kernel::dsl::zspace::shape;
13use ruda_kernel::dsl::zspace::strides;
14use ruda_kernel::tiling::launch::tma::{remap_storage_for_tma, tma_meta_tiled, transpose_inner_for_tma};
15use ruda_kernel::tiling::{InputBinding, MatrixLayout, stage::SwizzleMode};
16
17use crate::kernel_ir::components::global::memory::{
18    BatchLayout, BatchLayoutLaunch, GlobalLayout, GlobalLayoutConfig, GlobalLayoutLaunch,
19    GlobalScaleLayout, NoopLayout, NoopLayoutLaunch, SimpleTmaGlobalLayout,
20    SimpleTmaGlobalLayoutLaunch,
21};
22use crate::kernel_ir::{
23    definition::{Blueprint as _, MatmulElems, MatmulProblem, MatmulVectorSizes},
24    routines::Routine,
25};
26
27define_scalar!(pub Lhs);
28define_scalar!(pub Rhs);
29define_scalar!(pub Acc);
30
31define_size!(pub LhsSize);
32define_size!(pub RhsSize);
33define_size!(pub AccSize);
34
35/// Input argument
36pub type InputArg<MA> =
37    <MA as MatmulArgs>::Input<Vector<Lhs, LhsSize>, Vector<Rhs, RhsSize>, Vector<Acc, AccSize>>;
38
39/// Output argument
40pub type OutputArg<MA> = <MA as MatmulArgs>::Output<Vector<Acc, AccSize>>;
41
42/// Config argument
43pub type ConfigArg<MA> = <MA as MatmulArgs>::Config;
44
45/// Input runtime argument
46pub type InputRuntimeArg<MA, R> = <InputArg<MA> as LaunchArg>::RuntimeArg<R>;
47
48/// Config runtime argument
49pub type ConfigRuntimeArg<MA, R> = <ConfigArg<MA> as LaunchArg>::RuntimeArg<R>;
50
51/// Output runtime argument
52pub type OutputRuntimeArg<MA, R> = <OutputArg<MA> as LaunchArg>::RuntimeArg<R>;
53
54pub type BatchedCoords = (usize, u32, u32);
55
56/// Create the input runtime arguments for a matmul kernel that works on concrete inputs and
57/// output (not fused).
58pub trait ConcreteInputsFactory<A: Routine<()>>: LaunchArg {
59    #[allow(clippy::too_many_arguments)]
60    fn create<R: Runtime>(
61        lhs: InputBinding<R>,
62        rhs: InputBinding<R>,
63        blueprint: &A::Blueprint,
64        problem: &MatmulProblem,
65        vector_sizes: &MatmulVectorSizes,
66        dtypes: &MatmulElems,
67    ) -> Self::RuntimeArg<R>;
68}
69
70/// Create the output runtime argument for a matmul kernel that works on concrete inputs and
71/// output (not fused).
72pub trait ConcreteOutputFactory<A: Routine<()>>: LaunchArg {
73    #[allow(clippy::too_many_arguments)]
74    fn create<R: Runtime>(
75        out: TensorBinding<R>,
76        blueprint: &A::Blueprint,
77        problem: &MatmulProblem,
78        vector_sizes: &MatmulVectorSizes,
79        dtypes: &MatmulElems,
80    ) -> Self::RuntimeArg<R>;
81}
82
83pub trait RuntimeConfig: LaunchArg + RudaType + Clone + Send + Sync {}
84impl<T: LaunchArg + RudaType + Clone + Send + Sync> RuntimeConfig for T {}
85
86#[ruda]
87/// Arguments for the matrix multiplication algorithm.
88pub trait MatmulArgs: Send + Sync + 'static + Clone {
89    /// Type used for the input.
90    type Input<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>: LaunchArg + RudaType;
91
92    /// Type used for the output.
93    type Output<EO: RudaPrimitive>: LaunchArg + RudaType;
94
95    /// Type used for runtime configuration.
96    type Config: RuntimeConfig;
97
98    /// Inner state that is used to create tensor inputs and
99    /// tensor outputs.
100    type State<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>: RudaType;
101
102    /// Init the state.
103    fn init_state<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
104        input: &Self::Input<Lhs, Rhs, EO>,
105        output: &mut Self::Output<EO>,
106        config: Self::Config,
107        #[comptime] lhs_layout_config: GlobalLayoutConfig,
108        #[comptime] rhs_layout_config: GlobalLayoutConfig,
109        #[comptime] out_layout_config: GlobalLayoutConfig,
110    ) -> Self::State<Lhs, Rhs, EO>;
111
112    fn view_lhs<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
113        _state: &Self::State<Lhs, Rhs, EO>,
114    ) -> View<Lhs, BatchedCoords> {
115        unexpanded!()
116    }
117    fn batch_lhs<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
118        _state: &Self::State<Lhs, Rhs, EO>,
119        _batch: usize,
120    ) -> usize {
121        unexpanded!()
122    }
123    fn view_rhs<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
124        _state: &Self::State<Lhs, Rhs, EO>,
125    ) -> View<Rhs, BatchedCoords> {
126        unexpanded!()
127    }
128    fn batch_rhs<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
129        _state: &Self::State<Lhs, Rhs, EO>,
130        _batch: usize,
131    ) -> usize {
132        unexpanded!()
133    }
134    fn view_acc<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
135        _state: &Self::State<Lhs, Rhs, EO>,
136    ) -> ComptimeOption<View<EO, BatchedCoords>> {
137        unexpanded!()
138    }
139    fn batch_acc<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
140        _state: &Self::State<Lhs, Rhs, EO>,
141        _batch: usize,
142    ) -> usize {
143        unexpanded!()
144    }
145    fn view_out<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
146        _state: &mut Self::State<Lhs, Rhs, EO>,
147    ) -> View<EO, BatchedCoords, ReadWrite> {
148        unexpanded!()
149    }
150    fn batch_out<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
151        _state: &Self::State<Lhs, Rhs, EO>,
152        _batch: usize,
153    ) -> usize {
154        unexpanded!()
155    }
156
157    fn runtime_config<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
158        _state: &Self::State<Lhs, Rhs, EO>,
159    ) -> Self::Config {
160        unexpanded!()
161    }
162}
163
164#[derive(Clone, Copy)]
165/// Identification of the tensor input.
166pub enum TensorInputIdent {
167    Lhs,
168    Rhs,
169}
170
171#[derive(Clone)]
172/// Type implementing [MatmulArgs] where all inputs and the output are materialized tensors.
173///
174/// Other types might implement [MatmulArgs] for fused matrix multiplication kernels.
175pub struct TensorArgs<Config: RuntimeConfig = ()> {
176    _config: PhantomData<Config>,
177}
178
179#[derive(RudaLaunch, RudaType, Clone, Copy)]
180/// Input representation for [TensorArgs] implementing [MatmulArgs].
181pub struct TensorInputs<Lhs: RudaPrimitive, Rhs: RudaPrimitive, Acc: RudaPrimitive> {
182    /// The lhs tensor.
183    lhs_batch: VirtualLayout<Coords1d, Coords1d>,
184    lhs: View<Lhs, BatchedCoords>,
185    /// The rhs tensor.
186    rhs_batch: VirtualLayout<Coords1d, Coords1d>,
187    rhs: View<Rhs, BatchedCoords>,
188    /// The tensor for loading the accumulator, if present
189    acc_batch: ComptimeOption<VirtualLayout<Coords1d, Coords1d>>,
190    acc: ComptimeOption<View<Acc, BatchedCoords>>,
191}
192
193impl<Lhs: RudaPrimitive, Rhs: RudaPrimitive, Acc: RudaPrimitive, A: Routine<()>>
194    ConcreteInputsFactory<A> for TensorInputs<Lhs, Rhs, Acc>
195{
196    fn create<R: Runtime>(
197        lhs: InputBinding<R>,
198        rhs: InputBinding<R>,
199        blueprint: &A::Blueprint,
200        problem: &MatmulProblem,
201        vector_sizes: &MatmulVectorSizes,
202        _dtypes: &MatmulElems,
203    ) -> Self::RuntimeArg<R> {
204        let view = |handle: InputBinding<R>, config: GlobalLayoutConfig, vector_size| match handle {
205            InputBinding::Normal(handle, _dtype) => {
206                let layout = GlobalLayoutLaunch::from_handle(&handle, vector_size, config);
207                ViewArg::new_tensor::<GlobalLayout>(handle.into_tensor_arg(), layout)
208            }
209            InputBinding::Quantized {
210                data,
211                scale,
212                shape,
213                scheme,
214                ..
215            } => {
216                let (data_layout, scales_layout) = GlobalLayoutLaunch::from_quantized_handle(
217                    &data,
218                    &scale,
219                    &shape,
220                    problem,
221                    scheme,
222                    vector_size,
223                    config,
224                );
225                let data_view =
226                    ViewArg::new_tensor::<GlobalLayout>(data.into_tensor_arg(), data_layout);
227                let scales_view = ViewArg::new_tensor::<GlobalScaleLayout>(
228                    scale.into_tensor_arg(),
229                    scales_layout,
230                );
231                ViewArg::new_quantized(data_view, scales_view, scheme)
232            }
233        };
234        let batch_layout = |handle: &InputBinding<R>| match handle {
235            InputBinding::Normal(handle, _dtype) => {
236                let layout = BatchLayoutLaunch::from_handle(handle, problem);
237                VirtualLayoutLaunch::new::<BatchLayout>(layout)
238            }
239            InputBinding::Quantized { .. } => {
240                VirtualLayoutLaunch::new::<NoopLayout>(NoopLayoutLaunch::new())
241            }
242        };
243
244        TensorInputsLaunch::new(
245            batch_layout(&lhs),
246            view(lhs, blueprint.lhs_global_layout_config(), vector_sizes.lhs),
247            batch_layout(&rhs),
248            view(rhs, blueprint.rhs_global_layout_config(), vector_sizes.rhs),
249            ComptimeOptionArgs::None,
250            ComptimeOptionArgs::None,
251        )
252    }
253}
254
255#[derive(RudaType, RudaLaunch, Clone, Copy)]
256pub struct TensorOutput<EG: RudaPrimitive> {
257    view: View<EG, BatchedCoords, ReadWrite>,
258    batch: VirtualLayout<Coords1d, Coords1d>,
259}
260
261impl<EG: RudaPrimitive, A: Routine<()>> ConcreteOutputFactory<A> for TensorOutput<EG> {
262    fn create<R: Runtime>(
263        out: TensorBinding<R>,
264        blueprint: &A::Blueprint,
265        problem: &MatmulProblem,
266        vector_sizes: &MatmulVectorSizes,
267        _dtypes: &MatmulElems,
268    ) -> Self::RuntimeArg<R> {
269        let layout = GlobalLayoutLaunch::from_handle(
270            &out,
271            vector_sizes.out,
272            blueprint.out_global_layout_config(),
273        );
274        let batch = BatchLayoutLaunch::from_handle(&out, problem);
275        let view = ViewArg::new_tensor::<GlobalLayout>(out.into_tensor_arg(), layout);
276        TensorOutputLaunch::new(view, VirtualLayoutLaunch::new::<BatchLayout>(batch))
277    }
278}
279
280#[ruda]
281impl<Config: RuntimeConfig> MatmulArgs for TensorArgs<Config> {
282    type Output<EO: RudaPrimitive> = TensorOutput<EO>;
283    type Input<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive> =
284        TensorInputs<Lhs, Rhs, EO>;
285    type Config = Config;
286    type State<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive> =
287        (TensorInputs<Lhs, Rhs, EO>, TensorOutput<EO>, Config);
288
289    fn init_state<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
290        input: &Self::Input<Lhs, Rhs, EO>,
291        output: &mut Self::Output<EO>,
292        config: Self::Config,
293        #[comptime] _lhs_layout_config: GlobalLayoutConfig,
294        #[comptime] _rhs_layout_config: GlobalLayoutConfig,
295        #[comptime] _out_layout_config: GlobalLayoutConfig,
296    ) -> Self::State<Lhs, Rhs, EO> {
297        (*input, *output, config)
298    }
299
300    fn view_lhs<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
301        state: &Self::State<Lhs, Rhs, EO>,
302    ) -> View<Lhs, BatchedCoords> {
303        state.0.lhs
304    }
305
306    fn batch_lhs<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
307        state: &Self::State<Lhs, Rhs, EO>,
308        batch: usize,
309    ) -> usize {
310        state.0.lhs_batch.to_source_pos(batch)
311    }
312
313    fn view_rhs<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
314        state: &Self::State<Lhs, Rhs, EO>,
315    ) -> View<Rhs, BatchedCoords> {
316        state.0.rhs
317    }
318
319    fn batch_rhs<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
320        state: &Self::State<Lhs, Rhs, EO>,
321        batch: usize,
322    ) -> usize {
323        state.0.rhs_batch.to_source_pos(batch)
324    }
325
326    fn view_acc<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
327        state: &Self::State<Lhs, Rhs, EO>,
328    ) -> ComptimeOption<View<EO, BatchedCoords>> {
329        state.0.acc
330    }
331
332    fn batch_acc<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
333        state: &Self::State<Lhs, Rhs, EO>,
334        batch: usize,
335    ) -> usize {
336        #[comptime]
337        #[comptime]
338        match state.0.acc_batch {
339            ComptimeOption::Some(layout) => layout.to_source_pos(batch),
340            ComptimeOption::None => batch,
341        }
342    }
343
344    fn view_out<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
345        state: &mut Self::State<Lhs, Rhs, EO>,
346    ) -> View<EO, BatchedCoords, ReadWrite> {
347        state.1.view
348    }
349
350    fn batch_out<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
351        state: &Self::State<Lhs, Rhs, EO>,
352        batch: usize,
353    ) -> usize {
354        state.1.batch.to_source_pos(batch)
355    }
356
357    fn runtime_config<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
358        state: &Self::State<Lhs, Rhs, EO>,
359    ) -> Self::Config {
360        state.2.clone()
361    }
362}
363
364#[derive(Clone)]
365/// Type implementing [MatmulArgs] where all inputs and the output are materialized tensor maps.
366///
367/// Other types might implement [MatmulArgs] for fused matrix multiplication kernels.
368pub struct TensorMapArgs<Config: RuntimeConfig = ()> {
369    _config: PhantomData<Config>,
370}
371
372#[derive(RudaLaunch, RudaType, Clone, Copy)]
373/// Input representation for [TensorArgs] implementing [MatmulArgs].
374pub struct TensorMapInputs<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive> {
375    /// The lhs tensor.
376    pub lhs: View<Lhs, BatchedCoords>,
377    /// The rhs tensor.
378    pub rhs: View<Rhs, BatchedCoords>,
379    /// The accumulator
380    pub acc: ComptimeOption<View<EO, BatchedCoords>>,
381    /// The accumulator batch layout
382    pub acc_batch: ComptimeOption<VirtualLayout<Coords1d, Coords1d>>,
383}
384
385impl<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive, A: Routine<()>>
386    ConcreteInputsFactory<A> for TensorMapInputs<Lhs, Rhs, EO>
387{
388    fn create<R: Runtime>(
389        lhs_handle: InputBinding<R>,
390        rhs_handle: InputBinding<R>,
391        blueprint: &A::Blueprint,
392        problem: &MatmulProblem,
393        _vector_sizes: &MatmulVectorSizes,
394        dtypes: &MatmulElems,
395    ) -> Self::RuntimeArg<R> {
396        let lhs = lhs_handle.into_data();
397        let rhs = rhs_handle.into_data();
398
399        let tiling_scheme = blueprint.tiling_scheme();
400        let stage_m = tiling_scheme.elements_per_stage_along_m();
401        let stage_n = tiling_scheme.elements_per_stage_along_n();
402        let stage_k = tiling_scheme.elements_per_stage_along_k();
403
404        // Loaders use dynamic layout based on swizzle setting. For no swizzle, contiguous tiles are
405        // loaded and TMA loads single tile wide columns.
406        // For swizzled, bank conflicts aren't an issue so the tile size is the full stage.
407        let stage_size_lhs = match blueprint.swizzle_modes().lhs {
408            SwizzleMode::None => match problem.lhs_layout {
409                MatrixLayout::RowMajor => {
410                    shape![1, stage_m as usize, tiling_scheme.tile_size.k as usize]
411                }
412                MatrixLayout::ColMajor => {
413                    shape![1, stage_k as usize, tiling_scheme.tile_size.m as usize]
414                }
415            },
416            _ => match problem.lhs_layout {
417                MatrixLayout::RowMajor => {
418                    shape![1, stage_m as usize, stage_k as usize]
419                }
420                MatrixLayout::ColMajor => {
421                    shape![1, stage_k as usize, stage_m as usize]
422                }
423            },
424        };
425        let stage_size_rhs = match blueprint.swizzle_modes().rhs {
426            SwizzleMode::None => match problem.rhs_layout {
427                MatrixLayout::RowMajor => {
428                    shape![1, stage_k as usize, tiling_scheme.tile_size.n as usize]
429                }
430                MatrixLayout::ColMajor => {
431                    shape![1, stage_n as usize, tiling_scheme.tile_size.k as usize]
432                }
433            },
434            _ => match problem.rhs_layout {
435                MatrixLayout::RowMajor => {
436                    shape![1, stage_k as usize, stage_n as usize]
437                }
438                MatrixLayout::ColMajor => {
439                    shape![1, stage_n as usize, stage_k as usize]
440                }
441            },
442        };
443
444        let lhs_rank = lhs.shape.len();
445        let mut lhs_shape = shape![
446            problem.lhs_batches.iter().product(),
447            lhs.shape[lhs_rank - 2],
448            lhs.shape[lhs_rank - 1],
449        ];
450        let mut lhs_strides = if lhs_rank > 2 {
451            lhs.strides[lhs_rank - 3..].into()
452        } else {
453            strides![lhs.strides[0], lhs.strides[1]]
454        };
455
456        let rhs_rank = rhs.shape.len();
457        let mut rhs_shape = shape![
458            problem.rhs_batches.iter().product(),
459            rhs.shape[rhs_rank - 2],
460            rhs.shape[rhs_rank - 1],
461        ];
462        let mut rhs_strides = if rhs_rank > 2 {
463            rhs.strides[rhs_rank - 3..].into()
464        } else {
465            strides![rhs.strides[0], rhs.strides[1]]
466        };
467
468        let lhs_transposed =
469            transpose_inner_for_tma(&mut lhs_shape, &mut lhs_strides, problem.lhs_layout);
470        let rhs_transposed =
471            transpose_inner_for_tma(&mut rhs_shape, &mut rhs_strides, problem.rhs_layout);
472
473        // Insert batch stride after swap so we can easily get the non-contiguous stride
474        if lhs_strides.len() == 2 {
475            let stride = lhs_strides[0];
476            lhs_strides.insert(0, stride);
477        }
478        if rhs_strides.len() == 2 {
479            let stride = rhs_strides[0];
480            rhs_strides.insert(0, stride);
481        }
482
483        let meta_lhs = tma_meta_tiled(
484            Metadata::new(lhs_shape.clone(), lhs_strides),
485            stage_size_lhs,
486            remap_storage_for_tma(dtypes.lhs_stage),
487            blueprint.swizzle_modes().lhs.into(),
488        );
489
490        let meta_rhs = tma_meta_tiled(
491            Metadata::new(rhs_shape.clone(), rhs_strides),
492            stage_size_rhs,
493            remap_storage_for_tma(dtypes.rhs_stage),
494            blueprint.swizzle_modes().rhs.into(),
495        );
496
497        let lhs = TensorMapArg {
498            tensor: lhs.into_tensor_arg(),
499            metadata: meta_lhs,
500            _kind: PhantomData,
501        };
502        let rhs = TensorMapArg {
503            tensor: rhs.into_tensor_arg(),
504            metadata: meta_rhs,
505            _kind: PhantomData,
506        };
507
508        let view = |buffer, shape: &[usize], transposed| {
509            let batches = shape[0];
510            let (rows, cols) = match transposed {
511                true => (shape[2] as u32, shape[1] as u32),
512                false => (shape[1] as u32, shape[2] as u32),
513            };
514            let shape = (batches, rows, cols);
515            let layout = SimpleTmaGlobalLayoutLaunch::new(transposed, shape);
516            ViewArg::new_tensor_map_tiled::<SimpleTmaGlobalLayout>(buffer, layout)
517        };
518
519        TensorMapInputsLaunch::new(
520            view(lhs, &lhs_shape, lhs_transposed),
521            view(rhs, &rhs_shape, rhs_transposed),
522            ComptimeOptionArgs::None,
523            ComptimeOptionArgs::None,
524        )
525    }
526}
527
528#[ruda]
529impl<Config: RuntimeConfig> MatmulArgs for TensorMapArgs<Config> {
530    type Input<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive> =
531        TensorMapInputs<Lhs, Rhs, EO>;
532    type Output<EO: RudaPrimitive> = TensorOutput<EO>;
533    type Config = Config;
534    type State<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive> =
535        (TensorMapInputs<Lhs, Rhs, EO>, TensorOutput<EO>, Config);
536
537    fn init_state<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
538        input: &Self::Input<Lhs, Rhs, EO>,
539        output: &mut Self::Output<EO>,
540        config: Self::Config,
541        #[comptime] _lhs_layout_config: GlobalLayoutConfig,
542        #[comptime] _rhs_layout_config: GlobalLayoutConfig,
543        #[comptime] _out_layout_config: GlobalLayoutConfig,
544    ) -> Self::State<Lhs, Rhs, EO> {
545        (*input, *output, config)
546    }
547
548    fn view_lhs<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
549        state: &Self::State<Lhs, Rhs, EO>,
550    ) -> View<Lhs, BatchedCoords> {
551        state.0.lhs
552    }
553
554    fn batch_lhs<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
555        _state: &Self::State<Lhs, Rhs, EO>,
556        batch: usize,
557    ) -> usize {
558        batch
559    }
560
561    fn view_rhs<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
562        state: &Self::State<Lhs, Rhs, EO>,
563    ) -> View<Rhs, BatchedCoords> {
564        state.0.rhs
565    }
566
567    fn batch_rhs<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
568        _state: &Self::State<Lhs, Rhs, EO>,
569        batch: usize,
570    ) -> usize {
571        batch
572    }
573
574    fn view_acc<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
575        state: &Self::State<Lhs, Rhs, EO>,
576    ) -> ComptimeOption<View<EO, BatchedCoords>> {
577        state.0.acc
578    }
579
580    fn batch_acc<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
581        state: &Self::State<Lhs, Rhs, EO>,
582        batch: usize,
583    ) -> usize {
584        #[comptime]
585        #[comptime]
586        match state.0.acc_batch {
587            ComptimeOption::Some(layout) => layout.to_source_pos(batch),
588            ComptimeOption::None => batch,
589        }
590    }
591
592    fn view_out<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
593        state: &mut Self::State<Lhs, Rhs, EO>,
594    ) -> View<EO, BatchedCoords, ReadWrite> {
595        state.1.view
596    }
597
598    fn batch_out<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
599        state: &Self::State<Lhs, Rhs, EO>,
600        batch: usize,
601    ) -> usize {
602        state.1.batch.to_source_pos(batch)
603    }
604
605    fn runtime_config<Lhs: RudaPrimitive, Rhs: RudaPrimitive, EO: RudaPrimitive>(
606        state: &Self::State<Lhs, Rhs, EO>,
607    ) -> Self::Config {
608        state.2.clone()
609    }
610}