use scirs2_core::ndarray::Array1;
use scirs2_core::numeric::Float;
use std::fmt::Debug;
use super::config::GpuConfig;
use super::traits::GpuAccelerated;
use crate::error::{Result, TimeSeriesError};
#[derive(Debug)]
pub struct GpuArray<F: Float + Debug> {
cpu_data: Option<Array1<F>>,
#[allow(dead_code)]
gpu_handle: Option<usize>,
#[allow(dead_code)]
config: GpuConfig,
on_gpu: bool,
}
impl<F: Float + Debug + Clone> GpuArray<F> {
pub fn from_cpu(data: Array1<F>, config: GpuConfig) -> Self {
Self {
cpu_data: Some(data),
gpu_handle: None,
config,
on_gpu: false,
}
}
pub fn zeros(len: usize, config: GpuConfig) -> Self {
let data = Array1::zeros(len);
Self::from_cpu(data, config)
}
pub fn len(&self) -> usize {
if let Some(ref data) = self.cpu_data {
data.len()
} else {
0 }
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn to_cpu_data(&self) -> Result<Array1<F>> {
if let Some(ref data) = self.cpu_data {
Ok(data.clone())
} else {
Err(TimeSeriesError::NotImplemented(
"GPU to CPU transfer requires GPU framework dependencies".to_string(),
))
}
}
}
impl<F: Float + Debug + Clone> GpuAccelerated<F> for GpuArray<F> {
fn to_gpu(&self, config: &GpuConfig) -> Result<Self> {
let optimized_data = if config.use_half_precision {
self.cpu_data.as_ref().map(|data| {
data.mapv(|x| {
let fp16_sim = (x.to_f64().unwrap_or(0.0) * 1000.0).round() / 1000.0;
F::from(fp16_sim).unwrap_or(x)
})
})
} else {
self.cpu_data.clone()
};
Ok(Self {
cpu_data: optimized_data,
gpu_handle: Some(42), config: config.clone(),
on_gpu: true, })
}
fn to_cpu(&self) -> Result<Self> {
if !self.on_gpu {
return Ok(Self {
cpu_data: self.cpu_data.clone(),
gpu_handle: None,
config: self.config.clone(),
on_gpu: false,
});
}
let transferred_data = if let Some(ref cpu_data) = self.cpu_data {
Some(cpu_data.clone())
} else {
return Err(TimeSeriesError::NotImplemented(
"GPU memory reconstruction not implemented without CPU fallback".to_string(),
));
};
Ok(Self {
cpu_data: transferred_data,
gpu_handle: None, config: self.config.clone(),
on_gpu: false,
})
}
fn is_on_gpu(&self) -> bool {
self.on_gpu
}
fn gpu_memory_usage(&self) -> usize {
if self.on_gpu {
self.len() * std::mem::size_of::<F>()
} else {
0
}
}
}