cubecl_tile/launch/arg/
tma.rs1use cubecl::prelude::*;
5use cubecl_std::tensor::{
6 layout::{CoordsDyn, Layout, LayoutExpand, as_dyn::IntoDynLayout},
7 view::launch::VirtualViewLayoutLaunch,
8};
9
10use crate::*;
11
12#[derive(Clone, Copy, PartialEq, Eq, Debug)]
15pub struct TmaBox {
16 pub rows: u32,
17 pub cols: u32,
18 pub batch: Option<u32>,
19 pub transposed: bool,
20}
21
22pub struct TmaOperand {
24 pub map: TensorMapArg<Tiled>,
25 pub axes: Vec<Axis>,
26 pub shape: TmaBox,
27}
28
29impl TmaOperand {
30 pub fn arg(self) -> TileArgLaunch {
32 TileArgLaunch::tensor_map(self.map, &self.axes, self.shape)
33 }
34}
35
36impl TileArgLaunch {
37 pub fn tensor_map(tensor_map: TensorMapArg<Tiled>, axes: &[Axis], shape: TmaBox) -> Self {
39 let layout = Self::dyn_layout(axes, shape);
40 Self::of_tensor_map(
41 tensor_map,
42 VirtualViewLayoutLaunch::new::<IntoDynLayout<TmaDynLayout>>(layout),
43 TileSpec::direct(axes),
44 )
45 }
46
47 fn dyn_layout(axes: &[Axis], shape: TmaBox) -> TmaDynLayoutLaunch {
49 let batched = match (axes.len(), shape.batch) {
50 (2, None) => false,
51 (3, Some(_)) => true,
52 (r, batch) => panic!(
53 "TileArgLaunch::tensor_map: the descriptor is (batch, row, col); {r} axes with \
54 batch {batch:?} is not a matrix nor a batched one"
55 ),
56 };
57 let dims = (shape.batch.unwrap_or(1), shape.rows, shape.cols);
58 TmaDynLayoutLaunch::new(dims, batched, shape.transposed)
59 }
60}
61
62#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
65pub enum TmaLanding {
66 Tiles,
69 Rows,
75}
76
77#[derive(CubeType, CubeLaunch, Clone)]
80pub(crate) struct TmaDynLayout {
81 dims: (u32, u32, u32),
83 #[cube(comptime)]
84 batched: bool,
85 #[cube(comptime)]
86 transposed: bool,
87}
88
89#[cube]
90impl Layout for TmaDynLayout {
91 type Coordinates = CoordsDyn;
92 type SourceCoordinates = CoordsDyn;
93
94 fn to_source_pos(&self, pos: Self::Coordinates) -> Self::SourceCoordinates {
95 let (batch, _rows, _cols) = self.dims;
96 let mut src = CoordsDyn::new();
97 if comptime!(self.batched) {
98 src.push(select(batch == 1, 0u32, pos[0]));
100 } else {
101 src.push(0u32);
102 }
103 let (r, c) = comptime!(if self.batched { (1, 2) } else { (0, 1) });
104 if comptime!(self.transposed) {
106 src.push(pos[c]);
107 src.push(pos[r]);
108 } else {
109 src.push(pos[r]);
110 src.push(pos[c]);
111 }
112 src
113 }
114
115 fn to_source_pos_checked(&self, pos: Self::Coordinates) -> (Self::SourceCoordinates, bool) {
116 (self.to_source_pos(pos), true)
118 }
119
120 fn shape(&self) -> Self::Coordinates {
121 let (batch, rows, cols) = self.dims;
122 let mut s = CoordsDyn::new();
123 if comptime!(self.batched) {
124 s.push(batch);
125 }
126 s.push(rows);
127 s.push(cols);
128 s
129 }
130
131 fn is_in_bounds(&self, _pos: Self::Coordinates) -> bool {
132 true
133 }
134}