cubecl_core/frontend/container/tensor/
launch.rs1use core::marker::PhantomData;
2
3use cubecl_ir::{AddressType, Id};
4use cubecl_runtime::{runtime::Runtime, server::CopyDescriptor};
5use cubecl_zspace::{Shape, Strides};
6
7use crate::{
8 self as cubecl,
9 compute::{KernelBuilder, KernelLauncher},
10 frontend::container::slice,
11 prelude::*,
12};
13
14use super::Tensor;
15
16#[derive(CubeType, CubeLaunch, Clone, Copy)]
17#[expand(derive(Clone, Copy))]
18pub struct TensorMeta {
19 pub len: usize,
20 pub rank: usize,
21}
22
23#[derive(Debug)]
25pub enum TensorArg<R: Runtime> {
26 Handle {
28 handle: TensorBinding<R>,
30 },
31 Alias {
33 input_pos: usize,
35 strides: Strides,
36 shape: Shape,
37 },
38}
39
40pub struct TensorBinding<R: Runtime> {
43 pub handle: cubecl_runtime::server::Binding,
44 pub strides: Strides,
45 pub shape: Shape,
46 pub runtime: PhantomData<R>,
47}
48
49impl<R: Runtime> Clone for TensorBinding<R> {
50 fn clone(&self) -> Self {
51 Self {
52 handle: self.handle.clone(),
53 strides: self.strides.clone(),
54 shape: self.shape.clone(),
55 runtime: PhantomData,
56 }
57 }
58}
59
60impl<R: Runtime> TensorBinding<R> {
61 pub fn size(&self) -> usize {
62 self.shape.iter().product()
63 }
64
65 pub fn required_address_type(&self, elem_size: usize) -> AddressType {
67 AddressType::from_len(self.handle.size() as usize / elem_size)
68 }
69}
70
71impl<R: Runtime> core::fmt::Debug for TensorBinding<R> {
72 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
73 writeln!(
74 f,
75 "TensorHandleRef {{ strides: {:?}, shape: {:?} }}",
76 self.strides, self.shape
77 )
78 }
79}
80
81#[derive(Clone, PartialEq, Eq, Hash, Debug)]
83pub struct TensorCompilationArg {
84 pub meta: TensorMetaCompilationArg,
85 pub buffer: BufferCompilationArg,
86}
87
88impl<C: CubePrimitive> LaunchArg for Tensor<C> {
89 type RuntimeArg<R: Runtime> = TensorArg<R>;
90 type CompilationArg = TensorCompilationArg;
91
92 fn register<R: Runtime>(
93 arg: Self::RuntimeArg<R>,
94 launcher: &mut KernelLauncher<R>,
95 ) -> Self::CompilationArg {
96 let ty = launcher.with_scope(|scope| C::__expand_as_type(scope));
97 let len = arg.size() / ty.vector_size();
98 let meta_arg = TensorMetaLaunch::new(len, arg.shape().len());
99 let buffer = match &arg {
100 TensorArg::Handle { .. } => BufferCompilationArg { inplace: None },
101 TensorArg::Alias { input_pos, .. } => BufferCompilationArg {
102 inplace: Some(*input_pos as Id),
103 },
104 };
105 launcher.register_tensor(arg, ty);
106 let meta = TensorMeta::register(meta_arg, launcher);
107 TensorCompilationArg { meta, buffer }
108 }
109
110 fn expand(arg: &Self::CompilationArg, builder: &mut KernelBuilder) -> TensorExpand<C> {
111 let buffer = match arg.buffer.inplace {
112 Some(id) => builder.inplace(id),
113 None => builder.tensor(C::__expand_as_type(&builder.scope)),
114 };
115 let meta = TensorMeta::expand(&arg.meta, builder);
116 let scope = &builder.scope;
117 let len = expand_buffer_length_native(scope, buffer);
118 let buffer =
119 slice::from_raw_parts::<C>(scope, buffer, 0usize.into_expand(scope), len.into());
120 TensorExpand { meta, buffer }
121 }
122}
123
124impl<C: CubePrimitive> LaunchArg for OwnedTensor<C> {
125 type RuntimeArg<R: Runtime> = TensorArg<R>;
126 type CompilationArg = TensorCompilationArg;
127
128 fn register<R: Runtime>(
129 arg: Self::RuntimeArg<R>,
130 launcher: &mut KernelLauncher<R>,
131 ) -> Self::CompilationArg {
132 Tensor::<C>::register(arg, launcher)
133 }
134
135 fn expand(arg: &Self::CompilationArg, builder: &mut KernelBuilder) -> OwnedTensorExpand<C> {
136 let tensor = Tensor::<C>::expand(arg, builder);
137 OwnedTensorExpand {
138 meta: tensor.meta,
139 buffer: tensor.buffer.expand.into(),
140 }
141 }
142}
143
144impl<R: Runtime> TensorArg<R> {
145 pub unsafe fn from_raw_parts(
152 handle: cubecl_runtime::server::Handle,
153 strides: Strides,
154 shape: Shape,
155 ) -> Self {
156 unsafe { Self::from_raw_parts_binding(handle.binding(), strides, shape) }
157 }
158
159 pub(crate) unsafe fn from_raw_parts_binding(
160 handle: cubecl_runtime::server::Binding,
161 strides: Strides,
162 shape: Shape,
163 ) -> Self {
164 unsafe {
165 Self::Handle {
166 handle: TensorBinding::from_raw_parts_binding(handle, strides, shape),
167 }
168 }
169 }
170
171 pub fn into_alias(self, position: usize) -> Self {
173 match self {
174 TensorArg::Handle { handle } => handle.into_alias(position),
175 alias @ TensorArg::Alias { .. } => alias,
176 }
177 }
178
179 pub fn size(&self) -> usize {
180 match self {
181 TensorArg::Handle { handle } => handle.size(),
182 TensorArg::Alias { shape, .. } => shape.iter().product(),
183 }
184 }
185
186 pub fn shape(&self) -> &[usize] {
187 match self {
188 TensorArg::Handle { handle } => &handle.shape,
189 TensorArg::Alias { shape, .. } => shape,
190 }
191 }
192
193 pub fn strides(&self) -> &[usize] {
194 match self {
195 TensorArg::Handle { handle } => &handle.strides,
196 TensorArg::Alias { strides, .. } => strides,
197 }
198 }
199}
200
201impl<R: Runtime> TensorArg<R> {
202 pub fn into_buffer_arg(self) -> BufferArg<R> {
203 match self {
204 TensorArg::Handle { handle } => {
205 let handle = unsafe {
206 let size = handle.size();
207 BufferBinding::from_raw_parts_binding(handle.handle, size)
208 };
209 BufferArg::Handle { handle }
210 }
211 TensorArg::Alias {
212 input_pos, shape, ..
213 } => BufferArg::Alias {
214 input_pos,
215 length: [shape.iter().product()],
216 },
217 }
218 }
219}
220
221impl<R: Runtime> TensorBinding<R> {
222 pub fn into_tensor_arg(self) -> TensorArg<R> {
224 TensorArg::Handle { handle: self }
225 }
226 pub fn into_alias(self, index: usize) -> TensorArg<R> {
228 TensorArg::Alias {
229 input_pos: index,
230 strides: self.strides,
231 shape: self.shape,
232 }
233 }
234 pub fn as_alias(&self, index: usize) -> TensorArg<R> {
236 TensorArg::Alias {
237 input_pos: index,
238 strides: self.strides.clone(),
239 shape: self.shape.clone(),
240 }
241 }
242 pub fn into_buffer_arg(self) -> BufferArg<R> {
244 unsafe { BufferArg::from_raw_parts_binding(self.handle, self.shape.iter().product()) }
245 }
246
247 pub unsafe fn from_raw_parts(
254 handle: cubecl_runtime::server::Handle,
255 strides: Strides,
256 shape: Shape,
257 ) -> Self {
258 unsafe { Self::from_raw_parts_binding(handle.binding(), strides, shape) }
259 }
260
261 pub unsafe fn from_raw_parts_binding(
268 handle: cubecl_runtime::server::Binding,
269 strides: Strides,
270 shape: Shape,
271 ) -> Self {
272 Self {
273 handle,
274 strides,
275 shape,
276 runtime: PhantomData,
277 }
278 }
279
280 pub fn into_copy_descriptor(self, elem_size: usize) -> CopyDescriptor {
281 CopyDescriptor {
282 handle: self.handle,
283 shape: self.shape,
284 strides: self.strides,
285 elem_size,
286 }
287 }
288}