use crate::hist::History;
use std::collections::HashMap;
#[cfg(target_os = "macos")]
use crate::apple as source;
#[cfg(not(target_os = "macos"))]
use crate::nvidia as source;
#[derive(Default, Clone)]
pub struct Gpu {
pub index: u32,
pub name: String,
pub util: Option<u32>,
pub mem_used: u64,
pub mem_total: u64,
pub temp: Option<u32>,
pub power: Option<u32>,
pub power_limit: Option<u32>,
pub fan: Option<u32>,
pub clock_gr: Option<u32>,
pub clock_gr_max: Option<u32>,
pub clock_mem: Option<u32>,
pub pcie_tx: Option<u64>,
pub pcie_rx: Option<u64>,
pub enc: Option<u32>,
pub dec: Option<u32>,
pub pstate: Option<String>,
pub cores: Option<u32>,
pub hist_util: History,
pub hist_mem: History,
}
impl Gpu {
pub fn mem_frac(&self) -> f64 {
crate::sys::frac(self.mem_used, self.mem_total)
}
fn clear(&mut self) {
*self = Gpu {
index: self.index,
name: std::mem::take(&mut self.name),
mem_total: self.mem_total,
power_limit: self.power_limit,
clock_gr_max: self.clock_gr_max,
cores: self.cores,
hist_util: std::mem::take(&mut self.hist_util),
hist_mem: std::mem::take(&mut self.hist_mem),
..Default::default()
};
}
fn record(&mut self) {
self.hist_util.push(self.util.unwrap_or(0) as f64);
self.hist_mem.push(100.0 * self.mem_frac());
}
}
#[derive(Default, Clone)]
pub struct GpuUse {
pub gpus: Vec<u32>,
pub mem: Option<u64>,
pub sm: Option<u32>,
}
pub struct Gpus {
source: Option<source::Source>,
pub info: String,
pub gpus: Vec<Gpu>,
pub procs: HashMap<u32, GpuUse>,
}
impl Gpus {
pub fn new() -> Self {
let (source, info, gpus) = match source::Source::open() {
Ok((s, info, gpus)) => (Some(s), info, gpus),
Err(why) => (None, why, Vec::new()),
};
let mut g = Gpus {
source,
info,
gpus,
procs: HashMap::new(),
};
g.sample();
g
}
pub fn per_process(&self) -> bool {
source::PER_PROCESS && !self.gpus.is_empty()
}
pub fn sample(&mut self) {
if let Some(s) = &mut self.source {
self.procs.clear();
for g in &mut self.gpus {
g.clear();
}
s.sample(&mut self.gpus, &mut self.procs);
for g in &mut self.gpus {
g.record();
}
}
}
}