use std::time::Duration;
#[derive(Clone)]
pub struct SizeRule {
pub min_size: usize,
pub kernel_idx: usize,
}
pub struct SizeAwareDispatch {
pub name: String,
pub rules: Vec<SizeRule>,
pub default_idx: usize,
}
impl SizeAwareDispatch {
pub fn new(name: &str, default_idx: usize) -> Self {
Self {
name: name.into(),
rules: Vec::new(),
default_idx,
}
}
pub fn add_rule(&mut self, min_size: usize, kernel_idx: usize) {
self.rules.push(SizeRule { min_size, kernel_idx });
self.rules.sort_by_key(|r| r.min_size);
}
pub fn select(&self, size: usize) -> usize {
for rule in self.rules.iter().rev() {
if size >= rule.min_size {
return rule.kernel_idx;
}
}
self.default_idx
}
}
pub struct ThresholdTuner {
cpu_times: Vec<Duration>,
gpu_times: Vec<Duration>,
current_threshold: usize,
min_threshold: usize,
max_threshold: usize,
adaptation_rate: f64,
}
impl ThresholdTuner {
pub fn new(initial: usize) -> Self {
Self {
cpu_times: Vec::with_capacity(32),
gpu_times: Vec::with_capacity(32),
current_threshold: initial,
min_threshold: 64,
max_threshold: 1_000_000,
adaptation_rate: 0.1,
}
}
pub fn threshold(&self) -> usize {
self.current_threshold
}
pub fn observe_cpu(&mut self, elapsed: Duration) {
self.cpu_times.push(elapsed);
if self.cpu_times.len() > 64 { self.cpu_times.remove(0); }
}
pub fn observe_gpu(&mut self, elapsed: Duration) {
self.gpu_times.push(elapsed);
if self.gpu_times.len() > 64 { self.gpu_times.remove(0); }
}
pub fn adapt(&mut self) {
if self.cpu_times.len() < 4 || self.gpu_times.len() < 4 {
return;
}
let cpu_avg: Duration = self.cpu_times.iter().sum::<Duration>() / self.cpu_times.len() as u32;
let gpu_avg: Duration = self.gpu_times.iter().sum::<Duration>() / self.gpu_times.len() as u32;
let ratio = cpu_avg.as_secs_f64() / gpu_avg.as_secs_f64();
if ratio > 1.2 {
self.current_threshold = ((self.current_threshold as f64) * (1.0 - self.adaptation_rate)) as usize;
self.current_threshold = self.current_threshold.max(self.min_threshold);
} else if ratio < 0.8 {
self.current_threshold = ((self.current_threshold as f64) * (1.0 + self.adaptation_rate)) as usize;
self.current_threshold = self.current_threshold.max(self.min_threshold).min(self.max_threshold);
}
}
}