use crate::scalar::Scalar;
use crate::simd::KernelSimd;
#[cfg(feature = "complex")]
pub mod complex;
pub mod epilogue;
pub mod float;
#[cfg(feature = "int8")]
pub mod int;
#[cfg(feature = "half")]
pub mod mixed;
#[cfg(feature = "complex")]
pub use complex::ComplexGemm;
pub use epilogue::{Epilogue, Identity};
pub use float::FloatGemm;
#[cfg(feature = "int8")]
pub use int::{IntGemm, IntGemmVnni};
#[cfg(all(feature = "int8", feature = "epilogue"))]
pub use int::{IntGemmQ, IntGemmVnniQ};
#[cfg(feature = "half")]
pub use mixed::{Bf16DotGemm, Bf16DotGemmF32, MixedGemm, MixedGemmF32};
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum AlphaStatus {
One,
Other,
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum BetaStatus {
Zero,
One,
Other,
}
pub const MAX_MR: usize = 64;
pub const MAX_NR: usize = 32;
pub const SCRATCH_LEN: usize = MAX_MR * MAX_NR;
pub trait KernelFamily: Copy + Send + Sync + 'static {
type Lhs: Scalar;
type Rhs: Scalar;
type Acc: Scalar;
type Out: Scalar;
const OUT_IS_ACC: bool = true;
const FORCE_PACK_LHS: bool = false;
const FORCE_PACK_RHS: bool = false;
const DEPTH_MULTIPLE: usize = 1;
unsafe fn pack_lhs(
dst: *mut Self::Lhs,
src: *const Self::Lhs,
rs: isize,
cs: isize,
mc: usize,
kc: usize,
mr: usize,
);
unsafe fn pack_rhs(
dst: *mut Self::Rhs,
src: *const Self::Rhs,
rs: isize,
cs: isize,
kc: usize,
nc: usize,
nr: usize,
);
#[allow(clippy::too_many_arguments)]
#[inline(always)]
unsafe fn microkernel<S, const MR_REG: usize, const NR: usize>(
simd: S,
kc: usize,
alpha: Self::Acc,
beta: Self::Acc,
alpha_status: AlphaStatus,
beta_status: BetaStatus,
a: *const Self::Lhs,
a_cs: isize,
b: *const Self::Rhs,
b_rs: isize,
b_cs: isize,
c: *mut Self::Out,
rsc: isize,
csc: isize,
mr_eff: usize,
nr_eff: usize,
scratch: *mut Self::Acc,
) where
S: KernelSimd<Self::Lhs, Self::Rhs, Self::Acc, Self::Out>,
{
let _ = (
simd,
kc,
alpha,
beta,
alpha_status,
beta_status,
a,
a_cs,
b,
b_rs,
b_cs,
c,
rsc,
csc,
mr_eff,
nr_eff,
scratch,
);
unreachable!("this family fuses via microkernel_epi and has no plain microkernel")
}
#[allow(clippy::too_many_arguments)]
#[inline(always)]
unsafe fn microkernel_epi<S, E, const MR_REG: usize, const NR: usize>(
simd: S,
kc: usize,
alpha: Self::Acc,
beta: Self::Acc,
alpha_status: AlphaStatus,
beta_status: BetaStatus,
a: *const Self::Lhs,
a_cs: isize,
b: *const Self::Rhs,
b_rs: isize,
b_cs: isize,
c: *mut Self::Out,
rsc: isize,
csc: isize,
mr_eff: usize,
nr_eff: usize,
row0: usize,
col0: usize,
last_k: bool,
epi: &E,
scratch: *mut Self::Acc,
) where
S: KernelSimd<Self::Lhs, Self::Rhs, Self::Acc, Self::Out>,
E: Epilogue<Self>,
{
assert!(
E::IS_IDENTITY,
"this family does not implement fused epilogues"
);
let _ = (row0, col0, last_k, epi);
unsafe {
Self::microkernel::<S, MR_REG, NR>(
simd,
kc,
alpha,
beta,
alpha_status,
beta_status,
a,
a_cs,
b,
b_rs,
b_cs,
c,
rsc,
csc,
mr_eff,
nr_eff,
scratch,
)
}
}
}