sim_lib_compute_cuda/
storage.rs1use std::{
4 any::Any,
5 sync::{Arc, OnceLock},
6};
7
8use sim_kernel::{DefaultFactory, Error, Factory, Result, Symbol, Value};
9use sim_lib_numbers_tensor::{Tensor, TensorLocation, TensorStorage};
10
11#[derive(Clone, Debug, PartialEq, Eq)]
13pub struct CudaAllocation {
14 pub id: usize,
16 pub bytes: u64,
18 pub operation: Symbol,
20}
21
22impl CudaAllocation {
23 fn id_symbol(&self) -> Symbol {
24 Symbol::qualified("compute.alloc.cuda", self.id.to_string())
25 }
26}
27
28pub struct CudaResidentStorage {
30 site: Symbol,
31 allocation: CudaAllocation,
32 shape: Arc<[usize]>,
33 dtype: Symbol,
34 cells: Arc<[Value]>,
35 materialized: OnceLock<Result<Arc<dyn TensorStorage>>>,
36}
37
38impl CudaResidentStorage {
39 pub fn new(
41 site: Symbol,
42 allocation: CudaAllocation,
43 shape: Vec<usize>,
44 dtype: Symbol,
45 cells: Arc<[Value]>,
46 ) -> Self {
47 Self {
48 site,
49 allocation,
50 shape: shape.into(),
51 dtype,
52 cells,
53 materialized: OnceLock::new(),
54 }
55 }
56
57 pub fn allocation(&self) -> &CudaAllocation {
59 &self.allocation
60 }
61
62 pub fn resident_tensor(&self) -> Option<Tensor> {
64 Tensor::from_storage(
65 self.shape.to_vec(),
66 self.dtype.clone(),
67 Arc::new(BoxedCudaStorage::new(
68 self.dtype.clone(),
69 self.cells.clone(),
70 )),
71 )
72 .ok()
73 }
74}
75
76impl TensorStorage for CudaResidentStorage {
77 fn dtype(&self) -> &Symbol {
78 &self.dtype
79 }
80
81 fn len(&self) -> usize {
82 self.cells.len()
83 }
84
85 fn location(&self) -> TensorLocation {
86 TensorLocation::Resident {
87 site: self.site.clone(),
88 allocation: self.allocation.id_symbol(),
89 }
90 }
91
92 fn cell(&self, index: usize) -> Result<Value> {
93 self.materialize()?.cell(index)
94 }
95
96 fn materialize(&self) -> Result<Arc<dyn TensorStorage>> {
97 self.materialized
98 .get_or_init(|| {
99 Ok(Arc::new(BoxedCudaStorage::new(
100 self.dtype.clone(),
101 self.cells.clone(),
102 )))
103 })
104 .clone()
105 }
106
107 fn as_any(&self) -> &dyn Any {
108 self
109 }
110}
111
112struct BoxedCudaStorage {
113 dtype: Symbol,
114 cells: Arc<[Value]>,
115}
116
117impl BoxedCudaStorage {
118 fn new(dtype: Symbol, cells: Arc<[Value]>) -> Self {
119 Self { dtype, cells }
120 }
121}
122
123impl TensorStorage for BoxedCudaStorage {
124 fn dtype(&self) -> &Symbol {
125 &self.dtype
126 }
127
128 fn len(&self) -> usize {
129 self.cells.len()
130 }
131
132 fn location(&self) -> TensorLocation {
133 TensorLocation::Host
134 }
135
136 fn cell(&self, index: usize) -> Result<Value> {
137 self.cells
138 .get(index)
139 .cloned()
140 .ok_or_else(|| Error::Eval("cuda tensor cell index was out of bounds".to_owned()))
141 }
142
143 fn materialize(&self) -> Result<Arc<dyn TensorStorage>> {
144 Ok(Arc::new(Self {
145 dtype: self.dtype.clone(),
146 cells: self.cells.clone(),
147 }))
148 }
149
150 fn as_any(&self) -> &dyn Any {
151 self
152 }
153}
154
155impl sim_kernel::Object for CudaAllocation {
156 fn display(&self, _cx: &mut sim_kernel::Cx) -> Result<String> {
157 Ok(format!("#<cuda-allocation {} {}b>", self.id, self.bytes))
158 }
159
160 fn as_any(&self) -> &dyn Any {
161 self
162 }
163}
164
165impl sim_kernel::ObjectCompat for CudaAllocation {
166 fn class(&self, _cx: &mut sim_kernel::Cx) -> Result<sim_kernel::ClassRef> {
167 DefaultFactory.class_stub(
168 sim_kernel::CORE_FUNCTION_CLASS_ID,
169 Symbol::qualified("compute", "CudaAllocation"),
170 )
171 }
172}