scirs2_series/gpu_acceleration/
array.rs1use scirs2_core::ndarray::Array1;
7use scirs2_core::numeric::Float;
8use std::fmt::Debug;
9
10use super::config::GpuConfig;
11use super::traits::GpuAccelerated;
12use crate::error::{Result, TimeSeriesError};
13
14#[derive(Debug)]
16pub struct GpuArray<F: Float + Debug> {
17 cpu_data: Option<Array1<F>>,
19 #[allow(dead_code)]
21 gpu_handle: Option<usize>,
22 #[allow(dead_code)]
24 config: GpuConfig,
25 on_gpu: bool,
27}
28
29impl<F: Float + Debug + Clone> GpuArray<F> {
30 pub fn from_cpu(data: Array1<F>, config: GpuConfig) -> Self {
32 Self {
33 cpu_data: Some(data),
34 gpu_handle: None,
35 config,
36 on_gpu: false,
37 }
38 }
39
40 pub fn zeros(len: usize, config: GpuConfig) -> Self {
42 let data = Array1::zeros(len);
43 Self::from_cpu(data, config)
44 }
45
46 pub fn len(&self) -> usize {
48 if let Some(ref data) = self.cpu_data {
49 data.len()
50 } else {
51 0 }
53 }
54
55 pub fn is_empty(&self) -> bool {
57 self.len() == 0
58 }
59
60 pub fn to_cpu_data(&self) -> Result<Array1<F>> {
62 if let Some(ref data) = self.cpu_data {
63 Ok(data.clone())
64 } else {
65 Err(TimeSeriesError::NotImplemented(
67 "GPU to CPU transfer requires GPU framework dependencies".to_string(),
68 ))
69 }
70 }
71}
72
73impl<F: Float + Debug + Clone> GpuAccelerated<F> for GpuArray<F> {
74 fn to_gpu(&self, config: &GpuConfig) -> Result<Self> {
75 let optimized_data = if config.use_half_precision {
78 self.cpu_data.as_ref().map(|data| {
80 data.mapv(|x| {
81 let fp16_sim = (x.to_f64().unwrap_or(0.0) * 1000.0).round() / 1000.0;
83 F::from(fp16_sim).unwrap_or(x)
84 })
85 })
86 } else {
87 self.cpu_data.clone()
88 };
89
90 Ok(Self {
91 cpu_data: optimized_data,
92 gpu_handle: Some(42), config: config.clone(),
94 on_gpu: true, })
96 }
97
98 fn to_cpu(&self) -> Result<Self> {
99 if !self.on_gpu {
100 return Ok(Self {
101 cpu_data: self.cpu_data.clone(),
102 gpu_handle: None,
103 config: self.config.clone(),
104 on_gpu: false,
105 });
106 }
107
108 let transferred_data = if let Some(ref cpu_data) = self.cpu_data {
111 Some(cpu_data.clone())
114 } else {
115 return Err(TimeSeriesError::NotImplemented(
118 "GPU memory reconstruction not implemented without CPU fallback".to_string(),
119 ));
120 };
121
122 Ok(Self {
123 cpu_data: transferred_data,
124 gpu_handle: None, config: self.config.clone(),
126 on_gpu: false,
127 })
128 }
129
130 fn is_on_gpu(&self) -> bool {
131 self.on_gpu
132 }
133
134 fn gpu_memory_usage(&self) -> usize {
135 if self.on_gpu {
136 self.len() * std::mem::size_of::<F>()
137 } else {
138 0
139 }
140 }
141}