cubecl_std/tensor/layout/
linear.rs1use cubecl::prelude::*;
2use cubecl_core::{self as cubecl, ir::UIntKind, zspace::Shape};
3
4use crate::tensor::{
5 View, ViewMut, is_contiguous, is_contiguous_pitched,
6 launch::{ConcreteLayout, ConcreteLayoutLaunch, MemoryArg, ViewArg, ViewLayoutLaunchArg},
7 layout::{
8 Coords1d, Layout, LayoutExpand, VirtualLayoutOperationsExpand,
9 permuted::{PermutedLayout, PermutedLayoutCompilationArg, PermutedLayoutLaunch},
10 plain::PlainLayout,
11 strided::{StridedLayout, StridedLayoutCompilationArg},
12 },
13};
14
15#[derive(CubeType, Clone)]
23pub enum LinearViewLayout {
24 Plain(PlainLayout),
26 Strided(StridedLayout),
28 Permuted(PermutedLayout),
30}
31
32impl LinearViewLayoutExpand {
33 fn __expand_inner_method(
34 &self,
35 _scope: &Scope,
36 ) -> &dyn VirtualLayoutOperationsExpand<Coords1d, Coords1d> {
37 match self {
38 LinearViewLayoutExpand::Plain(layout) => layout,
39 LinearViewLayoutExpand::Strided(layout) => layout,
40 LinearViewLayoutExpand::Permuted(layout) => layout,
41 }
42 }
43}
44
45#[derive(Default)]
46pub struct LinearViewLayoutLaunch {
47 reference_shape: Option<Shape>,
48}
49
50impl ViewLayoutLaunchArg for LinearViewLayout {
51 type RuntimeArg<R: Runtime> = LinearViewLayoutLaunch;
52 type CompilationArg = LinearLayoutCompilationArg;
53
54 fn register<R: Runtime, B: MemoryArg>(
55 runtime_arg: Self::RuntimeArg<R>,
56 buffer: &B,
57 ty: Type,
58 launcher: &mut KernelLauncher<R>,
59 ) -> Self::CompilationArg {
60 let shape = buffer.shape();
61 match runtime_arg.reference_shape {
62 Some(reference_shape) if reference_shape.as_slice() != shape => {
63 let arg = PermutedLayoutLaunch::from_reference_shape(reference_shape);
64 let comp_arg = PermutedLayout::register(arg, buffer, ty, launcher);
65 LinearLayoutCompilationArg::Permuted(comp_arg)
66 }
67 _ => {
68 let strides = buffer.strides();
69 if is_contiguous(shape, strides) {
70 PlainLayout::register((), buffer, ty, launcher);
71 LinearLayoutCompilationArg::Plain
72 } else if is_contiguous_pitched(shape, strides) {
73 let comp_arg = StridedLayout::register((), buffer, ty, launcher);
74 LinearLayoutCompilationArg::Strided(comp_arg)
75 } else {
76 let comp_arg =
77 PermutedLayout::register(Default::default(), buffer, ty, launcher);
78 LinearLayoutCompilationArg::Permuted(comp_arg)
79 }
80 }
81 }
82 }
83 fn expand(
84 compilation_arg: &Self::CompilationArg,
85 ty: Type,
86 builder: &mut cubecl::prelude::KernelBuilder,
87 ) -> <Self as cubecl::prelude::CubeType>::ExpandType {
88 match compilation_arg {
89 LinearLayoutCompilationArg::Plain => {
90 LinearViewLayoutExpand::Plain(PlainLayout::expand(&(), ty, builder))
91 }
92 LinearLayoutCompilationArg::Strided(arg) => {
93 LinearViewLayoutExpand::Strided(StridedLayout::expand(arg, ty, builder))
94 }
95 LinearLayoutCompilationArg::Permuted(arg) => {
96 LinearViewLayoutExpand::Permuted(PermutedLayout::expand(arg, ty, builder))
97 }
98 }
99 }
100}
101
102#[derive(Debug, Hash, PartialEq, Eq, Clone)]
103pub enum LinearLayoutCompilationArg {
104 Plain,
105 Strided(StridedLayoutCompilationArg),
106 Permuted(PermutedLayoutCompilationArg),
107}
108
109impl LinearViewLayoutLaunch {
110 pub fn new() -> Self {
112 Self::default()
113 }
114
115 pub fn from_reference_shape(reference_shape: Shape) -> Self {
117 Self {
118 reference_shape: Some(reference_shape),
119 }
120 }
121
122 pub fn from_reference_handle<R: Runtime>(reference: TensorBinding<R>) -> Self {
124 Self::from_reference_shape(reference.shape)
125 }
126}
127
128#[cube]
129impl Layout for LinearViewLayout {
130 type Coordinates = Coords1d;
131 type SourceCoordinates = Coords1d;
132
133 #[allow(unused)]
134 fn to_source_pos(&self, pos: Self::Coordinates) -> usize {
135 intrinsic!(|scope| {
136 let inner = self.__expand_inner_method(scope);
137 inner.__expand_to_source_pos_virt_method(scope, pos)
138 })
139 }
140
141 fn to_source_pos_checked(&self, pos: Self::Coordinates) -> (usize, bool) {
142 (self.to_source_pos(pos), self.is_in_bounds(pos))
143 }
144
145 fn shape(&self) -> Self::Coordinates {
146 intrinsic!(|scope| {
147 let inner = self.__expand_inner_method(scope);
148 inner.__expand_shape_virt_method(scope)
149 })
150 }
151
152 #[allow(unused)]
153 fn is_in_bounds(&self, pos: Self::Coordinates) -> bool {
154 intrinsic!(|scope| {
155 let inner = self.__expand_inner_method(scope);
156 inner.__expand_is_in_bounds_virt_method(scope, pos)
157 })
158 }
159}
160
161pub type LinearLayout = ConcreteLayout<LinearViewLayout>;
163pub type LinearLayoutLaunch<R> = ConcreteLayoutLaunch<LinearViewLayout, R>;
164
165pub type LinearView<'a, E> = View<'a, E, Coords1d>;
168pub type LinearViewMut<'a, E> = ViewMut<'a, E, Coords1d>;
169pub type LinearViewLaunch<R> = ViewArg<Coords1d, R>;
171
172pub fn linear_layout<R: Runtime>(
174 handle: &TensorBinding<R>,
175 vector_size: VectorSize,
176) -> LinearLayoutLaunch<R> {
177 LinearLayoutLaunch::from_handle(
178 handle,
179 Type::new(UIntKind::U32.into()).with_vector_size(vector_size),
181 LinearViewLayoutLaunch::new(),
182 )
183}
184
185pub fn linear_view<R: Runtime>(handle: TensorBinding<R>) -> LinearViewLaunch<R> {
187 let layout = LinearViewLayoutLaunch::new();
188 LinearViewLaunch::new_tensor::<LinearViewLayout>(handle.into_tensor_arg(), layout)
189}
190
191pub fn linear_view_with_reference<R: Runtime>(
193 handle: TensorBinding<R>,
194 reference: TensorBinding<R>,
195) -> LinearViewLaunch<R> {
196 let layout = LinearViewLayoutLaunch::from_reference_handle(reference);
197 LinearViewLaunch::new_tensor::<LinearViewLayout>(handle.into_tensor_arg(), layout)
198}
199
200pub fn linear_view_alias<R: Runtime>(handle: &TensorBinding<R>, pos: usize) -> LinearViewLaunch<R> {
201 let layout = LinearViewLayoutLaunch::new();
202 LinearViewLaunch::new_tensor::<LinearViewLayout>(handle.as_alias(pos), layout)
203}