use std::sync::Arc;
use cudarc::driver::CudaContext;
use super::error::GpuError;
#[cfg(feature = "mpi")]
use crate::engine::cuda_context::libnccl_present;
use crate::engine::cuda_context::{self, libcuda_present, libnvrtc_present};
pub fn cuda_available() -> bool {
libcuda_present() && libnvrtc_present() && device_count() > 0
}
#[cfg(feature = "mpi")]
pub fn nccl_available() -> bool {
cuda_available() && libnccl_present()
}
pub fn device_count() -> usize {
if !libcuda_present() {
return 0;
}
CudaContext::device_count().map(|count| count.max(0) as usize).unwrap_or(0)
}
#[derive(Debug, Clone)]
pub struct DeviceInfo {
pub ordinal: u32,
pub name: String,
pub compute_capability: (u32, u32),
pub total_memory: u64,
}
pub fn devices() -> Result<Vec<DeviceInfo>, GpuError> {
if !libcuda_present() {
return Err(GpuError::LibraryMissing("libcuda"));
}
let count = CudaContext::device_count().map_err(GpuError::from)?;
if count <= 0 {
return Err(GpuError::NoDevice);
}
let mut out = Vec::with_capacity(count as usize);
for ordinal in 0..count as u32 {
let context = context(ordinal)?;
let (major, minor) = context.compute_capability().map_err(GpuError::from)?;
out.push(DeviceInfo {
ordinal,
name: context.name().map_err(GpuError::from)?,
compute_capability: (major as u32, minor as u32),
total_memory: context.total_mem().map_err(GpuError::from)? as u64,
});
}
Ok(out)
}
pub(crate) fn context(ordinal: u32) -> Result<Arc<CudaContext>, GpuError> {
Ok(cuda_context::context(ordinal)?)
}
#[cfg(test)]
mod tests;