pub trait SIMDSchema<T, U, A: Architecture = Current>: Copy {
type SIMDWidth: Constant<Type = usize>;
type Accumulator: Add<Output = Self::Accumulator> + Debug + Copy;
type Left: SIMDVector<Arch = A, Scalar = T, ConstLanes = Self::SIMDWidth>;
type Right: SIMDVector<Arch = A, Scalar = U, ConstLanes = Self::SIMDWidth>;
type Return;
type Main: MainLoop;
// Required methods
fn init(&self, arch: A) -> Self::Accumulator;
fn accumulate(
&self,
x: Self::Left,
y: Self::Right,
acc: Self::Accumulator,
) -> Self::Accumulator;
fn reduce(&self, x: Self::Accumulator) -> Self::Return;
// Provided methods
fn combine(
&self,
x: Self::Accumulator,
y: Self::Accumulator,
) -> Self::Accumulator { ... }
unsafe fn epilogue(
&self,
arch: A,
x: *const T,
y: *const U,
len: usize,
acc: Self::Accumulator,
) -> Self::Accumulator { ... }
fn get_simd_width() -> usize { ... }
fn get_main_bocksize() -> usize { ... }
}Expand description
An interface trait for SIMD operations.
Patterns like unrolling, pointer arithmetic, and epilogue handling are common across many different combinations of left and right hand types for distance computations.
This higher level handling is delegated to functions like simd_op, which in turn
uses a SIMDSchema to customize the mechanics of loading and accumulation.
Required Associated Types§
Sourcetype SIMDWidth: Constant<Type = usize>
type SIMDWidth: Constant<Type = usize>
The desired SIMD read width. Reads from the input slice will be use this stride when accessing memory.
Sourcetype Accumulator: Add<Output = Self::Accumulator> + Debug + Copy
type Accumulator: Add<Output = Self::Accumulator> + Debug + Copy
The type used to represent partial accumulated values.
Sourcetype Left: SIMDVector<Arch = A, Scalar = T, ConstLanes = Self::SIMDWidth>
type Left: SIMDVector<Arch = A, Scalar = T, ConstLanes = Self::SIMDWidth>
The type used for the left-hand side.
Sourcetype Right: SIMDVector<Arch = A, Scalar = U, ConstLanes = Self::SIMDWidth>
type Right: SIMDVector<Arch = A, Scalar = U, ConstLanes = Self::SIMDWidth>
The type used for the right-hand side.
Required Methods§
Sourcefn init(&self, arch: A) -> Self::Accumulator
fn init(&self, arch: A) -> Self::Accumulator
Initialize an empty (identity) accumulator.
Sourcefn accumulate(
&self,
x: Self::Left,
y: Self::Right,
acc: Self::Accumulator,
) -> Self::Accumulator
fn accumulate( &self, x: Self::Left, y: Self::Right, acc: Self::Accumulator, ) -> Self::Accumulator
Perform an accumulation.
Sourcefn reduce(&self, x: Self::Accumulator) -> Self::Return
fn reduce(&self, x: Self::Accumulator) -> Self::Return
Perform a reduction on the accumulator to yield the final result.
This will be called at the end of distance processing.
Provided Methods§
Sourcefn combine(
&self,
x: Self::Accumulator,
y: Self::Accumulator,
) -> Self::Accumulator
fn combine( &self, x: Self::Accumulator, y: Self::Accumulator, ) -> Self::Accumulator
Combine two independent accumulators (allows for unrolling).
Sourceunsafe fn epilogue(
&self,
arch: A,
x: *const T,
y: *const U,
len: usize,
acc: Self::Accumulator,
) -> Self::Accumulator
unsafe fn epilogue( &self, arch: A, x: *const T, y: *const U, len: usize, acc: Self::Accumulator, ) -> Self::Accumulator
A supplied trait for dealing with non-full-width epilogues. Often, masked based loading will do the right thing, but for architectures like AVX2 that have limited support for masking 8 and 16-bit operations, using a scalar fallback may just be better.
This provides a customization point to enable a scalar fallback.
§Safety
- Both pointers
xandymust point to memory. - It must be safe to read
lencontiguous items of typeTstarting atxandlencontiguous items of typeUstarting aty.
The following guarantee is made:
- No read will be emitted to memory locations at and after
x.add(len)andy.add(len).
Sourcefn get_simd_width() -> usize
fn get_simd_width() -> usize
!! Do not extend this function !!
Due to limitations on how associated constants can be used, we need a function to access the SIMD width and rely on the compiler to constant propagate the result.
Sourcefn get_main_bocksize() -> usize
fn get_main_bocksize() -> usize
!! Do not extend this function !!
Due to limitations on how associated constants can be used, we need a function to access the unroll factor of the main loop and rely on the compiler to constant propagate the result.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.