#[cutile::module]
mod kernels {
use cutile::core::*;
pub fn softmax_impl<
const BM: i32,
const BN: i32,
const LOG_OUTPUT: bool,
const NEGATE_INPUT: bool,
>(
out: &mut Tensor<f32, { [BM, BN] }>,
input: &Tensor<f32, { [-1, -1] }>,
) {
let input_tile_raw: Tile<f32, { [BM, BN] }> = load_tile_like(input, out);
let zero = constant(0.0f32, out.shape());
let input_tile_raw = if NEGATE_INPUT {
zero - input_tile_raw
} else {
input_tile_raw
};
let col_iota: Tile<i32, { [BN] }> = iota(const_shape![BN]);
let col_iota = col_iota
.reshape(const_shape![1i32, BN])
.broadcast(out.shape());
let input_shape: [i32; 2] = get_tensor_shape(input);
let cols_tile = broadcast_scalar(input_shape[1], out.shape());
let valid_cols = cmpi(col_iota, cols_tile, predicate::LessThan);
let negative_infinity = constant(f32::NEG_INFINITY, out.shape());
let input_tile = select(valid_cols, input_tile_raw, negative_infinity);
let input_max: Tile<f32, { [BM] }> = reduce_max(input_tile, 1i32);
let input_max = input_max
.reshape(const_shape![BM, 1i32])
.broadcast(out.shape());
let numerator = exp(input_tile - input_max);
let denominator: Tile<f32, { [BM] }> = reduce_sum(numerator, 1i32);
let denominator = denominator
.reshape(const_shape![BM, 1i32])
.broadcast(out.shape());
let value = if LOG_OUTPUT {
input_tile - input_max - log(denominator)
} else {
numerator / denominator
};
out.store(value);
}
#[cutile::entry()]
pub fn softmax_f32<const BM: i32, const BN: i32>(
out: &mut Tensor<f32, { [BM, BN] }>,
input: &Tensor<f32, { [-1, -1] }>,
) {
softmax_impl::<BM, BN, false, false>(out, input);
}
#[cutile::entry()]
pub fn log_softmax_f32<const BM: i32, const BN: i32>(
out: &mut Tensor<f32, { [BM, BN] }>,
input: &Tensor<f32, { [-1, -1] }>,
) {
softmax_impl::<BM, BN, true, false>(out, input);
}
#[cutile::entry()]
pub fn softmin_f32<const BM: i32, const BN: i32>(
out: &mut Tensor<f32, { [BM, BN] }>,
input: &Tensor<f32, { [-1, -1] }>,
) {
softmax_impl::<BM, BN, false, true>(out, input);
}
}
pub use crate::cuda::cutile::kernel::f32::utility::softmax_lse_f32;
pub use kernels::*;