#![allow(non_snake_case)]
use teeny_core::dtype::Float;
use teeny_macros::kernel;
use teeny_triton::triton::{
types::{AddOffsets, Comparison},
*,
};
#[kernel(backward = HardtanhBackward)]
pub fn hardtanh_forward<T: Triton, D: Float, const BLOCK_SIZE: i32>(
x_ptr: T::Pointer<D>,
y_ptr: T::Pointer<D>,
n_elements: i32,
min_val: f32,
max_val: f32,
) where
T::I32Tensor: types::Tensor<i32, 1>,
T::I32Tensor: Comparison<i32, BoolTensor = T::BoolTensor>,
T::Pointer<D>: AddOffsets<i32, 1, T::I32Tensor, Output = T::Tensor<T::Pointer<D>>>,
{
let pid = T::program_id(Axis::X);
let block_start = pid * BLOCK_SIZE;
let offsets = T::arange(0, BLOCK_SIZE) + block_start;
let in_bounds = offsets.lt(n_elements);
let x = T::load(
x_ptr.add_offsets(offsets),
Some(in_bounds),
None,
&[],
None,
None,
None,
false,
);
let lo = T::full(&[BLOCK_SIZE], D::from_f64(min_val as f64));
let hi = T::full(&[BLOCK_SIZE], D::from_f64(max_val as f64));
let y = T::clamp(x, lo, hi);
T::store(
y_ptr.add_offsets(offsets),
y,
Some(in_bounds),
&[],
None,
None,
);
}
#[kernel]
pub fn hardtanh_backward<T: Triton, D: Float, const BLOCK_SIZE: i32>(
dy_ptr: T::Pointer<D>,
x_ptr: T::Pointer<D>,
dx_ptr: T::Pointer<D>,
n_elements: i32,
min_val: f32,
max_val: f32,
) where
T::I32Tensor: types::Tensor<i32, 1>,
T::I32Tensor: Comparison<i32, BoolTensor = T::BoolTensor>,
T::Pointer<D>: AddOffsets<i32, 1, T::I32Tensor, Output = T::Tensor<T::Pointer<D>>>,
{
let pid = T::program_id(Axis::X);
let block_start = pid * BLOCK_SIZE;
let offsets = T::arange(0, BLOCK_SIZE) + block_start;
let in_bounds = offsets.lt(n_elements);
let dy = T::load(
dy_ptr.add_offsets(offsets),
Some(in_bounds),
None,
&[],
None,
None,
None,
false,
);
let x = T::load(
x_ptr.add_offsets(offsets),
Some(in_bounds),
None,
&[],
None,
None,
None,
false,
);
let lo = T::full(&[BLOCK_SIZE], D::from_f64(min_val as f64));
let hi = T::full(&[BLOCK_SIZE], D::from_f64(max_val as f64));
let in_range = T::gt(T::minimum(x - lo, hi - x), T::zeros_like(x));
let dx = T::where_(in_range, dy, T::zeros_like(dy));
T::store(
dx_ptr.add_offsets(offsets),
dx,
Some(in_bounds),
&[],
None,
None,
);
}
#[kernel(backward = Relu6Backward)]
pub fn relu6_forward<T: Triton, D: Float, const BLOCK_SIZE: i32>(
x_ptr: T::Pointer<D>,
y_ptr: T::Pointer<D>,
n_elements: i32,
) where
T::I32Tensor: types::Tensor<i32, 1>,
T::I32Tensor: Comparison<i32, BoolTensor = T::BoolTensor>,
T::Pointer<D>: AddOffsets<i32, 1, T::I32Tensor, Output = T::Tensor<T::Pointer<D>>>,
{
let pid = T::program_id(Axis::X);
let block_start = pid * BLOCK_SIZE;
let offsets = T::arange(0, BLOCK_SIZE) + block_start;
let in_bounds = offsets.lt(n_elements);
let x = T::load(
x_ptr.add_offsets(offsets),
Some(in_bounds),
None,
&[],
None,
None,
None,
false,
);
let lo = T::zeros_like(x);
let hi = T::full(&[BLOCK_SIZE], D::from_f64(6.0));
let y = T::clamp(x, lo, hi);
T::store(
y_ptr.add_offsets(offsets),
y,
Some(in_bounds),
&[],
None,
None,
);
}
#[kernel]
pub fn relu6_backward<T: Triton, D: Float, const BLOCK_SIZE: i32>(
dy_ptr: T::Pointer<D>,
x_ptr: T::Pointer<D>,
dx_ptr: T::Pointer<D>,
n_elements: i32,
) where
T::I32Tensor: types::Tensor<i32, 1>,
T::I32Tensor: Comparison<i32, BoolTensor = T::BoolTensor>,
T::Pointer<D>: AddOffsets<i32, 1, T::I32Tensor, Output = T::Tensor<T::Pointer<D>>>,
{
let pid = T::program_id(Axis::X);
let block_start = pid * BLOCK_SIZE;
let offsets = T::arange(0, BLOCK_SIZE) + block_start;
let in_bounds = offsets.lt(n_elements);
let dy = T::load(
dy_ptr.add_offsets(offsets),
Some(in_bounds),
None,
&[],
None,
None,
None,
false,
);
let x = T::load(
x_ptr.add_offsets(offsets),
Some(in_bounds),
None,
&[],
None,
None,
None,
false,
);
let six = T::full(&[BLOCK_SIZE], D::from_f64(6.0));
let in_range = T::gt(T::minimum(x, six - x), T::zeros_like(x));
let dx = T::where_(in_range, dy, T::zeros_like(dy));
T::store(
dx_ptr.add_offsets(offsets),
dx,
Some(in_bounds),
&[],
None,
None,
);
}
#[kernel(backward = HardsigmoidBackward)]
pub fn hardsigmoid_forward<T: Triton, D: Float, const BLOCK_SIZE: i32>(
x_ptr: T::Pointer<D>,
y_ptr: T::Pointer<D>,
n_elements: i32,
) where
T::I32Tensor: types::Tensor<i32, 1>,
T::I32Tensor: Comparison<i32, BoolTensor = T::BoolTensor>,
T::Pointer<D>: AddOffsets<i32, 1, T::I32Tensor, Output = T::Tensor<T::Pointer<D>>>,
{
let pid = T::program_id(Axis::X);
let block_start = pid * BLOCK_SIZE;
let offsets = T::arange(0, BLOCK_SIZE) + block_start;
let in_bounds = offsets.lt(n_elements);
let x = T::load(
x_ptr.add_offsets(offsets),
Some(in_bounds),
None,
&[],
None,
None,
None,
false,
);
let three = T::full(&[BLOCK_SIZE], D::from_f64(3.0));
let six = T::full(&[BLOCK_SIZE], D::from_f64(6.0));
let lo = T::zeros_like(x);
let hi = T::full(&[BLOCK_SIZE], D::from_f64(1.0));
let y = T::clamp((x + three) / six, lo, hi);
T::store(
y_ptr.add_offsets(offsets),
y,
Some(in_bounds),
&[],
None,
None,
);
}
#[kernel]
pub fn hardsigmoid_backward<T: Triton, D: Float, const BLOCK_SIZE: i32>(
dy_ptr: T::Pointer<D>,
x_ptr: T::Pointer<D>,
dx_ptr: T::Pointer<D>,
n_elements: i32,
) where
T::I32Tensor: types::Tensor<i32, 1>,
T::I32Tensor: Comparison<i32, BoolTensor = T::BoolTensor>,
T::Pointer<D>: AddOffsets<i32, 1, T::I32Tensor, Output = T::Tensor<T::Pointer<D>>>,
{
let pid = T::program_id(Axis::X);
let block_start = pid * BLOCK_SIZE;
let offsets = T::arange(0, BLOCK_SIZE) + block_start;
let in_bounds = offsets.lt(n_elements);
let dy = T::load(
dy_ptr.add_offsets(offsets),
Some(in_bounds),
None,
&[],
None,
None,
None,
false,
);
let x = T::load(
x_ptr.add_offsets(offsets),
Some(in_bounds),
None,
&[],
None,
None,
None,
false,
);
let three = T::full(&[BLOCK_SIZE], D::from_f64(3.0));
let in_range = T::lt(T::abs(x), three); let sixth = T::full(&[BLOCK_SIZE], D::from_f64(1.0 / 6.0));
let dx = T::where_(in_range, dy * sixth, T::zeros_like(dy));
T::store(
dx_ptr.add_offsets(offsets),
dx,
Some(in_bounds),
&[],
None,
None,
);
}
#[kernel(backward = HardswishBackward)]
pub fn hardswish_forward<T: Triton, D: Float, const BLOCK_SIZE: i32>(
x_ptr: T::Pointer<D>,
y_ptr: T::Pointer<D>,
n_elements: i32,
) where
T::I32Tensor: types::Tensor<i32, 1>,
T::I32Tensor: Comparison<i32, BoolTensor = T::BoolTensor>,
T::Pointer<D>: AddOffsets<i32, 1, T::I32Tensor, Output = T::Tensor<T::Pointer<D>>>,
{
let pid = T::program_id(Axis::X);
let block_start = pid * BLOCK_SIZE;
let offsets = T::arange(0, BLOCK_SIZE) + block_start;
let in_bounds = offsets.lt(n_elements);
let x = T::load(
x_ptr.add_offsets(offsets),
Some(in_bounds),
None,
&[],
None,
None,
None,
false,
);
let three = T::full(&[BLOCK_SIZE], D::from_f64(3.0));
let six = T::full(&[BLOCK_SIZE], D::from_f64(6.0));
let lo = T::zeros_like(x);
let hi = T::full(&[BLOCK_SIZE], D::from_f64(1.0));
let hs = T::clamp((x + three) / six, lo, hi);
let y = x * hs;
T::store(
y_ptr.add_offsets(offsets),
y,
Some(in_bounds),
&[],
None,
None,
);
}
#[kernel]
pub fn hardswish_backward<T: Triton, D: Float, const BLOCK_SIZE: i32>(
dy_ptr: T::Pointer<D>,
x_ptr: T::Pointer<D>,
dx_ptr: T::Pointer<D>,
n_elements: i32,
) where
T::I32Tensor: types::Tensor<i32, 1>,
T::I32Tensor: Comparison<i32, BoolTensor = T::BoolTensor>,
T::Pointer<D>: AddOffsets<i32, 1, T::I32Tensor, Output = T::Tensor<T::Pointer<D>>>,
{
let pid = T::program_id(Axis::X);
let block_start = pid * BLOCK_SIZE;
let offsets = T::arange(0, BLOCK_SIZE) + block_start;
let in_bounds = offsets.lt(n_elements);
let dy = T::load(
dy_ptr.add_offsets(offsets),
Some(in_bounds),
None,
&[],
None,
None,
None,
false,
);
let x = T::load(
x_ptr.add_offsets(offsets),
Some(in_bounds),
None,
&[],
None,
None,
None,
false,
);
let three = T::full(&[BLOCK_SIZE], D::from_f64(3.0));
let neg_three = T::full(&[BLOCK_SIZE], D::from_f64(-3.0));
let six = T::full(&[BLOCK_SIZE], D::from_f64(6.0));
let two = T::full(&[BLOCK_SIZE], D::from_f64(2.0));
let x_le_neg3 = T::le(x, neg_three);
let x_ge_3 = T::ge(x, three);
let dx_mid = dy * (two * x + three) / six;
let dx_not_lo = T::where_(x_ge_3, dy, dx_mid);
let dx = T::where_(x_le_neg3, T::zeros_like(dy), dx_not_lo);
T::store(
dx_ptr.add_offsets(offsets),
dx,
Some(in_bounds),
&[],
None,
None,
);
}
#[kernel(backward = HardshrinkBackward)]
pub fn hardshrink_forward<T: Triton, D: Float, const BLOCK_SIZE: i32>(
x_ptr: T::Pointer<D>,
y_ptr: T::Pointer<D>,
n_elements: i32,
lambda: f32,
) where
T::I32Tensor: types::Tensor<i32, 1>,
T::I32Tensor: Comparison<i32, BoolTensor = T::BoolTensor>,
T::Pointer<D>: AddOffsets<i32, 1, T::I32Tensor, Output = T::Tensor<T::Pointer<D>>>,
{
let pid = T::program_id(Axis::X);
let block_start = pid * BLOCK_SIZE;
let offsets = T::arange(0, BLOCK_SIZE) + block_start;
let in_bounds = offsets.lt(n_elements);
let x = T::load(
x_ptr.add_offsets(offsets),
Some(in_bounds),
None,
&[],
None,
None,
None,
false,
);
let lam = T::full(&[BLOCK_SIZE], D::from_f64(lambda as f64));
let outside = T::gt(T::abs(x), lam);
let y = T::where_(outside, x, T::zeros_like(x));
T::store(
y_ptr.add_offsets(offsets),
y,
Some(in_bounds),
&[],
None,
None,
);
}
#[kernel]
pub fn hardshrink_backward<T: Triton, D: Float, const BLOCK_SIZE: i32>(
dy_ptr: T::Pointer<D>,
x_ptr: T::Pointer<D>,
dx_ptr: T::Pointer<D>,
n_elements: i32,
lambda: f32,
) where
T::I32Tensor: types::Tensor<i32, 1>,
T::I32Tensor: Comparison<i32, BoolTensor = T::BoolTensor>,
T::Pointer<D>: AddOffsets<i32, 1, T::I32Tensor, Output = T::Tensor<T::Pointer<D>>>,
{
let pid = T::program_id(Axis::X);
let block_start = pid * BLOCK_SIZE;
let offsets = T::arange(0, BLOCK_SIZE) + block_start;
let in_bounds = offsets.lt(n_elements);
let dy = T::load(
dy_ptr.add_offsets(offsets),
Some(in_bounds),
None,
&[],
None,
None,
None,
false,
);
let x = T::load(
x_ptr.add_offsets(offsets),
Some(in_bounds),
None,
&[],
None,
None,
None,
false,
);
let lam = T::full(&[BLOCK_SIZE], D::from_f64(lambda as f64));
let outside = T::gt(T::abs(x), lam);
let dx = T::where_(outside, dy, T::zeros_like(dy));
T::store(
dx_ptr.add_offsets(offsets),
dx,
Some(in_bounds),
&[],
None,
None,
);
}
pub struct HardtanhOp<D: Float> {
pub forward: HardtanhForward<D>,
pub backward: HardtanhBackward<D>,
}
pub struct Relu6Op<D: Float> {
pub forward: Relu6Forward<D>,
pub backward: Relu6Backward<D>,
}
pub struct HardsigmoidOp<D: Float> {
pub forward: HardsigmoidForward<D>,
pub backward: HardsigmoidBackward<D>,
}
pub struct HardswishOp<D: Float> {
pub forward: HardswishForward<D>,
pub backward: HardswishBackward<D>,
}
pub struct HardshrinkOp<D: Float> {
pub forward: HardshrinkForward<D>,
pub backward: HardshrinkBackward<D>,
}