1use crate::{DType, Error, Result, WithDType};
10use float8::F8E4M3;
11use half::{bf16, f16};
12
13#[derive(Debug, Clone)]
22pub enum HostBuffer {
23 U8(Vec<u8>),
24 I8(Vec<i8>),
25 U32(Vec<u32>),
26 I16(Vec<i16>),
27 I32(Vec<i32>),
28 I64(Vec<i64>),
29 BF16(Vec<bf16>),
30 F16(Vec<f16>),
31 F32(Vec<f32>),
32 F64(Vec<f64>),
33 F8E4M3(Vec<F8E4M3>),
34 F6E2M3(Vec<u8>),
36 F6E3M2(Vec<u8>),
37 F4(Vec<u8>),
38 F8E8M0(Vec<u8>),
39 Bool(Vec<u8>),
44}
45
46pub type CpuStorage = HostBuffer;
48
49#[derive(Debug, Clone)]
51pub enum HostBufferRef<'a> {
52 U8(&'a [u8]),
53 I8(&'a [i8]),
54 U32(&'a [u32]),
55 I16(&'a [i16]),
56 I32(&'a [i32]),
57 I64(&'a [i64]),
58 BF16(&'a [bf16]),
59 F16(&'a [f16]),
60 F32(&'a [f32]),
61 F64(&'a [f64]),
62 F8E4M3(&'a [F8E4M3]),
63 F6E2M3(&'a [u8]),
65 F6E3M2(&'a [u8]),
66 F4(&'a [u8]),
67 F8E8M0(&'a [u8]),
68 Bool(&'a [u8]),
71}
72
73pub type CpuStorageRef<'a> = HostBufferRef<'a>;
75
76#[derive(Debug, Clone)]
78pub struct CpuDevice;
79
80impl HostBuffer {
81 pub fn dtype(&self) -> DType {
83 match self {
84 Self::U8(_) => DType::U8,
85 Self::I8(_) => DType::I8,
86 Self::U32(_) => DType::U32,
87 Self::I16(_) => DType::I16,
88 Self::I32(_) => DType::I32,
89 Self::I64(_) => DType::I64,
90 Self::BF16(_) => DType::BF16,
91 Self::F16(_) => DType::F16,
92 Self::F32(_) => DType::F32,
93 Self::F64(_) => DType::F64,
94 Self::F8E4M3(_) => DType::F8E4M3,
95 Self::F6E2M3(_) => DType::F6E2M3,
96 Self::F6E3M2(_) => DType::F6E3M2,
97 Self::F4(_) => DType::F4,
98 Self::F8E8M0(_) => DType::F8E8M0,
99 Self::Bool(_) => DType::Bool,
100 }
101 }
102
103 pub fn as_slice<D: HostDType>(&self) -> crate::Result<&[D]> {
105 D::cpu_storage_as_slice(self)
106 }
107
108 pub fn concat(storages: &[CpuStorage]) -> crate::Result<CpuStorage> {
110 let storage0 = &storages[0];
111 let s = match storage0 {
112 Self::U8(_) => {
113 let storages = storages
114 .iter()
115 .map(|s| match s {
116 Self::U8(s) => Ok(s.as_slice()),
117 _ => crate::bail!("dtype mismatch"),
118 })
119 .collect::<crate::Result<Vec<_>>>()?;
120 Self::U8(storages.concat())
121 }
122 Self::I8(_) => {
123 let storages = storages
124 .iter()
125 .map(|s| match s {
126 Self::I8(s) => Ok(s.as_slice()),
127 _ => crate::bail!("dtype mismatch"),
128 })
129 .collect::<crate::Result<Vec<_>>>()?;
130 Self::I8(storages.concat())
131 }
132 Self::U32(_) => {
133 let storages = storages
134 .iter()
135 .map(|s| match s {
136 Self::U32(s) => Ok(s.as_slice()),
137 _ => crate::bail!("dtype mismatch"),
138 })
139 .collect::<crate::Result<Vec<_>>>()?;
140 Self::U32(storages.concat())
141 }
142 Self::I16(_) => {
143 let storages = storages
144 .iter()
145 .map(|s| match s {
146 Self::I16(s) => Ok(s.as_slice()),
147 _ => crate::bail!("dtype mismatch"),
148 })
149 .collect::<crate::Result<Vec<_>>>()?;
150 Self::I16(storages.concat())
151 }
152 Self::I32(_) => {
153 let storages = storages
154 .iter()
155 .map(|s| match s {
156 Self::I32(s) => Ok(s.as_slice()),
157 _ => crate::bail!("dtype mismatch"),
158 })
159 .collect::<crate::Result<Vec<_>>>()?;
160 Self::I32(storages.concat())
161 }
162 Self::I64(_) => {
163 let storages = storages
164 .iter()
165 .map(|s| match s {
166 Self::I64(s) => Ok(s.as_slice()),
167 _ => crate::bail!("dtype mismatch"),
168 })
169 .collect::<crate::Result<Vec<_>>>()?;
170 Self::I64(storages.concat())
171 }
172 Self::BF16(_) => {
173 let storages = storages
174 .iter()
175 .map(|s| match s {
176 Self::BF16(s) => Ok(s.as_slice()),
177 _ => crate::bail!("dtype mismatch"),
178 })
179 .collect::<crate::Result<Vec<_>>>()?;
180 Self::BF16(storages.concat())
181 }
182 Self::F16(_) => {
183 let storages = storages
184 .iter()
185 .map(|s| match s {
186 Self::F16(s) => Ok(s.as_slice()),
187 _ => crate::bail!("dtype mismatch"),
188 })
189 .collect::<crate::Result<Vec<_>>>()?;
190 Self::F16(storages.concat())
191 }
192 Self::F32(_) => {
193 let storages = storages
194 .iter()
195 .map(|s| match s {
196 Self::F32(s) => Ok(s.as_slice()),
197 _ => crate::bail!("dtype mismatch"),
198 })
199 .collect::<crate::Result<Vec<_>>>()?;
200 Self::F32(storages.concat())
201 }
202 Self::F64(_) => {
203 let storages = storages
204 .iter()
205 .map(|s| match s {
206 Self::F64(s) => Ok(s.as_slice()),
207 _ => crate::bail!("dtype mismatch"),
208 })
209 .collect::<crate::Result<Vec<_>>>()?;
210 Self::F64(storages.concat())
211 }
212 Self::F8E4M3(_) => {
213 let storages = storages
214 .iter()
215 .map(|s| match s {
216 Self::F8E4M3(s) => Ok(s.as_slice()),
217 _ => crate::bail!("dtype mismatch"),
218 })
219 .collect::<crate::Result<Vec<_>>>()?;
220 Self::F8E4M3(storages.concat())
221 }
222 Self::F6E2M3(_) => {
223 let storages = storages
224 .iter()
225 .map(|s| match s {
226 Self::F6E2M3(s) => Ok(s.as_slice()),
227 _ => crate::bail!("dtype mismatch"),
228 })
229 .collect::<crate::Result<Vec<_>>>()?;
230 Self::F6E2M3(storages.concat())
231 }
232 Self::F6E3M2(_) => {
233 let storages = storages
234 .iter()
235 .map(|s| match s {
236 Self::F6E3M2(s) => Ok(s.as_slice()),
237 _ => crate::bail!("dtype mismatch"),
238 })
239 .collect::<crate::Result<Vec<_>>>()?;
240 Self::F6E3M2(storages.concat())
241 }
242 Self::F4(_) => {
243 let storages = storages
244 .iter()
245 .map(|s| match s {
246 Self::F4(s) => Ok(s.as_slice()),
247 _ => crate::bail!("dtype mismatch"),
248 })
249 .collect::<crate::Result<Vec<_>>>()?;
250 Self::F4(storages.concat())
251 }
252 Self::F8E8M0(_) => {
253 let storages = storages
254 .iter()
255 .map(|s| match s {
256 Self::F8E8M0(s) => Ok(s.as_slice()),
257 _ => crate::bail!("dtype mismatch"),
258 })
259 .collect::<crate::Result<Vec<_>>>()?;
260 Self::F8E8M0(storages.concat())
261 }
262 Self::Bool(_) => {
263 let storages = storages
264 .iter()
265 .map(|s| match s {
266 Self::Bool(s) => Ok(s.as_slice()),
267 _ => crate::bail!("dtype mismatch"),
268 })
269 .collect::<crate::Result<Vec<_>>>()?;
270 Self::Bool(storages.concat())
271 }
272 };
273 Ok(s)
274 }
275
276 pub fn as_ref(&self) -> HostBufferRef<'_> {
281 match self {
282 Self::U8(v) => HostBufferRef::U8(v),
283 Self::I8(v) => HostBufferRef::I8(v),
284 Self::U32(v) => HostBufferRef::U32(v),
285 Self::I16(v) => HostBufferRef::I16(v),
286 Self::I32(v) => HostBufferRef::I32(v),
287 Self::I64(v) => HostBufferRef::I64(v),
288 Self::BF16(v) => HostBufferRef::BF16(v),
289 Self::F16(v) => HostBufferRef::F16(v),
290 Self::F32(v) => HostBufferRef::F32(v),
291 Self::F64(v) => HostBufferRef::F64(v),
292 Self::F8E4M3(v) => HostBufferRef::F8E4M3(v),
293 Self::F6E2M3(v) => HostBufferRef::F6E2M3(v),
294 Self::F6E3M2(v) => HostBufferRef::F6E3M2(v),
295 Self::F4(v) => HostBufferRef::F4(v),
296 Self::F8E8M0(v) => HostBufferRef::F8E8M0(v),
297 Self::Bool(v) => HostBufferRef::Bool(v),
298 }
299 }
300}
301
302impl<'a> HostBufferRef<'a> {
303 pub fn dtype(&self) -> DType {
305 match self {
306 Self::U8(_) => DType::U8,
307 Self::I8(_) => DType::I8,
308 Self::U32(_) => DType::U32,
309 Self::I16(_) => DType::I16,
310 Self::I32(_) => DType::I32,
311 Self::I64(_) => DType::I64,
312 Self::BF16(_) => DType::BF16,
313 Self::F16(_) => DType::F16,
314 Self::F32(_) => DType::F32,
315 Self::F64(_) => DType::F64,
316 Self::F8E4M3(_) => DType::F8E4M3,
317 Self::F6E2M3(_) => DType::F6E2M3,
318 Self::F6E3M2(_) => DType::F6E3M2,
319 Self::F4(_) => DType::F4,
320 Self::F8E8M0(_) => DType::F8E8M0,
321 Self::Bool(_) => DType::Bool,
322 }
323 }
324
325 pub fn len(&self) -> usize {
327 match self {
328 Self::U8(v) => v.len(),
329 Self::I8(v) => v.len(),
330 Self::U32(v) => v.len(),
331 Self::I16(v) => v.len(),
332 Self::I32(v) => v.len(),
333 Self::I64(v) => v.len(),
334 Self::BF16(v) => v.len(),
335 Self::F16(v) => v.len(),
336 Self::F32(v) => v.len(),
337 Self::F64(v) => v.len(),
338 Self::F8E4M3(v) => v.len(),
339 Self::F6E2M3(v) => v.len(),
340 Self::F6E3M2(v) => v.len(),
341 Self::F4(v) => v.len(),
342 Self::F8E8M0(v) => v.len(),
343 Self::Bool(v) => v.len(),
344 }
345 }
346
347 pub fn is_empty(&self) -> bool {
349 self.len() == 0
350 }
351
352 pub fn to_owned(&self) -> HostBuffer {
359 match self {
360 Self::U8(v) => HostBuffer::U8(v.to_vec()),
361 Self::I8(v) => HostBuffer::I8(v.to_vec()),
362 Self::U32(v) => HostBuffer::U32(v.to_vec()),
363 Self::I16(v) => HostBuffer::I16(v.to_vec()),
364 Self::I32(v) => HostBuffer::I32(v.to_vec()),
365 Self::I64(v) => HostBuffer::I64(v.to_vec()),
366 Self::BF16(v) => HostBuffer::BF16(v.to_vec()),
367 Self::F16(v) => HostBuffer::F16(v.to_vec()),
368 Self::F32(v) => HostBuffer::F32(v.to_vec()),
369 Self::F64(v) => HostBuffer::F64(v.to_vec()),
370 Self::F8E4M3(v) => HostBuffer::F8E4M3(v.to_vec()),
371 Self::F6E2M3(v) => HostBuffer::F6E2M3(v.to_vec()),
372 Self::F6E3M2(v) => HostBuffer::F6E3M2(v.to_vec()),
373 Self::F4(v) => HostBuffer::F4(v.to_vec()),
374 Self::F8E8M0(v) => HostBuffer::F8E8M0(v.to_vec()),
375 Self::Bool(v) => HostBuffer::Bool(v.to_vec()),
376 }
377 }
378}
379
380pub trait HostDType: WithDType {
388 fn cpu_storage_ref(data: &[Self]) -> HostBufferRef<'_>;
389 fn to_cpu_storage_owned(data: Vec<Self>) -> HostBuffer;
390
391 fn to_cpu_storage(data: &[Self]) -> HostBuffer {
392 Self::to_cpu_storage_owned(data.to_vec())
393 }
394
395 fn cpu_storage_as_slice(s: &HostBuffer) -> Result<&[Self]>;
396 fn cpu_storage_data(s: HostBuffer) -> Result<Vec<Self>>;
397}
398
399macro_rules! host_dtype {
400 ($ty:ty, $dtype:ident) => {
401 impl HostDType for $ty {
402 fn cpu_storage_ref(data: &[Self]) -> HostBufferRef<'_> {
403 HostBufferRef::$dtype(data)
404 }
405
406 fn to_cpu_storage_owned(data: Vec<Self>) -> HostBuffer {
407 HostBuffer::$dtype(data)
408 }
409
410 fn cpu_storage_data(s: HostBuffer) -> Result<Vec<Self>> {
411 match s {
412 HostBuffer::$dtype(data) => Ok(data),
413 _ => Err(Error::UnexpectedDType {
414 expected: DType::$dtype,
415 got: s.dtype(),
416 msg: "unexpected dtype",
417 }
418 .bt()),
419 }
420 }
421
422 fn cpu_storage_as_slice(s: &HostBuffer) -> Result<&[Self]> {
423 match s {
424 HostBuffer::$dtype(data) => Ok(data),
425 _ => Err(Error::UnexpectedDType {
426 expected: DType::$dtype,
427 got: s.dtype(),
428 msg: "unexpected dtype",
429 }
430 .bt()),
431 }
432 }
433 }
434 };
435}
436
437host_dtype!(u8, U8);
438host_dtype!(i8, I8);
439host_dtype!(u32, U32);
440host_dtype!(i16, I16);
441host_dtype!(i32, I32);
442host_dtype!(i64, I64);
443host_dtype!(f16, F16);
444host_dtype!(bf16, BF16);
445host_dtype!(f32, F32);
446host_dtype!(f64, F64);
447host_dtype!(F8E4M3, F8E4M3);