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

Generic over number of simd lanes with rand #1359

Open
maxbla opened this issue Dec 3, 2023 · 4 comments
Open

Generic over number of simd lanes with rand #1359

maxbla opened this issue Dec 3, 2023 · 4 comments

Comments

@maxbla
Copy link

maxbla commented Dec 3, 2023

I'm writing a function that is supposed to be generic over the number of simd lanes. Minimal example:

more code
#![feature(portable_simd)]

use std::simd::{Simd, SupportedLaneCount, LaneCount};
use rand::SeedableRng;
pub fn example<const LANES: usize> (max: i32) -> i32 
    where LaneCount<LANES>: SupportedLaneCount
{
    let mut rng = rand::rngs::StdRng::from_entropy();
    let zero = Simd::from_array([0; LANES]);
    let max = Simd::from_array([max; LANES]);
    let dist = rand::distributions::Uniform::new(zero, max).unwrap();
    let rands = dist.sample(&mut rng);
}

Unfortunately I can't do this. The compiler gives error[E0277]: the trait bound Simd<u32, LANES>: distributions::utils::WideningMultiply is not satisfied on line 7 of this example. I tried adding that trait bound

pub fn example<const LANES: usize> (max: i32) -> i32 
where LaneCount<LANES>: SupportedLaneCount,
    Simd<u32, LANES> : WideningMultiply<Output = (Simd<u32, LANES>, Simd<u32, LANES>)>

but WideningMultiply is pub(crate) so I can't use it.

Is there any way I can make this work? I realize SMID is experimental in rand and in rust. I have a workaround for now, which is to just declare a constant LANES outside the function, but then benchmarking with different number of lanes involves copy pasting or a macro.

@TheIronBorn
Copy link
Collaborator

Due to the way SIMD works there are going to be inefficiencies with code generic over lanes.

But yes, we should try to at least provide a slow generic version.

@TheIronBorn
Copy link
Collaborator

Though I don't know if const generics can even be specialized like this. Which means we face a choice of poor optimization or poor generics.
If we keep the current generics we should consider publicizing the WideningMultiply trait so code like the above works. (Or maybe a public/sealed trait pattern?)

@maxbla
Copy link
Author

maxbla commented Dec 6, 2023

Due to the way SIMD works there are going to be inefficiencies with code generic over lanes.

huh. I thought rust monomorphizes const generics. I can't imagine where the inefficiency is. Whatever it is might be partially responsible for the simd version of the function I wrote being significantly slower than the non-simd version.

we should consider publicizing the WideningMultiply trait so code like the above works.

That's what I was thinking, although its is a bit awkward to use right now - the only way I figured out how was by inspecting the source of rand::distributions::Uniform::new. Maybe some other way would be more obvious, but I'm not holding my breath.

@TheIronBorn
Copy link
Collaborator

I can't imagine where the inefficiency is
Specifically the inefficiency is that we currently use architecture specific optimizations which a generic version could not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants