use std::sync::Arc;
use oxicuda_blas::BlasHandle;
use oxicuda_driver::{Context, Stream};
use oxicuda_ptx::arch::SmVersion;
use oxicuda_ptx::cache::PtxCache;
use crate::error::{SparseError, SparseResult};
pub struct SparseHandle {
context: Arc<Context>,
stream: Stream,
blas_handle: BlasHandle,
ptx_cache: PtxCache,
sm_version: SmVersion,
}
impl SparseHandle {
pub fn new(ctx: &Arc<Context>) -> SparseResult<Self> {
let stream = Stream::new(ctx)?;
Self::build(ctx, stream)
}
pub fn with_stream(ctx: &Arc<Context>, stream: Stream) -> SparseResult<Self> {
Self::build(ctx, stream)
}
fn build(ctx: &Arc<Context>, stream: Stream) -> SparseResult<Self> {
let device = ctx.device();
let (major, minor) = device.compute_capability()?;
let sm_version = SmVersion::from_compute_capability(major, minor).ok_or_else(|| {
SparseError::InternalError(format!("unsupported compute capability: {major}.{minor}"))
})?;
let blas_stream = Stream::new(ctx)?;
let blas_handle = BlasHandle::with_stream(ctx, blas_stream)?;
let ptx_cache = PtxCache::new()?;
Ok(Self {
context: Arc::clone(ctx),
stream,
blas_handle,
ptx_cache,
sm_version,
})
}
#[inline]
pub fn context(&self) -> &Arc<Context> {
&self.context
}
#[inline]
pub fn stream(&self) -> &Stream {
&self.stream
}
#[inline]
pub fn blas_handle(&self) -> &BlasHandle {
&self.blas_handle
}
#[inline]
pub fn blas_handle_mut(&mut self) -> &mut BlasHandle {
&mut self.blas_handle
}
#[inline]
pub fn sm_version(&self) -> SmVersion {
self.sm_version
}
#[inline]
pub fn ptx_cache(&self) -> &PtxCache {
&self.ptx_cache
}
pub fn set_stream(&mut self, stream: Stream) {
self.stream = stream;
}
}
#[cfg(test)]
mod tests {
use oxicuda_ptx::arch::SmVersion;
#[test]
fn sm_version_is_copy() {
let v = SmVersion::Sm80;
let v2 = v;
assert_eq!(v, v2);
}
}