luma-cuda 0.3.2

luma cuda implement
use luma_tensor::Layout;
use crate::kernel;
use crate::{Cuda, CudaError, CudaResult};
use cudarc::driver::{CudaSlice, DeviceRepr, LaunchConfig, PushKernelArg};

pub(crate) fn launch_pick<T: DeviceRepr>(
    device: &Cuda,
    val_suffix: &str,
    module: &kernel::Module,
    mask: &CudaSlice<u8>,
    mask_l: &Layout,
    t: &CudaSlice<T>,
    true_l: &Layout,
    f: &CudaSlice<T>,
    false_l: &Layout,
) -> CudaResult<CudaSlice<T>> {
    let kernel_name = format!("pick_{}", val_suffix);
    let dims = mask_l.dims();
    let elem_count = mask_l.shape().element_count();
    let num_dims = dims.len();
    let func = device.load_function(&kernel_name, module)?;

    let mut builder = func.builder();

    let dims = device.memcpy_stod(dims)?;
    let mask_strides = device.memcpy_stod(mask_l.stride())?;
    let t_strides = device.memcpy_stod(true_l.stride())?;
    let f_strides = device.memcpy_stod(false_l.stride())?;

    let mask_view = mask.slice(mask_l.start_offset()..);
    let t_view = t.slice(true_l.start_offset()..);
    let f_view = f.slice(false_l.start_offset()..);
    let output = device.alloc::<T>(elem_count)?;

    builder.arg(&elem_count);
    builder.arg(&num_dims);
    builder.arg(&dims);
    builder.arg(&mask_strides);
    builder.arg(&t_strides);
    builder.arg(&f_strides);
    builder.arg(&mask_view);
    builder.arg(&t_view);
    builder.arg(&f_view);
    builder.arg(&output);

    let config = LaunchConfig::for_num_elems(elem_count as u32);
    unsafe { builder.launch(config) }.map_err(CudaError::CudaDriver)?;
    Ok(output)
}

#[allow(unused_variables)]
pub(crate) fn launch_pick_true<T: DeviceRepr, I: DeviceRepr>(
    device: &Cuda,
    val_suffix: &str,
    module: &kernel::Module,
    mask: &CudaSlice<I>,
    mask_l: &Layout,
    val: T,
    f: &CudaSlice<T>,
    false_l: &Layout,
) -> CudaResult<CudaSlice<T>> {
    let kernel_name = format!("pick_true_{}", val_suffix);
    let dims = mask_l.dims();
    let elem_count = mask_l.shape().element_count();
    let num_dims = dims.len();
    let func = device.load_function(&kernel_name, module)?;

    let mut builder = func.builder();

    let dims = device.memcpy_stod(dims)?;
    let mask_strides = device.memcpy_stod(mask_l.stride())?;
    let f_strides = device.memcpy_stod(false_l.stride())?;

    let mask_view = mask.slice(mask_l.start_offset()..);
    let f_view = f.slice(false_l.start_offset()..);
    let output = device.alloc::<T>(elem_count)?;

    builder.arg(&elem_count);
    builder.arg(&num_dims);
    builder.arg(&dims);
    builder.arg(&mask_strides);
    builder.arg(&f_strides);
    builder.arg(&mask_view);
    builder.arg(&val);
    builder.arg(&f_view);
    builder.arg(&output);

    let config = LaunchConfig::for_num_elems(elem_count as u32);
    unsafe { builder.launch(config) }.map_err(CudaError::CudaDriver)?;
    Ok(output)
}

#[allow(unused_variables)]
pub(crate) fn launch_pick_false<T: DeviceRepr, I: DeviceRepr>(
    device: &Cuda,
    val_suffix: &str,
    module: &kernel::Module,
    mask: &CudaSlice<I>,
    mask_l: &Layout,
    t: &CudaSlice<T>,
    true_l: &Layout,
    val: T,
) -> CudaResult<CudaSlice<T>> {
    let kernel_name = format!("pick_false_{}", val_suffix);
    let dims = mask_l.dims();
    let elem_count = mask_l.shape().element_count();
    let num_dims = dims.len();
    let func = device.load_function(&kernel_name, module)?;

    let mut builder = func.builder();

    let dims = device.memcpy_stod(dims)?;
    let mask_strides = device.memcpy_stod(mask_l.stride())?;
    let t_strides = device.memcpy_stod(true_l.stride())?;

    let mask_view = mask.slice(mask_l.start_offset()..);
    let t_view = t.slice(true_l.start_offset()..);
    let output = device.alloc::<T>(elem_count)?;

    builder.arg(&elem_count);
    builder.arg(&num_dims);
    builder.arg(&dims);
    builder.arg(&mask_strides);
    builder.arg(&t_strides);
    builder.arg(&mask_view);
    builder.arg(&t_view);
    builder.arg(&val);
    builder.arg(&output);

    let config = LaunchConfig::for_num_elems(elem_count as u32);
    unsafe { builder.launch(config) }.map_err(CudaError::CudaDriver)?;
    Ok(output)
}