Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

easier functions to work with slices with dynamic length #240

Open
vova616 opened this issue Apr 25, 2019 · 2 comments
Open

easier functions to work with slices with dynamic length #240

vova616 opened this issue Apr 25, 2019 · 2 comments
Labels
Enhancement New feature or request

Comments

@vova616
Copy link

vova616 commented Apr 25, 2019

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
    });
}
@vova616
Copy link
Author

vova616 commented Apr 26, 2019

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 }
    }
}

@gnzlbg
Copy link
Contributor

gnzlbg commented Apr 29, 2019

Many crates do something like that, yes, e.g., https://crates.io/crates/simd_aligned

@Lokathor Lokathor added the Enhancement New feature or request label Sep 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants