xps 13 3980
This commit is contained in:
115
src/engine/mod.rs
Normal file
115
src/engine/mod.rs
Normal file
@@ -0,0 +1,115 @@
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
pub mod formatters;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct ThermalPoint {
|
||||
pub power_w: f32,
|
||||
pub temp_c: f32,
|
||||
pub freq_mhz: f32,
|
||||
pub fan_rpm: u32,
|
||||
pub throughput: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
||||
pub struct ThermalProfile {
|
||||
pub points: Vec<ThermalPoint>,
|
||||
pub ambient_temp: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct OptimizationResult {
|
||||
pub profile: ThermalProfile,
|
||||
pub silicon_knee_watts: f32,
|
||||
pub thermal_resistance_kw: f32,
|
||||
pub recommended_pl1: f32,
|
||||
pub recommended_pl2: f32,
|
||||
pub max_temp_c: f32,
|
||||
pub is_partial: bool,
|
||||
}
|
||||
|
||||
pub struct OptimizerEngine {
|
||||
window_size: usize,
|
||||
}
|
||||
|
||||
impl OptimizerEngine {
|
||||
pub fn new(window_size: usize) -> Self {
|
||||
Self { window_size }
|
||||
}
|
||||
|
||||
/// Applies a simple moving average (SMA) filter to a stream of values.
|
||||
pub fn smooth(&self, data: &[f32]) -> Vec<f32> {
|
||||
if data.is_empty() { return vec![]; }
|
||||
let mut smoothed = Vec::with_capacity(data.len());
|
||||
|
||||
for i in 0..data.len() {
|
||||
let start = if i < self.window_size { 0 } else { i - self.window_size + 1 };
|
||||
let end = i + 1;
|
||||
let sum: f32 = data[start..end].iter().sum();
|
||||
smoothed.push(sum / (end - start) as f32);
|
||||
}
|
||||
smoothed
|
||||
}
|
||||
|
||||
/// Calculates Thermal Resistance: R_theta = (T_core - T_ambient) / P_package
|
||||
pub fn calculate_thermal_resistance(&self, profile: &ThermalProfile) -> f32 {
|
||||
profile.points.iter()
|
||||
.max_by(|a, b| a.power_w.partial_cmp(&b.power_w).unwrap_or(std::cmp::Ordering::Equal))
|
||||
.map(|p| {
|
||||
if p.power_w < 1.0 { 0.0 }
|
||||
else { (p.temp_c - profile.ambient_temp) / p.power_w }
|
||||
})
|
||||
.unwrap_or(0.0)
|
||||
}
|
||||
|
||||
pub fn get_max_temp(&self, profile: &ThermalProfile) -> f32 {
|
||||
profile.points.iter()
|
||||
.map(|p| p.temp_c)
|
||||
.max_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal))
|
||||
.unwrap_or(0.0)
|
||||
}
|
||||
|
||||
/// Finds the "Silicon Knee" - the point where performance per watt plateaus
|
||||
/// and thermal density spikes.
|
||||
pub fn find_silicon_knee(&self, profile: &ThermalProfile) -> f32 {
|
||||
if profile.points.len() < 3 {
|
||||
return profile.points.last().map(|p| p.power_w).unwrap_or(15.0);
|
||||
}
|
||||
|
||||
let mut points = profile.points.clone();
|
||||
points.sort_by(|a, b| a.power_w.partial_cmp(&b.power_w).unwrap_or(std::cmp::Ordering::Equal));
|
||||
|
||||
let mut best_pl = points[0].power_w;
|
||||
let mut max_score = f32::MIN;
|
||||
|
||||
for i in 1..points.len() - 1 {
|
||||
let prev = &points[i - 1];
|
||||
let curr = &points[i];
|
||||
let next = &points[i + 1];
|
||||
|
||||
// 1. Performance Gradient (dMHz/dW)
|
||||
let dmhz_dw_prev = (curr.freq_mhz - prev.freq_mhz) / (curr.power_w - prev.power_w).max(0.1);
|
||||
let dmhz_dw_next = (next.freq_mhz - curr.freq_mhz) / (next.power_w - curr.power_w).max(0.1);
|
||||
let freq_diminish = dmhz_dw_prev - dmhz_dw_next;
|
||||
|
||||
// 2. Thermal Gradient (d2T/dW2)
|
||||
let dt_dw_prev = (curr.temp_c - prev.temp_c) / (curr.power_w - prev.power_w).max(0.1);
|
||||
let dt_dw_next = (next.temp_c - curr.temp_c) / (next.power_w - curr.power_w).max(0.1);
|
||||
let temp_accel = (dt_dw_next - dt_dw_prev) / (next.power_w - prev.power_w).max(0.1);
|
||||
|
||||
// 3. Wall Detection
|
||||
let is_throttling = next.freq_mhz < curr.freq_mhz;
|
||||
let penalty = if is_throttling { 2000.0 } else { 0.0 };
|
||||
|
||||
// Heuristic scoring: Weight thermal acceleration and diminishing frequency gains
|
||||
let score = (freq_diminish * 2.0) + (temp_accel * 10.0) - penalty;
|
||||
|
||||
if score > max_score {
|
||||
max_score = score;
|
||||
best_pl = curr.power_w;
|
||||
}
|
||||
}
|
||||
|
||||
best_pl
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user