libmir-cuda 0.1.0

CUDA inference backend for libmir
use super::CudaOutputHeadTemplate;
use crate::{
    CudaBackend, CudaOutputHead, DensePlanRequest, DenseRole, Error, ExecutionPhase,
    OutputHeadExecution, Result, backend::output::projection::OutputHeadWeight,
};

impl CudaOutputHeadTemplate {
    pub(crate) fn instantiate(&self, backend: &CudaBackend) -> Result<CudaOutputHead> {
        match &self.weight {
            OutputHeadWeight::Bf16(weight) => Ok(CudaOutputHead::bf16(
                backend.prepare_bf16_projection(DensePlanRequest {
                    phase: ExecutionPhase::Decode,
                    role: DenseRole::OutputHead,
                    tokens: 1,
                    input_features: self.input_features,
                    output_features: self.output_features,
                })?,
                weight.clone(),
                backend.inner.stream.clone(),
            )),
            OutputHeadWeight::Fp8 { weight, scales, row_scales } => {
                self.instantiate_fp8(backend, weight, scales, row_scales)
            },
            OutputHeadWeight::Fp8Residual {
                weight,
                row_scales,
                residual,
                residual_scales,
            } => Ok(CudaOutputHead::fp8_residual(
                self.kernels
                    .clone()
                    .ok_or(Error::InvalidExecutionPlan("missing residual output kernels"))?,
                weight.clone(),
                row_scales.clone(),
                residual.clone(),
                residual_scales.clone(),
                backend.inner.stream.clone(),
            )),
            OutputHeadWeight::Fp8BlockVectorized { kernels, weight, scales } => {
                Ok(CudaOutputHead::fp8_block_vectorized(
                    kernels.clone(),
                    weight.clone(),
                    scales.clone(),
                    backend.inner.stream.clone(),
                ))
            },
            OutputHeadWeight::Fp8BlockRefined {
                kernels,
                refinement,
                exact_tensor,
                exact_weight,
                weight,
                scales,
            } => match self.execution {
                OutputHeadExecution::AutoRefined => CudaOutputHead::auto_refined(
                    backend,
                    kernels.clone(),
                    refinement.clone(),
                    exact_tensor.clone(),
                    exact_weight.clone(),
                    weight.clone(),
                    scales.clone(),
                    self.input_features,
                    self.output_features,
                ),
                OutputHeadExecution::Fp8BlockRefined => CudaOutputHead::fp8_block_refined(
                    backend,
                    kernels.clone(),
                    refinement.clone(),
                    exact_weight.clone(),
                    weight.clone(),
                    scales.clone(),
                    self.output_features,
                ),
                _ => Err(Error::InvalidExecutionPlan(
                    "refined output storage differs from execution plan",
                )),
            },
        }
    }

    fn instantiate_fp8(
        &self,
        backend: &CudaBackend,
        weight: &mircuda::DeviceBuffer<u8>,
        scales: &mircuda::DeviceBuffer<f32>,
        row_scales: &mircuda::DeviceBuffer<f32>,
    ) -> Result<CudaOutputHead> {
        let kernels = self
            .kernels
            .clone()
            .ok_or(Error::InvalidExecutionPlan("missing FP8 output kernels"))?;
        match self.execution {
            OutputHeadExecution::Fp8Blockwise => CudaOutputHead::fp8(
                backend,
                kernels,
                weight.clone(),
                scales.clone(),
                row_scales.clone(),
                self.input_features,
                self.output_features,
            ),
            OutputHeadExecution::Fp8Vectorized => Ok(CudaOutputHead::fp8_vectorized(
                kernels,
                weight.clone(),
                row_scales.clone(),
                backend.inner.stream.clone(),
            )),
            _ => Err(Error::InvalidExecutionPlan(
                "per-row FP8 output storage differs from execution plan",
            )),
        }
    }
}