use openvm_cuda_common::{
d_buffer::DeviceBuffer,
error::{check, CudaError},
stream::cudaStream_t,
};
use crate::{
cuda::LOG_WARP_SIZE,
prelude::{EF, F},
};
extern "C" {
fn _mle_interpolate_stage(
buffer: *mut F,
total_len: usize,
step: u32,
is_eval_to_coeff: bool,
stream: cudaStream_t,
) -> i32;
fn _mle_interpolate_stage_ext(
buffer: *mut EF,
total_len: usize,
step: u32,
is_eval_to_coeff: bool,
stream: cudaStream_t,
) -> i32;
fn _mle_interpolate_stage_2d(
buffer: *mut F,
width: u16,
height: u32,
padded_height: u32,
step: u32,
is_eval_to_coeff: bool,
stream: cudaStream_t,
) -> i32;
fn _mle_interpolate_fused_2d(
buffer: *mut F,
width: u16,
padded_height: u32,
log_stride: u32,
start_step: u32,
num_stages: u32,
is_eval_to_coeff: bool,
right_pad: bool,
stream: cudaStream_t,
) -> i32;
fn _mle_interpolate_shared_2d(
buffer: *mut F,
width: u16,
padded_height: u32,
log_stride: u32,
start_log_step: u32,
end_log_step: u32,
is_eval_to_coeff: bool,
right_pad: bool,
stream: cudaStream_t,
) -> i32;
}
#[inline]
fn narrow_mle_width(width: usize) -> Result<u16, CudaError> {
if width > u16::MAX as usize {
return Err(CudaError::new(1));
}
Ok(width as u16)
}
pub unsafe fn mle_interpolate_stage(
buffer: &mut DeviceBuffer<F>,
step: u32,
is_eval_to_coeff: bool,
stream: cudaStream_t,
) -> Result<(), CudaError> {
check(_mle_interpolate_stage(
buffer.as_mut_ptr(),
buffer.len(),
step,
is_eval_to_coeff,
stream,
))
}
pub unsafe fn mle_interpolate_stage_ext(
buffer: &mut DeviceBuffer<EF>,
step: u32,
is_eval_to_coeff: bool,
stream: cudaStream_t,
) -> Result<(), CudaError> {
check(_mle_interpolate_stage_ext(
buffer.as_mut_ptr(),
buffer.len(),
step,
is_eval_to_coeff,
stream,
))
}
pub unsafe fn mle_interpolate_stage_2d(
buffer: *mut F,
width: usize,
height: u32,
padded_height: u32,
step: u32,
is_eval_to_coeff: bool,
stream: cudaStream_t,
) -> Result<(), CudaError> {
let width = narrow_mle_width(width)?;
debug_assert!(height <= padded_height);
debug_assert_eq!(padded_height % (step * 2), 0);
check(_mle_interpolate_stage_2d(
buffer,
width,
height,
padded_height,
step,
is_eval_to_coeff,
stream,
))
}
#[allow(clippy::too_many_arguments)]
pub unsafe fn mle_interpolate_fused_2d(
buffer: *mut F,
width: usize,
padded_height: u32,
log_stride: u32,
start_step: u32,
num_stages: u32,
is_eval_to_coeff: bool,
right_pad: bool,
stream: cudaStream_t,
) -> Result<(), CudaError> {
let width = narrow_mle_width(width)?;
debug_assert!((1..=LOG_WARP_SIZE as u32).contains(&num_stages));
debug_assert!((start_step << (num_stages - 1)) <= 16);
check(_mle_interpolate_fused_2d(
buffer,
width,
padded_height,
log_stride,
start_step,
num_stages,
is_eval_to_coeff,
right_pad,
stream,
))
}
pub const MLE_SHARED_TILE_LOG_SIZE: u32 = 12;
#[allow(clippy::too_many_arguments)]
pub unsafe fn mle_interpolate_shared_2d(
buffer: *mut F,
width: usize,
padded_height: u32,
log_stride: u32,
start_log_step: u32,
end_log_step: u32,
is_eval_to_coeff: bool,
right_pad: bool,
stream: cudaStream_t,
) -> Result<(), CudaError> {
let width = narrow_mle_width(width)?;
debug_assert!(end_log_step < MLE_SHARED_TILE_LOG_SIZE);
check(_mle_interpolate_shared_2d(
buffer,
width,
padded_height,
log_stride,
start_log_step,
end_log_step,
is_eval_to_coeff,
right_pad,
stream,
))
}