libmir-cuda 0.3.0

CUDA inference backend for libmir
use mircuda::{DeviceBuffer, bf16};

use crate::{
    AffineQuantizedEmbedding, Bf16Embedding, CudaBackend, DenseRole, Error, MxFp4EmbeddingLookup,
    Result,
    backend::linear::{
        CheckpointProjection, CheckpointProjectionWeight, CompressedInt8Embedding,
        packed_integer_embedding,
    },
};

#[derive(Debug)]
pub(super) enum SharedRoutedEmbedding {
    Affine {
        operation: AffineQuantizedEmbedding,
        weight: crate::AffineQuantizedWeight,
        vocab: usize,
    },
    Dense {
        operation: Bf16Embedding,
        weight: crate::CudaTensor,
        vocab: usize,
    },
    MxFp4(MxFp4EmbeddingLookup),
    PackedInteger {
        operation: CompressedInt8Embedding,
        vocab: usize,
    },
}

#[derive(Debug)]
pub(super) struct SharedRoutedOutputHead {
    operation: CheckpointProjection,
    hidden: usize,
    vocab: usize,
}

impl SharedRoutedEmbedding {
    pub(super) fn new(
        backend: &CudaBackend,
        hidden: usize,
        vocab: usize,
        weight: &CheckpointProjectionWeight,
    ) -> Result<Self> {
        weight.affine_format(1, hidden, vocab)?;
        match weight {
            CheckpointProjectionWeight::Affine(weight) => {
                let config = weight.infer_config(1, hidden, vocab)?;
                Ok(Self::Affine {
                    operation: backend.prepare_affine_embedding(config, 1.0)?,
                    weight: weight.clone(),
                    vocab,
                })
            },
            CheckpointProjectionWeight::Dense(weight) => Ok(Self::Dense {
                operation: backend.prepare_bf16_embedding(vocab, hidden, 1.0)?,
                weight: weight.clone(),
                vocab,
            }),
            CheckpointProjectionWeight::DirectFp8(_) => Err(Error::InvalidExecutionPlan(
                "shared routed embedding does not support direct FP8",
            )),
            CheckpointProjectionWeight::MxFp4(weight) => {
                weight.prepare_embedding(backend, 1.0).map(Self::MxFp4)
            },
            CheckpointProjectionWeight::MxFp8(_) => {
                Err(Error::InvalidExecutionPlan("shared routed embedding does not support MXFP8"))
            },
            CheckpointProjectionWeight::NvFp4(_)
            | CheckpointProjectionWeight::NvFp4WeightOnly(_) => {
                Err(Error::InvalidExecutionPlan("shared routed embedding does not support NVFP4"))
            },
            CheckpointProjectionWeight::PackedInteger(weight) => Ok(Self::PackedInteger {
                operation: packed_integer_embedding(backend, vocab, hidden, 1.0, weight.clone())?,
                vocab,
            }),
        }
    }

    pub(super) fn execute_batch(
        &self,
        selected: &DeviceBuffer<u32>,
        tokens: usize,
        output: &mut DeviceBuffer<bf16>,
    ) -> Result<()> {
        match self {
            Self::Affine { operation, weight, .. } => {
                operation.execute_batch(selected, 0, tokens, weight.tensors(), output)
            },
            Self::Dense { operation, weight, .. } => {
                operation.execute_batch(selected, 0, tokens, weight, output)
            },
            Self::PackedInteger { operation, .. } => {
                operation.execute_batch(selected, 0, tokens, output)
            },
            Self::MxFp4(operation) => operation.execute_batch(selected, 0, tokens, output),
        }
    }

    pub(super) fn validate_token(&self, token: u32) -> Result<()> {
        if let Self::MxFp4(operation) = self {
            return operation.validate_token(token);
        }
        let vocab = match self {
            Self::Affine { vocab, .. }
            | Self::Dense { vocab, .. }
            | Self::PackedInteger { vocab, .. } => *vocab,
            Self::MxFp4(_) => unreachable!(),
        };
        if usize::try_from(token)? < vocab {
            Ok(())
        } else {
            Err(Error::InvalidToken { token, vocab })
        }
    }
}

impl SharedRoutedOutputHead {
    pub(super) fn new(
        backend: &CudaBackend,
        hidden: usize,
        vocab: usize,
        weight: &CheckpointProjectionWeight,
    ) -> Result<Self> {
        Ok(Self {
            operation: CheckpointProjection::new(
                backend,
                1,
                hidden,
                vocab,
                DenseRole::OutputHead,
                weight,
            )?,
            hidden,
            vocab,
        })
    }

    pub(super) fn execute(
        &mut self,
        input: &DeviceBuffer<bf16>,
        output: &mut DeviceBuffer<bf16>,
    ) -> Result<()> {
        if input.len() != self.hidden || output.len() != self.vocab {
            return Err(Error::InvalidDecoderKernel("shared-routed output-head buffer mismatch"));
        }
        self.operation.execute(input, output)
    }
}