cubecl_core/frontend/container/
shared_memory.rs1use core::ops::{Deref, DerefMut};
2
3use crate::{
4 self as cubecl,
5 frontend::container::slice,
6 prelude::{Vectorized, VectorizedExpand},
7 unexpanded,
8};
9use cubecl_ir::{
10 AggregateKind, BoundsCheckMetadata, Marker, MetadataKind, SliceMetadata, VectorSize,
11};
12use cubecl_macros::{cube, intrinsic};
13
14use crate::{
15 frontend::{CubePrimitive, CubeType, IntoMut, NativeExpand},
16 ir::Scope,
17 prelude::*,
18};
19
20pub type SharedExpand<T> = NativeExpand<Shared<T>>;
21
22pub struct Shared<E: NativeCubeType + ?Sized> {
23 _val: *mut E,
24}
25
26impl<E: NativeCubeType + ?Sized> Clone for Shared<E> {
28 fn clone(&self) -> Self {
29 Self { _val: self._val }
30 }
31}
32
33impl<T: NativeCubeType + ?Sized> IntoMut for NativeExpand<Shared<T>> {
34 fn into_mut(self, _scope: &Scope) -> Self {
35 self
36 }
37}
38
39impl<T: NativeCubeType + ?Sized> CubeType for Shared<T> {
40 type ExpandType = NativeExpand<Shared<T>>;
41}
42
43impl<T: NativeCubeType + ?Sized> AsMutExpand for SharedExpand<T> {
44 fn __expand_ref_mut_method(&mut self, _: &Scope) -> &mut Self {
45 self
46 }
47}
48
49#[cube]
50impl<T: CubePrimitive> Shared<[T]> {
51 pub fn new_slice(#[comptime] len: usize) -> Self {
57 intrinsic!(|scope| {
58 let ty = Type::array(T::__expand_as_type(scope), len);
59 let buffer = scope.create_shared(ty, None);
60 let slice = slice::from_raw_parts::<T>(
61 scope,
62 buffer,
63 0usize.into_expand(scope),
64 len.into_expand(scope),
65 );
66 slice.expand.into()
67 })
68 }
69
70 #[allow(unused_variables)]
76 pub fn new_aligned_slice(#[comptime] len: usize, #[comptime] alignment: usize) -> Self {
77 intrinsic!(|scope| {
78 let ty = Type::array(T::__expand_as_type(scope), len);
79 let buffer = scope.create_shared(ty, Some(alignment));
80 let slice = slice::from_raw_parts::<T>(
81 scope,
82 buffer,
83 0usize.into_expand(scope),
84 len.into_expand(scope),
85 );
86 slice.expand.into()
87 })
88 }
89
90 #[allow(clippy::len_without_is_empty)]
91 pub fn len(&self) -> usize {
92 intrinsic!(|_| len_static(&self))
93 }
94}
95
96impl<T: NativeCubeType + ?Sized> Shared<T> {
97 pub fn map<U: NativeCubeType + ?Sized>(self, _map: impl FnOnce(&T) -> &U) -> Shared<U> {
98 unexpanded!()
99 }
100}
101
102impl<T: NativeCubeType + ?Sized> SharedExpand<T> {
103 pub fn __expand_map_method<U: NativeCubeType + ?Sized>(
104 self,
105 scope: &Scope,
106 map: impl for<'a> FnOnce(&Scope, &'a NativeExpand<T>) -> &'a NativeExpand<U>,
107 ) -> SharedExpand<U> {
108 let out = map(scope, self.__expand_ref_method(scope));
109 out.expand.into()
110 }
111}
112
113#[cube]
114impl<T: CubePrimitive> Shared<T> {
115 pub fn new() -> Self {
121 intrinsic!(|scope| {
122 let val = scope.create_shared(T::__expand_as_type(scope), None);
123 NativeExpand::new(val)
124 })
125 }
126}
127
128#[cube]
129impl<T: NativeCubeType + ?Sized> Shared<T> {
130 pub fn inner_ref(&self) -> &T {
131 intrinsic!(|scope| { unsafe { self.as_type_ref_unchecked() } })
132 }
133
134 pub fn inner_mut(&mut self) -> &mut T {
135 intrinsic!(|scope| { unsafe { self.as_type_mut_unchecked() } })
136 }
137}
138
139impl<T: CubePrimitive> Default for Shared<T> {
140 fn default() -> Self {
141 Self::new()
142 }
143}
144impl<T: CubePrimitive> Shared<T> {
145 pub fn __expand_default(scope: &Scope) -> <Self as CubeType>::ExpandType {
146 Self::__expand_new(scope)
147 }
148}
149
150#[cube]
151impl<T: NativeCubeType + ?Sized> Shared<T> {
152 pub unsafe fn free(&self) {
158 intrinsic!(|scope| {
159 let val = match self.expand.ty {
160 Type::Aggregate(aggregate_kind) => match aggregate_kind {
161 AggregateKind::Ptr {
162 meta: MetadataKind::Slice,
163 ..
164 } => scope.extract_field(self.expand, self.expand.ty, SliceMetadata::LIST),
165 AggregateKind::Ptr {
166 meta: MetadataKind::BoundsCheck,
167 ..
168 } => scope.extract_field(
169 self.expand,
170 self.expand.ty,
171 BoundsCheckMetadata::POINTER,
172 ),
173 },
174 _ => self.expand,
175 };
176 scope.register(Marker::Free(val))
177 })
178 }
179}
180
181fn len_static<T: CubePrimitive>(shared: &NativeExpand<Shared<[T]>>) -> NativeExpand<usize> {
182 let Type::Array(_, length) = shared.expand.ty else {
183 unreachable!("Kind of shared memory is always shared memory")
184 };
185 length.into()
186}
187
188impl<T: CubePrimitive> List<T> for Shared<[T]> {}
189impl<T: CubePrimitive> ListExpand<T> for NativeExpand<Shared<[T]>> {
190 fn __expand_len_method(&self, scope: &Scope) -> NativeExpand<usize> {
191 Self::__expand_len_method(self, scope)
192 }
193}
194
195impl<T: CubePrimitive> Vectorized for Shared<[T]> {}
196impl<T: CubePrimitive> VectorizedExpand for NativeExpand<Shared<[T]>> {
197 fn vector_size(&self) -> VectorSize {
198 self.expand.ty.vector_size()
199 }
200}
201
202impl<T: NativeCubeType + ?Sized> Deref for Shared<T> {
203 type Target = T;
204
205 fn deref(&self) -> &Self::Target {
206 unexpanded!()
207 }
208}
209impl<T: NativeCubeType + ?Sized> DerefMut for Shared<T> {
210 fn deref_mut(&mut self) -> &mut Self::Target {
211 unexpanded!()
212 }
213}
214
215impl<T: NativeCubeType + ?Sized> Deref for SharedExpand<T> {
216 type Target = NativeExpand<T>;
217
218 fn deref(&self) -> &Self::Target {
219 unsafe { self.as_type_ref_unchecked() }
220 }
221}
222impl<T: NativeCubeType + ?Sized> DerefMut for SharedExpand<T> {
223 fn deref_mut(&mut self) -> &mut Self::Target {
224 unsafe { self.as_type_mut_unchecked() }
225 }
226}
227
228impl<'a, T: NativeCubeType + ?Sized> From<&'a SharedExpand<T>> for &'a NativeExpand<T> {
229 fn from(value: &'a SharedExpand<T>) -> Self {
230 value
231 }
232}
233
234impl<'a, T: NativeCubeType + ?Sized> From<&'a mut SharedExpand<T>> for &'a mut NativeExpand<T> {
235 fn from(value: &'a mut SharedExpand<T>) -> Self {
236 value
237 }
238}
239
240impl<T: NativeCubeType + ?Sized> AsDerefExpand for SharedExpand<T> {
241 type Target = NativeExpand<T>;
242
243 fn __expand_as_deref_method(&self, _: &Scope) -> &Self::Target {
244 unsafe { self.as_type_ref_unchecked::<T>() }
245 }
246}
247impl<T: NativeCubeType + ?Sized> AsDerefMutExpand for SharedExpand<T> {
248 fn __expand_as_deref_mut_method(&mut self, _: &Scope) -> &mut Self::Target {
249 unsafe { self.as_type_mut_unchecked::<T>() }
250 }
251}
252
253impl<T: CubePrimitive> Assign<NativeExpand<T>> for SharedExpand<T> {
254 fn __expand_assign_method(&mut self, scope: &Scope, value: NativeExpand<T>) {
255 let value = read_value(scope, value.expand);
256 assign::expand_element(scope, value, self.expand);
257 }
258}
259
260impl<T: CubePrimitive> RuntimeAssign<NativeExpand<T>> for SharedExpand<T> {
261 fn init_mut(&self, scope: &Scope) -> Self::Expand {
262 Shared::<T>::__expand_new(scope)
263 }
264}