libmir-cuda 0.3.0

CUDA inference backend for libmir
use super::DenseGateUpSource;
use crate::{
    AffineQuantizedWeight, Bf16LinearPairWeights, BlockFp8LinearWeight, CudaBackend,
    DenseExecution, DenseGateUpWeights, DensePlanRequest, DenseRole, DirectFp8CheckpointWeight,
    ExecutionPhase, Fp8ResidualLinearWeight, MxFp4CheckpointWeight, MxFp8CheckpointWeight,
    NvFp4LinearWeight, PackedIntegerWeight, Result,
};

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

impl DenseGateUpOwned {
    pub(super) fn new(backend: &CudaBackend, source: DenseGateUpSource<'_>) -> Result<Self> {
        let DenseGateUpSource::Bf16(weights) = source else {
            return Ok(match source {
                DenseGateUpSource::Affine { gate, up } => {
                    Self::Affine { gate: gate.clone(), up: up.clone() }
                },
                DenseGateUpSource::PackedInteger { gate, up } => {
                    Self::PackedInteger { gate: gate.clone(), up: up.clone() }
                },
                DenseGateUpSource::DirectFp8 { gate, up } => {
                    Self::DirectFp8 { gate: gate.clone(), up: up.clone() }
                },
                DenseGateUpSource::MxFp4 { gate, up } => {
                    Self::MxFp4 { gate: gate.clone(), up: up.clone() }
                },
                DenseGateUpSource::MxFp8 { gate, up } => {
                    Self::MxFp8 { gate: gate.clone(), up: up.clone() }
                },
                DenseGateUpSource::NvFp4 { gate, up } => {
                    Self::NvFp4 { gate: gate.clone(), up: up.clone() }
                },
                DenseGateUpSource::Bf16(_) => unreachable!(),
            });
        };
        let request = DensePlanRequest {
            phase: ExecutionPhase::Decode,
            role: DenseRole::DenseGateUp,
            tokens: 1,
            input_features: weights.input_features(),
            output_features: weights.packed_output_features()?,
        };
        Ok(
            match backend
                .execution_planner()
                .plan_dense_with_prepared_weights(request)?
                .execution()
            {
                DenseExecution::BlockFp8Vector => Self::BlockFp8 {
                    exact: weights.clone(),
                    quantized: backend.prepare_block_fp8_linear_pair_weight(weights)?,
                },
                DenseExecution::Fp8Int4Vector => Self::Fp8Int4 {
                    exact: weights.clone(),
                    quantized: backend.prepare_fp8_residual_linear_pair_weight(weights)?,
                },
                DenseExecution::Matrix | DenseExecution::Vector | DenseExecution::CublasLt => {
                    Self::Bf16(weights.clone())
                },
            },
        )
    }

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