#![cfg(feature = "cuda")]
use std::sync::{Arc, RwLock};
use fuel_ir::DType;
use fuel_ir::dispatch::OpKind;
use fuel_ir::{Error, Layout, Result, probe::BackendId};
use crate::kernel::{KernelBindingTable, OpParams};
use fuel_memory::Storage;
use crate::dispatch::{cuda_input, cuda_output, read_storage, write_storage};
macro_rules! cuda_unary_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
layouts: &[Layout],
_params: &OpParams,
) -> Result<()> {
if inputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(stringify!($wrapper_name), ": expected 1 input, got {}"),
inputs.len(),
))
.bt());
}
if outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(stringify!($wrapper_name), ": expected 1 output, got {}"),
outputs.len(),
))
.bt());
}
let layout = layouts.first();
let in_guard = read_storage(&inputs[0])?;
let mut out_guard = write_storage(&outputs[0])?;
let src_cuda = cuda_input(&in_guard)?;
let out_cuda = cuda_output(&mut out_guard)?;
$baracuda_fn(src_cuda, layout, out_cuda)
}
};
}
macro_rules! cuda_unary_inplace_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
_layouts: &[Layout],
_params: &OpParams,
) -> Result<()> {
if !inputs.is_empty() || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 0 inputs + 1 output (target adopted by executor), got {} + {}"
),
inputs.len(),
outputs.len(),
))
.bt());
}
let mut out_guard = write_storage(&outputs[0])?;
let out_cuda = cuda_output(&mut out_guard)?;
$baracuda_fn(out_cuda)
}
};
}
macro_rules! cuda_binary_baracuda_wrapper {
($wrapper_name:ident, $baracuda_into_fn:path) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
layouts: &[Layout],
_params: &OpParams,
) -> Result<()> {
if inputs.len() != 2 {
return Err(Error::Msg(format!(
concat!(stringify!($wrapper_name), ": expected 2 inputs, got {}"),
inputs.len(),
))
.bt());
}
if outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(stringify!($wrapper_name), ": expected 1 output, got {}"),
outputs.len(),
))
.bt());
}
let lhs_layout = layouts.first();
let rhs_layout = layouts.get(1);
let lhs_guard = read_storage(&inputs[0])?;
let rhs_guard = read_storage(&inputs[1])?;
let mut out_guard = write_storage(&outputs[0])?;
let lhs_cuda = cuda_input(&lhs_guard)?;
let rhs_cuda = cuda_input(&rhs_guard)?;
let out_cuda = cuda_output(&mut out_guard)?;
$baracuda_into_fn(lhs_cuda, rhs_cuda, lhs_layout, rhs_layout, out_cuda)
}
};
}
macro_rules! cuda_rope_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 1 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 1 input + 1 output, got {} + {}",
),
inputs.len(),
outputs.len(),
))
.bt());
}
let (outer_count, seq, head_dim) = match params {
OpParams::Rope {
outer_count,
seq,
head_dim,
} => (*outer_count, *seq, *head_dim),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::Rope, got {:?}",
),
other,
))
.bt());
}
};
let layout = layouts.first();
let in_guard = read_storage(&inputs[0])?;
let mut out_guard = write_storage(&outputs[0])?;
let src_cuda = cuda_input(&in_guard)?;
let out_cuda = cuda_output(&mut out_guard)?;
$baracuda_fn(src_cuda, layout, outer_count, seq, head_dim, out_cuda)
}
};
}
macro_rules! cuda_index_select_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
_layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 2 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 2 inputs + 1 output, got {} + {}",
),
inputs.len(),
outputs.len(),
))
.bt());
}
let (outer_count, source_dim_size, n_indices, inner_count) = match params {
OpParams::IndexSelect {
outer_count,
source_dim_size,
n_indices,
inner_count,
} => (*outer_count, *source_dim_size, *n_indices, *inner_count),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::IndexSelect, got {:?}",
),
other,
))
.bt());
}
};
let src_guard = read_storage(&inputs[0])?;
let idx_guard = read_storage(&inputs[1])?;
if idx_guard.dtype != DType::U32 {
return Err(Error::Msg(format!(
concat!(stringify!($wrapper_name), ": indices must be U32, got {:?}",),
idx_guard.dtype,
))
.bt());
}
let mut out_guard = write_storage(&outputs[0])?;
let src_cuda = cuda_input(&src_guard)?;
let idx_cuda = cuda_input(&idx_guard)?;
let out_cuda = cuda_output(&mut out_guard)?;
$baracuda_fn(
src_cuda,
idx_cuda,
outer_count,
source_dim_size,
n_indices,
inner_count,
out_cuda,
)
}
};
}
macro_rules! cuda_gather_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
_layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 2 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 2 inputs + 1 output, got {} + {}"
),
inputs.len(),
outputs.len(),
))
.bt());
}
let (source_shape, output_shape, dim) = match params {
OpParams::Gather {
source_shape,
output_shape,
dim,
} => (source_shape.clone(), output_shape.clone(), *dim),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::Gather, got {:?}"
),
other,
))
.bt());
}
};
let src_guard = read_storage(&inputs[0])?;
let idx_guard = read_storage(&inputs[1])?;
if idx_guard.dtype != DType::U32 {
return Err(Error::Msg(format!(
concat!(stringify!($wrapper_name), ": indices must be U32, got {:?}"),
idx_guard.dtype,
))
.bt());
}
let mut out_guard = write_storage(&outputs[0])?;
let src_cuda = cuda_input(&src_guard)?;
let idx_cuda = cuda_input(&idx_guard)?;
let result = $baracuda_fn(src_cuda, idx_cuda, &source_shape, &output_shape, dim)?;
let out_cuda = cuda_output(&mut out_guard)?;
*out_cuda = result;
Ok(())
}
};
}
macro_rules! cuda_scatter_add_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
_layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 3 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 3 inputs + 1 output, got {} + {}"
),
inputs.len(),
outputs.len(),
))
.bt());
}
let (base_shape, src_shape, dim) = match params {
OpParams::ScatterAdd {
base_shape,
src_shape,
dim,
} => (base_shape.clone(), src_shape.clone(), *dim),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::ScatterAdd, got {:?}"
),
other,
))
.bt());
}
};
let base_guard = read_storage(&inputs[0])?;
let idx_guard = read_storage(&inputs[1])?;
if idx_guard.dtype != DType::U32 {
return Err(Error::Msg(format!(
concat!(stringify!($wrapper_name), ": indices must be U32, got {:?}"),
idx_guard.dtype,
))
.bt());
}
let src_guard = read_storage(&inputs[2])?;
let mut out_guard = write_storage(&outputs[0])?;
let base_cuda = cuda_input(&base_guard)?;
let idx_cuda = cuda_input(&idx_guard)?;
let src_cuda = cuda_input(&src_guard)?;
let result = $baracuda_fn(base_cuda, idx_cuda, src_cuda, &base_shape, &src_shape, dim)?;
let out_cuda = cuda_output(&mut out_guard)?;
*out_cuda = result;
Ok(())
}
};
}
macro_rules! cuda_masked_fill_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
_layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 2 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 2 inputs + 1 output, got {} + {}"
),
inputs.len(),
outputs.len(),
))
.bt());
}
let fill_bytes = match params {
OpParams::MaskedFill { fill_bytes } => fill_bytes.clone(),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::MaskedFill, got {:?}"
),
other,
))
.bt());
}
};
let src_guard = read_storage(&inputs[0])?;
let mask_guard = read_storage(&inputs[1])?;
let mut out_guard = write_storage(&outputs[0])?;
let src_cuda = cuda_input(&src_guard)?;
let mask_cuda = cuda_input(&mask_guard)?;
let result = $baracuda_fn(src_cuda, mask_cuda, &fill_bytes)?;
let out_cuda = cuda_output(&mut out_guard)?;
*out_cuda = result;
Ok(())
}
};
}
pub mod indexing {
use super::*;
use fuel_cuda_backend::baracuda::indexing as bk;
cuda_index_select_baracuda_wrapper!(index_select_f32, bk::index_select_f32_into);
cuda_index_select_baracuda_wrapper!(index_select_f64, bk::index_select_f64_into);
cuda_index_select_baracuda_wrapper!(index_select_i32, bk::index_select_i32_into);
cuda_gather_baracuda_wrapper!(gather_f32, bk::gather_f32);
cuda_gather_baracuda_wrapper!(gather_f64, bk::gather_f64);
cuda_gather_baracuda_wrapper!(gather_i32, bk::gather_i32);
cuda_scatter_add_baracuda_wrapper!(scatter_add_f32, bk::scatter_add_f32);
cuda_scatter_add_baracuda_wrapper!(scatter_add_f64, bk::scatter_add_f64);
cuda_masked_fill_baracuda_wrapper!(masked_fill_f32, bk::masked_fill_f32);
cuda_masked_fill_baracuda_wrapper!(masked_fill_f64, bk::masked_fill_f64);
cuda_masked_fill_baracuda_wrapper!(masked_fill_i32, bk::masked_fill_i32);
}
macro_rules! cuda_matmul_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path $(,)?) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
_layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 2 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 2 inputs + 1 output, got {} + {}",
),
inputs.len(),
outputs.len(),
))
.bt());
}
let (lhs_batch_dims, rhs_batch_dims, m, n, k) = match params {
OpParams::Matmul {
lhs_batch_dims,
rhs_batch_dims,
m,
n,
k,
..
} => (lhs_batch_dims.clone(), rhs_batch_dims.clone(), *m, *n, *k),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::Matmul, got {:?}"
),
other,
))
.bt());
}
};
let lhs_guard = read_storage(&inputs[0])?;
let rhs_guard = read_storage(&inputs[1])?;
let mut out_guard = write_storage(&outputs[0])?;
let lhs_cuda = cuda_input(&lhs_guard)?;
let rhs_cuda = cuda_input(&rhs_guard)?;
let result = $baracuda_fn(
lhs_cuda,
rhs_cuda,
&lhs_batch_dims,
&rhs_batch_dims,
m,
n,
k,
)?;
let out_cuda = cuda_output(&mut out_guard)?;
*out_cuda = result;
Ok(())
}
};
}
macro_rules! cuda_matmul_into_baracuda_wrapper {
($wrapper_name:ident, $baracuda_into_fn:path $(,)?) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
_layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 2 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 2 inputs + 1 output, got {} + {}",
),
inputs.len(),
outputs.len(),
))
.bt());
}
let (lhs_batch_dims, rhs_batch_dims, m, n, k) = match params {
OpParams::Matmul {
lhs_batch_dims,
rhs_batch_dims,
m,
n,
k,
..
} => (lhs_batch_dims.clone(), rhs_batch_dims.clone(), *m, *n, *k),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::Matmul, got {:?}"
),
other,
))
.bt());
}
};
let lhs_guard = read_storage(&inputs[0])?;
let rhs_guard = read_storage(&inputs[1])?;
let mut out_guard = write_storage(&outputs[0])?;
let lhs_cuda = cuda_input(&lhs_guard)?;
let rhs_cuda = cuda_input(&rhs_guard)?;
let out_cuda = cuda_output(&mut out_guard)?;
$baracuda_into_fn(
lhs_cuda,
rhs_cuda,
&lhs_batch_dims,
&rhs_batch_dims,
m,
n,
k,
out_cuda,
)
}
};
}
pub mod gemm_int {
use super::*;
use fuel_cuda_backend::baracuda::gemm_int as bk;
cuda_matmul_baracuda_wrapper!(gemm_s8_rrr, bk::gemm_s8_rrr);
cuda_matmul_baracuda_wrapper!(gemm_u8_rrr, bk::gemm_u8_rrr);
}
pub mod gemm_dense {
use super::*;
use fuel_cuda_backend::baracuda::gemm_dense as bk;
cuda_matmul_into_baracuda_wrapper!(matmul_f32, bk::matmul_f32_into);
cuda_matmul_into_baracuda_wrapper!(matmul_f64, bk::matmul_f64_into);
cuda_matmul_into_baracuda_wrapper!(matmul_f16, bk::matmul_f16_into);
cuda_matmul_into_baracuda_wrapper!(matmul_bf16, bk::matmul_bf16_into);
}
macro_rules! cuda_reduce_to_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path, $variant:ident $(,)?) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 1 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 1 input + 1 output, got {} + {}",
),
inputs.len(),
outputs.len(),
))
.bt());
}
let (input_shape, output_shape) = match params {
OpParams::$variant {
input_shape,
output_shape,
} => (input_shape.clone(), output_shape.clone()),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::",
stringify!($variant),
", got {:?}",
),
other,
))
.bt());
}
};
let input_layout = layouts.first().ok_or_else(|| {
Error::Msg(concat!(stringify!($wrapper_name), ": layouts empty").to_string()).bt()
})?;
let in_guard = read_storage(&inputs[0])?;
let mut out_guard = write_storage(&outputs[0])?;
let src_cuda = cuda_input(&in_guard)?;
let result = $baracuda_fn(src_cuda, input_layout, &input_shape, &output_shape)?;
let out_cuda = cuda_output(&mut out_guard)?;
*out_cuda = result;
Ok(())
}
};
}
pub mod reduce_to {
use super::*;
use fuel_cuda_backend::baracuda::reduce_to as bk;
cuda_reduce_to_baracuda_wrapper!(sum_to_f32, bk::reduce_sum_to_f32, ReduceSumTo);
cuda_reduce_to_baracuda_wrapper!(sum_to_f64, bk::reduce_sum_to_f64, ReduceSumTo);
cuda_reduce_to_baracuda_wrapper!(sum_to_f16, bk::reduce_sum_to_f16, ReduceSumTo);
cuda_reduce_to_baracuda_wrapper!(sum_to_bf16, bk::reduce_sum_to_bf16, ReduceSumTo);
cuda_reduce_to_baracuda_wrapper!(max_to_f32, bk::reduce_max_to_f32, ReduceMaxTo);
cuda_reduce_to_baracuda_wrapper!(max_to_f64, bk::reduce_max_to_f64, ReduceMaxTo);
cuda_reduce_to_baracuda_wrapper!(max_to_f16, bk::reduce_max_to_f16, ReduceMaxTo);
cuda_reduce_to_baracuda_wrapper!(max_to_bf16, bk::reduce_max_to_bf16, ReduceMaxTo);
}
macro_rules! cuda_causal_conv1d_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path $(,)?) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
_layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 3 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 3 inputs (x, weight, bias), got {}",
),
inputs.len(),
))
.bt());
}
if outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(stringify!($wrapper_name), ": expected 1 output, got {}"),
outputs.len(),
))
.bt());
}
let (batch, channels, seq_in, seq_out, kernel, use_silu) = match params {
OpParams::CausalConv1d {
batch,
channels,
seq_in,
seq_out,
kernel,
use_silu,
} => (*batch, *channels, *seq_in, *seq_out, *kernel, *use_silu),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::CausalConv1d, got {:?}",
),
other,
))
.bt());
}
};
let x_guard = read_storage(&inputs[0])?;
let w_guard = read_storage(&inputs[1])?;
let bias_guard = read_storage(&inputs[2])?;
let mut out_guard = write_storage(&outputs[0])?;
let x_cuda = cuda_input(&x_guard)?;
let w_cuda = cuda_input(&w_guard)?;
let bias_cuda = cuda_input(&bias_guard)?;
let result = $baracuda_fn(
x_cuda, w_cuda, bias_cuda, batch, channels, seq_in, seq_out, kernel, use_silu,
)?;
let out_cuda = cuda_output(&mut out_guard)?;
*out_cuda = result;
Ok(())
}
};
}
pub mod conv1d {
use super::*;
use fuel_cuda_backend::baracuda::mamba as bk;
cuda_causal_conv1d_baracuda_wrapper!(causal_conv1d_f32, bk::causal_conv1d_fuel_prepad_f32);
cuda_causal_conv1d_baracuda_wrapper!(causal_conv1d_f64, bk::causal_conv1d_fuel_prepad_f64);
cuda_causal_conv1d_baracuda_wrapper!(causal_conv1d_bf16, bk::causal_conv1d_fuel_prepad_bf16);
cuda_causal_conv1d_baracuda_wrapper!(causal_conv1d_f16, bk::causal_conv1d_fuel_prepad_f16);
}
macro_rules! cuda_arg_reduce_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path $(,)?) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 1 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 1 input + 1 output, got {} + {}"
),
inputs.len(),
outputs.len(),
))
.bt());
}
let dim = match params {
OpParams::Reduce { dims, keepdim: _ } => {
if dims.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected a single reduce dim, got {:?}"
),
dims,
))
.bt());
}
dims[0]
}
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::Reduce, got {:?}"
),
other,
))
.bt());
}
};
let layout = layouts.first().ok_or_else(|| {
Error::Msg(format!(concat!(
stringify!($wrapper_name),
": layouts empty"
),))
.bt()
})?;
let in_guard = read_storage(&inputs[0])?;
let mut out_guard = write_storage(&outputs[0])?;
let src_cuda = cuda_input(&in_guard)?;
let result = $baracuda_fn(src_cuda, layout, dim)?;
let out_cuda = cuda_output(&mut out_guard)?;
*out_cuda = result;
Ok(())
}
};
}
pub mod arg_reduce {
use super::*;
use fuel_cuda_backend::baracuda::arg_reduce as bk;
cuda_arg_reduce_baracuda_wrapper!(argmax_dim_u32_f32, bk::argmax_dim_u32_f32);
cuda_arg_reduce_baracuda_wrapper!(argmin_dim_u32_f32, bk::argmin_dim_u32_f32);
cuda_arg_reduce_baracuda_wrapper!(argmax_dim_u32_f64, bk::argmax_dim_u32_f64);
cuda_arg_reduce_baracuda_wrapper!(argmin_dim_u32_f64, bk::argmin_dim_u32_f64);
cuda_arg_reduce_baracuda_wrapper!(argmax_dim_u32_f16, bk::argmax_dim_u32_f16);
cuda_arg_reduce_baracuda_wrapper!(argmin_dim_u32_f16, bk::argmin_dim_u32_f16);
cuda_arg_reduce_baracuda_wrapper!(argmax_dim_u32_bf16, bk::argmax_dim_u32_bf16);
cuda_arg_reduce_baracuda_wrapper!(argmin_dim_u32_bf16, bk::argmin_dim_u32_bf16);
}
macro_rules! cuda_powi_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path $(,)?) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 1 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 1 input + 1 output, got {} + {}"
),
inputs.len(),
outputs.len(),
))
.bt());
}
let exp = match params {
OpParams::PowI { exp } => *exp,
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::PowI, got {:?}"
),
other,
))
.bt());
}
};
let layout = layouts.first();
let in_guard = read_storage(&inputs[0])?;
let mut out_guard = write_storage(&outputs[0])?;
let src_cuda = cuda_input(&in_guard)?;
let result = $baracuda_fn(src_cuda, layout, exp)?;
let out_cuda = cuda_output(&mut out_guard)?;
*out_cuda = result;
Ok(())
}
};
}
pub mod powi {
use super::*;
use fuel_cuda_backend::baracuda::powi as bk;
cuda_powi_baracuda_wrapper!(powi_f32, bk::powi_f32);
cuda_powi_baracuda_wrapper!(powi_f64, bk::powi_f64);
cuda_powi_baracuda_wrapper!(powi_f16, bk::powi_f16);
cuda_powi_baracuda_wrapper!(powi_bf16, bk::powi_bf16);
}
macro_rules! cuda_powi_backward_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path $(,)?) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 2 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 2 inputs + 1 output, got {} + {}"
),
inputs.len(),
outputs.len(),
))
.bt());
}
let exp = match params {
OpParams::PowI { exp } => *exp,
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::PowI, got {:?}"
),
other,
))
.bt());
}
};
let layout = layouts.first();
let x_guard = read_storage(&inputs[0])?;
let up_guard = read_storage(&inputs[1])?;
let mut out_guard = write_storage(&outputs[0])?;
let x_cuda = cuda_input(&x_guard)?;
let up_cuda = cuda_input(&up_guard)?;
let result = $baracuda_fn(x_cuda, up_cuda, layout, exp)?;
let out_cuda = cuda_output(&mut out_guard)?;
*out_cuda = result;
Ok(())
}
};
}
pub mod powi_backward {
use super::*;
use fuel_cuda_backend::baracuda::powi as bk;
cuda_powi_backward_baracuda_wrapper!(powi_backward_f32, bk::powi_backward_f32);
cuda_powi_backward_baracuda_wrapper!(powi_backward_f64, bk::powi_backward_f64);
cuda_powi_backward_baracuda_wrapper!(powi_backward_f16, bk::powi_backward_f16);
cuda_powi_backward_baracuda_wrapper!(powi_backward_bf16, bk::powi_backward_bf16);
}
macro_rules! cuda_clamp_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path, $scalar_ty:ty $(,)?) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 1 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 1 input + 1 output, got {} + {}"
),
inputs.len(),
outputs.len(),
))
.bt());
}
let (min_f64, max_f64) = match params {
OpParams::Clamp { min, max } => (*min, *max),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::Clamp, got {:?}"
),
other,
))
.bt());
}
};
let layout = layouts.first().ok_or_else(|| {
Error::Msg(
concat!(
stringify!($wrapper_name),
": Clamp requires an input layout (call with layouts[0])",
)
.to_string(),
)
.bt()
})?;
let in_guard = read_storage(&inputs[0])?;
let mut out_guard = write_storage(&outputs[0])?;
let src_cuda = cuda_input(&in_guard)?;
let result = $baracuda_fn(
src_cuda,
layout,
min_f64 as $scalar_ty,
max_f64 as $scalar_ty,
)?;
let out_cuda = cuda_output(&mut out_guard)?;
*out_cuda = result;
Ok(())
}
};
}
pub mod clamp {
use super::*;
use fuel_cuda_backend::baracuda::clamp as bk;
cuda_clamp_baracuda_wrapper!(clamp_f32, bk::clamp_f32, f32);
cuda_clamp_baracuda_wrapper!(clamp_f64, bk::clamp_f64, f64);
cuda_clamp_baracuda_wrapper!(clamp_f16, bk::clamp_f16, f32);
cuda_clamp_baracuda_wrapper!(clamp_bf16, bk::clamp_bf16, f32);
}
macro_rules! cuda_clamp_inplace_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path, $scalar_ty:ty $(,)?) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
_layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if !inputs.is_empty() || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 0 inputs + 1 output (target adopted by executor), got {} + {}"
),
inputs.len(),
outputs.len(),
))
.bt());
}
let (min_f64, max_f64) = match params {
OpParams::Clamp { min, max } => (*min, *max),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::Clamp, got {:?}"
),
other,
))
.bt());
}
};
let mut out_guard = write_storage(&outputs[0])?;
let out_cuda = cuda_output(&mut out_guard)?;
$baracuda_fn(out_cuda, min_f64 as $scalar_ty, max_f64 as $scalar_ty)
}
};
}
macro_rules! cuda_powi_inplace_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path $(,)?) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
_layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if !inputs.is_empty() || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 0 inputs + 1 output (target adopted by executor), got {} + {}"
),
inputs.len(),
outputs.len(),
))
.bt());
}
let exp = match params {
OpParams::PowI { exp } => *exp,
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::PowI, got {:?}"
),
other,
))
.bt());
}
};
let mut out_guard = write_storage(&outputs[0])?;
let out_cuda = cuda_output(&mut out_guard)?;
$baracuda_fn(out_cuda, exp)
}
};
}
pub mod clamp_inplace {
use super::*;
use fuel_cuda_backend::baracuda::clamp as bk;
cuda_clamp_inplace_baracuda_wrapper!(clamp_inplace_f32, bk::clamp_inplace_f32, f32);
cuda_clamp_inplace_baracuda_wrapper!(clamp_inplace_f64, bk::clamp_inplace_f64, f64);
cuda_clamp_inplace_baracuda_wrapper!(clamp_inplace_f16, bk::clamp_inplace_f16, f32);
cuda_clamp_inplace_baracuda_wrapper!(clamp_inplace_bf16, bk::clamp_inplace_bf16, f32);
}
pub mod powi_inplace {
use super::*;
use fuel_cuda_backend::baracuda::powi as bk;
cuda_powi_inplace_baracuda_wrapper!(powi_inplace_f32, bk::powi_inplace_f32);
cuda_powi_inplace_baracuda_wrapper!(powi_inplace_f64, bk::powi_inplace_f64);
cuda_powi_inplace_baracuda_wrapper!(powi_inplace_f16, bk::powi_inplace_f16);
cuda_powi_inplace_baracuda_wrapper!(powi_inplace_bf16, bk::powi_inplace_bf16);
}
macro_rules! cuda_concat_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path, $baracuda_into_fn:path $(,)?) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.is_empty() {
return Err(Error::Msg(format!(concat!(
stringify!($wrapper_name),
": at least 1 input required"
),))
.bt());
}
if outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(stringify!($wrapper_name), ": expected 1 output, got {}"),
outputs.len(),
))
.bt());
}
let (outer_count, input_dim_sizes, inner_count, axis) = match params {
OpParams::Concat {
outer_count,
input_dim_sizes,
inner_count,
axis,
} => (*outer_count, input_dim_sizes.clone(), *inner_count, *axis),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::Concat, got {:?}"
),
other,
))
.bt());
}
};
if input_dim_sizes.len() != inputs.len() {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": OpParams declares {} inputs but the work item carries {}",
),
input_dim_sizes.len(),
inputs.len(),
))
.bt());
}
let input_layouts = if layouts.len() >= inputs.len() {
Some(&layouts[..inputs.len()])
} else {
None
};
let in_guards: Vec<_> = inputs
.iter()
.map(read_storage)
.collect::<Result<Vec<_>>>()?;
let mut in_cudas: Vec<&fuel_cuda_backend::CudaStorageBytes> =
Vec::with_capacity(in_guards.len());
for g in &in_guards {
in_cudas.push(cuda_input(g)?);
}
if in_cudas.len() == 2 {
let mut out_guard = write_storage(&outputs[0])?;
let out_cuda = cuda_output(&mut out_guard)?;
$baracuda_into_fn(
&in_cudas,
input_layouts,
axis,
outer_count,
&input_dim_sizes,
inner_count,
out_cuda,
)
} else {
let result = $baracuda_fn(
&in_cudas,
input_layouts,
axis,
outer_count,
&input_dim_sizes,
inner_count,
)?;
let mut out_guard = write_storage(&outputs[0])?;
let out_cuda = cuda_output(&mut out_guard)?;
out_cuda.copy_from_device(&result)
}
}
};
}
pub mod concat {
use super::*;
use fuel_cuda_backend::baracuda::concat as bk;
cuda_concat_baracuda_wrapper!(concat_f32, bk::concat_f32, bk::concat_f32_into);
cuda_concat_baracuda_wrapper!(concat_f64, bk::concat_f64, bk::concat_f64_into);
cuda_concat_baracuda_wrapper!(concat_f16, bk::concat_f16, bk::concat_f16_into);
cuda_concat_baracuda_wrapper!(concat_bf16, bk::concat_bf16, bk::concat_bf16_into);
}
macro_rules! cuda_write_slice_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
_layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 1 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 1 input + 1 output, got {} + {}"
),
inputs.len(),
outputs.len(),
))
.bt());
}
let (dest_shape, ranges) = match params {
OpParams::WriteSlice {
dest_shape, ranges, ..
} => (dest_shape, ranges),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::WriteSlice, got {:?}"
),
other,
))
.bt());
}
};
let rank = dest_shape.len();
let mut source_shape = Vec::with_capacity(rank);
let mut range_start = Vec::with_capacity(rank);
for &(start, end) in ranges.iter() {
source_shape.push(end - start);
range_start.push(start);
}
let in_guard = read_storage(&inputs[0])?;
let mut out_guard = write_storage(&outputs[0])?;
let src_cuda = cuda_input(&in_guard)?;
let dest_cuda = cuda_output(&mut out_guard)?;
$baracuda_fn(dest_cuda, src_cuda, dest_shape, &source_shape, &range_start)
}
};
}
pub mod write_slice {
use super::*;
use fuel_cuda_backend::baracuda::write_slice as bk;
cuda_write_slice_baracuda_wrapper!(write_slice_b1, bk::write_slice_b1);
cuda_write_slice_baracuda_wrapper!(write_slice_b2, bk::write_slice_b2);
cuda_write_slice_baracuda_wrapper!(write_slice_b4, bk::write_slice_b4);
cuda_write_slice_baracuda_wrapper!(write_slice_b8, bk::write_slice_b8);
cuda_write_slice_baracuda_wrapper!(write_slice_b16, bk::write_slice_b16);
}
macro_rules! cuda_write_slice_rotating_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path, $dtype_size:expr) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
_layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 2 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 2 inputs (source, position) + 1 output (dest), got {} + {}"
),
inputs.len(),
outputs.len(),
))
.bt());
}
let (dest_shape, axis, modulus, ranges) = match params {
OpParams::WriteSliceRotating {
dest_shape,
axis,
modulus,
ranges,
} => (dest_shape, *axis, *modulus, ranges),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::WriteSliceRotating, got {:?}"
),
other,
))
.bt());
}
};
let rank = dest_shape.len();
if ranges.len() != rank {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": ranges.len() {} != dest rank {}"
),
ranges.len(),
rank,
))
.bt());
}
let pos_guard = read_storage(&inputs[1])?;
let pos_cuda = cuda_input(&pos_guard)?;
let pos_bytes = pos_cuda.to_cpu_bytes()?;
if pos_bytes.len() < 4 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": position storage has {} bytes, need >= 4"
),
pos_bytes.len(),
))
.bt());
}
let position =
u32::from_ne_bytes([pos_bytes[0], pos_bytes[1], pos_bytes[2], pos_bytes[3]])
as usize;
let wrapped_start = position % modulus;
let mut slab_shape: Vec<usize> = Vec::with_capacity(rank);
for (i, &(start, end)) in ranges.iter().enumerate() {
if end < start {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": ranges[{i}] = ({start}, {end}) has end < start"
),
i = i,
start = start,
end = end,
))
.bt());
}
let slab = end - start;
if i == axis && slab > modulus {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": rotating-axis slab {slab} > modulus {modulus}"
),
slab = slab,
modulus = modulus,
))
.bt());
}
slab_shape.push(slab);
}
let slab_axis_len = slab_shape[axis];
let slab_elems: usize = slab_shape.iter().copied().product();
if slab_elems == 0 {
return Ok(());
}
let first_len = slab_axis_len.min(modulus - wrapped_start);
let second_len = slab_axis_len - first_len;
let outer_count: usize = slab_shape[..axis].iter().copied().product();
let inner_per_row: usize = slab_shape[axis + 1..].iter().copied().product();
let row_bytes = inner_per_row * $dtype_size;
let stride_bytes = slab_axis_len * row_bytes;
let src_guard = read_storage(&inputs[0])?;
let src_cuda = cuda_input(&src_guard)?;
if first_len > 0 {
let chunk_row_bytes = first_len * row_bytes;
let src_first = src_cuda.extract_strided_to_new(
outer_count,
stride_bytes,
0,
chunk_row_bytes,
)?;
let mut sub_source_shape = slab_shape.clone();
sub_source_shape[axis] = first_len;
let mut sub_range_start: Vec<usize> = ranges.iter().map(|r| r.0).collect();
sub_range_start[axis] = wrapped_start;
let mut out_guard = write_storage(&outputs[0])?;
let dest_cuda = cuda_output(&mut out_guard)?;
$baracuda_fn(
dest_cuda,
&src_first,
dest_shape,
&sub_source_shape,
&sub_range_start,
)?;
}
if second_len > 0 {
let chunk_row_bytes = second_len * row_bytes;
let offset_in_outer = first_len * row_bytes;
let src_second = src_cuda.extract_strided_to_new(
outer_count,
stride_bytes,
offset_in_outer,
chunk_row_bytes,
)?;
let mut sub_source_shape = slab_shape.clone();
sub_source_shape[axis] = second_len;
let mut sub_range_start: Vec<usize> = ranges.iter().map(|r| r.0).collect();
sub_range_start[axis] = 0;
let mut out_guard = write_storage(&outputs[0])?;
let dest_cuda = cuda_output(&mut out_guard)?;
$baracuda_fn(
dest_cuda,
&src_second,
dest_shape,
&sub_source_shape,
&sub_range_start,
)?;
}
Ok(())
}
};
}
pub mod write_slice_rotating {
use super::*;
use fuel_cuda_backend::baracuda::write_slice as bk;
cuda_write_slice_rotating_baracuda_wrapper!(write_slice_rotating_b1, bk::write_slice_b1, 1);
cuda_write_slice_rotating_baracuda_wrapper!(write_slice_rotating_b2, bk::write_slice_b2, 2);
cuda_write_slice_rotating_baracuda_wrapper!(write_slice_rotating_b4, bk::write_slice_b4, 4);
cuda_write_slice_rotating_baracuda_wrapper!(write_slice_rotating_b8, bk::write_slice_b8, 8);
cuda_write_slice_rotating_baracuda_wrapper!(write_slice_rotating_b16, bk::write_slice_b16, 16);
}
macro_rules! cuda_write_slice_doff_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
_layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 2 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 2 inputs (source, offset) + 1 output (dest), got {} + {}"
),
inputs.len(),
outputs.len(),
))
.bt());
}
let (dest_shape, axis, ranges) = match params {
OpParams::WriteSliceDoff {
dest_shape,
axis,
ranges,
} => (dest_shape, *axis, ranges),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::WriteSliceDoff, got {:?}"
),
other,
))
.bt());
}
};
let rank = dest_shape.len();
if ranges.len() != rank {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": ranges.len() {} != dest rank {}"
),
ranges.len(),
rank,
))
.bt());
}
if axis >= rank {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": axis {} out of bounds for rank {}"
),
axis, rank,
))
.bt());
}
let mut source_shape = Vec::with_capacity(rank);
let mut range_start = Vec::with_capacity(rank);
for &(start, end) in ranges.iter() {
if end < start {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": range ({}, {}) has end < start"
),
start, end,
))
.bt());
}
source_shape.push(end - start);
range_start.push(start);
}
let src_guard = read_storage(&inputs[0])?;
let off_guard = read_storage(&inputs[1])?;
let mut out_guard = write_storage(&outputs[0])?;
let src_cuda = cuda_input(&src_guard)?;
let off_cuda = cuda_input(&off_guard)?;
if off_cuda.len_bytes() < 8 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": offset storage has {} bytes, need >= 8 (I64)"
),
off_cuda.len_bytes(),
))
.bt());
}
let dyn_start_dev = off_cuda.buffer().as_raw().0 as *const i64;
let dest_cuda = cuda_output(&mut out_guard)?;
unsafe {
$baracuda_fn(
dest_cuda,
src_cuda,
dest_shape,
&source_shape,
&range_start,
axis,
dyn_start_dev,
)
}
}
};
}
pub mod write_slice_doff {
use super::*;
use fuel_cuda_backend::baracuda::write_slice as bk;
cuda_write_slice_doff_baracuda_wrapper!(write_slice_doff_b1, bk::write_slice_doff_b1);
cuda_write_slice_doff_baracuda_wrapper!(write_slice_doff_b2, bk::write_slice_doff_b2);
cuda_write_slice_doff_baracuda_wrapper!(write_slice_doff_b4, bk::write_slice_doff_b4);
cuda_write_slice_doff_baracuda_wrapper!(write_slice_doff_b8, bk::write_slice_doff_b8);
}
macro_rules! cuda_triangular_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 1 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 1 input + 1 output, got {} + {}"
),
inputs.len(),
outputs.len(),
))
.bt());
}
let (batch, rows, cols, diag) = match params {
OpParams::Triangular {
batch_count,
rows,
cols,
diagonal,
} => (*batch_count, *rows, *cols, *diagonal),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::Triangular, got {:?}"
),
other,
))
.bt());
}
};
let layout = layouts.first();
let in_guard = read_storage(&inputs[0])?;
let mut out_guard = write_storage(&outputs[0])?;
let src_cuda = cuda_input(&in_guard)?;
let result = $baracuda_fn(src_cuda, layout, batch, rows, cols, diag)?;
let out_cuda = cuda_output(&mut out_guard)?;
*out_cuda = result;
Ok(())
}
};
}
pub mod triangular {
use super::*;
use fuel_cuda_backend::baracuda::triangular as bk;
cuda_triangular_baracuda_wrapper!(triu_f32, bk::triu_f32);
cuda_triangular_baracuda_wrapper!(triu_f64, bk::triu_f64);
cuda_triangular_baracuda_wrapper!(triu_f16, bk::triu_f16);
cuda_triangular_baracuda_wrapper!(triu_bf16, bk::triu_bf16);
cuda_triangular_baracuda_wrapper!(triu_i32, bk::triu_i32);
cuda_triangular_baracuda_wrapper!(triu_i64, bk::triu_i64);
cuda_triangular_baracuda_wrapper!(triu_bool, bk::triu_bool);
cuda_triangular_baracuda_wrapper!(tril_f32, bk::tril_f32);
cuda_triangular_baracuda_wrapper!(tril_f64, bk::tril_f64);
cuda_triangular_baracuda_wrapper!(tril_f16, bk::tril_f16);
cuda_triangular_baracuda_wrapper!(tril_bf16, bk::tril_bf16);
cuda_triangular_baracuda_wrapper!(tril_i32, bk::tril_i32);
cuda_triangular_baracuda_wrapper!(tril_i64, bk::tril_i64);
cuda_triangular_baracuda_wrapper!(tril_bool, bk::tril_bool);
}
macro_rules! cuda_flip_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 1 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 1 input + 1 output, got {} + {}"
),
inputs.len(),
outputs.len(),
))
.bt());
}
let (outer, dim_size, inner, axis) = match params {
OpParams::Flip {
outer_count,
dim_size,
inner_count,
axis,
} => (*outer_count, *dim_size, *inner_count, *axis),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::Flip, got {:?}"
),
other,
))
.bt());
}
};
let layout = layouts.first();
let in_guard = read_storage(&inputs[0])?;
let mut out_guard = write_storage(&outputs[0])?;
let src_cuda = cuda_input(&in_guard)?;
let result = $baracuda_fn(src_cuda, layout, axis, outer, dim_size, inner)?;
let out_cuda = cuda_output(&mut out_guard)?;
*out_cuda = result;
Ok(())
}
};
}
pub mod flip {
use super::*;
use fuel_cuda_backend::baracuda::flip as bk;
cuda_flip_baracuda_wrapper!(flip_f32, bk::flip_f32);
cuda_flip_baracuda_wrapper!(flip_f64, bk::flip_f64);
cuda_flip_baracuda_wrapper!(flip_f16, bk::flip_f16);
cuda_flip_baracuda_wrapper!(flip_bf16, bk::flip_bf16);
}
macro_rules! cuda_roll_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 1 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 1 input + 1 output, got {} + {}"
),
inputs.len(),
outputs.len(),
))
.bt());
}
let (outer, dim_size, inner, shift, axis) = match params {
OpParams::Roll {
outer_count,
dim_size,
inner_count,
shift,
axis,
} => (*outer_count, *dim_size, *inner_count, *shift, *axis),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::Roll, got {:?}"
),
other,
))
.bt());
}
};
let layout = layouts.first();
let in_guard = read_storage(&inputs[0])?;
let mut out_guard = write_storage(&outputs[0])?;
let src_cuda = cuda_input(&in_guard)?;
let result = $baracuda_fn(src_cuda, layout, axis, outer, dim_size, inner, shift)?;
let out_cuda = cuda_output(&mut out_guard)?;
*out_cuda = result;
Ok(())
}
};
}
pub mod roll {
use super::*;
use fuel_cuda_backend::baracuda::roll as bk;
cuda_roll_baracuda_wrapper!(roll_f32, bk::roll_f32);
cuda_roll_baracuda_wrapper!(roll_f64, bk::roll_f64);
cuda_roll_baracuda_wrapper!(roll_f16, bk::roll_f16);
cuda_roll_baracuda_wrapper!(roll_bf16, bk::roll_bf16);
}
macro_rules! cuda_cumsum_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 1 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 1 input + 1 output, got {} + {}"
),
inputs.len(),
outputs.len(),
))
.bt());
}
let (outer, dim_size, inner, axis) = match params {
OpParams::CumSum {
outer_count,
dim_size,
inner_count,
axis,
} => (*outer_count, *dim_size, *inner_count, *axis),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::CumSum, got {:?}"
),
other,
))
.bt());
}
};
let layout = layouts.first();
let in_guard = read_storage(&inputs[0])?;
let mut out_guard = write_storage(&outputs[0])?;
let src_cuda = cuda_input(&in_guard)?;
let result = $baracuda_fn(src_cuda, layout, axis, outer, dim_size, inner)?;
let out_cuda = cuda_output(&mut out_guard)?;
*out_cuda = result;
Ok(())
}
};
}
pub mod cumsum {
use super::*;
use fuel_cuda_backend::baracuda::cumsum as bk;
cuda_cumsum_baracuda_wrapper!(cumsum_f32, bk::cumsum_f32);
cuda_cumsum_baracuda_wrapper!(cumsum_f64, bk::cumsum_f64);
cuda_cumsum_baracuda_wrapper!(cumsum_f16, bk::cumsum_f16);
cuda_cumsum_baracuda_wrapper!(cumsum_bf16, bk::cumsum_bf16);
}
fn decode_fill_f32(b: &[u8]) -> Result<f32> {
if b.len() != 4 {
return Err(Error::Msg(format!(
"pad_constant_f32: fill_bytes.len()={} != 4",
b.len(),
))
.bt());
}
Ok(f32::from_le_bytes([b[0], b[1], b[2], b[3]]))
}
fn decode_fill_f64(b: &[u8]) -> Result<f64> {
if b.len() != 8 {
return Err(Error::Msg(format!(
"pad_constant_f64: fill_bytes.len()={} != 8",
b.len(),
))
.bt());
}
Ok(f64::from_le_bytes([
b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
]))
}
fn decode_fill_f16(b: &[u8]) -> Result<half::f16> {
if b.len() != 2 {
return Err(Error::Msg(format!(
"pad_constant_f16: fill_bytes.len()={} != 2",
b.len(),
))
.bt());
}
Ok(half::f16::from_le_bytes([b[0], b[1]]))
}
fn decode_fill_bf16(b: &[u8]) -> Result<half::bf16> {
if b.len() != 2 {
return Err(Error::Msg(format!(
"pad_constant_bf16: fill_bytes.len()={} != 2",
b.len(),
))
.bt());
}
Ok(half::bf16::from_le_bytes([b[0], b[1]]))
}
macro_rules! cuda_pad_baracuda_wrapper {
($wrapper_name:ident, $const_fn:path, $reflect_fn:path, $replicate_fn:path, $decode_fn:path) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
_layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 1 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 1 input + 1 output, got {} + {}"
),
inputs.len(),
outputs.len(),
))
.bt());
}
let (in_shape, out_shape, padding, mode_tag, fill_bytes) = match params {
OpParams::Pad {
in_shape,
out_shape,
padding,
mode_tag,
fill_bytes,
} => (in_shape, out_shape, padding, *mode_tag, fill_bytes),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::Pad, got {:?}"
),
other,
))
.bt());
}
};
let in_guard = read_storage(&inputs[0])?;
let mut out_guard = write_storage(&outputs[0])?;
let src_cuda = cuda_input(&in_guard)?;
let result = match mode_tag {
0 => {
let value = $decode_fn(fill_bytes)?;
$const_fn(src_cuda, in_shape, out_shape, padding, value)?
}
1 => $reflect_fn(src_cuda, in_shape, out_shape, padding)?,
2 => $replicate_fn(src_cuda, in_shape, out_shape, padding)?,
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": mode_tag {} not supported \
(Constant=0, Reflect=1, Replicate=2; Circular=3 not yet)"
),
other,
))
.bt());
}
};
let out_cuda = cuda_output(&mut out_guard)?;
*out_cuda = result;
Ok(())
}
};
}
macro_rules! cuda_pad_backward_baracuda_wrapper {
($wrapper_name:ident, $bw_fn:path) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
_layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 1 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 1 input + 1 output, got {} + {}"
),
inputs.len(),
outputs.len(),
))
.bt());
}
let (in_shape, out_shape, padding, mode_tag) = match params {
OpParams::PadBackward {
in_shape,
out_shape,
padding,
mode_tag,
} => (in_shape, out_shape, padding, *mode_tag),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::PadBackward, got {:?}"
),
other,
))
.bt());
}
};
if mode_tag != 0 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": only Constant-mode backward (tag 0) supported \
on CUDA today, got mode_tag {}"
),
mode_tag,
))
.bt());
}
let in_guard = read_storage(&inputs[0])?;
let mut out_guard = write_storage(&outputs[0])?;
let dy_cuda = cuda_input(&in_guard)?;
let result = $bw_fn(dy_cuda, in_shape, out_shape, padding)?;
let dx_cuda = cuda_output(&mut out_guard)?;
*dx_cuda = result;
Ok(())
}
};
}
pub mod pad {
use super::*;
use fuel_cuda_backend::baracuda::pad as bk;
cuda_pad_baracuda_wrapper!(
pad_f32,
bk::pad_constant_f32,
bk::pad_reflect_f32,
bk::pad_replicate_f32,
super::decode_fill_f32
);
cuda_pad_baracuda_wrapper!(
pad_f64,
bk::pad_constant_f64,
bk::pad_reflect_f64,
bk::pad_replicate_f64,
super::decode_fill_f64
);
cuda_pad_baracuda_wrapper!(
pad_f16,
bk::pad_constant_f16,
bk::pad_reflect_f16,
bk::pad_replicate_f16,
super::decode_fill_f16
);
cuda_pad_baracuda_wrapper!(
pad_bf16,
bk::pad_constant_bf16,
bk::pad_reflect_bf16,
bk::pad_replicate_bf16,
super::decode_fill_bf16
);
cuda_pad_backward_baracuda_wrapper!(pad_backward_f32, bk::pad_backward_f32);
cuda_pad_backward_baracuda_wrapper!(pad_backward_f64, bk::pad_backward_f64);
cuda_pad_backward_baracuda_wrapper!(pad_backward_f16, bk::pad_backward_f16);
cuda_pad_backward_baracuda_wrapper!(pad_backward_bf16, bk::pad_backward_bf16);
}
macro_rules! cuda_affine_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path, $scalar_cast:expr $(,)?) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 1 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 1 input + 1 output, got {} + {}"
),
inputs.len(),
outputs.len(),
))
.bt());
}
let (mul_f64, add_f64) = match params {
OpParams::Affine { mul, add } => (*mul, *add),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::Affine, got {:?}"
),
other,
))
.bt());
}
};
let cast = $scalar_cast;
let mul = cast(mul_f64);
let add = cast(add_f64);
let layout = layouts.first();
let in_guard = read_storage(&inputs[0])?;
let mut out_guard = write_storage(&outputs[0])?;
let src_cuda = cuda_input(&in_guard)?;
let out_cuda = cuda_output(&mut out_guard)?;
$baracuda_fn(src_cuda, layout, mul, add, out_cuda)
}
};
}
pub mod affine {
use super::*;
use fuel_cuda_backend::baracuda::affine as bk;
cuda_affine_baracuda_wrapper!(affine_f32, bk::affine_f32_into, |v: f64| v as f32);
cuda_affine_baracuda_wrapper!(affine_f64, bk::affine_f64_into, |v: f64| v);
cuda_affine_baracuda_wrapper!(affine_f16, bk::affine_f16_into, |v: f64| v as f32);
cuda_affine_baracuda_wrapper!(affine_bf16, bk::affine_bf16_into, |v: f64| v as f32);
cuda_affine_baracuda_wrapper!(affine_i32, bk::affine_i32_into, |v: f64| v as i32);
cuda_affine_baracuda_wrapper!(affine_i64, bk::affine_i64_into, |v: f64| v as i64);
cuda_affine_baracuda_wrapper!(affine_u8, bk::affine_u8_into, |v: f64| v as u8);
macro_rules! cuda_affine_inplace_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path, $scalar_cast:expr $(,)?) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
_layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if !inputs.is_empty() || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(stringify!($wrapper_name),
": expected 0 inputs + 1 output (target adopted by executor), got {} + {}"),
inputs.len(), outputs.len(),
)).bt());
}
let (mul_f64, add_f64) = match params {
OpParams::Affine { mul, add } => (*mul, *add),
other => {
return Err(Error::Msg(format!(
concat!(stringify!($wrapper_name), ": expected OpParams::Affine, got {:?}"),
other,
)).bt());
}
};
let cast = $scalar_cast;
let mul = cast(mul_f64);
let add = cast(add_f64);
let mut out_guard = write_storage(&outputs[0])?;
let out_cuda = cuda_output(&mut out_guard)?;
$baracuda_fn(out_cuda, mul, add)
}
};
}
cuda_affine_inplace_baracuda_wrapper!(affine_inplace_f32, bk::affine_inplace_f32, |v: f64| v
as f32);
cuda_affine_inplace_baracuda_wrapper!(affine_inplace_f64, bk::affine_inplace_f64, |v: f64| v);
cuda_affine_inplace_baracuda_wrapper!(
affine_inplace_bf16,
bk::affine_inplace_bf16,
|v: f64| v as f32
);
cuda_affine_inplace_baracuda_wrapper!(affine_inplace_f16, bk::affine_inplace_f16, |v: f64| v
as f32);
}
pub mod cast {
use super::*;
use fuel_cuda_backend::baracuda::cast as bk;
pub fn cast_baracuda_wrapper(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
_layouts: &[Layout],
_params: &OpParams,
) -> Result<()> {
if inputs.len() != 1 || outputs.len() != 1 {
return Err(Error::Msg(format!(
"cast_baracuda_wrapper: expected 1 input + 1 output, got {} + {}",
inputs.len(),
outputs.len(),
))
.bt());
}
let in_guard = read_storage(&inputs[0])?;
let mut out_guard = write_storage(&outputs[0])?;
let src_dtype = in_guard.dtype;
let dst_dtype = out_guard.dtype;
let src_cuda = cuda_input(&in_guard)?;
let result = bk::dispatch(src_cuda, src_dtype, dst_dtype)?;
let out_cuda = cuda_output(&mut out_guard)?;
*out_cuda = result;
Ok(())
}
}
macro_rules! cuda_softmax_last_dim_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 1 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 1 input + 1 output, got {} + {}",
),
inputs.len(),
outputs.len(),
))
.bt());
}
match params {
OpParams::SoftmaxLastDim { .. } | OpParams::LogSoftmaxLastDim { .. } => {}
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::SoftmaxLastDim/LogSoftmaxLastDim, got {:?}",
),
other,
))
.bt());
}
}
let layout = layouts.first().ok_or_else(|| {
Error::Msg(
concat!(
stringify!($wrapper_name),
": SoftmaxLastDim requires an input layout (call with layouts[0])",
)
.to_string(),
)
.bt()
})?;
let in_guard = read_storage(&inputs[0])?;
let mut out_guard = write_storage(&outputs[0])?;
let src_cuda = cuda_input(&in_guard)?;
let out_cuda = cuda_output(&mut out_guard)?;
$baracuda_fn(src_cuda, layout, out_cuda)
}
};
}
pub mod softmax {
use super::*;
use fuel_cuda_backend::baracuda::softmax as bk;
cuda_softmax_last_dim_baracuda_wrapper!(softmax_f32, bk::softmax_last_dim_f32_into);
cuda_softmax_last_dim_baracuda_wrapper!(softmax_f16, bk::softmax_last_dim_f16_into);
cuda_softmax_last_dim_baracuda_wrapper!(softmax_bf16, bk::softmax_last_dim_bf16_into);
cuda_softmax_last_dim_baracuda_wrapper!(softmax_f64, bk::softmax_last_dim_f64_into);
cuda_softmax_last_dim_baracuda_wrapper!(log_softmax_f32, bk::log_softmax_last_dim_f32_into);
cuda_softmax_last_dim_baracuda_wrapper!(log_softmax_f16, bk::log_softmax_last_dim_f16_into);
cuda_softmax_last_dim_baracuda_wrapper!(log_softmax_bf16, bk::log_softmax_last_dim_bf16_into);
cuda_softmax_last_dim_baracuda_wrapper!(log_softmax_f64, bk::log_softmax_last_dim_f64_into);
}
pub mod attention {
use super::*;
use fuel_cuda_backend::baracuda::attention as bk;
cuda_rope_baracuda_wrapper!(rope_f32, bk::rope_f32_into);
cuda_rope_baracuda_wrapper!(rope_f16, bk::rope_f16_into);
cuda_rope_baracuda_wrapper!(rope_bf16, bk::rope_bf16_into);
cuda_rope_baracuda_wrapper!(rope_f64, bk::rope_f64_into);
}
macro_rules! cuda_flash_decoding_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path $(,)?) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 3 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 3 inputs (q, k, v) + 1 output, got {} + {}",
),
inputs.len(),
outputs.len(),
))
.bt());
}
let (b, hq, hkv, sq, sk, d, k_len, scale) = match params {
OpParams::FlashAttn {
b,
hq,
hkv,
sq,
sk,
d,
k_len,
softmax_scale,
causal: _,
window_size_left,
window_size_right,
softcap,
} => {
if window_size_left.is_some()
|| window_size_right.is_some()
|| softcap.is_some()
{
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": window/softcap not supported by flash_decoding \
(window_left={:?}, window_right={:?}, softcap={:?}); \
the ranker must route these to the decomposed base map",
),
window_size_left, window_size_right, softcap,
))
.bt());
}
(*b, *hq, *hkv, *sq, *sk, *d, *k_len, *softmax_scale)
}
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::FlashAttn, got {:?}",
),
other,
))
.bt());
}
};
let q_layout = layouts.first();
let k_layout = layouts.get(1);
let v_layout = layouts.get(2);
let q_guard = read_storage(&inputs[0])?;
let k_guard = read_storage(&inputs[1])?;
let v_guard = read_storage(&inputs[2])?;
let mut out_guard = write_storage(&outputs[0])?;
let q_cuda = cuda_input(&q_guard)?;
let k_cuda = cuda_input(&k_guard)?;
let v_cuda = cuda_input(&v_guard)?;
let result = $baracuda_fn(
q_cuda, k_cuda, v_cuda, q_layout, k_layout, v_layout, b, hq, hkv, sq, sk, d, k_len,
scale,
)?;
let out_cuda = cuda_output(&mut out_guard)?;
*out_cuda = result;
Ok(())
}
};
}
pub mod flash_decoding {
use super::*;
use fuel_cuda_backend::baracuda::attention as bk;
cuda_flash_decoding_baracuda_wrapper!(flash_decoding_f16, bk::flash_decoding_f16);
cuda_flash_decoding_baracuda_wrapper!(flash_decoding_bf16, bk::flash_decoding_bf16);
}
macro_rules! cuda_norm_last_dim_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 1 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 1 input + 1 output, got {} + {}",
),
inputs.len(),
outputs.len(),
))
.bt());
}
let eps = match params {
OpParams::NormLastDim { eps, .. } => *eps,
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::NormLastDim, got {:?}",
),
other,
))
.bt());
}
};
let layout = layouts.first().ok_or_else(|| {
Error::Msg(
concat!(
stringify!($wrapper_name),
": NormLastDim requires an input layout (call with layouts[0])",
)
.to_string(),
)
.bt()
})?;
let in_guard = read_storage(&inputs[0])?;
let mut out_guard = write_storage(&outputs[0])?;
let src_cuda = cuda_input(&in_guard)?;
let result = $baracuda_fn(src_cuda, layout, eps)?;
let out_cuda = cuda_output(&mut out_guard)?;
*out_cuda = result;
Ok(())
}
};
}
macro_rules! cuda_rms_norm_into_baracuda_wrapper {
($wrapper_name:ident, $baracuda_into_fn:path) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 1 || outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected 1 input + 1 output, got {} + {}",
),
inputs.len(),
outputs.len(),
))
.bt());
}
let eps = match params {
OpParams::NormLastDim { eps, .. } => *eps,
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::NormLastDim, got {:?}",
),
other,
))
.bt());
}
};
let layout = layouts.first().ok_or_else(|| {
Error::Msg(
concat!(
stringify!($wrapper_name),
": NormLastDim requires an input layout (call with layouts[0])",
)
.to_string(),
)
.bt()
})?;
let in_guard = read_storage(&inputs[0])?;
let mut out_guard = write_storage(&outputs[0])?;
let src_cuda = cuda_input(&in_guard)?;
let out_cuda = cuda_output(&mut out_guard)?;
$baracuda_into_fn(src_cuda, layout, eps, out_cuda)
}
};
}
pub mod norm {
use super::*;
use fuel_cuda_backend::baracuda::norm as bk;
cuda_rms_norm_into_baracuda_wrapper!(rms_f32, bk::rms_norm_last_dim_f32_into);
cuda_rms_norm_into_baracuda_wrapper!(rms_f16, bk::rms_norm_last_dim_f16_into);
cuda_rms_norm_into_baracuda_wrapper!(rms_bf16, bk::rms_norm_last_dim_bf16_into);
cuda_rms_norm_into_baracuda_wrapper!(rms_f64, bk::rms_norm_last_dim_f64_into);
cuda_norm_last_dim_baracuda_wrapper!(layer_f32, bk::layer_norm_last_dim_f32);
cuda_norm_last_dim_baracuda_wrapper!(layer_f16, bk::layer_norm_last_dim_f16);
cuda_norm_last_dim_baracuda_wrapper!(layer_bf16, bk::layer_norm_last_dim_bf16);
cuda_norm_last_dim_baracuda_wrapper!(layer_f64, bk::layer_norm_last_dim_f64);
}
macro_rules! cuda_reduce_baracuda_wrapper {
($wrapper_name:ident, $baracuda_fn:path) => {
pub fn $wrapper_name(
inputs: &[Arc<RwLock<Storage>>],
outputs: &mut [Arc<RwLock<Storage>>],
layouts: &[Layout],
params: &OpParams,
) -> Result<()> {
if inputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(stringify!($wrapper_name), ": expected 1 input, got {}"),
inputs.len(),
))
.bt());
}
if outputs.len() != 1 {
return Err(Error::Msg(format!(
concat!(stringify!($wrapper_name), ": expected 1 output, got {}"),
outputs.len(),
))
.bt());
}
let (dims, keepdim) = match params {
OpParams::Reduce { dims, keepdim } => (dims.clone(), *keepdim),
other => {
return Err(Error::Msg(format!(
concat!(
stringify!($wrapper_name),
": expected OpParams::Reduce, got {:?}",
),
other,
))
.bt());
}
};
let layout = layouts.first().ok_or_else(|| {
Error::Msg(format!(concat!(
stringify!($wrapper_name),
": reduce requires an input layout (call with layouts[0])",
),))
.bt()
})?;
let in_guard = read_storage(&inputs[0])?;
let mut out_guard = write_storage(&outputs[0])?;
let src_cuda = cuda_input(&in_guard)?;
let result = $baracuda_fn(src_cuda, layout, &dims, keepdim)?;
let out_cuda = cuda_output(&mut out_guard)?;
*out_cuda = result;
Ok(())
}
};
}
pub mod reduce {
use super::*;
use fuel_cuda_backend::baracuda::reduce as bk;
cuda_reduce_baracuda_wrapper!(sum_f32, bk::reduce_sum_f32);
cuda_reduce_baracuda_wrapper!(max_f32, bk::reduce_max_f32);
cuda_reduce_baracuda_wrapper!(min_f32, bk::reduce_min_f32);
cuda_reduce_baracuda_wrapper!(mean_f32, bk::reduce_mean_f32);
cuda_reduce_baracuda_wrapper!(sum_f16, bk::reduce_sum_f16);
cuda_reduce_baracuda_wrapper!(max_f16, bk::reduce_max_f16);
cuda_reduce_baracuda_wrapper!(min_f16, bk::reduce_min_f16);
cuda_reduce_baracuda_wrapper!(mean_f16, bk::reduce_mean_f16);
cuda_reduce_baracuda_wrapper!(sum_bf16, bk::reduce_sum_bf16);
cuda_reduce_baracuda_wrapper!(max_bf16, bk::reduce_max_bf16);
cuda_reduce_baracuda_wrapper!(min_bf16, bk::reduce_min_bf16);
cuda_reduce_baracuda_wrapper!(mean_bf16, bk::reduce_mean_bf16);
cuda_reduce_baracuda_wrapper!(sum_f64, bk::reduce_sum_f64);
cuda_reduce_baracuda_wrapper!(max_f64, bk::reduce_max_f64);
cuda_reduce_baracuda_wrapper!(min_f64, bk::reduce_min_f64);
cuda_reduce_baracuda_wrapper!(mean_f64, bk::reduce_mean_f64);
}
pub mod binary {
use super::*;
use fuel_cuda_backend::baracuda::binary as bk;
cuda_binary_baracuda_wrapper!(eq_f32_u8, bk::binary_cmp_eq_f32_into);
cuda_binary_baracuda_wrapper!(eq_f64_u8, bk::binary_cmp_eq_f64_into);
cuda_binary_baracuda_wrapper!(eq_f16_u8, bk::binary_cmp_eq_f16_into);
cuda_binary_baracuda_wrapper!(eq_bf16_u8, bk::binary_cmp_eq_bf16_into);
cuda_binary_baracuda_wrapper!(ne_f32_u8, bk::binary_cmp_ne_f32_into);
cuda_binary_baracuda_wrapper!(ne_f64_u8, bk::binary_cmp_ne_f64_into);
cuda_binary_baracuda_wrapper!(ne_f16_u8, bk::binary_cmp_ne_f16_into);
cuda_binary_baracuda_wrapper!(ne_bf16_u8, bk::binary_cmp_ne_bf16_into);
cuda_binary_baracuda_wrapper!(lt_f32_u8, bk::binary_cmp_lt_f32_into);
cuda_binary_baracuda_wrapper!(lt_f64_u8, bk::binary_cmp_lt_f64_into);
cuda_binary_baracuda_wrapper!(lt_f16_u8, bk::binary_cmp_lt_f16_into);
cuda_binary_baracuda_wrapper!(lt_bf16_u8, bk::binary_cmp_lt_bf16_into);
cuda_binary_baracuda_wrapper!(le_f32_u8, bk::binary_cmp_le_f32_into);
cuda_binary_baracuda_wrapper!(le_f64_u8, bk::binary_cmp_le_f64_into);
cuda_binary_baracuda_wrapper!(le_f16_u8, bk::binary_cmp_le_f16_into);
cuda_binary_baracuda_wrapper!(le_bf16_u8, bk::binary_cmp_le_bf16_into);
cuda_binary_baracuda_wrapper!(gt_f32_u8, bk::binary_cmp_gt_f32_into);
cuda_binary_baracuda_wrapper!(gt_f64_u8, bk::binary_cmp_gt_f64_into);
cuda_binary_baracuda_wrapper!(gt_f16_u8, bk::binary_cmp_gt_f16_into);
cuda_binary_baracuda_wrapper!(gt_bf16_u8, bk::binary_cmp_gt_bf16_into);
cuda_binary_baracuda_wrapper!(ge_f32_u8, bk::binary_cmp_ge_f32_into);
cuda_binary_baracuda_wrapper!(ge_f64_u8, bk::binary_cmp_ge_f64_into);
cuda_binary_baracuda_wrapper!(ge_f16_u8, bk::binary_cmp_ge_f16_into);
cuda_binary_baracuda_wrapper!(ge_bf16_u8, bk::binary_cmp_ge_bf16_into);
cuda_binary_baracuda_wrapper!(add_f32, bk::binary_add_f32_into);
cuda_binary_baracuda_wrapper!(sub_f32, bk::binary_sub_f32_into);
cuda_binary_baracuda_wrapper!(mul_f32, bk::binary_mul_f32_into);
cuda_binary_baracuda_wrapper!(div_f32, bk::binary_div_f32_into);
cuda_binary_baracuda_wrapper!(maximum_f32, bk::binary_maximum_f32_into);
cuda_binary_baracuda_wrapper!(minimum_f32, bk::binary_minimum_f32_into);
cuda_binary_baracuda_wrapper!(pow_f32, bk::binary_pow_f32_into);
cuda_binary_baracuda_wrapper!(rem_f32, bk::binary_rem_f32_into);
cuda_binary_baracuda_wrapper!(add_f16, bk::binary_add_f16_into);
cuda_binary_baracuda_wrapper!(sub_f16, bk::binary_sub_f16_into);
cuda_binary_baracuda_wrapper!(mul_f16, bk::binary_mul_f16_into);
cuda_binary_baracuda_wrapper!(div_f16, bk::binary_div_f16_into);
cuda_binary_baracuda_wrapper!(maximum_f16, bk::binary_maximum_f16_into);
cuda_binary_baracuda_wrapper!(minimum_f16, bk::binary_minimum_f16_into);
cuda_binary_baracuda_wrapper!(pow_f16, bk::binary_pow_f16_into);
cuda_binary_baracuda_wrapper!(rem_f16, bk::binary_rem_f16_into);
cuda_binary_baracuda_wrapper!(add_bf16, bk::binary_add_bf16_into);
cuda_binary_baracuda_wrapper!(sub_bf16, bk::binary_sub_bf16_into);
cuda_binary_baracuda_wrapper!(mul_bf16, bk::binary_mul_bf16_into);
cuda_binary_baracuda_wrapper!(div_bf16, bk::binary_div_bf16_into);
cuda_binary_baracuda_wrapper!(maximum_bf16, bk::binary_maximum_bf16_into);
cuda_binary_baracuda_wrapper!(minimum_bf16, bk::binary_minimum_bf16_into);
cuda_binary_baracuda_wrapper!(pow_bf16, bk::binary_pow_bf16_into);
cuda_binary_baracuda_wrapper!(rem_bf16, bk::binary_rem_bf16_into);
cuda_binary_baracuda_wrapper!(add_f64, bk::binary_add_f64_into);
cuda_binary_baracuda_wrapper!(sub_f64, bk::binary_sub_f64_into);
cuda_binary_baracuda_wrapper!(mul_f64, bk::binary_mul_f64_into);
cuda_binary_baracuda_wrapper!(div_f64, bk::binary_div_f64_into);
cuda_binary_baracuda_wrapper!(maximum_f64, bk::binary_maximum_f64_into);
cuda_binary_baracuda_wrapper!(minimum_f64, bk::binary_minimum_f64_into);
cuda_binary_baracuda_wrapper!(pow_f64, bk::binary_pow_f64_into);
cuda_binary_baracuda_wrapper!(rem_f64, bk::binary_rem_f64_into);
}
pub mod unary {
use super::*;
use fuel_cuda_backend::baracuda::elementwise as bk;
cuda_unary_baracuda_wrapper!(neg_f32, bk::unary_neg_f32_into);
cuda_unary_baracuda_wrapper!(abs_f32, bk::unary_abs_f32_into);
cuda_unary_baracuda_wrapper!(sign_f32, bk::unary_sign_f32_into);
cuda_unary_baracuda_wrapper!(sqr_f32, bk::unary_sqr_f32_into);
cuda_unary_baracuda_wrapper!(sqrt_f32, bk::unary_sqrt_f32_into);
cuda_unary_baracuda_wrapper!(rsqrt_f32, bk::unary_rsqrt_f32_into);
cuda_unary_baracuda_wrapper!(recip_f32, bk::unary_recip_f32_into);
cuda_unary_baracuda_wrapper!(exp_f32, bk::unary_exp_f32_into);
cuda_unary_baracuda_wrapper!(log_f32, bk::unary_log_f32_into);
cuda_unary_baracuda_wrapper!(sin_f32, bk::unary_sin_f32_into);
cuda_unary_baracuda_wrapper!(cos_f32, bk::unary_cos_f32_into);
cuda_unary_baracuda_wrapper!(tanh_f32, bk::unary_tanh_f32_into);
cuda_unary_baracuda_wrapper!(relu_f32, bk::unary_relu_f32_into);
cuda_unary_baracuda_wrapper!(gelu_f32, bk::unary_gelu_f32_into);
cuda_unary_baracuda_wrapper!(gelu_tanh_f32, bk::unary_gelu_tanh_f32_into);
cuda_unary_baracuda_wrapper!(step_f32, bk::unary_step_f32_into);
cuda_unary_baracuda_wrapper!(silu_f32, bk::unary_silu_f32_into);
cuda_unary_baracuda_wrapper!(sigmoid_f32, bk::unary_sigmoid_f32_into);
cuda_unary_baracuda_wrapper!(floor_f32, bk::unary_floor_f32_into);
cuda_unary_baracuda_wrapper!(ceil_f32, bk::unary_ceil_f32_into);
cuda_unary_baracuda_wrapper!(round_f32, bk::unary_round_f32_into);
cuda_unary_baracuda_wrapper!(erf_f32, bk::unary_erf_f32_into);
cuda_unary_inplace_baracuda_wrapper!(relu_inplace_f32, bk::unary_inplace_relu_f32);
cuda_unary_inplace_baracuda_wrapper!(silu_inplace_f32, bk::unary_inplace_silu_f32);
cuda_unary_inplace_baracuda_wrapper!(gelu_inplace_f32, bk::unary_inplace_gelu_f32);
cuda_unary_inplace_baracuda_wrapper!(tanh_inplace_f32, bk::unary_inplace_tanh_f32);
cuda_unary_inplace_baracuda_wrapper!(sigmoid_inplace_f32, bk::unary_inplace_sigmoid_f32);
cuda_unary_inplace_baracuda_wrapper!(relu_inplace_f64, bk::unary_inplace_relu_f64);
cuda_unary_inplace_baracuda_wrapper!(silu_inplace_f64, bk::unary_inplace_silu_f64);
cuda_unary_inplace_baracuda_wrapper!(gelu_inplace_f64, bk::unary_inplace_gelu_f64);
cuda_unary_inplace_baracuda_wrapper!(tanh_inplace_f64, bk::unary_inplace_tanh_f64);
cuda_unary_inplace_baracuda_wrapper!(sigmoid_inplace_f64, bk::unary_inplace_sigmoid_f64);
cuda_unary_inplace_baracuda_wrapper!(relu_inplace_bf16, bk::unary_inplace_relu_bf16);
cuda_unary_inplace_baracuda_wrapper!(silu_inplace_bf16, bk::unary_inplace_silu_bf16);
cuda_unary_inplace_baracuda_wrapper!(gelu_inplace_bf16, bk::unary_inplace_gelu_bf16);
cuda_unary_inplace_baracuda_wrapper!(tanh_inplace_bf16, bk::unary_inplace_tanh_bf16);
cuda_unary_inplace_baracuda_wrapper!(sigmoid_inplace_bf16, bk::unary_inplace_sigmoid_bf16);
cuda_unary_inplace_baracuda_wrapper!(relu_inplace_f16, bk::unary_inplace_relu_f16);
cuda_unary_inplace_baracuda_wrapper!(silu_inplace_f16, bk::unary_inplace_silu_f16);
cuda_unary_inplace_baracuda_wrapper!(gelu_inplace_f16, bk::unary_inplace_gelu_f16);
cuda_unary_inplace_baracuda_wrapper!(tanh_inplace_f16, bk::unary_inplace_tanh_f16);
cuda_unary_inplace_baracuda_wrapper!(sigmoid_inplace_f16, bk::unary_inplace_sigmoid_f16);
cuda_unary_inplace_baracuda_wrapper!(neg_inplace_f32, bk::unary_inplace_neg_f32);
cuda_unary_inplace_baracuda_wrapper!(neg_inplace_f64, bk::unary_inplace_neg_f64);
cuda_unary_inplace_baracuda_wrapper!(neg_inplace_bf16, bk::unary_inplace_neg_bf16);
cuda_unary_inplace_baracuda_wrapper!(neg_inplace_f16, bk::unary_inplace_neg_f16);
cuda_unary_inplace_baracuda_wrapper!(abs_inplace_f32, bk::unary_inplace_abs_f32);
cuda_unary_inplace_baracuda_wrapper!(abs_inplace_f64, bk::unary_inplace_abs_f64);
cuda_unary_inplace_baracuda_wrapper!(abs_inplace_bf16, bk::unary_inplace_abs_bf16);
cuda_unary_inplace_baracuda_wrapper!(abs_inplace_f16, bk::unary_inplace_abs_f16);
cuda_unary_inplace_baracuda_wrapper!(sqr_inplace_f32, bk::unary_inplace_sqr_f32);
cuda_unary_inplace_baracuda_wrapper!(sqr_inplace_f64, bk::unary_inplace_sqr_f64);
cuda_unary_inplace_baracuda_wrapper!(sqr_inplace_bf16, bk::unary_inplace_sqr_bf16);
cuda_unary_inplace_baracuda_wrapper!(sqr_inplace_f16, bk::unary_inplace_sqr_f16);
cuda_unary_inplace_baracuda_wrapper!(sqrt_inplace_f32, bk::unary_inplace_sqrt_f32);
cuda_unary_inplace_baracuda_wrapper!(sqrt_inplace_f64, bk::unary_inplace_sqrt_f64);
cuda_unary_inplace_baracuda_wrapper!(sqrt_inplace_bf16, bk::unary_inplace_sqrt_bf16);
cuda_unary_inplace_baracuda_wrapper!(sqrt_inplace_f16, bk::unary_inplace_sqrt_f16);
cuda_unary_inplace_baracuda_wrapper!(rsqrt_inplace_f32, bk::unary_inplace_rsqrt_f32);
cuda_unary_inplace_baracuda_wrapper!(rsqrt_inplace_f64, bk::unary_inplace_rsqrt_f64);
cuda_unary_inplace_baracuda_wrapper!(rsqrt_inplace_bf16, bk::unary_inplace_rsqrt_bf16);
cuda_unary_inplace_baracuda_wrapper!(rsqrt_inplace_f16, bk::unary_inplace_rsqrt_f16);
cuda_unary_inplace_baracuda_wrapper!(recip_inplace_f32, bk::unary_inplace_recip_f32);
cuda_unary_inplace_baracuda_wrapper!(recip_inplace_f64, bk::unary_inplace_recip_f64);
cuda_unary_inplace_baracuda_wrapper!(recip_inplace_bf16, bk::unary_inplace_recip_bf16);
cuda_unary_inplace_baracuda_wrapper!(recip_inplace_f16, bk::unary_inplace_recip_f16);
cuda_unary_inplace_baracuda_wrapper!(exp_inplace_f32, bk::unary_inplace_exp_f32);
cuda_unary_inplace_baracuda_wrapper!(exp_inplace_f64, bk::unary_inplace_exp_f64);
cuda_unary_inplace_baracuda_wrapper!(exp_inplace_bf16, bk::unary_inplace_exp_bf16);
cuda_unary_inplace_baracuda_wrapper!(exp_inplace_f16, bk::unary_inplace_exp_f16);
cuda_unary_inplace_baracuda_wrapper!(log_inplace_f32, bk::unary_inplace_log_f32);
cuda_unary_inplace_baracuda_wrapper!(log_inplace_f64, bk::unary_inplace_log_f64);
cuda_unary_inplace_baracuda_wrapper!(log_inplace_bf16, bk::unary_inplace_log_bf16);
cuda_unary_inplace_baracuda_wrapper!(log_inplace_f16, bk::unary_inplace_log_f16);
cuda_unary_inplace_baracuda_wrapper!(sin_inplace_f32, bk::unary_inplace_sin_f32);
cuda_unary_inplace_baracuda_wrapper!(sin_inplace_f64, bk::unary_inplace_sin_f64);
cuda_unary_inplace_baracuda_wrapper!(sin_inplace_bf16, bk::unary_inplace_sin_bf16);
cuda_unary_inplace_baracuda_wrapper!(sin_inplace_f16, bk::unary_inplace_sin_f16);
cuda_unary_inplace_baracuda_wrapper!(cos_inplace_f32, bk::unary_inplace_cos_f32);
cuda_unary_inplace_baracuda_wrapper!(cos_inplace_f64, bk::unary_inplace_cos_f64);
cuda_unary_inplace_baracuda_wrapper!(cos_inplace_bf16, bk::unary_inplace_cos_bf16);
cuda_unary_inplace_baracuda_wrapper!(cos_inplace_f16, bk::unary_inplace_cos_f16);
cuda_unary_inplace_baracuda_wrapper!(sign_inplace_f32, bk::unary_inplace_sign_f32);
cuda_unary_inplace_baracuda_wrapper!(sign_inplace_f64, bk::unary_inplace_sign_f64);
cuda_unary_inplace_baracuda_wrapper!(sign_inplace_bf16, bk::unary_inplace_sign_bf16);
cuda_unary_inplace_baracuda_wrapper!(sign_inplace_f16, bk::unary_inplace_sign_f16);
cuda_unary_inplace_baracuda_wrapper!(floor_inplace_f32, bk::unary_inplace_floor_f32);
cuda_unary_inplace_baracuda_wrapper!(floor_inplace_f64, bk::unary_inplace_floor_f64);
cuda_unary_inplace_baracuda_wrapper!(floor_inplace_bf16, bk::unary_inplace_floor_bf16);
cuda_unary_inplace_baracuda_wrapper!(floor_inplace_f16, bk::unary_inplace_floor_f16);
cuda_unary_inplace_baracuda_wrapper!(ceil_inplace_f32, bk::unary_inplace_ceil_f32);
cuda_unary_inplace_baracuda_wrapper!(ceil_inplace_f64, bk::unary_inplace_ceil_f64);
cuda_unary_inplace_baracuda_wrapper!(ceil_inplace_bf16, bk::unary_inplace_ceil_bf16);
cuda_unary_inplace_baracuda_wrapper!(ceil_inplace_f16, bk::unary_inplace_ceil_f16);
cuda_unary_inplace_baracuda_wrapper!(round_inplace_f32, bk::unary_inplace_round_f32);
cuda_unary_inplace_baracuda_wrapper!(round_inplace_f64, bk::unary_inplace_round_f64);
cuda_unary_inplace_baracuda_wrapper!(round_inplace_bf16, bk::unary_inplace_round_bf16);
cuda_unary_inplace_baracuda_wrapper!(round_inplace_f16, bk::unary_inplace_round_f16);
cuda_unary_inplace_baracuda_wrapper!(erf_inplace_f32, bk::unary_inplace_erf_f32);
cuda_unary_inplace_baracuda_wrapper!(erf_inplace_f64, bk::unary_inplace_erf_f64);
cuda_unary_inplace_baracuda_wrapper!(erf_inplace_bf16, bk::unary_inplace_erf_bf16);
cuda_unary_inplace_baracuda_wrapper!(erf_inplace_f16, bk::unary_inplace_erf_f16);
cuda_unary_inplace_baracuda_wrapper!(gelu_erf_inplace_f32, bk::unary_inplace_gelu_erf_f32);
cuda_unary_inplace_baracuda_wrapper!(gelu_erf_inplace_f64, bk::unary_inplace_gelu_erf_f64);
cuda_unary_inplace_baracuda_wrapper!(gelu_erf_inplace_bf16, bk::unary_inplace_gelu_erf_bf16);
cuda_unary_inplace_baracuda_wrapper!(gelu_erf_inplace_f16, bk::unary_inplace_gelu_erf_f16);
cuda_unary_baracuda_wrapper!(neg_f16, bk::unary_neg_f16_into);
cuda_unary_baracuda_wrapper!(abs_f16, bk::unary_abs_f16_into);
cuda_unary_baracuda_wrapper!(sqr_f16, bk::unary_sqr_f16_into);
cuda_unary_baracuda_wrapper!(sqrt_f16, bk::unary_sqrt_f16_into);
cuda_unary_baracuda_wrapper!(recip_f16, bk::unary_recip_f16_into);
cuda_unary_baracuda_wrapper!(exp_f16, bk::unary_exp_f16_into);
cuda_unary_baracuda_wrapper!(log_f16, bk::unary_log_f16_into);
cuda_unary_baracuda_wrapper!(sin_f16, bk::unary_sin_f16_into);
cuda_unary_baracuda_wrapper!(cos_f16, bk::unary_cos_f16_into);
cuda_unary_baracuda_wrapper!(tanh_f16, bk::unary_tanh_f16_into);
cuda_unary_baracuda_wrapper!(relu_f16, bk::unary_relu_f16_into);
cuda_unary_baracuda_wrapper!(gelu_f16, bk::unary_gelu_f16_into);
cuda_unary_baracuda_wrapper!(gelu_tanh_f16, bk::unary_gelu_tanh_f16_into);
cuda_unary_baracuda_wrapper!(step_f16, bk::unary_step_f16_into);
cuda_unary_baracuda_wrapper!(silu_f16, bk::unary_silu_f16_into);
cuda_unary_baracuda_wrapper!(sigmoid_f16, bk::unary_sigmoid_f16_into);
cuda_unary_baracuda_wrapper!(rsqrt_f16, bk::unary_rsqrt_f16_into);
cuda_unary_baracuda_wrapper!(floor_f16, bk::unary_floor_f16_into);
cuda_unary_baracuda_wrapper!(ceil_f16, bk::unary_ceil_f16_into);
cuda_unary_baracuda_wrapper!(round_f16, bk::unary_round_f16_into);
cuda_unary_baracuda_wrapper!(erf_f16, bk::unary_erf_f16_into);
cuda_unary_baracuda_wrapper!(neg_bf16, bk::unary_neg_bf16_into);
cuda_unary_baracuda_wrapper!(abs_bf16, bk::unary_abs_bf16_into);
cuda_unary_baracuda_wrapper!(sqr_bf16, bk::unary_sqr_bf16_into);
cuda_unary_baracuda_wrapper!(sqrt_bf16, bk::unary_sqrt_bf16_into);
cuda_unary_baracuda_wrapper!(recip_bf16, bk::unary_recip_bf16_into);
cuda_unary_baracuda_wrapper!(exp_bf16, bk::unary_exp_bf16_into);
cuda_unary_baracuda_wrapper!(log_bf16, bk::unary_log_bf16_into);
cuda_unary_baracuda_wrapper!(sin_bf16, bk::unary_sin_bf16_into);
cuda_unary_baracuda_wrapper!(cos_bf16, bk::unary_cos_bf16_into);
cuda_unary_baracuda_wrapper!(tanh_bf16, bk::unary_tanh_bf16_into);
cuda_unary_baracuda_wrapper!(relu_bf16, bk::unary_relu_bf16_into);
cuda_unary_baracuda_wrapper!(gelu_bf16, bk::unary_gelu_bf16_into);
cuda_unary_baracuda_wrapper!(gelu_tanh_bf16, bk::unary_gelu_tanh_bf16_into);
cuda_unary_baracuda_wrapper!(step_bf16, bk::unary_step_bf16_into);
cuda_unary_baracuda_wrapper!(silu_bf16, bk::unary_silu_bf16_into);
cuda_unary_baracuda_wrapper!(sigmoid_bf16, bk::unary_sigmoid_bf16_into);
cuda_unary_baracuda_wrapper!(rsqrt_bf16, bk::unary_rsqrt_bf16_into);
cuda_unary_baracuda_wrapper!(floor_bf16, bk::unary_floor_bf16_into);
cuda_unary_baracuda_wrapper!(ceil_bf16, bk::unary_ceil_bf16_into);
cuda_unary_baracuda_wrapper!(round_bf16, bk::unary_round_bf16_into);
cuda_unary_baracuda_wrapper!(erf_bf16, bk::unary_erf_bf16_into);
cuda_unary_baracuda_wrapper!(neg_f64, bk::unary_neg_f64_into);
cuda_unary_baracuda_wrapper!(abs_f64, bk::unary_abs_f64_into);
cuda_unary_baracuda_wrapper!(sqr_f64, bk::unary_sqr_f64_into);
cuda_unary_baracuda_wrapper!(sqrt_f64, bk::unary_sqrt_f64_into);
cuda_unary_baracuda_wrapper!(recip_f64, bk::unary_recip_f64_into);
cuda_unary_baracuda_wrapper!(exp_f64, bk::unary_exp_f64_into);
cuda_unary_baracuda_wrapper!(log_f64, bk::unary_log_f64_into);
cuda_unary_baracuda_wrapper!(sin_f64, bk::unary_sin_f64_into);
cuda_unary_baracuda_wrapper!(cos_f64, bk::unary_cos_f64_into);
cuda_unary_baracuda_wrapper!(tanh_f64, bk::unary_tanh_f64_into);
cuda_unary_baracuda_wrapper!(relu_f64, bk::unary_relu_f64_into);
cuda_unary_baracuda_wrapper!(gelu_f64, bk::unary_gelu_f64_into);
cuda_unary_baracuda_wrapper!(gelu_tanh_f64, bk::unary_gelu_tanh_f64_into);
cuda_unary_baracuda_wrapper!(step_f64, bk::unary_step_f64_into);
cuda_unary_baracuda_wrapper!(silu_f64, bk::unary_silu_f64_into);
cuda_unary_baracuda_wrapper!(sigmoid_f64, bk::unary_sigmoid_f64_into);
cuda_unary_baracuda_wrapper!(rsqrt_f64, bk::unary_rsqrt_f64_into);
cuda_unary_baracuda_wrapper!(floor_f64, bk::unary_floor_f64_into);
cuda_unary_baracuda_wrapper!(ceil_f64, bk::unary_ceil_f64_into);
cuda_unary_baracuda_wrapper!(round_f64, bk::unary_round_f64_into);
cuda_unary_baracuda_wrapper!(erf_f64, bk::unary_erf_f64_into);
}
const CUDA_CAST_CONTRACT: &str = include_str!("../../docs/kernel-contracts/cuda/cast.fkc.md");
fn register_cuda_cast_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(CUDA_CAST_CONTRACT, &crate::fkc::CudaLinkRegistry)
.expect(
"authored CUDA cast contract must import \
(embedded via include_str!, resolved through CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda cast contract declares no fused ops",
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA cast contract must register into the binding table");
}
const CUDA_FLASH_DECODING_CONTRACT: &str =
include_str!("../../docs/kernel-contracts/cuda/flash_decoding.fkc.md");
fn register_cuda_flash_decoding_from_contract(table: &mut KernelBindingTable) {
let provider =
crate::fkc::import_bundle_str(CUDA_FLASH_DECODING_CONTRACT, &crate::fkc::CudaLinkRegistry)
.expect(
"authored CUDA flash_decoding contract must import \
(embedded via include_str!, resolved through CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda flash_decoding contract declares no fused ops",
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA flash_decoding contract must register into the binding table");
}
const CUDA_BINARY_CONTRACT: &str = include_str!("../../docs/kernel-contracts/cuda/binary.fkc.md");
const CUDA_COMPARE_CONTRACT: &str = include_str!("../../docs/kernel-contracts/cuda/compare.fkc.md");
fn register_cuda_compare_from_contract(table: &mut KernelBindingTable) {
let provider =
crate::fkc::import_bundle_str(CUDA_COMPARE_CONTRACT, &crate::fkc::CudaLinkRegistry).expect(
"authored CUDA compare contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda compare contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA compare contract must register into the binding table");
}
fn register_cuda_binary_from_contract(table: &mut KernelBindingTable) {
let provider =
crate::fkc::import_bundle_str(CUDA_BINARY_CONTRACT, &crate::fkc::CudaLinkRegistry).expect(
"authored CUDA binary contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda binary contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA binary contract must register into the binding table");
}
const CUDA_REDUCE_CONTRACT: &str = include_str!("../../docs/kernel-contracts/cuda/reduce.fkc.md");
fn register_cuda_reduce_from_contract(table: &mut KernelBindingTable) {
let provider =
crate::fkc::import_bundle_str(CUDA_REDUCE_CONTRACT, &crate::fkc::CudaLinkRegistry).expect(
"authored CUDA reduce contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda reduce contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA reduce contract must register into the binding table");
}
const CUDA_NORM_CONTRACT: &str = include_str!("../../docs/kernel-contracts/cuda/norm.fkc.md");
fn register_cuda_norm_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(CUDA_NORM_CONTRACT, &crate::fkc::CudaLinkRegistry)
.expect(
"authored CUDA norm contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda norm contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA norm contract must register into the binding table");
}
const CUDA_SOFTMAX_CONTRACT: &str = include_str!("../../docs/kernel-contracts/cuda/softmax.fkc.md");
fn register_cuda_softmax_from_contract(table: &mut KernelBindingTable) {
let provider =
crate::fkc::import_bundle_str(CUDA_SOFTMAX_CONTRACT, &crate::fkc::CudaLinkRegistry).expect(
"authored CUDA softmax contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda softmax contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA softmax contract must register into the binding table");
}
const CUDA_POWI_CONTRACT: &str = include_str!("../../docs/kernel-contracts/cuda/powi.fkc.md");
fn register_cuda_powi_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(CUDA_POWI_CONTRACT, &crate::fkc::CudaLinkRegistry)
.expect(
"authored CUDA powi contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda powi contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA powi contract must register into the binding table");
}
const CUDA_POWI_BACKWARD_CONTRACT: &str =
include_str!("../../docs/kernel-contracts/cuda/powi_backward.fkc.md");
fn register_cuda_powi_backward_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(CUDA_POWI_BACKWARD_CONTRACT, &crate::fkc::CudaLinkRegistry)
.expect("authored CUDA powi_backward contract must import (embedded include_str!, CudaLinkRegistry)");
debug_assert!(
provider.fused.is_empty(),
"cuda powi_backward contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA powi_backward contract must register into the binding table");
}
const CUDA_CLAMP_CONTRACT: &str = include_str!("../../docs/kernel-contracts/cuda/clamp.fkc.md");
fn register_cuda_clamp_from_contract(table: &mut KernelBindingTable) {
let provider =
crate::fkc::import_bundle_str(CUDA_CLAMP_CONTRACT, &crate::fkc::CudaLinkRegistry).expect(
"authored CUDA clamp contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda clamp contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA clamp contract must register into the binding table");
}
const CUDA_FLIP_CONTRACT: &str = include_str!("../../docs/kernel-contracts/cuda/flip.fkc.md");
fn register_cuda_flip_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(CUDA_FLIP_CONTRACT, &crate::fkc::CudaLinkRegistry)
.expect(
"authored CUDA flip contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda flip contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA flip contract must register into the binding table");
}
const CUDA_ROLL_CONTRACT: &str = include_str!("../../docs/kernel-contracts/cuda/roll.fkc.md");
fn register_cuda_roll_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(CUDA_ROLL_CONTRACT, &crate::fkc::CudaLinkRegistry)
.expect(
"authored CUDA roll contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda roll contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA roll contract must register into the binding table");
}
const CUDA_CUMSUM_CONTRACT: &str = include_str!("../../docs/kernel-contracts/cuda/cumsum.fkc.md");
fn register_cuda_cumsum_from_contract(table: &mut KernelBindingTable) {
let provider =
crate::fkc::import_bundle_str(CUDA_CUMSUM_CONTRACT, &crate::fkc::CudaLinkRegistry).expect(
"authored CUDA cumsum contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda cumsum contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA cumsum contract must register into the binding table");
}
const CUDA_TRIANGULAR_CONTRACT: &str =
include_str!("../../docs/kernel-contracts/cuda/triangular.fkc.md");
fn register_cuda_triangular_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(
CUDA_TRIANGULAR_CONTRACT,
&crate::fkc::CudaLinkRegistry,
)
.expect(
"authored CUDA triangular contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda triangular contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA triangular contract must register into the binding table");
}
const CUDA_ARG_REDUCE_CONTRACT: &str =
include_str!("../../docs/kernel-contracts/cuda/arg_reduce.fkc.md");
fn register_cuda_arg_reduce_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(
CUDA_ARG_REDUCE_CONTRACT,
&crate::fkc::CudaLinkRegistry,
)
.expect(
"authored CUDA arg_reduce contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda arg_reduce contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA arg_reduce contract must register into the binding table");
}
const CUDA_REDUCE_TO_CONTRACT: &str =
include_str!("../../docs/kernel-contracts/cuda/reduce_to.fkc.md");
fn register_cuda_reduce_to_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(
CUDA_REDUCE_TO_CONTRACT,
&crate::fkc::CudaLinkRegistry,
)
.expect(
"authored CUDA reduce_to contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda reduce_to contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA reduce_to contract must register into the binding table");
}
const CUDA_ROPE_CONTRACT: &str = include_str!("../../docs/kernel-contracts/cuda/rope.fkc.md");
fn register_cuda_rope_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(CUDA_ROPE_CONTRACT, &crate::fkc::CudaLinkRegistry)
.expect(
"authored CUDA rope contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda rope contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA rope contract must register into the binding table");
}
const CUDA_UNARY_CONTRACT: &str = include_str!("../../docs/kernel-contracts/cuda/unary.fkc.md");
fn register_cuda_unary_from_contract(table: &mut KernelBindingTable) {
let provider =
crate::fkc::import_bundle_str(CUDA_UNARY_CONTRACT, &crate::fkc::CudaLinkRegistry).expect(
"authored CUDA unary contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda unary contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA unary contract must register into the binding table");
}
const CUDA_CLAMP_INPLACE_CONTRACT: &str =
include_str!("../../docs/kernel-contracts/cuda/clamp_inplace.fkc.md");
fn register_cuda_clamp_inplace_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(CUDA_CLAMP_INPLACE_CONTRACT, &crate::fkc::CudaLinkRegistry)
.expect("authored CUDA clamp_inplace contract must import (embedded include_str!, CudaLinkRegistry)");
debug_assert!(
provider.fused.is_empty(),
"cuda clamp_inplace contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA clamp_inplace contract must register into the binding table");
}
const CUDA_POWI_INPLACE_CONTRACT: &str =
include_str!("../../docs/kernel-contracts/cuda/powi_inplace.fkc.md");
fn register_cuda_powi_inplace_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(
CUDA_POWI_INPLACE_CONTRACT,
&crate::fkc::CudaLinkRegistry,
)
.expect(
"authored CUDA powi_inplace contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda powi_inplace contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA powi_inplace contract must register into the binding table");
}
const CUDA_INPLACE_UNARY_CONTRACT: &str =
include_str!("../../docs/kernel-contracts/cuda/inplace_unary.fkc.md");
fn register_cuda_inplace_unary_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(CUDA_INPLACE_UNARY_CONTRACT, &crate::fkc::CudaLinkRegistry)
.expect("authored CUDA inplace_unary contract must import (embedded include_str!, CudaLinkRegistry)");
debug_assert!(
provider.fused.is_empty(),
"cuda inplace_unary contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA inplace_unary contract must register into the binding table");
}
const CUDA_WRITE_SLICE_CONTRACT: &str =
include_str!("../../docs/kernel-contracts/cuda/write_slice.fkc.md");
fn register_cuda_write_slice_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(
CUDA_WRITE_SLICE_CONTRACT,
&crate::fkc::CudaLinkRegistry,
)
.expect(
"authored CUDA write_slice contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda write_slice contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA write_slice contract must register into the binding table");
}
const CUDA_WRITE_SLICE_ROTATING_CONTRACT: &str =
include_str!("../../docs/kernel-contracts/cuda/write_slice_rotating.fkc.md");
fn register_cuda_write_slice_rotating_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(CUDA_WRITE_SLICE_ROTATING_CONTRACT, &crate::fkc::CudaLinkRegistry)
.expect("authored CUDA write_slice_rotating contract must import (embedded include_str!, CudaLinkRegistry)");
debug_assert!(
provider.fused.is_empty(),
"cuda write_slice_rotating contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA write_slice_rotating contract must register into the binding table");
}
const CUDA_WRITE_SLICE_DOFF_CONTRACT: &str =
include_str!("../../docs/kernel-contracts/cuda/write_slice_doff.fkc.md");
fn register_cuda_write_slice_doff_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(CUDA_WRITE_SLICE_DOFF_CONTRACT, &crate::fkc::CudaLinkRegistry)
.expect("authored CUDA write_slice_doff contract must import (embedded include_str!, CudaLinkRegistry)");
debug_assert!(
provider.fused.is_empty(),
"cuda write_slice_doff contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA write_slice_doff contract must register into the binding table");
}
const CUDA_CONCAT_CONTRACT: &str = include_str!("../../docs/kernel-contracts/cuda/concat.fkc.md");
fn register_cuda_concat_from_contract(table: &mut KernelBindingTable) {
let provider =
crate::fkc::import_bundle_str(CUDA_CONCAT_CONTRACT, &crate::fkc::CudaLinkRegistry).expect(
"authored CUDA concat contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda concat contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA concat contract must register into the binding table");
}
const CUDA_AFFINE_CONTRACT: &str = include_str!("../../docs/kernel-contracts/cuda/affine.fkc.md");
fn register_cuda_affine_from_contract(table: &mut KernelBindingTable) {
let provider =
crate::fkc::import_bundle_str(CUDA_AFFINE_CONTRACT, &crate::fkc::CudaLinkRegistry).expect(
"authored CUDA affine contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda affine contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA affine contract must register into the binding table");
}
const CUDA_INPLACE_AFFINE_CONTRACT: &str =
include_str!("../../docs/kernel-contracts/cuda/inplace_affine.fkc.md");
fn register_cuda_inplace_affine_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(CUDA_INPLACE_AFFINE_CONTRACT, &crate::fkc::CudaLinkRegistry)
.expect("authored CUDA inplace_affine contract must import (embedded include_str!, CudaLinkRegistry)");
debug_assert!(
provider.fused.is_empty(),
"cuda inplace_affine contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA inplace_affine contract must register into the binding table");
}
const CUDA_PAD_CONTRACT: &str = include_str!("../../docs/kernel-contracts/cuda/pad.fkc.md");
fn register_cuda_pad_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(CUDA_PAD_CONTRACT, &crate::fkc::CudaLinkRegistry)
.expect("authored CUDA pad contract must import (embedded include_str!, CudaLinkRegistry)");
debug_assert!(
provider.fused.is_empty(),
"cuda pad contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA pad contract must register into the binding table");
}
const CUDA_PAD_BACKWARD_CONTRACT: &str =
include_str!("../../docs/kernel-contracts/cuda/pad_backward.fkc.md");
fn register_cuda_pad_backward_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(
CUDA_PAD_BACKWARD_CONTRACT,
&crate::fkc::CudaLinkRegistry,
)
.expect(
"authored CUDA pad_backward contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda pad_backward contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA pad_backward contract must register into the binding table");
}
const CUDA_CAUSAL_CONV1D_CONTRACT: &str =
include_str!("../../docs/kernel-contracts/cuda/causal_conv1d.fkc.md");
fn register_cuda_causal_conv1d_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(CUDA_CAUSAL_CONV1D_CONTRACT, &crate::fkc::CudaLinkRegistry)
.expect("authored CUDA causal_conv1d contract must import (embedded include_str!, CudaLinkRegistry)");
debug_assert!(
provider.fused.is_empty(),
"cuda causal_conv1d contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA causal_conv1d contract must register into the binding table");
}
const CUDA_GEMM_DENSE_CONTRACT: &str =
include_str!("../../docs/kernel-contracts/cuda/gemm_dense.fkc.md");
fn register_cuda_gemm_dense_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(
CUDA_GEMM_DENSE_CONTRACT,
&crate::fkc::CudaLinkRegistry,
)
.expect(
"authored CUDA gemm_dense contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda gemm_dense contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA gemm_dense contract must register into the binding table");
}
const CUDA_GEMM_INT_CONTRACT: &str =
include_str!("../../docs/kernel-contracts/cuda/gemm_int.fkc.md");
fn register_cuda_gemm_int_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(
CUDA_GEMM_INT_CONTRACT,
&crate::fkc::CudaLinkRegistry,
)
.expect(
"authored CUDA gemm_int contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda gemm_int contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA gemm_int contract must register into the binding table");
}
const CUDA_INDEXING_CONTRACT: &str =
include_str!("../../docs/kernel-contracts/cuda/indexing.fkc.md");
fn register_cuda_indexing_from_contract(table: &mut KernelBindingTable) {
let provider = crate::fkc::import_bundle_str(
CUDA_INDEXING_CONTRACT,
&crate::fkc::CudaLinkRegistry,
)
.expect(
"authored CUDA indexing contract must import (embedded include_str!, CudaLinkRegistry)",
);
debug_assert!(
provider.fused.is_empty(),
"cuda indexing contract declares no fused ops"
);
let mut fused = crate::fused::FusedKernelRegistry::new();
provider
.register_into(table, &mut fused)
.expect("CUDA indexing contract must register into the binding table");
}
pub fn register_baracuda_cuda_kernels(table: &mut KernelBindingTable) {
register_cuda_flash_decoding_from_contract(table);
register_cuda_cast_from_contract(table);
register_cuda_binary_from_contract(table);
register_cuda_compare_from_contract(table);
register_cuda_reduce_from_contract(table);
register_cuda_norm_from_contract(table);
register_cuda_softmax_from_contract(table);
register_cuda_powi_from_contract(table);
register_cuda_powi_backward_from_contract(table);
register_cuda_clamp_from_contract(table);
register_cuda_flip_from_contract(table);
register_cuda_roll_from_contract(table);
register_cuda_cumsum_from_contract(table);
register_cuda_triangular_from_contract(table);
register_cuda_arg_reduce_from_contract(table);
register_cuda_reduce_to_from_contract(table);
register_cuda_rope_from_contract(table);
register_cuda_unary_from_contract(table);
register_cuda_clamp_inplace_from_contract(table);
register_cuda_powi_inplace_from_contract(table);
register_cuda_inplace_unary_from_contract(table);
register_cuda_write_slice_from_contract(table);
register_cuda_write_slice_rotating_from_contract(table);
register_cuda_write_slice_doff_from_contract(table);
register_cuda_concat_from_contract(table);
register_cuda_affine_from_contract(table);
register_cuda_inplace_affine_from_contract(table);
register_cuda_pad_from_contract(table);
register_cuda_pad_backward_from_contract(table);
register_cuda_causal_conv1d_from_contract(table);
register_cuda_indexing_from_contract(table);
register_cuda_gemm_dense_from_contract(table);
register_cuda_gemm_int_from_contract(table);
}
#[cfg(test)]
mod cast_contract_tests {
use super::*;
use crate::kernel::{KernelBindingTable, KernelRef};
#[test]
fn register_baracuda_binds_cast_family_from_contract() {
let mut table = KernelBindingTable::new();
register_baracuda_cuda_kernels(&mut table);
let cuda = BackendId::Cuda;
let expected: KernelRef = cast::cast_baracuda_wrapper;
let base = [
DType::F32,
DType::F64,
DType::F16,
DType::BF16,
DType::I32,
DType::U32,
DType::I64,
DType::U8,
];
let mut pairs: Vec<(DType, DType)> = Vec::new();
for &src in &base {
for &dst in &base {
pairs.push((src, dst));
}
}
for dst in [DType::F32, DType::F16, DType::BF16] {
pairs.push((DType::F8E4M3, dst));
pairs.push((dst, DType::F8E4M3));
}
let mut checked = 0usize;
for (src, dst) in pairs {
let alts = table.lookup_alternatives(OpKind::Cast, &[src, dst], cuda);
let entry = alts
.iter()
.find(|e| e.kernel as usize == expected as usize)
.unwrap_or_else(|| {
panic!(
"Cast [{src:?}, {dst:?}]/Cuda: the production wrapper must be bound \
FROM the cuda cast contract in register_baracuda_cuda_kernels — found {} \
alternative(s) with sources {:?}",
alts.len(),
alts.iter().map(|e| e.kernel_source).collect::<Vec<_>>(),
)
});
assert_eq!(
entry.kernel_source, "baracuda",
"Cast [{src:?}, {dst:?}]: cast family must be contract-sourced \
(kernel_source=\"baracuda\"); got {:?}",
entry.kernel_source,
);
assert!(
!entry.caps.strided_input,
"Cast [{src:?}, {dst:?}]: caps preserved (contiguous-only, strided_input=false)",
);
checked += 1;
}
assert_eq!(checked, 70, "all 70 (SRC, DST) cast pairs checked");
}
#[test]
fn register_baracuda_binds_group1_families_from_contract() {
let mut table = KernelBindingTable::new();
register_baracuda_cuda_kernels(&mut table);
let cuda = BackendId::Cuda;
let cases: &[(OpKind, &[DType], KernelRef, bool)] = &[
(
OpKind::AddElementwise,
&[DType::F32, DType::F32, DType::F32][..],
binary::add_f32 as KernelRef,
true,
),
(
OpKind::AddElementwise,
&[DType::F16, DType::F16, DType::F16][..],
binary::add_f16 as KernelRef,
true,
),
(
OpKind::AddElementwise,
&[DType::BF16, DType::BF16, DType::BF16][..],
binary::add_bf16 as KernelRef,
true,
),
(
OpKind::AddElementwise,
&[DType::F64, DType::F64, DType::F64][..],
binary::add_f64 as KernelRef,
true,
),
(
OpKind::SubElementwise,
&[DType::F32, DType::F32, DType::F32][..],
binary::sub_f32 as KernelRef,
true,
),
(
OpKind::SubElementwise,
&[DType::F16, DType::F16, DType::F16][..],
binary::sub_f16 as KernelRef,
true,
),
(
OpKind::SubElementwise,
&[DType::BF16, DType::BF16, DType::BF16][..],
binary::sub_bf16 as KernelRef,
true,
),
(
OpKind::SubElementwise,
&[DType::F64, DType::F64, DType::F64][..],
binary::sub_f64 as KernelRef,
true,
),
(
OpKind::MulElementwise,
&[DType::F32, DType::F32, DType::F32][..],
binary::mul_f32 as KernelRef,
true,
),
(
OpKind::MulElementwise,
&[DType::F16, DType::F16, DType::F16][..],
binary::mul_f16 as KernelRef,
true,
),
(
OpKind::MulElementwise,
&[DType::BF16, DType::BF16, DType::BF16][..],
binary::mul_bf16 as KernelRef,
true,
),
(
OpKind::MulElementwise,
&[DType::F64, DType::F64, DType::F64][..],
binary::mul_f64 as KernelRef,
true,
),
(
OpKind::DivElementwise,
&[DType::F32, DType::F32, DType::F32][..],
binary::div_f32 as KernelRef,
true,
),
(
OpKind::DivElementwise,
&[DType::F16, DType::F16, DType::F16][..],
binary::div_f16 as KernelRef,
true,
),
(
OpKind::DivElementwise,
&[DType::BF16, DType::BF16, DType::BF16][..],
binary::div_bf16 as KernelRef,
true,
),
(
OpKind::DivElementwise,
&[DType::F64, DType::F64, DType::F64][..],
binary::div_f64 as KernelRef,
true,
),
(
OpKind::MaximumElementwise,
&[DType::F32, DType::F32, DType::F32][..],
binary::maximum_f32 as KernelRef,
true,
),
(
OpKind::MaximumElementwise,
&[DType::F16, DType::F16, DType::F16][..],
binary::maximum_f16 as KernelRef,
true,
),
(
OpKind::MaximumElementwise,
&[DType::BF16, DType::BF16, DType::BF16][..],
binary::maximum_bf16 as KernelRef,
true,
),
(
OpKind::MaximumElementwise,
&[DType::F64, DType::F64, DType::F64][..],
binary::maximum_f64 as KernelRef,
true,
),
(
OpKind::MinimumElementwise,
&[DType::F32, DType::F32, DType::F32][..],
binary::minimum_f32 as KernelRef,
true,
),
(
OpKind::MinimumElementwise,
&[DType::F16, DType::F16, DType::F16][..],
binary::minimum_f16 as KernelRef,
true,
),
(
OpKind::MinimumElementwise,
&[DType::BF16, DType::BF16, DType::BF16][..],
binary::minimum_bf16 as KernelRef,
true,
),
(
OpKind::MinimumElementwise,
&[DType::F64, DType::F64, DType::F64][..],
binary::minimum_f64 as KernelRef,
true,
),
(
OpKind::PowElementwise,
&[DType::F32, DType::F32, DType::F32][..],
binary::pow_f32 as KernelRef,
true,
),
(
OpKind::PowElementwise,
&[DType::F16, DType::F16, DType::F16][..],
binary::pow_f16 as KernelRef,
true,
),
(
OpKind::PowElementwise,
&[DType::BF16, DType::BF16, DType::BF16][..],
binary::pow_bf16 as KernelRef,
true,
),
(
OpKind::PowElementwise,
&[DType::F64, DType::F64, DType::F64][..],
binary::pow_f64 as KernelRef,
true,
),
(
OpKind::RemElementwise,
&[DType::F32, DType::F32, DType::F32][..],
binary::rem_f32 as KernelRef,
true,
),
(
OpKind::RemElementwise,
&[DType::F16, DType::F16, DType::F16][..],
binary::rem_f16 as KernelRef,
true,
),
(
OpKind::RemElementwise,
&[DType::BF16, DType::BF16, DType::BF16][..],
binary::rem_bf16 as KernelRef,
true,
),
(
OpKind::RemElementwise,
&[DType::F64, DType::F64, DType::F64][..],
binary::rem_f64 as KernelRef,
true,
),
(
OpKind::SumReduce,
&[DType::F32, DType::F32][..],
reduce::sum_f32 as KernelRef,
true,
),
(
OpKind::SumReduce,
&[DType::F16, DType::F16][..],
reduce::sum_f16 as KernelRef,
true,
),
(
OpKind::SumReduce,
&[DType::BF16, DType::BF16][..],
reduce::sum_bf16 as KernelRef,
true,
),
(
OpKind::SumReduce,
&[DType::F64, DType::F64][..],
reduce::sum_f64 as KernelRef,
true,
),
(
OpKind::MaxReduce,
&[DType::F32, DType::F32][..],
reduce::max_f32 as KernelRef,
true,
),
(
OpKind::MaxReduce,
&[DType::F16, DType::F16][..],
reduce::max_f16 as KernelRef,
true,
),
(
OpKind::MaxReduce,
&[DType::BF16, DType::BF16][..],
reduce::max_bf16 as KernelRef,
true,
),
(
OpKind::MaxReduce,
&[DType::F64, DType::F64][..],
reduce::max_f64 as KernelRef,
true,
),
(
OpKind::MinReduce,
&[DType::F32, DType::F32][..],
reduce::min_f32 as KernelRef,
true,
),
(
OpKind::MinReduce,
&[DType::F16, DType::F16][..],
reduce::min_f16 as KernelRef,
true,
),
(
OpKind::MinReduce,
&[DType::BF16, DType::BF16][..],
reduce::min_bf16 as KernelRef,
true,
),
(
OpKind::MinReduce,
&[DType::F64, DType::F64][..],
reduce::min_f64 as KernelRef,
true,
),
(
OpKind::MeanReduce,
&[DType::F32, DType::F32][..],
reduce::mean_f32 as KernelRef,
true,
),
(
OpKind::MeanReduce,
&[DType::F16, DType::F16][..],
reduce::mean_f16 as KernelRef,
true,
),
(
OpKind::MeanReduce,
&[DType::BF16, DType::BF16][..],
reduce::mean_bf16 as KernelRef,
true,
),
(
OpKind::MeanReduce,
&[DType::F64, DType::F64][..],
reduce::mean_f64 as KernelRef,
true,
),
(
OpKind::RmsNormLastDim,
&[DType::F32, DType::F32][..],
norm::rms_f32 as KernelRef,
true,
),
(
OpKind::RmsNormLastDim,
&[DType::F16, DType::F16][..],
norm::rms_f16 as KernelRef,
true,
),
(
OpKind::RmsNormLastDim,
&[DType::BF16, DType::BF16][..],
norm::rms_bf16 as KernelRef,
true,
),
(
OpKind::RmsNormLastDim,
&[DType::F64, DType::F64][..],
norm::rms_f64 as KernelRef,
true,
),
(
OpKind::LayerNormLastDim,
&[DType::F32, DType::F32][..],
norm::layer_f32 as KernelRef,
true,
),
(
OpKind::LayerNormLastDim,
&[DType::F16, DType::F16][..],
norm::layer_f16 as KernelRef,
true,
),
(
OpKind::LayerNormLastDim,
&[DType::BF16, DType::BF16][..],
norm::layer_bf16 as KernelRef,
true,
),
(
OpKind::LayerNormLastDim,
&[DType::F64, DType::F64][..],
norm::layer_f64 as KernelRef,
true,
),
(
OpKind::SoftmaxLastDim,
&[DType::F32, DType::F32][..],
softmax::softmax_f32 as KernelRef,
true,
),
(
OpKind::SoftmaxLastDim,
&[DType::F16, DType::F16][..],
softmax::softmax_f16 as KernelRef,
true,
),
(
OpKind::SoftmaxLastDim,
&[DType::BF16, DType::BF16][..],
softmax::softmax_bf16 as KernelRef,
true,
),
(
OpKind::SoftmaxLastDim,
&[DType::F64, DType::F64][..],
softmax::softmax_f64 as KernelRef,
true,
),
(
OpKind::LogSoftmaxLastDim,
&[DType::F32, DType::F32][..],
softmax::log_softmax_f32 as KernelRef,
true,
),
(
OpKind::LogSoftmaxLastDim,
&[DType::F16, DType::F16][..],
softmax::log_softmax_f16 as KernelRef,
true,
),
(
OpKind::LogSoftmaxLastDim,
&[DType::BF16, DType::BF16][..],
softmax::log_softmax_bf16 as KernelRef,
true,
),
(
OpKind::LogSoftmaxLastDim,
&[DType::F64, DType::F64][..],
softmax::log_softmax_f64 as KernelRef,
true,
),
(
OpKind::PowIElementwise,
&[DType::F32, DType::F32][..],
powi::powi_f32 as KernelRef,
true,
),
(
OpKind::PowIElementwise,
&[DType::F64, DType::F64][..],
powi::powi_f64 as KernelRef,
true,
),
(
OpKind::PowIElementwise,
&[DType::F16, DType::F16][..],
powi::powi_f16 as KernelRef,
true,
),
(
OpKind::PowIElementwise,
&[DType::BF16, DType::BF16][..],
powi::powi_bf16 as KernelRef,
true,
),
(
OpKind::PowIElementwiseBackward,
&[DType::F32, DType::F32, DType::F32][..],
powi_backward::powi_backward_f32 as KernelRef,
true,
),
(
OpKind::PowIElementwiseBackward,
&[DType::F64, DType::F64, DType::F64][..],
powi_backward::powi_backward_f64 as KernelRef,
true,
),
(
OpKind::PowIElementwiseBackward,
&[DType::F16, DType::F16, DType::F16][..],
powi_backward::powi_backward_f16 as KernelRef,
true,
),
(
OpKind::PowIElementwiseBackward,
&[DType::BF16, DType::BF16, DType::BF16][..],
powi_backward::powi_backward_bf16 as KernelRef,
true,
),
(
OpKind::ClampElementwise,
&[DType::F32, DType::F32][..],
clamp::clamp_f32 as KernelRef,
true,
),
(
OpKind::ClampElementwise,
&[DType::F64, DType::F64][..],
clamp::clamp_f64 as KernelRef,
true,
),
(
OpKind::ClampElementwise,
&[DType::F16, DType::F16][..],
clamp::clamp_f16 as KernelRef,
true,
),
(
OpKind::ClampElementwise,
&[DType::BF16, DType::BF16][..],
clamp::clamp_bf16 as KernelRef,
true,
),
(
OpKind::Flip,
&[DType::F32, DType::F32][..],
flip::flip_f32 as KernelRef,
true,
),
(
OpKind::Flip,
&[DType::F16, DType::F16][..],
flip::flip_f16 as KernelRef,
true,
),
(
OpKind::Flip,
&[DType::BF16, DType::BF16][..],
flip::flip_bf16 as KernelRef,
true,
),
(
OpKind::Flip,
&[DType::F64, DType::F64][..],
flip::flip_f64 as KernelRef,
true,
),
(
OpKind::Roll,
&[DType::F32, DType::F32][..],
roll::roll_f32 as KernelRef,
true,
),
(
OpKind::Roll,
&[DType::F16, DType::F16][..],
roll::roll_f16 as KernelRef,
true,
),
(
OpKind::Roll,
&[DType::BF16, DType::BF16][..],
roll::roll_bf16 as KernelRef,
true,
),
(
OpKind::Roll,
&[DType::F64, DType::F64][..],
roll::roll_f64 as KernelRef,
true,
),
(
OpKind::CumSum,
&[DType::F32, DType::F32][..],
cumsum::cumsum_f32 as KernelRef,
true,
),
(
OpKind::CumSum,
&[DType::F16, DType::F16][..],
cumsum::cumsum_f16 as KernelRef,
true,
),
(
OpKind::CumSum,
&[DType::BF16, DType::BF16][..],
cumsum::cumsum_bf16 as KernelRef,
true,
),
(
OpKind::CumSum,
&[DType::F64, DType::F64][..],
cumsum::cumsum_f64 as KernelRef,
true,
),
(
OpKind::Triu,
&[DType::F32, DType::F32][..],
triangular::triu_f32 as KernelRef,
true,
),
(
OpKind::Triu,
&[DType::F64, DType::F64][..],
triangular::triu_f64 as KernelRef,
true,
),
(
OpKind::Triu,
&[DType::F16, DType::F16][..],
triangular::triu_f16 as KernelRef,
true,
),
(
OpKind::Triu,
&[DType::BF16, DType::BF16][..],
triangular::triu_bf16 as KernelRef,
true,
),
(
OpKind::Triu,
&[DType::I32, DType::I32][..],
triangular::triu_i32 as KernelRef,
true,
),
(
OpKind::Triu,
&[DType::I64, DType::I64][..],
triangular::triu_i64 as KernelRef,
true,
),
(
OpKind::Tril,
&[DType::F32, DType::F32][..],
triangular::tril_f32 as KernelRef,
true,
),
(
OpKind::Tril,
&[DType::F64, DType::F64][..],
triangular::tril_f64 as KernelRef,
true,
),
(
OpKind::Tril,
&[DType::F16, DType::F16][..],
triangular::tril_f16 as KernelRef,
true,
),
(
OpKind::Tril,
&[DType::BF16, DType::BF16][..],
triangular::tril_bf16 as KernelRef,
true,
),
(
OpKind::Tril,
&[DType::I32, DType::I32][..],
triangular::tril_i32 as KernelRef,
true,
),
(
OpKind::Tril,
&[DType::I64, DType::I64][..],
triangular::tril_i64 as KernelRef,
true,
),
(
OpKind::ArgMaxDim,
&[DType::F32, DType::U32][..],
arg_reduce::argmax_dim_u32_f32 as KernelRef,
true,
),
(
OpKind::ArgMaxDim,
&[DType::F64, DType::U32][..],
arg_reduce::argmax_dim_u32_f64 as KernelRef,
true,
),
(
OpKind::ArgMaxDim,
&[DType::F16, DType::U32][..],
arg_reduce::argmax_dim_u32_f16 as KernelRef,
true,
),
(
OpKind::ArgMaxDim,
&[DType::BF16, DType::U32][..],
arg_reduce::argmax_dim_u32_bf16 as KernelRef,
true,
),
(
OpKind::ArgMinDim,
&[DType::F32, DType::U32][..],
arg_reduce::argmin_dim_u32_f32 as KernelRef,
true,
),
(
OpKind::ArgMinDim,
&[DType::F64, DType::U32][..],
arg_reduce::argmin_dim_u32_f64 as KernelRef,
true,
),
(
OpKind::ArgMinDim,
&[DType::F16, DType::U32][..],
arg_reduce::argmin_dim_u32_f16 as KernelRef,
true,
),
(
OpKind::ArgMinDim,
&[DType::BF16, DType::U32][..],
arg_reduce::argmin_dim_u32_bf16 as KernelRef,
true,
),
(
OpKind::ReduceSumTo,
&[DType::F32, DType::F32][..],
reduce_to::sum_to_f32 as KernelRef,
true,
),
(
OpKind::ReduceSumTo,
&[DType::F16, DType::F16][..],
reduce_to::sum_to_f16 as KernelRef,
true,
),
(
OpKind::ReduceSumTo,
&[DType::BF16, DType::BF16][..],
reduce_to::sum_to_bf16 as KernelRef,
true,
),
(
OpKind::ReduceSumTo,
&[DType::F64, DType::F64][..],
reduce_to::sum_to_f64 as KernelRef,
true,
),
(
OpKind::ReduceMaxTo,
&[DType::F32, DType::F32][..],
reduce_to::max_to_f32 as KernelRef,
true,
),
(
OpKind::ReduceMaxTo,
&[DType::F16, DType::F16][..],
reduce_to::max_to_f16 as KernelRef,
true,
),
(
OpKind::ReduceMaxTo,
&[DType::BF16, DType::BF16][..],
reduce_to::max_to_bf16 as KernelRef,
true,
),
(
OpKind::ReduceMaxTo,
&[DType::F64, DType::F64][..],
reduce_to::max_to_f64 as KernelRef,
true,
),
(
OpKind::Rope,
&[DType::F32, DType::F32][..],
attention::rope_f32 as KernelRef,
true,
),
(
OpKind::Rope,
&[DType::F16, DType::F16][..],
attention::rope_f16 as KernelRef,
true,
),
(
OpKind::Rope,
&[DType::BF16, DType::BF16][..],
attention::rope_bf16 as KernelRef,
true,
),
(
OpKind::Rope,
&[DType::F64, DType::F64][..],
attention::rope_f64 as KernelRef,
true,
),
];
let mut checked = 0usize;
for (op, key, expected, want_strided) in cases {
let alts = table.lookup_alternatives(*op, key, cuda);
let entry = alts
.iter()
.find(|e| e.kernel as usize == *expected as usize)
.unwrap_or_else(|| {
panic!(
"{op:?} {key:?}/Cuda: the production wrapper must be bound FROM the cuda \
contract in register_baracuda_cuda_kernels - found {} alternative(s) with \
sources {:?}",
alts.len(),
alts.iter().map(|e| e.kernel_source).collect::<Vec<_>>(),
)
});
assert_eq!(
entry.kernel_source, "baracuda",
"{op:?} {key:?}: family must be contract-sourced (kernel_source=\"baracuda\"); got {:?}",
entry.kernel_source,
);
assert_eq!(
entry.caps.strided_input, *want_strided,
"{op:?} {key:?}: caps preserved (strided_input == {want_strided})",
);
checked += 1;
}
assert_eq!(checked, 120, "all 120 Group-1 (op, dtype) keys checked");
}
#[test]
fn register_baracuda_binds_group3_forward_unary_from_contract() {
let mut table = KernelBindingTable::new();
register_baracuda_cuda_kernels(&mut table);
let cuda = BackendId::Cuda;
let cases: &[(OpKind, &[DType], KernelRef, bool)] = &[
(
OpKind::NegElementwise,
&[DType::F32, DType::F32][..],
unary::neg_f32 as KernelRef,
true,
),
(
OpKind::NegElementwise,
&[DType::F16, DType::F16][..],
unary::neg_f16 as KernelRef,
true,
),
(
OpKind::NegElementwise,
&[DType::BF16, DType::BF16][..],
unary::neg_bf16 as KernelRef,
true,
),
(
OpKind::NegElementwise,
&[DType::F64, DType::F64][..],
unary::neg_f64 as KernelRef,
true,
),
(
OpKind::AbsElementwise,
&[DType::F32, DType::F32][..],
unary::abs_f32 as KernelRef,
true,
),
(
OpKind::AbsElementwise,
&[DType::F16, DType::F16][..],
unary::abs_f16 as KernelRef,
true,
),
(
OpKind::AbsElementwise,
&[DType::BF16, DType::BF16][..],
unary::abs_bf16 as KernelRef,
true,
),
(
OpKind::AbsElementwise,
&[DType::F64, DType::F64][..],
unary::abs_f64 as KernelRef,
true,
),
(
OpKind::SqrElementwise,
&[DType::F32, DType::F32][..],
unary::sqr_f32 as KernelRef,
true,
),
(
OpKind::SqrElementwise,
&[DType::F16, DType::F16][..],
unary::sqr_f16 as KernelRef,
true,
),
(
OpKind::SqrElementwise,
&[DType::BF16, DType::BF16][..],
unary::sqr_bf16 as KernelRef,
true,
),
(
OpKind::SqrElementwise,
&[DType::F64, DType::F64][..],
unary::sqr_f64 as KernelRef,
true,
),
(
OpKind::SqrtElementwise,
&[DType::F32, DType::F32][..],
unary::sqrt_f32 as KernelRef,
true,
),
(
OpKind::SqrtElementwise,
&[DType::F16, DType::F16][..],
unary::sqrt_f16 as KernelRef,
true,
),
(
OpKind::SqrtElementwise,
&[DType::BF16, DType::BF16][..],
unary::sqrt_bf16 as KernelRef,
true,
),
(
OpKind::SqrtElementwise,
&[DType::F64, DType::F64][..],
unary::sqrt_f64 as KernelRef,
true,
),
(
OpKind::RecipElementwise,
&[DType::F32, DType::F32][..],
unary::recip_f32 as KernelRef,
true,
),
(
OpKind::RecipElementwise,
&[DType::F16, DType::F16][..],
unary::recip_f16 as KernelRef,
true,
),
(
OpKind::RecipElementwise,
&[DType::BF16, DType::BF16][..],
unary::recip_bf16 as KernelRef,
true,
),
(
OpKind::RecipElementwise,
&[DType::F64, DType::F64][..],
unary::recip_f64 as KernelRef,
true,
),
(
OpKind::ExpElementwise,
&[DType::F32, DType::F32][..],
unary::exp_f32 as KernelRef,
true,
),
(
OpKind::ExpElementwise,
&[DType::F16, DType::F16][..],
unary::exp_f16 as KernelRef,
true,
),
(
OpKind::ExpElementwise,
&[DType::BF16, DType::BF16][..],
unary::exp_bf16 as KernelRef,
true,
),
(
OpKind::ExpElementwise,
&[DType::F64, DType::F64][..],
unary::exp_f64 as KernelRef,
true,
),
(
OpKind::LogElementwise,
&[DType::F32, DType::F32][..],
unary::log_f32 as KernelRef,
true,
),
(
OpKind::LogElementwise,
&[DType::F16, DType::F16][..],
unary::log_f16 as KernelRef,
true,
),
(
OpKind::LogElementwise,
&[DType::BF16, DType::BF16][..],
unary::log_bf16 as KernelRef,
true,
),
(
OpKind::LogElementwise,
&[DType::F64, DType::F64][..],
unary::log_f64 as KernelRef,
true,
),
(
OpKind::SinElementwise,
&[DType::F32, DType::F32][..],
unary::sin_f32 as KernelRef,
true,
),
(
OpKind::SinElementwise,
&[DType::F16, DType::F16][..],
unary::sin_f16 as KernelRef,
true,
),
(
OpKind::SinElementwise,
&[DType::BF16, DType::BF16][..],
unary::sin_bf16 as KernelRef,
true,
),
(
OpKind::SinElementwise,
&[DType::F64, DType::F64][..],
unary::sin_f64 as KernelRef,
true,
),
(
OpKind::CosElementwise,
&[DType::F32, DType::F32][..],
unary::cos_f32 as KernelRef,
true,
),
(
OpKind::CosElementwise,
&[DType::F16, DType::F16][..],
unary::cos_f16 as KernelRef,
true,
),
(
OpKind::CosElementwise,
&[DType::BF16, DType::BF16][..],
unary::cos_bf16 as KernelRef,
true,
),
(
OpKind::CosElementwise,
&[DType::F64, DType::F64][..],
unary::cos_f64 as KernelRef,
true,
),
(
OpKind::TanhElementwise,
&[DType::F32, DType::F32][..],
unary::tanh_f32 as KernelRef,
true,
),
(
OpKind::TanhElementwise,
&[DType::F16, DType::F16][..],
unary::tanh_f16 as KernelRef,
true,
),
(
OpKind::TanhElementwise,
&[DType::BF16, DType::BF16][..],
unary::tanh_bf16 as KernelRef,
true,
),
(
OpKind::TanhElementwise,
&[DType::F64, DType::F64][..],
unary::tanh_f64 as KernelRef,
true,
),
(
OpKind::ReluElementwise,
&[DType::F32, DType::F32][..],
unary::relu_f32 as KernelRef,
true,
),
(
OpKind::ReluElementwise,
&[DType::F16, DType::F16][..],
unary::relu_f16 as KernelRef,
true,
),
(
OpKind::ReluElementwise,
&[DType::BF16, DType::BF16][..],
unary::relu_bf16 as KernelRef,
true,
),
(
OpKind::ReluElementwise,
&[DType::F64, DType::F64][..],
unary::relu_f64 as KernelRef,
true,
),
(
OpKind::GeluTanhElementwise,
&[DType::F32, DType::F32][..],
unary::gelu_tanh_f32 as KernelRef,
true,
),
(
OpKind::GeluTanhElementwise,
&[DType::F16, DType::F16][..],
unary::gelu_tanh_f16 as KernelRef,
true,
),
(
OpKind::GeluTanhElementwise,
&[DType::BF16, DType::BF16][..],
unary::gelu_tanh_bf16 as KernelRef,
true,
),
(
OpKind::GeluTanhElementwise,
&[DType::F64, DType::F64][..],
unary::gelu_tanh_f64 as KernelRef,
true,
),
(
OpKind::GeluElementwise,
&[DType::F32, DType::F32][..],
unary::gelu_f32 as KernelRef,
true,
),
(
OpKind::GeluElementwise,
&[DType::F16, DType::F16][..],
unary::gelu_f16 as KernelRef,
true,
),
(
OpKind::GeluElementwise,
&[DType::BF16, DType::BF16][..],
unary::gelu_bf16 as KernelRef,
true,
),
(
OpKind::GeluElementwise,
&[DType::F64, DType::F64][..],
unary::gelu_f64 as KernelRef,
true,
),
(
OpKind::StepElementwise,
&[DType::F32, DType::F32][..],
unary::step_f32 as KernelRef,
true,
),
(
OpKind::StepElementwise,
&[DType::F16, DType::F16][..],
unary::step_f16 as KernelRef,
true,
),
(
OpKind::StepElementwise,
&[DType::BF16, DType::BF16][..],
unary::step_bf16 as KernelRef,
true,
),
(
OpKind::StepElementwise,
&[DType::F64, DType::F64][..],
unary::step_f64 as KernelRef,
true,
),
(
OpKind::SiluElementwise,
&[DType::F32, DType::F32][..],
unary::silu_f32 as KernelRef,
true,
),
(
OpKind::SiluElementwise,
&[DType::F16, DType::F16][..],
unary::silu_f16 as KernelRef,
true,
),
(
OpKind::SiluElementwise,
&[DType::BF16, DType::BF16][..],
unary::silu_bf16 as KernelRef,
true,
),
(
OpKind::SiluElementwise,
&[DType::F64, DType::F64][..],
unary::silu_f64 as KernelRef,
true,
),
(
OpKind::SigmoidElementwise,
&[DType::F32, DType::F32][..],
unary::sigmoid_f32 as KernelRef,
true,
),
(
OpKind::SigmoidElementwise,
&[DType::F16, DType::F16][..],
unary::sigmoid_f16 as KernelRef,
true,
),
(
OpKind::SigmoidElementwise,
&[DType::BF16, DType::BF16][..],
unary::sigmoid_bf16 as KernelRef,
true,
),
(
OpKind::SigmoidElementwise,
&[DType::F64, DType::F64][..],
unary::sigmoid_f64 as KernelRef,
true,
),
(
OpKind::RsqrtElementwise,
&[DType::F32, DType::F32][..],
unary::rsqrt_f32 as KernelRef,
true,
),
(
OpKind::RsqrtElementwise,
&[DType::F16, DType::F16][..],
unary::rsqrt_f16 as KernelRef,
true,
),
(
OpKind::RsqrtElementwise,
&[DType::BF16, DType::BF16][..],
unary::rsqrt_bf16 as KernelRef,
true,
),
(
OpKind::RsqrtElementwise,
&[DType::F64, DType::F64][..],
unary::rsqrt_f64 as KernelRef,
true,
),
(
OpKind::FloorElementwise,
&[DType::F32, DType::F32][..],
unary::floor_f32 as KernelRef,
true,
),
(
OpKind::FloorElementwise,
&[DType::F16, DType::F16][..],
unary::floor_f16 as KernelRef,
true,
),
(
OpKind::FloorElementwise,
&[DType::BF16, DType::BF16][..],
unary::floor_bf16 as KernelRef,
true,
),
(
OpKind::FloorElementwise,
&[DType::F64, DType::F64][..],
unary::floor_f64 as KernelRef,
true,
),
(
OpKind::CeilElementwise,
&[DType::F32, DType::F32][..],
unary::ceil_f32 as KernelRef,
true,
),
(
OpKind::CeilElementwise,
&[DType::F16, DType::F16][..],
unary::ceil_f16 as KernelRef,
true,
),
(
OpKind::CeilElementwise,
&[DType::BF16, DType::BF16][..],
unary::ceil_bf16 as KernelRef,
true,
),
(
OpKind::CeilElementwise,
&[DType::F64, DType::F64][..],
unary::ceil_f64 as KernelRef,
true,
),
(
OpKind::RoundElementwise,
&[DType::F32, DType::F32][..],
unary::round_f32 as KernelRef,
true,
),
(
OpKind::RoundElementwise,
&[DType::F16, DType::F16][..],
unary::round_f16 as KernelRef,
true,
),
(
OpKind::RoundElementwise,
&[DType::BF16, DType::BF16][..],
unary::round_bf16 as KernelRef,
true,
),
(
OpKind::RoundElementwise,
&[DType::F64, DType::F64][..],
unary::round_f64 as KernelRef,
true,
),
(
OpKind::ErfElementwise,
&[DType::F32, DType::F32][..],
unary::erf_f32 as KernelRef,
true,
),
(
OpKind::ErfElementwise,
&[DType::F16, DType::F16][..],
unary::erf_f16 as KernelRef,
true,
),
(
OpKind::ErfElementwise,
&[DType::BF16, DType::BF16][..],
unary::erf_bf16 as KernelRef,
true,
),
(
OpKind::ErfElementwise,
&[DType::F64, DType::F64][..],
unary::erf_f64 as KernelRef,
true,
),
(
OpKind::SignElementwise,
&[DType::F32, DType::F32][..],
unary::sign_f32 as KernelRef,
true,
),
];
let mut checked = 0usize;
for (op, key, expected, want_strided) in cases {
let alts = table.lookup_alternatives(*op, key, cuda);
let entry = alts
.iter()
.find(|e| e.kernel as usize == *expected as usize)
.unwrap_or_else(|| {
panic!(
"{op:?} {key:?}/Cuda: the production wrapper must be bound FROM the cuda \
contract in register_baracuda_cuda_kernels - found {} alternative(s) with \
sources {:?}",
alts.len(),
alts.iter().map(|e| e.kernel_source).collect::<Vec<_>>(),
)
});
assert_eq!(
entry.kernel_source, "baracuda",
"{op:?} {key:?}: family must be contract-sourced (kernel_source=\"baracuda\"); got {:?}",
entry.kernel_source,
);
assert_eq!(
entry.caps.strided_input, *want_strided,
"{op:?} {key:?}: caps preserved (strided_input == {want_strided})",
);
checked += 1;
}
assert_eq!(checked, 85, "all 85 group3 keys checked");
}
#[test]
fn register_baracuda_binds_group2_inplace_families_from_contract() {
let mut table = KernelBindingTable::new();
register_baracuda_cuda_kernels(&mut table);
let cuda = BackendId::Cuda;
let cases: &[(OpKind, &[DType], KernelRef, bool)] = &[
(
OpKind::ClampInplace,
&[DType::F32, DType::F32][..],
clamp_inplace::clamp_inplace_f32 as KernelRef,
false,
),
(
OpKind::ClampInplace,
&[DType::F64, DType::F64][..],
clamp_inplace::clamp_inplace_f64 as KernelRef,
false,
),
(
OpKind::ClampInplace,
&[DType::BF16, DType::BF16][..],
clamp_inplace::clamp_inplace_bf16 as KernelRef,
false,
),
(
OpKind::ClampInplace,
&[DType::F16, DType::F16][..],
clamp_inplace::clamp_inplace_f16 as KernelRef,
false,
),
(
OpKind::PowIInplace,
&[DType::F32, DType::F32][..],
powi_inplace::powi_inplace_f32 as KernelRef,
false,
),
(
OpKind::PowIInplace,
&[DType::F64, DType::F64][..],
powi_inplace::powi_inplace_f64 as KernelRef,
false,
),
(
OpKind::PowIInplace,
&[DType::BF16, DType::BF16][..],
powi_inplace::powi_inplace_bf16 as KernelRef,
false,
),
(
OpKind::PowIInplace,
&[DType::F16, DType::F16][..],
powi_inplace::powi_inplace_f16 as KernelRef,
false,
),
(
OpKind::ReluInplace,
&[DType::F32, DType::F32][..],
unary::relu_inplace_f32 as KernelRef,
false,
),
(
OpKind::ReluInplace,
&[DType::F64, DType::F64][..],
unary::relu_inplace_f64 as KernelRef,
false,
),
(
OpKind::ReluInplace,
&[DType::BF16, DType::BF16][..],
unary::relu_inplace_bf16 as KernelRef,
false,
),
(
OpKind::ReluInplace,
&[DType::F16, DType::F16][..],
unary::relu_inplace_f16 as KernelRef,
false,
),
(
OpKind::SiluInplace,
&[DType::F32, DType::F32][..],
unary::silu_inplace_f32 as KernelRef,
false,
),
(
OpKind::SiluInplace,
&[DType::F64, DType::F64][..],
unary::silu_inplace_f64 as KernelRef,
false,
),
(
OpKind::SiluInplace,
&[DType::BF16, DType::BF16][..],
unary::silu_inplace_bf16 as KernelRef,
false,
),
(
OpKind::SiluInplace,
&[DType::F16, DType::F16][..],
unary::silu_inplace_f16 as KernelRef,
false,
),
(
OpKind::GeluTanhInplace,
&[DType::F32, DType::F32][..],
unary::gelu_inplace_f32 as KernelRef,
false,
),
(
OpKind::GeluTanhInplace,
&[DType::F64, DType::F64][..],
unary::gelu_inplace_f64 as KernelRef,
false,
),
(
OpKind::GeluTanhInplace,
&[DType::BF16, DType::BF16][..],
unary::gelu_inplace_bf16 as KernelRef,
false,
),
(
OpKind::GeluTanhInplace,
&[DType::F16, DType::F16][..],
unary::gelu_inplace_f16 as KernelRef,
false,
),
(
OpKind::TanhInplace,
&[DType::F32, DType::F32][..],
unary::tanh_inplace_f32 as KernelRef,
false,
),
(
OpKind::TanhInplace,
&[DType::F64, DType::F64][..],
unary::tanh_inplace_f64 as KernelRef,
false,
),
(
OpKind::TanhInplace,
&[DType::BF16, DType::BF16][..],
unary::tanh_inplace_bf16 as KernelRef,
false,
),
(
OpKind::TanhInplace,
&[DType::F16, DType::F16][..],
unary::tanh_inplace_f16 as KernelRef,
false,
),
(
OpKind::SigmoidInplace,
&[DType::F32, DType::F32][..],
unary::sigmoid_inplace_f32 as KernelRef,
false,
),
(
OpKind::SigmoidInplace,
&[DType::F64, DType::F64][..],
unary::sigmoid_inplace_f64 as KernelRef,
false,
),
(
OpKind::SigmoidInplace,
&[DType::BF16, DType::BF16][..],
unary::sigmoid_inplace_bf16 as KernelRef,
false,
),
(
OpKind::SigmoidInplace,
&[DType::F16, DType::F16][..],
unary::sigmoid_inplace_f16 as KernelRef,
false,
),
(
OpKind::NegInplace,
&[DType::F32, DType::F32][..],
unary::neg_inplace_f32 as KernelRef,
false,
),
(
OpKind::NegInplace,
&[DType::F64, DType::F64][..],
unary::neg_inplace_f64 as KernelRef,
false,
),
(
OpKind::NegInplace,
&[DType::BF16, DType::BF16][..],
unary::neg_inplace_bf16 as KernelRef,
false,
),
(
OpKind::NegInplace,
&[DType::F16, DType::F16][..],
unary::neg_inplace_f16 as KernelRef,
false,
),
(
OpKind::AbsInplace,
&[DType::F32, DType::F32][..],
unary::abs_inplace_f32 as KernelRef,
false,
),
(
OpKind::AbsInplace,
&[DType::F64, DType::F64][..],
unary::abs_inplace_f64 as KernelRef,
false,
),
(
OpKind::AbsInplace,
&[DType::BF16, DType::BF16][..],
unary::abs_inplace_bf16 as KernelRef,
false,
),
(
OpKind::AbsInplace,
&[DType::F16, DType::F16][..],
unary::abs_inplace_f16 as KernelRef,
false,
),
(
OpKind::SqrInplace,
&[DType::F32, DType::F32][..],
unary::sqr_inplace_f32 as KernelRef,
false,
),
(
OpKind::SqrInplace,
&[DType::F64, DType::F64][..],
unary::sqr_inplace_f64 as KernelRef,
false,
),
(
OpKind::SqrInplace,
&[DType::BF16, DType::BF16][..],
unary::sqr_inplace_bf16 as KernelRef,
false,
),
(
OpKind::SqrInplace,
&[DType::F16, DType::F16][..],
unary::sqr_inplace_f16 as KernelRef,
false,
),
(
OpKind::SqrtInplace,
&[DType::F32, DType::F32][..],
unary::sqrt_inplace_f32 as KernelRef,
false,
),
(
OpKind::SqrtInplace,
&[DType::F64, DType::F64][..],
unary::sqrt_inplace_f64 as KernelRef,
false,
),
(
OpKind::SqrtInplace,
&[DType::BF16, DType::BF16][..],
unary::sqrt_inplace_bf16 as KernelRef,
false,
),
(
OpKind::SqrtInplace,
&[DType::F16, DType::F16][..],
unary::sqrt_inplace_f16 as KernelRef,
false,
),
(
OpKind::RsqrtInplace,
&[DType::F32, DType::F32][..],
unary::rsqrt_inplace_f32 as KernelRef,
false,
),
(
OpKind::RsqrtInplace,
&[DType::F64, DType::F64][..],
unary::rsqrt_inplace_f64 as KernelRef,
false,
),
(
OpKind::RsqrtInplace,
&[DType::BF16, DType::BF16][..],
unary::rsqrt_inplace_bf16 as KernelRef,
false,
),
(
OpKind::RsqrtInplace,
&[DType::F16, DType::F16][..],
unary::rsqrt_inplace_f16 as KernelRef,
false,
),
(
OpKind::RecipInplace,
&[DType::F32, DType::F32][..],
unary::recip_inplace_f32 as KernelRef,
false,
),
(
OpKind::RecipInplace,
&[DType::F64, DType::F64][..],
unary::recip_inplace_f64 as KernelRef,
false,
),
(
OpKind::RecipInplace,
&[DType::BF16, DType::BF16][..],
unary::recip_inplace_bf16 as KernelRef,
false,
),
(
OpKind::RecipInplace,
&[DType::F16, DType::F16][..],
unary::recip_inplace_f16 as KernelRef,
false,
),
(
OpKind::ExpInplace,
&[DType::F32, DType::F32][..],
unary::exp_inplace_f32 as KernelRef,
false,
),
(
OpKind::ExpInplace,
&[DType::F64, DType::F64][..],
unary::exp_inplace_f64 as KernelRef,
false,
),
(
OpKind::ExpInplace,
&[DType::BF16, DType::BF16][..],
unary::exp_inplace_bf16 as KernelRef,
false,
),
(
OpKind::ExpInplace,
&[DType::F16, DType::F16][..],
unary::exp_inplace_f16 as KernelRef,
false,
),
(
OpKind::LogInplace,
&[DType::F32, DType::F32][..],
unary::log_inplace_f32 as KernelRef,
false,
),
(
OpKind::LogInplace,
&[DType::F64, DType::F64][..],
unary::log_inplace_f64 as KernelRef,
false,
),
(
OpKind::LogInplace,
&[DType::BF16, DType::BF16][..],
unary::log_inplace_bf16 as KernelRef,
false,
),
(
OpKind::LogInplace,
&[DType::F16, DType::F16][..],
unary::log_inplace_f16 as KernelRef,
false,
),
(
OpKind::SinInplace,
&[DType::F32, DType::F32][..],
unary::sin_inplace_f32 as KernelRef,
false,
),
(
OpKind::SinInplace,
&[DType::F64, DType::F64][..],
unary::sin_inplace_f64 as KernelRef,
false,
),
(
OpKind::SinInplace,
&[DType::BF16, DType::BF16][..],
unary::sin_inplace_bf16 as KernelRef,
false,
),
(
OpKind::SinInplace,
&[DType::F16, DType::F16][..],
unary::sin_inplace_f16 as KernelRef,
false,
),
(
OpKind::CosInplace,
&[DType::F32, DType::F32][..],
unary::cos_inplace_f32 as KernelRef,
false,
),
(
OpKind::CosInplace,
&[DType::F64, DType::F64][..],
unary::cos_inplace_f64 as KernelRef,
false,
),
(
OpKind::CosInplace,
&[DType::BF16, DType::BF16][..],
unary::cos_inplace_bf16 as KernelRef,
false,
),
(
OpKind::CosInplace,
&[DType::F16, DType::F16][..],
unary::cos_inplace_f16 as KernelRef,
false,
),
(
OpKind::SignInplace,
&[DType::F32, DType::F32][..],
unary::sign_inplace_f32 as KernelRef,
false,
),
(
OpKind::SignInplace,
&[DType::F64, DType::F64][..],
unary::sign_inplace_f64 as KernelRef,
false,
),
(
OpKind::SignInplace,
&[DType::BF16, DType::BF16][..],
unary::sign_inplace_bf16 as KernelRef,
false,
),
(
OpKind::SignInplace,
&[DType::F16, DType::F16][..],
unary::sign_inplace_f16 as KernelRef,
false,
),
(
OpKind::FloorInplace,
&[DType::F32, DType::F32][..],
unary::floor_inplace_f32 as KernelRef,
false,
),
(
OpKind::FloorInplace,
&[DType::F64, DType::F64][..],
unary::floor_inplace_f64 as KernelRef,
false,
),
(
OpKind::FloorInplace,
&[DType::BF16, DType::BF16][..],
unary::floor_inplace_bf16 as KernelRef,
false,
),
(
OpKind::FloorInplace,
&[DType::F16, DType::F16][..],
unary::floor_inplace_f16 as KernelRef,
false,
),
(
OpKind::CeilInplace,
&[DType::F32, DType::F32][..],
unary::ceil_inplace_f32 as KernelRef,
false,
),
(
OpKind::CeilInplace,
&[DType::F64, DType::F64][..],
unary::ceil_inplace_f64 as KernelRef,
false,
),
(
OpKind::CeilInplace,
&[DType::BF16, DType::BF16][..],
unary::ceil_inplace_bf16 as KernelRef,
false,
),
(
OpKind::CeilInplace,
&[DType::F16, DType::F16][..],
unary::ceil_inplace_f16 as KernelRef,
false,
),
(
OpKind::RoundInplace,
&[DType::F32, DType::F32][..],
unary::round_inplace_f32 as KernelRef,
false,
),
(
OpKind::RoundInplace,
&[DType::F64, DType::F64][..],
unary::round_inplace_f64 as KernelRef,
false,
),
(
OpKind::RoundInplace,
&[DType::BF16, DType::BF16][..],
unary::round_inplace_bf16 as KernelRef,
false,
),
(
OpKind::RoundInplace,
&[DType::F16, DType::F16][..],
unary::round_inplace_f16 as KernelRef,
false,
),
(
OpKind::ErfInplace,
&[DType::F32, DType::F32][..],
unary::erf_inplace_f32 as KernelRef,
false,
),
(
OpKind::ErfInplace,
&[DType::F64, DType::F64][..],
unary::erf_inplace_f64 as KernelRef,
false,
),
(
OpKind::ErfInplace,
&[DType::BF16, DType::BF16][..],
unary::erf_inplace_bf16 as KernelRef,
false,
),
(
OpKind::ErfInplace,
&[DType::F16, DType::F16][..],
unary::erf_inplace_f16 as KernelRef,
false,
),
(
OpKind::GeluInplace,
&[DType::F32, DType::F32][..],
unary::gelu_erf_inplace_f32 as KernelRef,
false,
),
(
OpKind::GeluInplace,
&[DType::F64, DType::F64][..],
unary::gelu_erf_inplace_f64 as KernelRef,
false,
),
(
OpKind::GeluInplace,
&[DType::BF16, DType::BF16][..],
unary::gelu_erf_inplace_bf16 as KernelRef,
false,
),
(
OpKind::GeluInplace,
&[DType::F16, DType::F16][..],
unary::gelu_erf_inplace_f16 as KernelRef,
false,
),
];
let mut checked = 0usize;
for (op, key, expected, want_strided) in cases {
let alts = table.lookup_alternatives(*op, key, cuda);
let entry = alts
.iter()
.find(|e| e.kernel as usize == *expected as usize)
.unwrap_or_else(|| {
panic!(
"{op:?} {key:?}/Cuda: the production wrapper must be bound FROM the cuda \
contract in register_baracuda_cuda_kernels - found {} alternative(s) with \
sources {:?}",
alts.len(),
alts.iter().map(|e| e.kernel_source).collect::<Vec<_>>(),
)
});
assert_eq!(
entry.kernel_source, "baracuda",
"{op:?} {key:?}: family must be contract-sourced (kernel_source=\"baracuda\"); got {:?}",
entry.kernel_source,
);
assert_eq!(
entry.caps.strided_input, *want_strided,
"{op:?} {key:?}: caps preserved (strided_input == {want_strided})",
);
checked += 1;
}
assert_eq!(checked, 92, "all 92 group2 keys checked");
}
#[test]
fn register_baracuda_binds_group4_byte_width_umbrellas_from_contract() {
let mut table = KernelBindingTable::new();
register_baracuda_cuda_kernels(&mut table);
let cuda = BackendId::Cuda;
let cases: &[(OpKind, &[DType], KernelRef, bool)] = &[
(
OpKind::WriteSlice,
&[DType::F32, DType::F32][..],
write_slice::write_slice_b4 as KernelRef,
false,
),
(
OpKind::WriteSlice,
&[DType::F64, DType::F64][..],
write_slice::write_slice_b8 as KernelRef,
false,
),
(
OpKind::WriteSlice,
&[DType::F16, DType::F16][..],
write_slice::write_slice_b2 as KernelRef,
false,
),
(
OpKind::WriteSlice,
&[DType::BF16, DType::BF16][..],
write_slice::write_slice_b2 as KernelRef,
false,
),
(
OpKind::WriteSlice,
&[DType::I32, DType::I32][..],
write_slice::write_slice_b4 as KernelRef,
false,
),
(
OpKind::WriteSlice,
&[DType::I64, DType::I64][..],
write_slice::write_slice_b8 as KernelRef,
false,
),
(
OpKind::WriteSlice,
&[DType::U32, DType::U32][..],
write_slice::write_slice_b4 as KernelRef,
false,
),
(
OpKind::WriteSlice,
&[DType::U8, DType::U8][..],
write_slice::write_slice_b1 as KernelRef,
false,
),
(
OpKind::WriteSlice,
&[DType::I8, DType::I8][..],
write_slice::write_slice_b1 as KernelRef,
false,
),
(
OpKind::WriteSliceRotating,
&[DType::F32, DType::F32][..],
write_slice_rotating::write_slice_rotating_b4 as KernelRef,
false,
),
(
OpKind::WriteSliceRotating,
&[DType::F64, DType::F64][..],
write_slice_rotating::write_slice_rotating_b8 as KernelRef,
false,
),
(
OpKind::WriteSliceRotating,
&[DType::F16, DType::F16][..],
write_slice_rotating::write_slice_rotating_b2 as KernelRef,
false,
),
(
OpKind::WriteSliceRotating,
&[DType::BF16, DType::BF16][..],
write_slice_rotating::write_slice_rotating_b2 as KernelRef,
false,
),
(
OpKind::WriteSliceRotating,
&[DType::I32, DType::I32][..],
write_slice_rotating::write_slice_rotating_b4 as KernelRef,
false,
),
(
OpKind::WriteSliceRotating,
&[DType::I64, DType::I64][..],
write_slice_rotating::write_slice_rotating_b8 as KernelRef,
false,
),
(
OpKind::WriteSliceRotating,
&[DType::U32, DType::U32][..],
write_slice_rotating::write_slice_rotating_b4 as KernelRef,
false,
),
(
OpKind::WriteSliceRotating,
&[DType::U8, DType::U8][..],
write_slice_rotating::write_slice_rotating_b1 as KernelRef,
false,
),
(
OpKind::WriteSliceRotating,
&[DType::I8, DType::I8][..],
write_slice_rotating::write_slice_rotating_b1 as KernelRef,
false,
),
(
OpKind::WriteSliceDoff,
&[DType::F32, DType::F32][..],
write_slice_doff::write_slice_doff_b4 as KernelRef,
false,
),
(
OpKind::WriteSliceDoff,
&[DType::F64, DType::F64][..],
write_slice_doff::write_slice_doff_b8 as KernelRef,
false,
),
(
OpKind::WriteSliceDoff,
&[DType::F16, DType::F16][..],
write_slice_doff::write_slice_doff_b2 as KernelRef,
false,
),
(
OpKind::WriteSliceDoff,
&[DType::BF16, DType::BF16][..],
write_slice_doff::write_slice_doff_b2 as KernelRef,
false,
),
(
OpKind::WriteSliceDoff,
&[DType::I32, DType::I32][..],
write_slice_doff::write_slice_doff_b4 as KernelRef,
false,
),
(
OpKind::WriteSliceDoff,
&[DType::I64, DType::I64][..],
write_slice_doff::write_slice_doff_b8 as KernelRef,
false,
),
(
OpKind::WriteSliceDoff,
&[DType::U32, DType::U32][..],
write_slice_doff::write_slice_doff_b4 as KernelRef,
false,
),
(
OpKind::WriteSliceDoff,
&[DType::U8, DType::U8][..],
write_slice_doff::write_slice_doff_b1 as KernelRef,
false,
),
(
OpKind::WriteSliceDoff,
&[DType::I8, DType::I8][..],
write_slice_doff::write_slice_doff_b1 as KernelRef,
false,
),
];
let mut checked = 0usize;
for (op, key, expected, want_strided) in cases {
let alts = table.lookup_alternatives(*op, key, cuda);
let entry = alts
.iter()
.find(|e| e.kernel as usize == *expected as usize)
.unwrap_or_else(|| {
panic!(
"{op:?} {key:?}/Cuda: the production wrapper must be bound FROM the cuda \
contract in register_baracuda_cuda_kernels - found {} alternative(s) with \
sources {:?}",
alts.len(),
alts.iter().map(|e| e.kernel_source).collect::<Vec<_>>(),
)
});
assert_eq!(
entry.kernel_source, "baracuda",
"{op:?} {key:?}: family must be contract-sourced (kernel_source=\"baracuda\"); got {:?}",
entry.kernel_source,
);
assert_eq!(
entry.caps.strided_input, *want_strided,
"{op:?} {key:?}: caps preserved (strided_input == {want_strided})",
);
checked += 1;
}
assert_eq!(checked, 27, "all 27 group4 keys checked");
}
#[test]
fn register_baracuda_binds_group5_multiop_families_from_contract() {
let mut table = KernelBindingTable::new();
register_baracuda_cuda_kernels(&mut table);
let cuda = BackendId::Cuda;
let cases: &[(OpKind, &[DType], KernelRef, bool)] = &[
(
OpKind::Concat,
&[DType::F32, DType::F32][..],
concat::concat_f32 as KernelRef,
true,
),
(
OpKind::Concat,
&[DType::F16, DType::F16][..],
concat::concat_f16 as KernelRef,
true,
),
(
OpKind::Concat,
&[DType::BF16, DType::BF16][..],
concat::concat_bf16 as KernelRef,
true,
),
(
OpKind::Concat,
&[DType::F64, DType::F64][..],
concat::concat_f64 as KernelRef,
true,
),
(
OpKind::Affine,
&[DType::F32, DType::F32][..],
affine::affine_f32 as KernelRef,
true,
),
(
OpKind::Affine,
&[DType::F64, DType::F64][..],
affine::affine_f64 as KernelRef,
true,
),
(
OpKind::Affine,
&[DType::F16, DType::F16][..],
affine::affine_f16 as KernelRef,
true,
),
(
OpKind::Affine,
&[DType::BF16, DType::BF16][..],
affine::affine_bf16 as KernelRef,
true,
),
(
OpKind::Affine,
&[DType::I32, DType::I32][..],
affine::affine_i32 as KernelRef,
true,
),
(
OpKind::Affine,
&[DType::I64, DType::I64][..],
affine::affine_i64 as KernelRef,
true,
),
(
OpKind::Affine,
&[DType::U8, DType::U8][..],
affine::affine_u8 as KernelRef,
true,
),
(
OpKind::InplaceAffine,
&[DType::F32, DType::F32][..],
affine::affine_inplace_f32 as KernelRef,
false,
),
(
OpKind::InplaceAffine,
&[DType::F64, DType::F64][..],
affine::affine_inplace_f64 as KernelRef,
false,
),
(
OpKind::InplaceAffine,
&[DType::BF16, DType::BF16][..],
affine::affine_inplace_bf16 as KernelRef,
false,
),
(
OpKind::InplaceAffine,
&[DType::F16, DType::F16][..],
affine::affine_inplace_f16 as KernelRef,
false,
),
(
OpKind::Pad,
&[DType::F32, DType::F32][..],
pad::pad_f32 as KernelRef,
false,
),
(
OpKind::Pad,
&[DType::F16, DType::F16][..],
pad::pad_f16 as KernelRef,
false,
),
(
OpKind::Pad,
&[DType::BF16, DType::BF16][..],
pad::pad_bf16 as KernelRef,
false,
),
(
OpKind::Pad,
&[DType::F64, DType::F64][..],
pad::pad_f64 as KernelRef,
false,
),
(
OpKind::PadBackward,
&[DType::F32, DType::F32][..],
pad::pad_backward_f32 as KernelRef,
false,
),
(
OpKind::PadBackward,
&[DType::F16, DType::F16][..],
pad::pad_backward_f16 as KernelRef,
false,
),
(
OpKind::PadBackward,
&[DType::BF16, DType::BF16][..],
pad::pad_backward_bf16 as KernelRef,
false,
),
(
OpKind::PadBackward,
&[DType::F64, DType::F64][..],
pad::pad_backward_f64 as KernelRef,
false,
),
(
OpKind::CausalConv1d,
&[DType::F32, DType::F32, DType::F32, DType::F32][..],
conv1d::causal_conv1d_f32 as KernelRef,
false,
),
(
OpKind::CausalConv1d,
&[DType::F64, DType::F64, DType::F64, DType::F64][..],
conv1d::causal_conv1d_f64 as KernelRef,
false,
),
(
OpKind::CausalConv1d,
&[DType::BF16, DType::BF16, DType::BF16, DType::BF16][..],
conv1d::causal_conv1d_bf16 as KernelRef,
false,
),
(
OpKind::CausalConv1d,
&[DType::F16, DType::F16, DType::F16, DType::F16][..],
conv1d::causal_conv1d_f16 as KernelRef,
false,
),
];
let mut checked = 0usize;
for (op, key, expected, want_strided) in cases {
let alts = table.lookup_alternatives(*op, key, cuda);
let entry = alts
.iter()
.find(|e| e.kernel as usize == *expected as usize)
.unwrap_or_else(|| {
panic!(
"{op:?} {key:?}/Cuda: the production wrapper must be bound FROM the cuda \
contract in register_baracuda_cuda_kernels - found {} alternative(s) with \
sources {:?}",
alts.len(),
alts.iter().map(|e| e.kernel_source).collect::<Vec<_>>(),
)
});
assert_eq!(
entry.kernel_source, "baracuda",
"{op:?} {key:?}: family must be contract-sourced (kernel_source=\"baracuda\"); got {:?}",
entry.kernel_source,
);
assert_eq!(
entry.caps.strided_input, *want_strided,
"{op:?} {key:?}: caps preserved (strided_input == {want_strided})",
);
checked += 1;
}
assert_eq!(checked, 27, "all 27 group5 keys checked");
}
#[test]
fn register_baracuda_binds_group6_matmul_facades_from_contract() {
let mut table = KernelBindingTable::new();
register_baracuda_cuda_kernels(&mut table);
let cuda = BackendId::Cuda;
let cases: &[(OpKind, &[DType], KernelRef, bool)] = &[
(
OpKind::MatMul,
&[DType::F32, DType::F32, DType::F32][..],
gemm_dense::matmul_f32 as KernelRef,
false,
),
(
OpKind::MatMul,
&[DType::F16, DType::F16, DType::F16][..],
gemm_dense::matmul_f16 as KernelRef,
false,
),
(
OpKind::MatMul,
&[DType::BF16, DType::BF16, DType::BF16][..],
gemm_dense::matmul_bf16 as KernelRef,
false,
),
(
OpKind::MatMul,
&[DType::F64, DType::F64, DType::F64][..],
gemm_dense::matmul_f64 as KernelRef,
false,
),
(
OpKind::MatMul,
&[DType::I8, DType::I8, DType::I8][..],
gemm_int::gemm_s8_rrr as KernelRef,
false,
),
(
OpKind::MatMul,
&[DType::U8, DType::U8, DType::U8][..],
gemm_int::gemm_u8_rrr as KernelRef,
false,
),
];
let mut checked = 0usize;
for (op, key, expected, want_strided) in cases {
let alts = table.lookup_alternatives(*op, key, cuda);
let entry = alts
.iter()
.find(|e| e.kernel as usize == *expected as usize)
.unwrap_or_else(|| {
panic!(
"{op:?} {key:?}/Cuda: the production wrapper must be bound FROM the cuda \
contract in register_baracuda_cuda_kernels - found {} alternative(s) with \
sources {:?}",
alts.len(),
alts.iter().map(|e| e.kernel_source).collect::<Vec<_>>(),
)
});
assert_eq!(
entry.kernel_source, "baracuda",
"{op:?} {key:?}: family must be contract-sourced (kernel_source=\"baracuda\"); got {:?}",
entry.kernel_source,
);
assert_eq!(
entry.caps.strided_input, *want_strided,
"{op:?} {key:?}: caps preserved (strided_input == {want_strided})",
);
checked += 1;
}
assert_eq!(checked, 6, "all 6 group6 keys checked");
}
#[test]
fn register_baracuda_binds_indexing_from_contract() {
let mut table = KernelBindingTable::new();
register_baracuda_cuda_kernels(&mut table);
let cuda = BackendId::Cuda;
let u32 = DType::U32;
let mask = DType::Bool;
let cases: &[(OpKind, &[DType], KernelRef)] = &[
(
OpKind::IndexSelect,
&[DType::F32, u32, DType::F32][..],
indexing::index_select_f32 as KernelRef,
),
(
OpKind::IndexSelect,
&[DType::F64, u32, DType::F64][..],
indexing::index_select_f64 as KernelRef,
),
(
OpKind::IndexSelect,
&[DType::I32, u32, DType::I32][..],
indexing::index_select_i32 as KernelRef,
),
(
OpKind::Gather,
&[DType::F32, u32, DType::F32][..],
indexing::gather_f32 as KernelRef,
),
(
OpKind::Gather,
&[DType::F64, u32, DType::F64][..],
indexing::gather_f64 as KernelRef,
),
(
OpKind::Gather,
&[DType::I32, u32, DType::I32][..],
indexing::gather_i32 as KernelRef,
),
(
OpKind::MaskedFill,
&[DType::F32, mask, DType::F32][..],
indexing::masked_fill_f32 as KernelRef,
),
(
OpKind::MaskedFill,
&[DType::F64, mask, DType::F64][..],
indexing::masked_fill_f64 as KernelRef,
),
(
OpKind::MaskedFill,
&[DType::I32, mask, DType::I32][..],
indexing::masked_fill_i32 as KernelRef,
),
(
OpKind::ScatterAdd,
&[DType::F32, u32, DType::F32, DType::F32][..],
indexing::scatter_add_f32 as KernelRef,
),
(
OpKind::ScatterAdd,
&[DType::F64, u32, DType::F64, DType::F64][..],
indexing::scatter_add_f64 as KernelRef,
),
];
let mut checked = 0usize;
for (op, key, expected) in cases {
let alts = table.lookup_alternatives(*op, key, cuda);
let entry = alts
.iter()
.find(|e| e.kernel as usize == *expected as usize)
.unwrap_or_else(|| {
panic!(
"{op:?} {key:?}/Cuda: the production wrapper must be bound FROM the cuda \
indexing contract in register_baracuda_cuda_kernels - found {} alternative(s) \
with sources {:?}",
alts.len(),
alts.iter().map(|e| e.kernel_source).collect::<Vec<_>>(),
)
});
assert_eq!(
entry.kernel_source, "baracuda",
"{op:?} {key:?}: family must be contract-sourced (kernel_source=\"baracuda\"); got {:?}",
entry.kernel_source,
);
assert_eq!(
entry.caps.strided_input, false,
"{op:?} {key:?}: caps preserved (strided_input == false)",
);
checked += 1;
}
assert_eq!(checked, 11, "all 11 indexing keys checked");
}
#[test]
fn register_baracuda_binds_flash_decoding_from_contract_with_cost_gate() {
let mut table = KernelBindingTable::new();
register_baracuda_cuda_kernels(&mut table);
let cuda = BackendId::Cuda;
let caps = fuel_ir::backend::BackendCapabilities {
backend_id: BackendId::Cuda,
device_location: fuel_ir::DeviceLocation::Cpu,
op_dtype_support: std::collections::HashSet::new(),
required_alignment: 1,
access_granularity_bits: 8,
transfer_paths: vec![],
storage_substrate: fuel_ir::backend::SubstrateClass::HostBytes,
compute_throughput_flops_per_ns: 1.0,
mem_bandwidth_bytes_per_ns: 4.0,
};
let cases: &[(&[DType], KernelRef)] = &[
(
&[DType::F16, DType::F16, DType::F16, DType::F16][..],
flash_decoding::flash_decoding_f16 as KernelRef,
),
(
&[DType::BF16, DType::BF16, DType::BF16, DType::BF16][..],
flash_decoding::flash_decoding_bf16 as KernelRef,
),
];
for (key, expected) in cases {
let alts = table.lookup_alternatives(OpKind::FlashAttn, key, cuda);
let entry = alts
.iter()
.find(|e| e.kernel as usize == *expected as usize)
.unwrap_or_else(|| {
panic!(
"FlashAttn {key:?}/Cuda: the flash_decoding wrapper must be bound FROM the \
cuda flash_decoding contract - found {} alternative(s) with sources {:?}",
alts.len(),
alts.iter().map(|e| e.kernel_source).collect::<Vec<_>>(),
)
});
assert_eq!(
entry.kernel_source, "baracuda",
"FlashAttn {key:?}: flash_decoding must be contract-sourced \
(kernel_source=\"baracuda\"); got {:?}",
entry.kernel_source,
);
assert!(
entry.caps.strided_input,
"FlashAttn {key:?}: caps preserved (strided_input == true, capacity-strided)",
);
assert_eq!(
entry.cost as usize,
crate::cost::cost_flash_decoding_cuda as usize,
"FlashAttn {key:?}: the contract-pinned cost_flash_decoding_cuda must survive \
fill_unset (Task-F trampoline) — else fill_unset clobbered the gate",
);
let dt = key[0];
let out = fuel_ir::Shape::from_dims(&[1, 8, 1, 64]);
let bad_sq = OpParams::FlashAttn {
b: 1,
hq: 8,
hkv: 8,
sq: 2,
sk: 16,
d: 64,
k_len: 16,
softmax_scale: 1.0,
causal: true,
window_size_left: None,
window_size_right: None,
softcap: None,
};
assert_eq!(
(entry.cost)(&[out.clone()], &[dt], &bad_sq, &caps).flops,
u64::MAX,
"FlashAttn {key:?}: seq_q!=1 must be INFEASIBLE (gate preserved)",
);
let bad_d = OpParams::FlashAttn {
b: 1,
hq: 8,
hkv: 8,
sq: 1,
sk: 16,
d: 256,
k_len: 16,
softmax_scale: 1.0,
causal: true,
window_size_left: None,
window_size_right: None,
softcap: None,
};
assert_eq!(
(entry.cost)(&[out.clone()], &[dt], &bad_d, &caps).flops,
u64::MAX,
"FlashAttn {key:?}: head_dim>128 must be INFEASIBLE (gate preserved)",
);
let good = OpParams::FlashAttn {
b: 1,
hq: 8,
hkv: 8,
sq: 1,
sk: 16,
d: 64,
k_len: 16,
softmax_scale: 1.0,
causal: true,
window_size_left: None,
window_size_right: None,
softcap: None,
};
assert_ne!(
(entry.cost)(&[out], &[dt], &good, &caps).flops,
u64::MAX,
"FlashAttn {key:?}: a supported decode shape must be FEASIBLE (real gate, not a constant)",
);
}
}
}