Skip to content

Change vectors to be generic over element type. #154

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

Merged
merged 16 commits into from
Aug 17, 2021

Conversation

calebzulawski
Copy link
Member

@calebzulawski calebzulawski commented Aug 7, 2021

Most important thing to note upfront: despite the pretty significant implementation changes, the API is basically unchanged.

This PR results in changing SimdI32<4> to Simd<i32, 4>, Mask8<2> to Mask<i8, 2>, etc.

This results in a pretty substantial reduction of the API, which now only contains 6 things (not counting type aliases): Simd, Mask, SimdElement, MaskElement, LaneCount, and SupportedLaneCount.

This allows functions such as splat, shuffle, gather_or, lanes_eq, select, etc to be implemented generically once for all vectors, rather than once for each element type (with tons of macros 🤢). Users can still call these functions in the same way as before this PR--only the implementation is different.

There is one notable downside: rustdoc really does not know how to handle this situation and the page for the Simd type is massive. This PR does not attempt to unify implementations over similar types, such as all float types or all unsigned integers. A future PR changing some of the functions to trait functions could reduce this and make those functions a little more discoverable. Alternatively, there might be some improvements we can suggest/add to rustdoc to help wrangle the extra functions.

@calebzulawski calebzulawski marked this pull request as ready for review August 7, 2021 22:04
Copy link
Member

@workingjubilee workingjubilee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most important thing to note upfront: despite the pretty significant implementation changes, the API is basically unchanged.

The API has undergone a significant change, IMO, in that it is a lot easier to use generically in most ways. Admittedly that's not what everyone might typically be thinking by API, but because SIMD often involves type shenanigans, I think it is relevant, eh?

Which is to say I think this will probably be a vast improvement for actual use also.
I have very small legibility remarks but I think this is good to merge.

Comment on lines +135 to +140
#[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")]
/// let x = Simd::from_array([MIN, -2, 3, MAX]);
/// let unsat = -x;
/// let sat = x.saturating_neg();
#[doc = concat!("assert_eq!(unsat, ", stringify!($name), "::from_array([MIN, 2, -3, MIN + 1]));")]
#[doc = concat!("assert_eq!(sat, ", stringify!($name), "::from_array([MAX, 2, -3, MIN + 1]));")]
/// assert_eq!(unsat, Simd::from_array([MIN, 2, -3, MIN + 1]));
/// assert_eq!(sat, Simd::from_array([MAX, 2, -3, MIN + 1]));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This diff alone is honestly pretty much enough to sell me on this on its own.

Comment on lines 6 to 9
pub struct Mask<Element, const LANES: usize>(
<LaneCount<LANES> as SupportedLaneCount>::BitMask,
PhantomData<Element>,
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am finding the use of a non-terse type variable syntax (Element instead of E) has been inspiring me to look for the struct or trait it represents and get confused when I can't find any. This is not so big a deal with const generics because those are visibly called out.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point. The standard library tends to use a single letter. I would probably just opt for T if we go that route.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Decided to go with T, like arrays and Vec.

@Lokathor
Copy link
Contributor

i think if you make a type alias and then impl methods on that type alias, rustdoc will collect the methods there.

However, that would halfway undo the PR

@calebzulawski
Copy link
Member Author

Even if that is true, is that desirable? It may be a temporary "solution" but in some ways I think it's more confusing because we want people to use Simd, not SimdF32.

@Lokathor
Copy link
Contributor

In practice many things still can't be generic over your element type anyway. Slightly jiggering things to make rustdoc behave a little better doesn't make it any worse.

@workingjubilee
Copy link
Member

Given there are multiple routes of exploration for improving the docs I am okay with deferring them somewhat to a later PR, even if they matter.

@workingjubilee workingjubilee merged commit d428753 into master Aug 17, 2021
@workingjubilee workingjubilee deleted the feature/generic-element-type branch January 26, 2022 23:43
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

Successfully merging this pull request may close these issues.

3 participants