use crate::{Context, DeviceBuffer, Error, Result, Stream, bf16};
mod paired;
pub use paired::{
PairedVariableGroupedFp4Launch, PairedVariableGroupedFp4Plan, VariableGroupedFp4Metadata,
VariableGroupedFp4Operands,
};
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct VariableGroupedFp4Spec {
groups: usize,
matrices: usize,
max_rows: usize,
n: usize,
k: usize,
capacity_rows: usize,
}
impl VariableGroupedFp4Spec {
pub fn new(
groups: usize,
matrices: usize,
max_rows: usize,
n: usize,
k: usize,
capacity_rows: usize,
) -> Result<Self> {
if groups == 0
|| matrices == 0
|| max_rows == 0
|| n == 0
|| k == 0
|| capacity_rows == 0
|| !k.is_multiple_of(64)
{
return Err(Error::InvalidMatmulShape);
}
for value in [groups, matrices, max_rows, n, k, capacity_rows] {
let _ = u32::try_from(value)?;
}
capacity_rows.checked_mul(k / 2).ok_or(Error::InvalidMatmulShape)?;
capacity_rows.checked_mul(n).ok_or(Error::InvalidMatmulShape)?;
Ok(Self {
groups,
matrices,
max_rows,
n,
k,
capacity_rows,
})
}
#[must_use]
pub const fn groups(self) -> usize {
self.groups
}
#[must_use]
pub const fn matrices(self) -> usize {
self.matrices
}
#[must_use]
pub const fn max_rows(self) -> usize {
self.max_rows
}
#[must_use]
pub const fn n(self) -> usize {
self.n
}
#[must_use]
pub const fn k(self) -> usize {
self.k
}
#[must_use]
pub const fn capacity_rows(self) -> usize {
self.capacity_rows
}
const fn native(self) -> mircuda_sys::VariableGroupedFp4Spec {
mircuda_sys::VariableGroupedFp4Spec {
groups: self.groups,
matrices: self.matrices,
max_m: self.max_rows,
n: self.n,
k: self.k,
capacity_rows: self.capacity_rows,
}
}
}
#[derive(Debug)]
pub struct VariableGroupedFp4Plan {
native: mircuda_sys::VariableGroupedFp4Plan,
spec: VariableGroupedFp4Spec,
}
impl VariableGroupedFp4Plan {
pub fn new(context: &Context, stream: &Stream, spec: VariableGroupedFp4Spec) -> Result<Self> {
Ok(Self {
native: context
.native
.create_variable_grouped_fp4_plan(&stream.native, spec.native())?,
spec,
})
}
#[must_use]
pub const fn spec(&self) -> VariableGroupedFp4Spec {
self.spec
}
#[allow(clippy::too_many_arguments)]
pub fn execute(
&mut self,
stream: &Stream,
a: &DeviceBuffer<u8>,
a_scales: &DeviceBuffer<u8>,
b: &DeviceBuffer<u8>,
b_scales: &DeviceBuffer<u8>,
alphas: &DeviceBuffer<f32>,
indices: &DeviceBuffer<u32>,
rows: &DeviceBuffer<u32>,
offsets: &DeviceBuffer<u32>,
output: &mut DeviceBuffer<bf16>,
) -> Result<()> {
Ok(self.native.execute(
&stream.native, &a.native, &a_scales.native, &b.native, &b_scales.native,
&alphas.native, &indices.native, &rows.native, &offsets.native, &output.native,
)?)
}
}