packed_simd
packed_simd copied to clipboard
easier functions to work with slices with dynamic length
I searched for an easy way to deal with sizes that cannot be always in the length you want so I made something like this and wondered why this isn't part of the library? or maybe I missed it?
The names/impl can change but thats the idea
pub trait SimdMap<T> where Self: Sized {
#[inline(always)]
fn simd_map<F>(slice: &mut [T], mut func: F) where F: FnMut(Self) -> Self;
}
impl SimdMap<u8> for u8x64 {
#[inline(always)]
fn simd_map<F>(mut slice: &mut [u8], mut func: F) where F: FnMut(Self) -> Self {
while slice.len() >= Self::lanes() {
func(Self::from_slice_unaligned(slice)).write_to_slice_unaligned(&mut slice);
slice = &mut slice[Self::lanes()..];
}
let mut temp = [0u8; Self::lanes()];
temp[..slice.len()].copy_from_slice(slice);
func(Self::from_slice_unaligned(&temp)).write_to_slice_unaligned(&mut temp);
slice.copy_from_slice(&temp[..slice.len()]);
}
}
then I can use this on any size buffer with the types I want and I don't have to worry about too much stuff or size
pub fn xor(buff: &mut [u8]) {
u8x64::simd_map(buff, |data| {
data ^ 0x15
});
}
something like this could work too
fn sum_ver(x: &[f32]) -> f32 {
//assert_eq!(x.len() % f32x8::lanes(), 0); //not needed
x.simd_iter().sum::<f32x8>().sum()
}
using this
pub struct SimdIter<'a, T,D> {
slice: &'a [D],
phantom: std::marker::PhantomData<T>
}
pub trait SimdIterator<'a,T,D> {
#[inline(always)]
fn simd_iter(&'a self) -> SimdIter<'a,T,D>;
}
impl<'a> Iterator for SimdIter<'a,f32x8,f32> {
type Item = f32x8;
fn next(&mut self) -> Option<Self::Item> {
if self.slice.len() >= Self::Item::lanes() {
let data = Self::Item::from_slice_unaligned(self.slice);
self.slice = &self.slice[Self::Item::lanes()..];
Some(data)
} else if self.slice.len() > 0 {
let mut temp = [0f32; Self::Item::lanes()];
temp[..self.slice.len()].copy_from_slice(self.slice);
self.slice = &self.slice[0..0];
Some(Self::Item::from_slice_unaligned(&temp))
} else {
None
}
}
}
impl<'a,T,D> SimdIterator<'a,T,D> for &[D] {
fn simd_iter(&'a self) -> SimdIter<'a,T,D> {
SimdIter{ slice: self, phantom: PhantomData }
}
}
Many crates do something like that, yes, e.g., https://crates.io/crates/simd_aligned