cubecl_runtime/storage/base.rs
1use core::fmt::Debug;
2
3use crate::{server::Binding, storage_id_type};
4
5// This ID is used to map a handle to its actual data.
6storage_id_type!(StorageId);
7
8/// Defines if data uses a full memory chunk or a slice of it.
9#[derive(Clone, Debug)]
10pub struct StorageUtilization {
11 /// The offset in bytes from the chunk start.
12 pub offset: u64,
13 /// The size of the slice in bytes.
14 pub size: u64,
15}
16
17/// Contains the [storage id](StorageId) of a resource and the way it is used.
18#[derive(new, Clone, Debug)]
19pub struct StorageHandle {
20 /// Storage id.
21 pub id: StorageId,
22 /// How the storage is used.
23 pub utilization: StorageUtilization,
24}
25
26impl StorageHandle {
27 /// Returns the size the handle is pointing to in memory.
28 pub fn size(&self) -> u64 {
29 self.utilization.size
30 }
31
32 /// Returns the size the handle is pointing to in memory.
33 pub fn offset(&self) -> u64 {
34 self.utilization.offset
35 }
36
37 /// Increase the current offset with the given value in bytes.
38 pub fn offset_start(&self, offset_bytes: u64) -> Self {
39 let utilization = StorageUtilization {
40 offset: self.offset() + offset_bytes,
41 size: self.size() - offset_bytes,
42 };
43
44 Self {
45 id: self.id,
46 utilization,
47 }
48 }
49
50 /// Reduce the size of the memory handle..
51 pub fn offset_end(&self, offset_bytes: u64) -> Self {
52 let utilization = StorageUtilization {
53 offset: self.offset(),
54 size: self.size() - offset_bytes,
55 };
56
57 Self {
58 id: self.id,
59 utilization,
60 }
61 }
62}
63
64/// Storage types are responsible for allocating and deallocating memory.
65pub trait ComputeStorage: Send {
66 /// The resource associated type determines the way data is implemented and how
67 /// it can be accessed by kernels.
68 type Resource: Send;
69
70 /// The alignment memory is allocated with in this storage.
71 fn alignment(&self) -> usize;
72
73 /// Returns the underlying resource for a specified storage handle
74 fn get(&mut self, handle: &StorageHandle) -> Self::Resource;
75
76 /// Allocates `size` units of memory and returns a handle to it
77 fn alloc(&mut self, size: u64) -> StorageHandle;
78
79 /// Deallocates the memory pointed by the given storage id.
80 ///
81 /// These deallocations might need to be flushed with [`Self::perform_deallocations`].
82 fn dealloc(&mut self, id: StorageId);
83}
84
85/// Access to the underlying resource for a given binding.
86#[derive(new, Debug)]
87pub struct BindingResource<Resource: Send> {
88 // This binding is here just to keep the underlying allocation alive.
89 // If the underlying allocation becomes invalid, someone else might
90 // allocate into this resource which could lead to bad behaviour.
91 #[allow(unused)]
92 binding: Binding,
93 resource: Resource,
94}
95
96impl<Resource: Send> BindingResource<Resource> {
97 /// access the underlying resource. Note: The resource might be bigger
98 /// than just the original allocation for the binding. Only the part
99 /// for the original binding is guaranteed to remain, other parts
100 /// of the resource *will* be re-used.
101 pub fn resource(&self) -> &Resource {
102 &self.resource
103 }
104}