1use std::{
2 ffi::{c_char, CStr},
3 sync::OnceLock,
4};
5
6use crate::{CudaError, TaskScope};
7use slop_alloc::{mem::CopyError, CopyIntoBackend, CopyToBackend, CpuBackend};
8use sp1_gpu_sys::runtime::{cuda_get_device_name, cuda_mem_get_info};
9
10pub trait DeviceCopy: Copy + 'static + Sized {}
11
12impl<T: Copy + 'static + Sized> DeviceCopy for T {}
13
14pub fn cuda_memory_info() -> Result<(usize, usize), CudaError> {
16 let mut free: usize = 0;
17 let mut total: usize = 0;
18 CudaError::result_from_ffi(unsafe { cuda_mem_get_info(&mut free, &mut total) })?;
19 Ok((free, total))
20}
21
22pub fn cuda_device_name() -> Result<&'static str, CudaError> {
28 static DEVICE_NAME: OnceLock<String> = OnceLock::new();
29 if let Some(name) = DEVICE_NAME.get() {
30 return Ok(name);
31 }
32
33 let mut name = [0u8; 256];
36 CudaError::result_from_ffi(unsafe {
37 cuda_get_device_name(name.as_mut_ptr().cast::<c_char>(), name.len())
38 })?;
39 let name = CStr::from_bytes_until_nul(&name)
40 .map(|name| name.to_string_lossy().into_owned())
41 .unwrap_or_default();
42
43 Ok(DEVICE_NAME.get_or_init(|| name))
44}
45
46pub trait IntoDevice: CopyIntoBackend<TaskScope, CpuBackend> + Sized {
47 fn into_device_in(self, backend: &TaskScope) -> Result<Self::Output, CopyError> {
48 self.copy_into_backend(backend)
49 }
50}
51
52impl<T> IntoDevice for T where T: CopyIntoBackend<TaskScope, CpuBackend> + Sized {}
53
54pub trait ToDevice: CopyToBackend<TaskScope, CpuBackend> + Sized {
55 fn to_device_in(&self, backend: &TaskScope) -> Result<Self::Output, CopyError> {
56 self.copy_to_backend(backend)
57 }
58}
59
60impl<T> ToDevice for T where T: CopyToBackend<TaskScope, CpuBackend> + Sized {}
61
62#[macro_export]
63macro_rules! args {
64 ($($arg:expr),*) => {
65 [
66 $(
67 &$arg as *const _ as *mut std::ffi::c_void
68 ),*
69 ]
70 };
71}