use crate::{
align::Alignment,
arch::SimdArch,
kernel::SimdKernel,
scalar::Scalar,
view::{SimdError, SimdView},
};
use core::marker::PhantomData;
mod dims;
pub mod dot;
pub mod gemm;
pub mod gemv;
pub mod gemv_transpose;
pub trait TilingStrategy<T, Arch: SimdArch, Align: Alignment> {
const TILE_M: usize;
const TILE_N: usize;
fn gemm(
a: &SimdView<'_, T, Arch, Align>,
b: &SimdView<'_, T, Arch, Align>,
c: &mut [T],
m: usize,
n: usize,
k: usize,
) -> Result<(), SimdError>;
fn gemv(
a: &SimdView<'_, T, Arch, Align>,
x: &SimdView<'_, T, Arch, Align>,
y: &mut [T],
nrows: usize,
ncols: usize,
) -> Result<(), SimdError>;
fn gemv_transpose(
a: &SimdView<'_, T, Arch, Align>,
x: &SimdView<'_, T, Arch, Align>,
y: &mut [T],
nrows: usize,
ncols: usize,
) -> Result<(), SimdError>;
fn gemv_strided(
a: &SimdView<'_, T, Arch, Align>,
x: &SimdView<'_, T, Arch, Align>,
y: &mut [T],
nrows: usize,
ncols: usize,
lda: usize,
) -> Result<(), SimdError>;
fn gemv_transpose_strided(
a: &SimdView<'_, T, Arch, Align>,
x: &SimdView<'_, T, Arch, Align>,
y: &mut [T],
nrows: usize,
ncols: usize,
lda: usize,
) -> Result<(), SimdError>;
fn dot(
a: &SimdView<'_, T, Arch, Align>,
b: &SimdView<'_, T, Arch, Align>,
) -> Result<T, SimdError>;
}
#[inline(always)]
pub fn tiled_dot<T, Arch, Align, const TILE_M: usize>(
a: &SimdView<'_, T, Arch, Align>,
b: &SimdView<'_, T, Arch, Align>,
) -> Result<T, SimdError>
where
Arch: SimdArch + SimdKernel<T>,
Align: Alignment,
T: Scalar,
{
<TilingPolicy<TILE_M, 1> as TilingStrategy<T, Arch, Align>>::dot(a, b)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TilingPolicy<const TILE_M: usize, const TILE_N: usize>;
impl<const TILE_M: usize, const TILE_N: usize> TilingPolicy<TILE_M, TILE_N> {
pub const AVX2_STANDARD: TilingPolicy<4, 4> = TilingPolicy;
pub const AVX512_OPTIMAL: TilingPolicy<8, 4> = TilingPolicy;
pub const SCALAR_DEGENERATE: TilingPolicy<1, 1> = TilingPolicy;
pub const fn validate(&self) {
assert!(TILE_M >= 1, "TILE_M must be >= 1");
assert!(TILE_N >= 1, "TILE_N must be >= 1");
}
}
pub struct _TileMarker<const M: usize, const N: usize>(PhantomData<TilingPolicy<M, N>>);
#[inline(always)]
pub fn tiled_gemv<T, Arch, Align, const TILE_M: usize>(
a: &SimdView<'_, T, Arch, Align>,
x: &SimdView<'_, T, Arch, Align>,
y: &mut [T],
nrows: usize,
ncols: usize,
) -> Result<(), SimdError>
where
Arch: SimdArch + SimdKernel<T>,
Align: Alignment,
T: Scalar,
{
<TilingPolicy<TILE_M, 1> as TilingStrategy<T, Arch, Align>>::gemv(a, x, y, nrows, ncols)
}
#[inline(always)]
pub fn tiled_gemm<T, Arch, Align, const TILE_M: usize, const TILE_N: usize>(
a: &SimdView<'_, T, Arch, Align>,
b: &SimdView<'_, T, Arch, Align>,
c: &mut [T],
m: usize,
n: usize,
k: usize,
) -> Result<(), SimdError>
where
Arch: SimdArch + SimdKernel<T>,
Align: Alignment,
T: Scalar,
{
<TilingPolicy<TILE_M, TILE_N> as TilingStrategy<T, Arch, Align>>::gemm(a, b, c, m, n, k)
}
impl<T, Arch, Align, const TILE_M: usize, const TILE_N: usize> TilingStrategy<T, Arch, Align>
for TilingPolicy<TILE_M, TILE_N>
where
Arch: SimdArch + SimdKernel<T>,
Align: Alignment,
T: Scalar,
{
const TILE_M: usize = TILE_M;
const TILE_N: usize = TILE_N;
#[inline]
fn gemm(
a: &SimdView<'_, T, Arch, Align>,
b: &SimdView<'_, T, Arch, Align>,
c: &mut [T],
m: usize,
n: usize,
k: usize,
) -> Result<(), SimdError> {
gemm::gemm_impl::<T, Arch, Align, TILE_M, TILE_N>(a, b, c, m, n, k)
}
#[inline]
fn gemv(
a: &SimdView<'_, T, Arch, Align>,
x: &SimdView<'_, T, Arch, Align>,
y: &mut [T],
nrows: usize,
ncols: usize,
) -> Result<(), SimdError> {
gemv::gemv_impl::<T, Arch, Align, TILE_M>(a, x, y, nrows, ncols)
}
#[inline]
fn gemv_transpose(
a: &SimdView<'_, T, Arch, Align>,
x: &SimdView<'_, T, Arch, Align>,
y: &mut [T],
nrows: usize,
ncols: usize,
) -> Result<(), SimdError> {
gemv_transpose::gemv_transpose_impl::<T, Arch, Align, TILE_N>(a, x, y, nrows, ncols)
}
#[inline]
fn gemv_strided(
a: &SimdView<'_, T, Arch, Align>,
x: &SimdView<'_, T, Arch, Align>,
y: &mut [T],
nrows: usize,
ncols: usize,
lda: usize,
) -> Result<(), SimdError> {
gemv::gemv_strided_impl::<T, Arch, Align, TILE_M>(a, x, y, nrows, ncols, lda)
}
#[inline]
fn gemv_transpose_strided(
a: &SimdView<'_, T, Arch, Align>,
x: &SimdView<'_, T, Arch, Align>,
y: &mut [T],
nrows: usize,
ncols: usize,
lda: usize,
) -> Result<(), SimdError> {
gemv_transpose::gemv_transpose_strided_impl::<T, Arch, Align, TILE_N>(
a, x, y, nrows, ncols, lda,
)
}
#[inline]
fn dot(
a: &SimdView<'_, T, Arch, Align>,
b: &SimdView<'_, T, Arch, Align>,
) -> Result<T, SimdError> {
dot::dot_impl::<T, Arch, Align, TILE_M>(a, b)
}
}