libmir-cuda 0.1.0

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

use super::{CudaBackend, DenseSwiGluConfig};
use crate::{Error, Result};

pub(super) struct DenseScratch {
    pub attention: DeviceBuffer<bf16>,
    pub residual: DeviceBuffer<bf16>,
    pub normalized: DeviceBuffer<bf16>,
    pub gate_up: DeviceBuffer<bf16>,
    pub gate_up_separate: [DeviceBuffer<bf16>; 2],
    pub activated: DeviceBuffer<bf16>,
    pub mlp: DeviceBuffer<bf16>,
}

impl DenseScratch {
    pub(super) fn new(
        backend: &CudaBackend,
        config: DenseSwiGluConfig,
        tokens: usize,
    ) -> Result<Self> {
        let hidden = elements(tokens, config.attention.hidden_size)?;
        let intermediate = elements(tokens, config.intermediate_size)?;
        let gate_up = intermediate
            .checked_mul(2)
            .ok_or(Error::InvalidDecoderKernel("dense gate/up scratch overflow"))?;
        let allocate = |size| backend.inner.pool.allocate(&backend.inner.stream, size);
        Ok(Self {
            attention: allocate(hidden)?,
            residual: allocate(hidden)?,
            normalized: allocate(hidden)?,
            gate_up: allocate(gate_up)?,
            gate_up_separate: [allocate(intermediate)?, allocate(intermediate)?],
            activated: allocate(intermediate)?,
            mlp: allocate(hidden)?,
        })
    }
}

pub(super) fn elements(tokens: usize, width: usize) -> Result<usize> {
    tokens
        .checked_mul(width)
        .ok_or(Error::InvalidDecoderKernel("dense SwiGLU shape overflow"))
}