use alloc::{sync::Arc, vec::Vec};
use core::time::Duration;
use cubecl::{
config::{CubeClRuntimeConfig, RuntimeConfig, autotune::AutotuneLevel},
tune::{AutotuneKey, Bounds, BoundsGenerator, Thresholds, TunableSet, TuneInputs},
};
pub fn with_roofline_bounds<K, I, Out, F>(
set: TunableSet<K, I, Out>,
bounds: F,
) -> TunableSet<K, I, Out>
where
K: AutotuneKey,
I: TuneInputs,
Out: 'static,
F: for<'a> Fn(&K, &I::At<'a>, Thresholds) -> Bounds + Send + Sync + 'static,
{
if configured_thresholds().is_none() {
return set;
}
set.with_bounds(Arc::new(AtConfiguredLevel(bounds)))
}
fn configured_thresholds() -> Option<Thresholds> {
let config = CubeClRuntimeConfig::get();
match &config.autotune.level {
AutotuneLevel::Full => None,
level => Some(Thresholds::for_level(level)),
}
}
struct AtConfiguredLevel<F>(F);
impl<K, I, F> BoundsGenerator<K, I> for AtConfiguredLevel<F>
where
K: 'static,
I: TuneInputs,
F: for<'a> Fn(&K, &I::At<'a>, Thresholds) -> Bounds + Send + Sync + 'static,
{
fn generate<'a>(&self, key: &K, inputs: &I::At<'a>) -> Bounds {
match configured_thresholds() {
Some(thresholds) => (self.0)(key, inputs, thresholds),
None => Bounds {
bounds: Vec::new(),
launch_overhead: Duration::ZERO,
},
}
}
}