use std::sync::{Arc, OnceLock};
use mircuda::{MxFp8Embedding, MxFp8EmbeddingSpec, MxFp8Gathered, MxFp8GatheredSpec, MxFp8Spec};
use models::weights::{BlockProjectionLayout, BlockQuantization, TensorBinding, TensorStorage};
use super::{
MxFp8Bf16Linear, MxFp8CheckpointWeight, MxFp8EmbeddingLookup, MxFp8GatheredBf16Linear,
projection_shape, require_shape, tensor, tuning, unsupported,
};
use crate::{CudaBackend, CudaTensorDType, CudaTensorSet, Error, Result};
impl MxFp8CheckpointWeight {
pub fn load_binding(tensors: &CudaTensorSet, binding: &TensorBinding) -> Result<Self> {
let TensorStorage::BlockQuantized {
format,
scales,
global_scale: None,
input_scale: None,
bias,
packing: _,
} = &binding.storage
else {
return Err(unsupported(binding, "requires self-contained MXFP8 storage"));
};
if *format != BlockQuantization::MXFP8 {
return Err(unsupported(binding, "does not match the native CUDA MXFP8 contract"));
}
let (layout, prefix, output_features, input_features) = projection_shape(binding)?;
let mut weight_shape = prefix.clone();
weight_shape.extend([output_features, input_features / 4]);
let weight = tensor(tensors, &binding.source, CudaTensorDType::U32, "U32")?;
require_shape(&weight, &weight_shape)?;
let mut scale_shape = prefix.clone();
scale_shape.extend([output_features, input_features / 32]);
let scales = tensor(tensors, scales, CudaTensorDType::U8, "U8")?;
require_shape(&scales, &scale_shape)?;
let mut bias_shape = prefix;
bias_shape.push(output_features);
let bias = bias
.as_deref()
.map(|name| tensor(tensors, name, CudaTensorDType::Bf16, "BF16"))
.transpose()?;
if let Some(bias) = &bias {
require_shape(bias, &bias_shape)?;
}
Ok(Self {
weight,
scales,
bias,
input_features,
output_features,
layout,
swizzled_scales: Arc::new(OnceLock::new()),
})
}
pub fn prepare(&self, backend: &CudaBackend, tokens: usize) -> Result<MxFp8Bf16Linear> {
if self.layout != BlockProjectionLayout::Matrix || self.bias.is_some() {
return Err(Error::InvalidExecutionPlan(
"MXFP8 ordinary projection requires a matrix without bias",
));
}
let spec = MxFp8Spec::new(tokens, self.input_features, self.output_features)?;
let operation = tuning::prepare(backend, spec, self)?;
Ok(MxFp8Bf16Linear {
operation,
stream: backend.inner.stream.clone(),
pool: backend.inner.pool.clone(),
spec,
})
}
pub fn prepare_gathered_routed(
&self,
backend: &CudaBackend,
input_rows: usize,
selections_per_input: usize,
) -> Result<MxFp8GatheredBf16Linear> {
self.prepare_gathered_routed_warps(backend, input_rows, selections_per_input, 8)
}
pub(super) fn prepare_gathered_routed_warps(
&self,
backend: &CudaBackend,
input_rows: usize,
selections_per_input: usize,
warps_per_block: usize,
) -> Result<MxFp8GatheredBf16Linear> {
let matrices = match self.layout {
BlockProjectionLayout::MatrixBank { matrices }
| BlockProjectionLayout::FusedGateUpBank { experts: matrices, .. } => matrices,
BlockProjectionLayout::Matrix => {
return Err(Error::InvalidExecutionPlan(
"ordinary MXFP8 matrix cannot use gathered projection",
));
},
};
let spec = MxFp8GatheredSpec::new_routed(
input_rows,
selections_per_input,
matrices,
self.input_features,
self.output_features,
)?;
Ok(MxFp8GatheredBf16Linear {
operation: MxFp8Gathered::compile_warps(
&backend.inner.compiler,
spec,
u32::try_from(warps_per_block)?,
)?,
stream: backend.inner.stream.clone(),
matrices,
input_features: self.input_features,
output_features: self.output_features,
has_bias: self.bias.is_some(),
})
}
pub(super) fn prepare_gathered_warps(
&self,
backend: &CudaBackend,
assignments: usize,
warps_per_block: usize,
) -> Result<MxFp8GatheredBf16Linear> {
self.prepare_gathered_routed_warps(backend, assignments, 1, warps_per_block)
}
pub(super) fn validate_bank(
&self,
matrices: usize,
input_features: usize,
output_features: usize,
) -> Result<()> {
if self.layout == (BlockProjectionLayout::MatrixBank { matrices })
&& self.input_features == input_features
&& self.output_features == output_features
{
Ok(())
} else {
Err(Error::InvalidExecutionPlan("MXFP8 matrix-bank geometry differs"))
}
}
pub(super) fn validate_interleaved_bank(
&self,
experts: usize,
input_features: usize,
output_features: usize,
) -> Result<()> {
if self.layout == (BlockProjectionLayout::FusedGateUpBank { experts, interleaved: true })
&& self.input_features == input_features
&& self.output_features == output_features * 2
{
Ok(())
} else {
Err(Error::InvalidExecutionPlan("interleaved MXFP8 gate/up geometry differs"))
}
}
#[must_use]
pub const fn input_features(&self) -> usize {
self.input_features
}
#[must_use]
pub const fn output_features(&self) -> usize {
self.output_features
}
pub fn validate(&self, input_features: usize, output_features: usize) -> Result<()> {
if self.input_features == input_features && self.output_features == output_features {
Ok(())
} else {
Err(Error::InvalidExecutionPlan("MXFP8 checkpoint geometry differs"))
}
}
pub fn prepare_embedding(
&self,
backend: &CudaBackend,
output_scale: f32,
) -> Result<MxFp8EmbeddingLookup> {
if self.layout != BlockProjectionLayout::Matrix || self.bias.is_some() {
return Err(Error::InvalidExecutionPlan(
"MXFP8 embedding requires an ordinary matrix without bias",
));
}
let spec =
MxFp8EmbeddingSpec::new(self.output_features, self.input_features, output_scale)?;
Ok(MxFp8EmbeddingLookup {
operation: MxFp8Embedding::compile(&backend.inner.compiler, spec)?,
stream: backend.inner.stream.clone(),
weight: self.clone(),
})
}
}