cubek_std/tile/variants/instruction/
plane_vec.rs1use cubecl::{define_size, prelude::*};
2
3use crate::{
4 MatrixLayout, StageIdent, TileSize,
5 tile::{SharedTile, Tile, TileKind, TileKindExpand, TileScope},
6};
7
8define_size!(pub NPlaneVec);
13
14#[derive(CubeType)]
20pub struct PlaneVecTile<N: Numeric> {
21 pub data: Array<Vector<N, NPlaneVec>>,
23 #[cube(comptime)]
24 pub matrix_layout: MatrixLayout,
25 #[cube(comptime)]
26 pub tile_size: TileSize,
27 #[cube(comptime)]
31 pub reduce_vector_size: u32,
32}
33
34#[cube]
37#[allow(unused_variables)]
38fn register_reduce_vector_size(#[comptime] reduce_vector_size: u32) {
39 intrinsic!(|scope| {
40 scope.register_size::<NPlaneVec>(reduce_vector_size as usize);
41 });
42}
43
44#[cube]
45pub fn planevec_allocate_lhs<L: Numeric, Sc: TileScope>(
46 #[comptime] layout: MatrixLayout,
47 #[comptime] tile_size: TileSize,
48 #[comptime] reduce_vector_size: u32,
49) -> Tile<L, Sc> {
50 register_reduce_vector_size(reduce_vector_size);
51 Tile::from_kind(TileKind::new_PlaneVec(PlaneVecTile::<L> {
52 data: Array::new(1usize),
53 matrix_layout: layout,
54 tile_size,
55 reduce_vector_size,
56 }))
57}
58
59#[cube]
60pub fn planevec_allocate_rhs<R: Numeric, Sc: TileScope>(
61 #[comptime] layout: MatrixLayout,
62 #[comptime] tile_size: TileSize,
63 #[comptime] reduce_vector_size: u32,
64) -> Tile<R, Sc> {
65 register_reduce_vector_size(reduce_vector_size);
66 Tile::from_kind(TileKind::new_PlaneVec(PlaneVecTile::<R> {
67 data: Array::new(tile_size.n() as usize),
68 matrix_layout: layout,
69 tile_size,
70 reduce_vector_size,
71 }))
72}
73
74#[cube]
75pub fn planevec_allocate_acc<A: Numeric, Sc: TileScope>(
76 #[comptime] layout: MatrixLayout,
77 #[comptime] tile_size: TileSize,
78 #[comptime] reduce_vector_size: u32,
79) -> Tile<A, Sc> {
80 register_reduce_vector_size(reduce_vector_size);
81 Tile::from_kind(TileKind::new_PlaneVec(PlaneVecTile::<A> {
82 data: Array::new(tile_size.n() as usize),
83 matrix_layout: layout,
84 tile_size,
85 reduce_vector_size,
86 }))
87}
88
89#[cube]
90impl<A: Numeric> PlaneVecTile<A> {
91 pub fn mma<L: Numeric, R: Numeric>(&mut self, lhs: &PlaneVecTile<L>, rhs: &PlaneVecTile<R>) {
94 planevec_execute(&lhs.data, &rhs.data, &mut self.data, self.tile_size);
95 }
96}
97
98#[cube]
99impl<N: Numeric> PlaneVecTile<N> {
100 pub fn copy_from<SE: Numeric, SS: Size, Sc: TileScope>(
103 &mut self,
104 source: &Tile<SE, Sc>,
105 #[comptime] ident: StageIdent,
106 ) {
107 match &source.kind {
108 TileKind::SharedTile(shared) => {
109 planevec_load_from_shared::<SE, SS, N>(
110 shared,
111 &mut self.data,
112 self.tile_size,
113 ident,
114 );
115 }
116 TileKind::None => planevec_load_zeros::<N>(&mut self.data, self.tile_size),
117 TileKind::Cmma(_)
118 | TileKind::Mma(_)
119 | TileKind::Register(_)
120 | TileKind::PlaneVec(_)
121 | TileKind::Interleaved(_)
122 | TileKind::Unit(_)
123 | TileKind::WhiteboxFragment(_)
124 | TileKind::RowWise(_)
125 | TileKind::Bounce(_)
126 | TileKind::Stage(_)
127 | TileKind::Partition(_)
128 | TileKind::Pipelined(_) => {
129 panic!("PlaneVecTile::copy_from: unsupported source variant")
130 }
131 }
132 }
133
134 pub fn init_zero(&mut self) {
135 planevec_load_zeros::<N>(&mut self.data, self.tile_size);
136 }
137}
138
139#[cube]
144pub fn planevec_execute<L: Numeric, R: Numeric, A: Numeric>(
145 lhs: &Array<Vector<L, NPlaneVec>>,
146 rhs: &Array<Vector<R, NPlaneVec>>,
147 acc: &mut Array<Vector<A, NPlaneVec>>,
148 #[comptime] tile_size: TileSize,
149) {
150 let n = tile_size.n();
151 #[unroll]
152 for n_idx in 0..n as usize {
153 let mut acc_vec = acc[n_idx];
154 #[unroll]
155 for vi in 0..NPlaneVec::value() {
156 let lhs_elem = A::cast_from(lhs[0].extract(vi));
157 let rhs_elem = A::cast_from(rhs[n_idx].extract(vi));
158 acc_vec.insert(vi, acc_vec.extract(vi) + plane_sum(lhs_elem * rhs_elem));
159 }
160 acc[n_idx] = acc_vec;
161 }
162}
163
164#[cube]
165pub fn planevec_load_from_shared<E: Numeric, ES: Size, N: Numeric>(
166 shared: &SharedTile<E>,
167 arr: &mut Array<Vector<N, NPlaneVec>>,
168 #[comptime] tile_size: TileSize,
169 #[comptime] ident: StageIdent,
170) {
171 let shared = shared.view::<ES>();
172 let shared = &shared;
173 match ident {
174 StageIdent::Lhs => {
175 let offset = shared.stage_offset(UNIT_POS_X);
176 arr[0] = Vector::cast_from(shared.container[offset as usize]);
177 }
178 StageIdent::Rhs | StageIdent::Acc => {
179 let n = tile_size.n();
180 #[unroll]
181 for n_idx in 0..n {
182 let offset = shared.stage_offset(UNIT_POS_X + n_idx * shared.stride);
183 arr[n_idx as usize] = Vector::cast_from(shared.container[offset as usize]);
184 }
185 }
186 _ => panic!("Invalid ident for PlaneVec load"),
187 }
188}
189
190#[cube]
191pub fn planevec_load_zeros<N: Numeric>(
192 arr: &mut Array<Vector<N, NPlaneVec>>,
193 #[comptime] tile_size: TileSize,
194) {
195 let n = tile_size.n();
196 let zero = N::from_int(0);
197 #[unroll]
198 for n_idx in 0..n as usize {
199 arr[n_idx] = Vector::cast_from(zero);
200 }
201}
202
203#[cube]
204pub fn planevec_write_to_shared<A: Numeric, E: Numeric, ES: Size>(
205 shared: &mut SharedTile<E>,
206 arr: &Array<Vector<A, NPlaneVec>>,
207 #[comptime] tile_size: TileSize,
208 #[comptime] reduce_vector_size: u32,
209) {
210 let mut shared = shared.view::<ES>();
211 let shared = &mut shared;
212 if UNIT_POS_X == 0 {
213 let out_vector_size = shared.container.vector_size().comptime();
214 let n = tile_size.n();
215 let total_out_vectors = n as usize / out_vector_size;
216 let reduce_vec = reduce_vector_size as usize;
217
218 #[unroll]
219 for out_vector_iter in 0..total_out_vectors {
220 let mut out_vector = Vector::<E, ES>::empty();
221 #[unroll]
222 for within_vector in 0..out_vector_size {
223 let n_idx = out_vector_iter * out_vector_size + within_vector;
224 let acc_vec = arr[n_idx];
225 let mut sum = A::from_int(0);
226 for i in 0..reduce_vec {
227 sum += acc_vec.extract(i);
228 }
229 out_vector.insert(within_vector, E::cast_from(sum));
230 }
231 let offset = shared.stage_offset(out_vector_iter as u32);
232 shared.container[offset as usize] = out_vector;
233 }
234 }
235}