use hermes_simd_core::view::SimdError;
pub mod bf16;
pub mod int8;
pub mod unpack;
pub use unpack::*;
#[inline(never)]
pub(crate) fn validate_gemm_sizes(
a_len: usize,
b_len: usize,
c_len: usize,
m: usize,
_n: usize,
k: usize,
a_stride: usize,
b_stride: usize,
c_stride: usize,
) -> Result<(), SimdError> {
if a_len < m * a_stride || b_len < k * b_stride || c_len < m * c_stride {
return Err(SimdError::LengthMismatch);
}
Ok(())
}
#[inline(always)]
pub(crate) unsafe fn tile_loop_generic<
TA,
TB,
TC,
Arch,
const M: usize,
const N: usize,
const K: usize,
>(
m: usize,
n: usize,
k: usize,
a: *const TA,
a_stride: usize,
b: *const TB,
b_stride: usize,
c: *mut TC,
c_stride: usize,
) where
Arch: hermes_simd_core::view::TileMatrixMultiply<TA, TB, TC, Arch, Arch, M, N, K>,
{
let mut i = 0;
while i + M <= m {
let mut j = 0;
while j + N <= n {
let mut kk = 0;
while kk + K <= k {
Arch::tile_matmul(
c.add(i * c_stride + j),
c_stride,
a.add(i * a_stride + kk),
a_stride,
b.add(kk * b_stride + j),
b_stride,
);
kk += K;
}
j += N;
}
i += M;
}
}
pub trait TiledGemm<TA, TB, TC> {
unsafe fn gemm(
m: usize,
n: usize,
k: usize,
a: &[TA],
a_stride: usize,
b: &[TB],
b_stride: usize,
c: &mut [TC],
c_stride: usize,
) -> Result<(), SimdError>;
unsafe fn dispatch_tile_matmul(
c: *mut TC,
c_stride: usize,
a: *const TA,
a_stride: usize,
b: *const TB,
b_stride: usize,
);
}
#[inline]
pub unsafe fn gemm<TA, TB, TC>(
m: usize,
n: usize,
k: usize,
a: &[TA],
a_stride: usize,
b: &[TB],
b_stride: usize,
c: &mut [TC],
c_stride: usize,
) -> Result<(), SimdError>
where
(TA, TB, TC): TiledGemm<TA, TB, TC>,
{
<(TA, TB, TC) as TiledGemm<TA, TB, TC>>::gemm(m, n, k, a, a_stride, b, b_stride, c, c_stride)
}
#[inline]
pub unsafe fn dispatch_tile_matmul<TA, TB, TC>(
c: *mut TC,
c_stride: usize,
a: *const TA,
a_stride: usize,
b: *const TB,
b_stride: usize,
) where
(TA, TB, TC): TiledGemm<TA, TB, TC>,
{
<(TA, TB, TC) as TiledGemm<TA, TB, TC>>::dispatch_tile_matmul(
c, c_stride, a, a_stride, b, b_stride,
)
}