nvtop/
gpu.rs

1use std::{fmt, ops::Deref};
2
3use nvml_wrapper::{
4    enum_wrappers::device::{Clock, ClockId, TemperatureSensor},
5    Device,
6};
7
8#[derive(Debug)]
9pub struct GpuInfo<'d> {
10    pub inner: &'d Device<'d>,
11    pub max_memory_clock: u32,
12    pub max_core_clock: u32,
13    pub card_type: String,
14    pub driver_version: String,
15    pub cuda_version: f32,
16    pub misc: String,
17    pub num_cores: u32,
18}
19
20impl<'d> Deref for GpuInfo<'d> {
21    type Target = &'d Device<'d>;
22
23    fn deref(&self) -> &Self::Target {
24        &self.inner
25    }
26}
27
28impl<'d> fmt::Display for GpuInfo<'d> {
29    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
30        let meminfo = self.inner.memory_info().unwrap();
31        let utilisation = self.inner.utilization_rates().unwrap();
32        writeln!(f, "Brand: {:?}", self.inner.brand())?;
33        writeln!(f, "core: {:?}%", utilisation.gpu)?;
34        writeln!(f, "mem_used: {:?}", meminfo.used as f64 / 1_073_741_824.0)?;
35        writeln!(f, "mem {:?}%", (meminfo.total / meminfo.used))?;
36        writeln!(f, "mem_total: {:?}", meminfo.total as f64 / 1_073_741_824.0)?;
37        writeln!(
38            f,
39            "Temp: {:?}C",
40            self.inner.temperature(TemperatureSensor::Gpu)
41        )?;
42
43        [
44            ClockId::Current,
45            ClockId::TargetAppClock,
46            ClockId::DefaultAppClock,
47            ClockId::CustomerMaxBoost,
48        ]
49        .into_iter()
50        .for_each(|clock_id| {
51            [Clock::Graphics, Clock::SM, Clock::Memory, Clock::Video]
52                .into_iter()
53                .for_each(|clock_type| {
54                    match self.inner.clock(clock_type.clone(), clock_id.clone()) {
55                        Ok(value) => {
56                            writeln!(f, "Clock {:?} for {:?}: {}", clock_type, clock_id, value)
57                                .unwrap_or_default()
58                        }
59                        Err(err) => {
60                            let formatted = format!(
61                                "clock_type={:?}\t\tclock_id={:?} {}",
62                                clock_type, clock_id, err,
63                            );
64                            log::error!("{formatted}")
65                        }
66                    }
67                });
68        });
69        Ok(())
70    }
71}
72
73#[cfg(test)]
74mod tests {
75    use nvml_wrapper::{
76        enum_wrappers::device::{Clock, ClockId},
77        Nvml,
78    };
79
80    #[ignore = ""]
81    #[test]
82    fn clock_memory() {
83        let nvml = Nvml::init().unwrap();
84        // Get the first `Device` (GPU) in the system
85        let device = nvml.device_by_index(0).unwrap();
86
87        (0..10).for_each(|_| {
88            [
89                ClockId::Current,
90                ClockId::TargetAppClock,
91                ClockId::DefaultAppClock,
92                ClockId::CustomerMaxBoost,
93            ]
94            .into_iter()
95            .for_each(|clock_id| {
96                [Clock::Graphics, Clock::SM, Clock::Memory, Clock::Video]
97                    .into_iter()
98                    .for_each(|clock_type| {
99                        match device.clock(clock_type.clone(), clock_id.clone()) {
100                            Ok(value) => {
101                                println!("Clock: {:?} for {:?}: {}\n", clock_type, clock_id, value);
102                            }
103                            Err(_err) => {}
104                        }
105                    });
106            });
107            std::thread::sleep(std::time::Duration::from_secs(1));
108        });
109    }
110}