#[cfg(feature = "_cuda-libraries")]
use cudarc::cublas::sys::cublasOperation_t;
#[cfg(feature = "_cuda-libraries")]
use cudarc::cublas::{Gemm, GemmConfig};
use cudarc::driver::{DevicePtr, DevicePtrMut};
#[cfg(feature = "_cuda-libraries")]
use super::error::{check_len, to_c_int};
use super::{CudaError, CudaRuntime};
use super::gemm::Sgemm;
impl Sgemm {
#[cfg(feature = "_cuda-libraries")]
fn column_major(&self) -> Result<GemmConfig<f32>, CudaError> {
let context = "sgemm";
let op = |transposed: bool| {
if transposed {
cublasOperation_t::CUBLAS_OP_T
} else {
cublasOperation_t::CUBLAS_OP_N
}
};
Ok(GemmConfig {
transa: op(self.b_transposed),
transb: op(self.a_transposed),
m: to_c_int(context, self.n)?,
n: to_c_int(context, self.m)?,
k: to_c_int(context, self.k)?,
alpha: self.alpha,
lda: to_c_int(context, if self.b_transposed { self.k } else { self.n })?,
ldb: to_c_int(context, if self.a_transposed { self.m } else { self.k })?,
beta: self.beta,
ldc: to_c_int(context, self.n)?,
})
}
}
impl CudaRuntime {
pub fn sgemm<A, B, C>(&self, spec: Sgemm, a: &A, b: &B, c: &mut C) -> Result<(), CudaError>
where
A: DevicePtr<f32>,
B: DevicePtr<f32>,
C: DevicePtrMut<f32>,
{
#[cfg(feature = "_cuda-libraries")]
{
if super::driver_only() {
return Err(Self::library_forbidden(super::CudaLibrary::Cublas));
}
check_len("sgemm a", spec.m.saturating_mul(spec.k), a.len())?;
check_len("sgemm b", spec.k.saturating_mul(spec.n), b.len())?;
check_len("sgemm c", spec.m.saturating_mul(spec.n), c.len())?;
let config = spec.column_major()?;
let _math = self.lock_blas(spec.math)?;
unsafe { self.blas()?.gemm(config, b, a, c) }?;
Ok(())
}
}
}