libmir-cuda 0.2.0

CUDA inference backend for libmir
use mircuda::{
    CompileOptions, Compiler, DeviceBuffer, LaunchConfig, Stream, TypedKernel, bf16, cuda_export,
    cuda_kernel_file,
};

use super::geometry::{narrow, product, require};
use crate::{Error, Result};

cuda_export!(
    RmsNormShiftKernel = "libmir_cuda_rms_norm_shift_bf16"(
        input: &DeviceBuffer<bf16>, weight: &DeviceBuffer<bf16>,
        output: &mut DeviceBuffer<bf16>, rows: u32, columns: u32,
        epsilon: f32, weight_shift: f32,
    )
);

#[derive(Clone, Debug)]
pub struct ShiftedRmsNorm {
    kernel: TypedKernel<RmsNormShiftKernel>,
    rows: usize,
    columns: usize,
    epsilon: f32,
    weight_shift: f32,
}

impl ShiftedRmsNorm {
    pub fn compile(
        compiler: &Compiler,
        rows: usize,
        columns: usize,
        epsilon: f32,
        weight_shift: f32,
    ) -> Result<Self> {
        if rows == 0
            || columns == 0
            || !epsilon.is_finite()
            || epsilon < 0.0
            || !weight_shift.is_finite()
        {
            return Err(Error::InvalidDecoderKernel("invalid shifted RMSNorm geometry"));
        }
        let source = cuda_kernel_file!("../../kernels/rms_norm_shift_bf16.cu");
        let module = compiler.compile(source, &CompileOptions::default())?;
        Ok(Self {
            kernel: module.kernel()?,
            rows,
            columns,
            epsilon,
            weight_shift,
        })
    }

    pub fn execute(
        &self,
        stream: &Stream,
        input: &DeviceBuffer<bf16>,
        weight: &DeviceBuffer<bf16>,
        output: &mut DeviceBuffer<bf16>,
    ) -> Result<()> {
        let elements = product(self.rows, self.columns)?;
        require("shifted RMSNorm input", elements, input.len())?;
        require("shifted RMSNorm weight", self.columns, weight.len())?;
        require("shifted RMSNorm output", elements, output.len())?;
        Ok(self.kernel.launch(
            stream,
            LaunchConfig {
                grid: (narrow(self.rows)?, 1, 1),
                block: (256, 1, 1),
                shared_memory_bytes: 0,
            },
            (
                input,
                weight,
                output,
                narrow(self.rows)?,
                narrow(self.columns)?,
                self.epsilon,
                self.weight_shift,
            ),
        )?)
    }
}