use ann_search_rs::gpu::tensor::GpuTensor;
use cubecl::Runtime;
use cubecl::prelude::*;
use crate::prelude::*;
pub struct GpuCompressedSparseData<R, F>
where
R: Runtime,
F: cubecl::CubeElement + cubecl::prelude::Numeric,
{
pub indptr: GpuTensor<R, u32>,
pub indices: GpuTensor<R, u32>,
pub values: GpuTensor<R, F>,
pub cs_type: CompressedSparseFormat,
pub shape: (usize, usize),
pub nnz: usize,
}
impl<R, F> Clone for GpuCompressedSparseData<R, F>
where
R: Runtime,
F: cubecl::CubeElement + cubecl::prelude::Numeric,
{
fn clone(&self) -> Self {
Self {
indptr: self.indptr.clone(),
indices: self.indices.clone(),
values: self.values.clone(),
cs_type: self.cs_type,
shape: self.shape,
nnz: self.nnz,
}
}
}
impl<R, F> GpuCompressedSparseData<R, F>
where
R: Runtime,
F: cubecl::CubeElement + cubecl::prelude::Numeric,
{
pub fn from_parts(
values: &[F],
indices: &[u32],
indptr: &[u32],
cs_type: CompressedSparseFormat,
shape: (usize, usize),
client: &ComputeClient<R>,
) -> Self {
let nnz = values.len();
Self {
indptr: GpuTensor::from_slice(indptr, vec![indptr.len()], client),
indices: GpuTensor::from_slice(indices, vec![nnz], client),
values: GpuTensor::from_slice(values, vec![nnz], client),
cs_type,
shape,
nnz,
}
}
pub fn from_compressed_sparse_data_2<T, U>(
src: &CompressedSparseData2<T, U>,
use_second_layer: bool,
client: &ComputeClient<R>,
) -> Result<Self, BixverseErrors>
where
T: BixverseNumeric + Into<F>,
U: BixverseNumeric + Into<F>,
{
let values: Vec<F> = if use_second_layer {
let layer = src
.data_2
.as_ref()
.ok_or(BixverseErrors::Data2NotAvailable)?;
layer.iter().copied().map(Into::into).collect()
} else {
src.data.iter().copied().map(Into::into).collect()
};
Ok(Self::from_parts(
&values,
&src.indices,
&src.indptr,
src.cs_type,
src.shape,
client,
))
}
pub fn vram_bytes(&self) -> usize {
self.indptr.vram_bytes() + self.indices.vram_bytes() + self.values.vram_bytes()
}
}