libmir-cuda 0.3.0

CUDA inference backend for libmir
use super::DenseDownSource;
use crate::{
    AffineQuantizedWeight, BlockFp8LinearWeight, CudaBackend, CudaTensor, DenseDownWeight,
    DenseExecution, DensePlanRequest, DenseRole, DirectFp8CheckpointWeight, Error, ExecutionPhase,
    Fp8ResidualLinearWeight, MxFp4CheckpointWeight, MxFp8CheckpointWeight, NvFp4LinearWeight,
    PackedIntegerWeight, Result,
};

#[derive(Clone)]
pub(super) enum DenseDownOwned {
    Affine(AffineQuantizedWeight),
    Bf16(CudaTensor),
    DirectFp8(DirectFp8CheckpointWeight),
    MxFp4(MxFp4CheckpointWeight),
    MxFp8(MxFp8CheckpointWeight),
    PackedInteger(PackedIntegerWeight),
    NvFp4(NvFp4LinearWeight),
    BlockFp8 {
        exact: CudaTensor,
        quantized: BlockFp8LinearWeight,
    },
    Fp8Int4 {
        exact: CudaTensor,
        quantized: Fp8ResidualLinearWeight,
    },
}

impl DenseDownOwned {
    pub(super) fn new(backend: &CudaBackend, source: DenseDownSource<'_>) -> Result<Self> {
        let DenseDownSource::Bf16(weight) = source else {
            return Ok(match source {
                DenseDownSource::Affine(weight) => Self::Affine(weight.clone()),
                DenseDownSource::PackedInteger(weight) => Self::PackedInteger(weight.clone()),
                DenseDownSource::DirectFp8(weight) => Self::DirectFp8(weight.clone()),
                DenseDownSource::MxFp4(weight) => Self::MxFp4(weight.clone()),
                DenseDownSource::MxFp8(weight) => Self::MxFp8(weight.clone()),
                DenseDownSource::NvFp4(weight) => Self::NvFp4(weight.clone()),
                DenseDownSource::Bf16(_) => unreachable!(),
            });
        };
        let [output_features, input_features] = weight.shape() else {
            return Err(Error::InvalidLinearWeight {
                name: weight.name().into(),
                expected: [0, 0],
                actual: weight.shape().to_vec(),
            });
        };
        let request = DensePlanRequest {
            phase: ExecutionPhase::Decode,
            role: DenseRole::DenseDown,
            tokens: 1,
            input_features: *input_features,
            output_features: *output_features,
        };
        Ok(
            match backend
                .execution_planner()
                .plan_dense_with_prepared_weights(request)?
                .execution()
            {
                DenseExecution::BlockFp8Vector => Self::BlockFp8 {
                    exact: weight.clone(),
                    quantized: backend.prepare_block_fp8_linear_weight(weight)?,
                },
                DenseExecution::Fp8Int4Vector => Self::Fp8Int4 {
                    exact: weight.clone(),
                    quantized: backend.prepare_fp8_residual_linear_weight(weight)?,
                },
                DenseExecution::Matrix | DenseExecution::Vector | DenseExecution::CublasLt => {
                    Self::Bf16(weight.clone())
                },
            },
        )
    }

    pub(super) fn borrow(&self) -> DenseDownWeight<'_> {
        match self {
            Self::Affine(weight) => DenseDownWeight::Affine(weight),
            Self::Bf16(weight) => DenseDownWeight::Bf16(weight),
            Self::DirectFp8(weight) => DenseDownWeight::DirectFp8(weight),
            Self::MxFp4(weight) => DenseDownWeight::MxFp4(weight),
            Self::MxFp8(weight) => DenseDownWeight::MxFp8(weight),
            Self::PackedInteger(weight) => DenseDownWeight::PackedInteger(weight),
            Self::NvFp4(weight) => DenseDownWeight::NvFp4(weight),
            Self::BlockFp8 { exact, quantized } => DenseDownWeight::BlockFp8 { exact, quantized },
            Self::Fp8Int4 { exact, quantized } => DenseDownWeight::Fp8Int4 { exact, quantized },
        }
    }
}