Files
foxhunt/vendor/cudarc/src/cusolver/safe.rs
jgrusewski 07d0e60fe4 feat(bf16): remove nvrtc from entire workspace + wire ml-core precompiled cubins
- 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>
2026-03-28 10:11:46 +01:00

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();
}
}