libmir-cuda 0.1.0

CUDA inference backend for libmir
use mircuda::{CompileOptions, Compiler, LaunchConfig, Stream, cuda_kernel_files};

use super::{
    NvFp4BankView, NvFp4MicroDownKernels, NvFp4MicroDownLaunch, NvFp4MicroSpec, activation,
    spec::require_len, validate_bank,
};
use crate::Result;

impl NvFp4MicroDownKernels {
    pub fn compile(compiler: &Compiler, spec: NvFp4MicroSpec) -> Result<Self> {
        spec.validate()?;
        let source = cuda_kernel_files!(
            "nvfp4_micro_down.cu";
            "../../../kernels/nvfp4_micro_common.cuh",
            "../../../kernels/nvfp4_micro_down.cu",
        );
        let module = compiler.compile(source, &CompileOptions::default())?;
        Ok(Self {
            gated_quantize: module.kernel()?,
            fc2: module.kernel()?,
            spec,
        })
    }

    #[allow(clippy::needless_pass_by_value)]
    pub fn execute(&self, stream: &Stream, launch: NvFp4MicroDownLaunch<'_>) -> Result<()> {
        self.validate(&launch)?;
        let spec = self.spec;
        let groups = spec.groups()?;
        self.gated_quantize.launch(
            stream,
            LaunchConfig {
                grid: (u32::try_from(groups * spec.intermediate / 16)?, 1, 1),
                block: (32, 1, 1),
                shared_memory_bytes: 0,
            },
            (
                launch.gate,
                launch.up,
                launch.selected,
                launch.down.input_globals,
                &mut *launch.workspace.packed,
                &mut *launch.workspace.scales,
                u32::try_from(groups)?,
                u32::try_from(spec.intermediate)?,
                activation(spec.activation),
            ),
        )?;
        self.execute_prepared(
            stream,
            &*launch.workspace.packed,
            &*launch.workspace.scales,
            launch.selected,
            launch.routing,
            launch.down,
            launch.output,
        )
    }

    #[allow(clippy::too_many_arguments)]
    pub(super) fn execute_prepared(
        &self,
        stream: &Stream,
        packed: &mircuda::DeviceBuffer<u8>,
        scales: &mircuda::DeviceBuffer<u8>,
        selected: &mircuda::DeviceBuffer<u32>,
        routing: &mircuda::DeviceBuffer<mircuda::bf16>,
        down: NvFp4BankView<'_>,
        output: &mut mircuda::DeviceBuffer<mircuda::bf16>,
    ) -> Result<()> {
        let spec = self.spec;
        Ok(self.fc2.launch(
            stream,
            LaunchConfig {
                grid: (u32::try_from(spec.hidden.div_ceil(8))?, u32::try_from(spec.tokens)?, 1),
                block: (256, 1, 1),
                shared_memory_bytes: 0,
            },
            (
                packed,
                scales,
                selected,
                routing,
                down.weight,
                down.scales,
                down.combined,
                output,
                u32::try_from(spec.intermediate)?,
                u32::try_from(spec.hidden)?,
                u32::try_from(spec.selected)?,
                u32::try_from(spec.tokens)?,
            ),
        )?)
    }

    fn validate(&self, launch: &NvFp4MicroDownLaunch<'_>) -> Result<()> {
        let spec = self.spec;
        let groups = spec.groups()?;
        require_len("micro down gate", groups * spec.intermediate, launch.gate.len())?;
        require_len("micro down up", groups * spec.intermediate, launch.up.len())?;
        require_len("micro down selected", groups, launch.selected.len())?;
        require_len("micro down routing", groups, launch.routing.len())?;
        require_len(
            "micro down packed",
            groups * spec.intermediate / 2,
            launch.workspace.packed.len(),
        )?;
        require_len(
            "micro down scales",
            groups * spec.intermediate / 16,
            launch.workspace.scales.len(),
        )?;
        require_len("micro down output", spec.tokens * spec.hidden, launch.output.len())?;
        validate_bank(launch.down, spec.experts, spec.intermediate, spec.hidden)
    }
}