use hermes_simd_core::{
align::Unaligned,
arch::SimdArch,
execution::Unmasked,
kernel::SimdKernel,
scalar::Scalar,
view::{SimdError, SimdView},
};
use hermes_simd_macros::runtime_dispatch;
#[runtime_dispatch(avx512f, avx2, neon, scalar)]
pub(super) fn dispatch_tiled_gemm_kernel<T, A>(
a: &[T],
b: &[T],
c: &mut [T],
m: usize,
n: usize,
k: usize,
) -> Result<(), SimdError>
where
T: Scalar,
A: SimdArch + SimdKernel<T>,
{
match (
SimdView::<T, A, Unaligned, Unmasked, &[T]>::new(a),
SimdView::<T, A, Unaligned, Unmasked, &[T]>::new(b),
) {
(Some(v1), Some(v2)) => {
use hermes_simd_core::tiling::{TilingPolicy, TilingStrategy};
if A::LANE_COUNT > 8 && m >= 16 && n >= 16 && k >= 32 {
<TilingPolicy<6, 4> as TilingStrategy<T, A, Unaligned>>::gemm(&v1, &v2, c, m, n, k)
} else if A::LANE_COUNT > 1 && m >= 16 && n >= 16 && k >= 32 {
<TilingPolicy<3, 3> as TilingStrategy<T, A, Unaligned>>::gemm(&v1, &v2, c, m, n, k)
} else {
<TilingPolicy<1, 1> as TilingStrategy<T, A, Unaligned>>::gemm(&v1, &v2, c, m, n, k)
}
}
_ => unsafe { core::hint::unreachable_unchecked() },
}
}
#[cfg(test)]
mod tests {
use crate::dispatch::gemm;
use hermes_simd_core::view::SimdError;
#[test]
fn tiled_gemm_rejects_dimension_overflow() {
let a = vec![1.0f64; 16];
let b = vec![1.0f64; 16];
let mut c = vec![0.0f64; 16];
let r = gemm::dispatch_tiled_gemm::<f64>(&a, &b, &mut c, 2, 8, usize::MAX);
assert_eq!(r, Err(SimdError::LengthMismatch));
}
}