drm gpu power

This commit is contained in:
Robin Appelman 2023-05-03 14:05:18 +02:00
commit 8d3e3e33a5
3 changed files with 56 additions and 2 deletions

View file

@ -1,7 +1,13 @@
use crate::sensors::Memory;
use std::fmt::Write;
use std::fs::read_to_string;
use std::fs::{read_to_string, File};
use std::io::{Read, Seek};
use std::path::Path;
use std::str::FromStr;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Mutex;
use std::thread::sleep;
use std::time::{Duration, Instant};
pub mod nvidia;
@ -81,3 +87,47 @@ pub fn utilization() -> impl Iterator<Item = GpuUsage> {
});
drm.chain(nv_usage)
}
static GPU_POWER_UJ: AtomicU64 = AtomicU64::new(0);
static GPU_POWER_LAST_READ: Mutex<Option<Instant>> = Mutex::new(None);
fn read_gpu_power() -> Option<u64> {
read_num("/sys/class/drm/card0/device/hwmon/hwmon0/power1_average")
}
fn get_gpu_power_elapsed() -> Option<Duration> {
let mut last_read = GPU_POWER_LAST_READ.lock().unwrap();
let now = Instant::now();
let elapsed = last_read.as_ref().map(|last_read| now - *last_read);
*last_read = Some(now);
elapsed
}
pub fn update_gpu_power() {
let mut buff = String::with_capacity(16);
if let Ok(mut file) = File::open("/sys/class/drm/card0/device/hwmon/hwmon0/power1_average") {
loop {
if let Some(elapsed) = get_gpu_power_elapsed() {
buff.clear();
file.rewind().ok();
let current_power: u64 = match file.read_to_string(&mut buff) {
Ok(_) => buff.trim().parse().unwrap_or_default(),
Err(_) => {
return;
}
};
let elapsed_milli = elapsed.as_millis() as u64;
let power = current_power * elapsed_milli / 1000;
GPU_POWER_UJ.fetch_add(power, Ordering::SeqCst);
}
sleep(Duration::from_millis(500));
}
}
}
pub fn gpu_power() -> u64 {
GPU_POWER_UJ.load(Ordering::SeqCst)
}

View file

@ -6,7 +6,7 @@ use libmdns::Responder;
use palantir::disk::zfs::arcstats;
use palantir::docker::{get_docker, stat, Container};
use palantir::get_metrics;
use palantir::gpu::gpu_metrics;
use palantir::gpu::{gpu_metrics, update_gpu_power};
use palantir::power::power_usage;
use std::time::Duration;
use tokio::runtime::Handle;
@ -84,6 +84,8 @@ async fn main() -> Result<()> {
));
}
std::thread::spawn(update_gpu_power);
let metrics = warp::path!("metrics").and(docker).and_then(serve_metrics);
warp::serve(metrics).run(([0, 0, 0, 0], host_port)).await;

View file

@ -1,3 +1,4 @@
use crate::gpu::gpu_power;
use color_eyre::{Report, Result};
use std::fmt::Write;
use std::fs::{read_dir, read_to_string};
@ -84,6 +85,7 @@ pub fn power_usage() -> Result<Option<PowerUsage>> {
}
}
usage.gpu_uj = gpu_power();
if let Some(nvidia_power) = crate::gpu::nvidia::power() {
usage.gpu_uj = nvidia_power;
}