- Fork cudarc locally (vendor/cudarc): add CudaContext::load_cubin() that calls cuModuleLoadData directly — zero nvrtc dependency - Remove "nvrtc" feature from ml-core, ml-dqn, ml-ppo Cargo.toml - Replace all 89 Ptx::from_binary + load_module calls with load_cubin - ml-core cuda_autograd: wire 9 stub constructors to precompiled cubins (activation, elementwise, linear, loss, reduction, dropout, layer_norm, optimizer) - ml-core build.rs: compile 8 BF16-native CUDA kernels via nvcc - cubin_loader.rs: thin wrapper around CudaContext::load_cubin() - Fix size_of::<f32> in gpu_tensor.rs, stream_ops.rs, layer_norm.rs - Fix test data: Vec<f32> → Vec<half::bf16> for memcpy_htod - Stub ml-ppo/ml-dqn runtime compile_ptx calls (dead code) - backtest_metrics_kernel.cu: full native BF16 rewrite (no float) - backtest_env_kernel.cu: shared memory → __nv_bfloat16 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
220 lines
6.5 KiB
Rust
220 lines
6.5 KiB
Rust
use std::sync::Arc;
|
|
|
|
use crate::driver::CudaStream;
|
|
|
|
use super::{result, sys};
|
|
|
|
pub use super::result::CusolverError;
|
|
|
|
/// Handle for Dense LAPACK functions
|
|
///
|
|
/// See [cuda docs](https://docs.nvidia.com/cuda/cusolver/index.html#cusolverdn-dense-lapack-function-reference)
|
|
///
|
|
/// This is [thread safe](https://docs.nvidia.com/cuda/cusolver/index.html#thread-safety)
|
|
#[derive(Debug)]
|
|
pub struct DnHandle {
|
|
handle: sys::cusolverDnHandle_t,
|
|
stream: Arc<CudaStream>,
|
|
}
|
|
|
|
unsafe impl Send for DnHandle {}
|
|
unsafe impl Sync for DnHandle {}
|
|
|
|
impl Drop for DnHandle {
|
|
fn drop(&mut self) {
|
|
let handle = std::mem::replace(&mut self.handle, std::ptr::null_mut());
|
|
if !handle.is_null() {
|
|
unsafe { result::dn_destroy(handle) }.unwrap();
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnHandle {
|
|
pub fn new(stream: Arc<CudaStream>) -> Result<Self, CusolverError> {
|
|
let handle = result::dn_create()?;
|
|
unsafe { result::dn_set_stream(handle, stream.cu_stream() as _) }?;
|
|
Ok(Self { handle, stream })
|
|
}
|
|
|
|
pub fn cu(&self) -> sys::cusolverDnHandle_t {
|
|
self.handle
|
|
}
|
|
|
|
pub fn stream(&self) -> &Arc<CudaStream> {
|
|
&self.stream
|
|
}
|
|
|
|
pub unsafe fn set_stream(&mut self, stream: Arc<CudaStream>) -> Result<(), CusolverError> {
|
|
self.stream = stream;
|
|
result::dn_set_stream(self.handle, self.stream.cu_stream() as _)
|
|
}
|
|
|
|
#[cfg(any(
|
|
feature = "cuda-12020",
|
|
feature = "cuda-12030",
|
|
feature = "cuda-12040",
|
|
feature = "cuda-12050",
|
|
feature = "cuda-12060",
|
|
feature = "cuda-12080",
|
|
feature = "cuda-12090",
|
|
feature = "cuda-13000",
|
|
))]
|
|
pub fn set_deterministic_mode(
|
|
&self,
|
|
mode: sys::cusolverDeterministicMode_t,
|
|
) -> Result<(), CusolverError> {
|
|
unsafe { result::dn_set_deterministic_mode(self.handle, mode) }
|
|
}
|
|
|
|
#[cfg(any(
|
|
feature = "cuda-12020",
|
|
feature = "cuda-12030",
|
|
feature = "cuda-12040",
|
|
feature = "cuda-12050",
|
|
feature = "cuda-12060",
|
|
feature = "cuda-12080",
|
|
feature = "cuda-12090",
|
|
feature = "cuda-13000",
|
|
))]
|
|
pub fn get_deterministic_mode(&self) -> sys::cusolverDeterministicMode_t {
|
|
// NOTE: the possible errors here are `CUSOLVER_STATUS_NOT_INITIALIZED`, which is not possible
|
|
// since we have `&self`, and `CUSOLVER_STATUS_INVALID_VALUE` when mode is a null pointer, which
|
|
// is handled via result level. So we can safely unwrap
|
|
unsafe { result::dn_get_deterministic_mode(self.handle) }.unwrap()
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct DnParams {
|
|
params: sys::cusolverDnParams_t,
|
|
}
|
|
|
|
impl Drop for DnParams {
|
|
fn drop(&mut self) {
|
|
let params = std::mem::replace(&mut self.params, std::ptr::null_mut());
|
|
if !params.is_null() {
|
|
unsafe { result::dn_destroy_params(params) }.unwrap();
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DnParams {
|
|
pub fn new(
|
|
function: sys::cusolverDnFunction_t,
|
|
algo: sys::cusolverAlgMode_t,
|
|
) -> Result<Self, CusolverError> {
|
|
let params = result::dn_create_params()?;
|
|
unsafe { result::dn_set_adv_options(params, function, algo) }?;
|
|
Ok(Self { params })
|
|
}
|
|
|
|
pub fn cu(&self) -> sys::cusolverDnParams_t {
|
|
self.params
|
|
}
|
|
}
|
|
|
|
/// Handle for Sparse LAPACK functions
|
|
///
|
|
/// See [cuda docs](https://docs.nvidia.com/cuda/cusolver/index.html#cusolversp-sparse-lapack-function-reference)
|
|
///
|
|
/// This is [thread safe](https://docs.nvidia.com/cuda/cusolver/index.html#thread-safety)
|
|
#[derive(Debug)]
|
|
pub struct SpHandle {
|
|
handle: sys::cusolverSpHandle_t,
|
|
stream: Arc<CudaStream>,
|
|
}
|
|
|
|
unsafe impl Send for SpHandle {}
|
|
unsafe impl Sync for SpHandle {}
|
|
|
|
impl Drop for SpHandle {
|
|
fn drop(&mut self) {
|
|
let handle = std::mem::replace(&mut self.handle, std::ptr::null_mut());
|
|
if !handle.is_null() {
|
|
unsafe { result::sp_destroy(handle) }.unwrap();
|
|
}
|
|
}
|
|
}
|
|
|
|
impl SpHandle {
|
|
pub fn new(stream: Arc<CudaStream>) -> Result<Self, CusolverError> {
|
|
let handle = result::sp_create()?;
|
|
unsafe { result::sp_set_stream(handle, stream.cu_stream() as _) }?;
|
|
Ok(Self { handle, stream })
|
|
}
|
|
|
|
pub fn cu(&self) -> sys::cusolverSpHandle_t {
|
|
self.handle
|
|
}
|
|
|
|
pub fn stream(&self) -> &Arc<CudaStream> {
|
|
&self.stream
|
|
}
|
|
|
|
pub unsafe fn set_stream(&mut self, stream: Arc<CudaStream>) -> Result<(), CusolverError> {
|
|
self.stream = stream;
|
|
result::sp_set_stream(self.handle, self.stream.cu_stream() as _)
|
|
}
|
|
}
|
|
|
|
/// Handle for refactorization functions
|
|
///
|
|
/// See [cuda docs](https://docs.nvidia.com/cuda/cusolver/index.html#cusolverrf-refactorization-reference)
|
|
///
|
|
/// This is [thread safe](https://docs.nvidia.com/cuda/cusolver/index.html#thread-safety)
|
|
#[derive(Debug)]
|
|
pub struct RfHandle {
|
|
handle: sys::cusolverRfHandle_t,
|
|
}
|
|
|
|
unsafe impl Send for RfHandle {}
|
|
unsafe impl Sync for RfHandle {}
|
|
|
|
impl Drop for RfHandle {
|
|
fn drop(&mut self) {
|
|
let handle = std::mem::replace(&mut self.handle, std::ptr::null_mut());
|
|
if !handle.is_null() {
|
|
unsafe { result::rf_destroy(handle) }.unwrap();
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RfHandle {
|
|
pub fn new() -> Result<Self, CusolverError> {
|
|
let handle = result::rf_create()?;
|
|
Ok(Self { handle })
|
|
}
|
|
|
|
pub fn cu(&self) -> sys::cusolverRfHandle_t {
|
|
self.handle
|
|
}
|
|
|
|
/// See [cuda docs](https://docs.nvidia.com/cuda/cusolver/index.html#cusolverrfsetmatrixformat)
|
|
pub fn set_matrix_format(
|
|
&self,
|
|
format: sys::cusolverRfMatrixFormat_t,
|
|
diag: sys::cusolverRfUnitDiagonal_t,
|
|
) {
|
|
unsafe { result::rf_set_matrix_format(self.handle, format, diag) }.unwrap()
|
|
}
|
|
|
|
/// See [cuda docs](https://docs.nvidia.com/cuda/cusolver/index.html#cusolverrfsetnumericproperties)
|
|
pub fn set_numeric_properties(&self, zero: f64, boost: f64) {
|
|
unsafe { result::rf_set_numeric_properties(self.handle, zero, boost) }.unwrap()
|
|
}
|
|
|
|
/// See [cuda docs](https://docs.nvidia.com/cuda/cusolver/index.html#cusolverrfsetresetvaluesfastmode)
|
|
pub fn set_reset_values_fast_mode(&self, fast_mode: sys::cusolverRfResetValuesFastMode_t) {
|
|
unsafe { result::rf_set_reset_values_fast_mode(self.handle, fast_mode) }.unwrap()
|
|
}
|
|
|
|
/// See [cuda docs](https://docs.nvidia.com/cuda/cusolver/index.html#cusolverrfsetalgs)
|
|
pub fn set_algs(
|
|
&self,
|
|
fact_alg: sys::cusolverRfFactorization_t,
|
|
alg: sys::cusolverRfTriangularSolve_t,
|
|
) {
|
|
unsafe { result::rf_set_algs(self.handle, fact_alg, alg) }.unwrap();
|
|
}
|
|
}
|