monitoring kit
add nvidia gpu monitors
| -rw-r--r-- | gpu/Cargo.toml | 9 | ||||
| -rw-r--r-- | gpu/src/intel.rs | 17 | ||||
| -rw-r--r-- | gpu/src/nvidia.rs | 113 | ||||
| -rw-r--r-- | grapher/src/lib.rs | 3 |
4 files changed, 132 insertions, 10 deletions
diff --git a/gpu/Cargo.toml b/gpu/Cargo.toml index 6c9335e..c2c923d 100644 --- a/gpu/Cargo.toml +++ b/gpu/Cargo.toml @@ -16,9 +16,18 @@ parking_lot = "0.12.3" termion = "4.0.4" grapher = { path = "../grapher" } memchr = "2.7.4" +implicit-fn = "0.1.0" +nvml-wrapper = "0.10.0" +pretty-bytes = "0.2.2" [[bin]] name = "intel" doc = false path = "src/intel.rs" + + +[[bin]] +name = "nvidia" +doc = false +path = "src/nvidia.rs" diff --git a/gpu/src/intel.rs b/gpu/src/intel.rs index 1352fb0..f7cc2db 100644 --- a/gpu/src/intel.rs +++ b/gpu/src/intel.rs @@ -72,19 +72,20 @@ unsafe extern "C" { fn igt_device_get_pretty_name(card: *const igt_device_card, numeric: bool) -> *const c_char; } +#[implicit_fn::implicit_fn] fn uh() -> Result<()> { dbg!("???"); let x = std::fs::read_dir("/sys/devices")? .filter_map(Result::ok) - .filter(|x| { - x.file_name() + .filter( + _.file_name() .into_string() - .is_ok_and(|x| x.starts_with("pci")) - }) + .is_ok_and(|x| x.starts_with("pci")), + ) .filter_map(|x| read_dir(x.path()).ok()) .flatten() .filter_map(Result::ok) - .find(|x| read(x.path().join("uevent")).is_ok_and(|x| x.contains("i915"))) + .find(|x| read(x.path().join("uevent")).is_ok_and(_.contains("nvidia"))) .ok_or(anyhow!("intelless"))? .path(); @@ -145,10 +146,6 @@ fn main() -> Result<()> { .unwrap() }; - fn inter([a, b, c]: [f32; 3], [d, e, f]: [f32; 3], fc: f32) -> [f32; 3] { - [a + (d - a) * fc, b + (e - b) * fc, c + (f - c) * fc] - } - let mut g = Grapher::new()?; sleep(Duration::from_secs_f32(0.5)); if let std::result::Result::Ok(Some(_)) = c.try_wait() { @@ -176,7 +173,7 @@ fn main() -> Result<()> { g.draw( |y| { Some( - inter( + grapher::inter( [243, 64, 64].map(|x| x as f32 / 255.0), // red [228, 197, 63].map(|x| x as f32 / 255.0), // yellow y as f32 / (h - 1) as f32, diff --git a/gpu/src/nvidia.rs b/gpu/src/nvidia.rs new file mode 100644 index 0000000..6b8be77 --- /dev/null +++ b/gpu/src/nvidia.rs @@ -0,0 +1,113 @@ +#![feature( + generic_arg_infer, + import_trait_associated_functions, + let_chains, + iter_array_chunks, + array_chunks, + portable_simd, + iter_chain +)] +use anyhow::*; +use grapher::inter; +use grapher::truncwrite; +use grapher::Grapher; +use nvml_wrapper::{ + enum_wrappers::device::{Clock, TemperatureSensor}, + Nvml, +}; +use pretty_bytes::converter::convert; +use std::array; +use std::convert::identity; +use std::io::Write; +use std::io::{stdout, Read}; +use std::thread::sleep; +use std::time::Duration; +use termion::color::*; +use termion::cursor::Hide; +use termion::raw::IntoRawMode; +use termion::screen::IntoAlternateScreen; +use termion::{async_stdin, clear, cursor, style}; +#[implicit_fn::implicit_fn] +fn main() -> Result<()> { + let vram = std::env::args().nth(1).is_some(); + let nvml = Nvml::init().context("nvml(nvidia) less")?; + let device = nvml.device_by_index(0).context("nvidialess")?; + let name = device.name()?; + let name = name.replace("NVIDIA GeForce RTX", "RTX"); + + let architecture = device.architecture()?; + let mut g = Grapher::new()?; + let mut d = 0.1; + let mut stdout = stdout().into_raw_mode()?.into_alternate_screen()?; + let mut stdin = async_stdin(); + write!(stdout, "{}{}{}", Hide, clear::All, style::Reset).unwrap(); + 'out: loop { + let (_, h) = termion::terminal_size()?; + + let mut key = 0; + while stdin.read(array::from_mut(&mut key)).unwrap() != 0 { + match key { + b'q' => break 'out, + b'+' => d = (d + 0.1f32).min(1.0), + b'-' if d >= 0.2 => d -= 0.1, + b'-' if d >= 0.02 => d -= 0.01, + b'-' => d = 0.00833, + _ => (), + } + } + + g.draw( + |y| { + Some( + inter( + [155, 221, 58].map(_ as f32 / 255.0), + [118, 185, 0].map(_ as f32 / 255.0), + y as f32 / (h - 1) as f32, + ) + .map(|x| (x * 255.0) as u8), + ) + }, + identity, + )?; + + write!(g.buffer, "{}{}", White.fg_str(), cursor::Goto(1, 1))?; + + let temperature = device.temperature(TemperatureSensor::Gpu)?; + let max = device.temperature_threshold( + nvml_wrapper::enum_wrappers::device::TemperatureThreshold::Slowdown, + )?; + + let mem_info = device.memory_info()?; + let util = device.utilization_rates()?.gpu; + + let graphics_clock = device.clock_info(Clock::Graphics)?; + let mem_clock = device.clock_info(Clock::Memory)?; + let usage = device.power_usage()? / 1000; + let of = device.power_management_limit()? / 1000; + + let used_mem = convert(mem_info.used as _); + let total_mem = convert(mem_info.total as _); + if vram { + truncwrite!( + g.buffer, + "{name} {used_mem}/ {total_mem} vRAM speed {mem_clock} MHZ" + )?; + } else { + truncwrite!(g.buffer, "{name} ({architecture}) @ {temperature}°C (max {max}°C) {usage}W/ {of}W {util}% usage\n\r")?; + truncwrite!(g.buffer, "{graphics_clock} MHz mem {mem_clock} MHz\n\r")?; + truncwrite!(g.buffer, "{used_mem}/ {total_mem} vRAM\n\r")?; + } + stdout.write_all(&g.buffer)?; + stdout.flush()?; + + sleep(Duration::from_secs_f32(d)); + if vram { + g.push_point(mem_info.used as f64 / mem_info.total as f64); + } else { + g.push_point(util as f64 / 1e2); + } + } + println!("\x1B[?7l"); + + Ok(()) +} diff --git a/grapher/src/lib.rs b/grapher/src/lib.rs index 6f98eed..3b4592f 100644 --- a/grapher/src/lib.rs +++ b/grapher/src/lib.rs @@ -14,6 +14,9 @@ use std::simd::prelude::*; use termion::color::*; use termion::{clear, cursor}; use unicode_width::*; +pub fn inter([a, b, c]: [f32; 3], [d, e, f]: [f32; 3], fc: f32) -> [f32; 3] { + [a + (d - a) * fc, b + (e - b) * fc, c + (f - c) * fc] +} pub struct Grapher { pub buffer: Vec<u8>, |