From c47997474b5b7064c2608a42d0d52a7d956affb3 Mon Sep 17 00:00:00 2001 From: Andrey Alekseenko Date: Sat, 4 Jan 2025 23:49:26 +0100 Subject: [PATCH] other: handle systems with only libnvidia-ml.so.1 Recently, NVIDIA CUDA repository packages started shipping only `libnvidia-ml.so.1` file, without `libnvidia-ml.so`. The upstream `nvml-wrapper` package has a fix proposed (https://github.com/Cldfire/nvml-wrapper/pull/63), yet the package is in search of a maintainer at the moment. To allow `bottom` to correctly detect NVIDIA GPUs on Ubuntu with official NVIDIA packages, add a wrapper around `Nvml::init` to be more persistent in its search for the NVML library. --- src/data_collection/nvidia.rs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/data_collection/nvidia.rs b/src/data_collection/nvidia.rs index b0e0a9567..091a82e54 100644 --- a/src/data_collection/nvidia.rs +++ b/src/data_collection/nvidia.rs @@ -21,12 +21,35 @@ pub struct GpusData { pub procs: Option<(u64, Vec>)>, } +/// Wrapper around Nvml::init +/// +/// On Linux, if `Nvml::init()` fails, this function attempts to explicitly load +/// the library from `libnvidia-ml.so.1`. On other platforms, it simply calls `Nvml::init`. +/// +/// This is a workaround until https://github.com/Cldfire/nvml-wrapper/pull/63 is accepted. +/// Then, we can gp back to just using `Nvml::init` on all platforms. +fn init_nvml() -> Result { + #[cfg(not(target_os = "linux"))] + { + Nvml::init() + } + #[cfg(target_os = "linux")] + { + match Nvml::init() { + Ok(nvml) => Ok(nvml), + Err(_) => Nvml::builder() + .lib_path(std::ffi::OsStr::new("libnvidia-ml.so.1")) + .init(), + } + } +} + /// Returns the GPU data from NVIDIA cards. #[inline] pub fn get_nvidia_vecs( temp_type: &TemperatureType, filter: &Option, widgets_to_harvest: &UsedWidgets, ) -> Option { - if let Ok(nvml) = NVML_DATA.get_or_init(Nvml::init) { + if let Ok(nvml) = NVML_DATA.get_or_init(init_nvml) { if let Ok(num_gpu) = nvml.device_count() { let mut temp_vec = Vec::with_capacity(num_gpu as usize); let mut mem_vec = Vec::with_capacity(num_gpu as usize);