use crate::{element::JitElement, ops::numeric::empty_device, tensor::JitTensor, JitRuntime};
use super::autotune_reduce;
pub use cubecl::reduce::instructions::{ArgMax, ArgMin, Mean, Prod, Sum};
pub fn reduce<Run: JitRuntime, In: JitElement, Out: JitElement, Rd: cubecl::reduce::Reduce>(
mut input: JitTensor<Run>,
strategy: ReduceStrategy,
) -> Result<JitTensor<Run>, cubecl::reduce::ReduceError> {
input.shape = input.shape.flatten();
input.strides = vec![1];
reduce_dim::<Run, In, Out, Rd>(input, 0, strategy)
}
pub fn reduce_dim<Run: JitRuntime, In: JitElement, Out: JitElement, Rd: cubecl::reduce::Reduce>(
input: JitTensor<Run>,
dim: usize,
strategy: ReduceStrategy,
) -> Result<JitTensor<Run>, cubecl::reduce::ReduceError> {
let client = input.client.clone();
let output = init_reduce_output::<Run, In, Out>(&input, dim).ok_or(
cubecl::reduce::ReduceError::InvalidAxis {
axis: dim,
rank: input.shape.num_dims(),
},
)?;
let result = match strategy {
ReduceStrategy::Unspecified => cubecl::reduce::reduce::<Run, In, Out, Rd>(
&client,
input.as_handle_ref(),
output.as_handle_ref(),
dim,
None,
),
ReduceStrategy::Specific(strategy) => cubecl::reduce::reduce::<Run, In, Out, Rd>(
&client,
input.as_handle_ref(),
output.as_handle_ref(),
dim,
Some(strategy),
),
#[cfg(feature = "autotune")]
ReduceStrategy::Autotune => {
autotune_reduce::<Run, In, Out, Rd>(&client, input, output.clone(), dim)
}
};
result.map(|_| output)
}
pub fn init_reduce_output<Run: JitRuntime, In: JitElement, Out: JitElement>(
input: &JitTensor<Run>,
dim: usize,
) -> Option<JitTensor<Run>> {
(dim < input.shape.num_dims()).then(|| {
let mut shape_out = input.shape.clone();
shape_out.dims[dim] = 1;
empty_device::<Run, Out>(input.client.clone(), input.device.clone(), shape_out)
})
}
#[derive(Copy, Clone, Debug)]
pub enum ReduceStrategy {
Unspecified,
Specific(cubecl::reduce::ReduceStrategy),
#[cfg(feature = "autotune")]
Autotune,
}
impl Default for ReduceStrategy {
fn default() -> Self {
#[cfg(feature = "autotune")]
return Self::Autotune;
#[cfg(not(feature = "autotune"))]
return Self::Unspecified;
}
}