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

New paper on simd<enum> #75

Open
mattkretz opened this issue Mar 4, 2020 · 6 comments
Open

New paper on simd<enum> #75

mattkretz opened this issue Mar 4, 2020 · 6 comments
Assignees

Comments

@mattkretz
Copy link
Owner

Make the following types vectorizable:

  • unscoped and scoped enums
  • std::pair<T, U> where T and U are vectorizable
  • std::tuple<Ts...> where Ts... are vectorizable
  • any other type that can be destructured (via structured bindings)
@mattkretz mattkretz added this to the pre-Varna Mailing milestone Mar 4, 2020
@mattkretz mattkretz self-assigned this Mar 4, 2020
@mattkretz mattkretz removed this from the pre-Varna Mailing milestone Feb 11, 2023
@mattkretz mattkretz moved this to Todo in std::simd in C++26 Feb 11, 2023
@mattkretz
Copy link
Owner Author

At this point I only want to pursue enums.

I believe that simd<pair<T, U>> etc. is only correct if the storage in memory/register than actually follows TUTUTUTU.... And I don't think that's interesting to have, especially because pair doesn't have much in terms of operations that simd could parallelize.
For "simdize<pair<T, U>>", the result should rather be a pair<simd<T>, simd<U>> and that's not the same as simd<pair<T, U>>.

@bernhardmgruber
Copy link
Contributor

I believe that simd<pair<T, U>> etc. is only correct if the storage in memory/register than actually follows TUTUTUTU....

I find that a little surprising and also question the usefulness, but it would be consistent if we would get simd<complex<F>>, which I think is also laid out like you described and apparently backed by according CPU instructions and has hardware precedence.

For "simdize<pair<T, U>>", the result should rather be a pair<simd<T>, simd<U>> and that's not the same as simd<pair<T, U>>.

Here I fully agree. This is also what I implemented in my LLAMA library, where I can vectorize any nested struct (described as nested typelists though). if you do it this way, then code like:

auto add(auto pair) {
    return pair.first + pair.second;
}

Would work efficienly on scalars and vectors, which I think is an important property in the face of heterogeneity. For CUDA, you would want to have scalar instantiations of your algorithms, and SIMD ones for CPUs.

At some point in the future, reflection may be powerful enough to also simdize structs and maybe whole classes (including member functions), while maintaining this scalar/vector flexibility, depending on how you instantiate.

any other type that can be destructured (via structured bindings)

That's also my poor man's reflection for now :D

@mattkretz
Copy link
Owner Author

Yes, since there's a place for both complex<simd> and simd<complex> we have to ensure that this subtle difference isn't getting muddied by simd<pair> having a layout of complex<simd>.

Wrt. simdize I have both the Vc implementation and a more recent experiment in vir-simd/simdize. Also relevant: Aggregates are named tuples. If this lands in C++26, we have a good basis to build a "simdize" meta function upon.

@danieltowner
Copy link
Collaborator

I believe that simd<pair<T, U>> etc. is only correct if the storage in memory/register than actually follows TUTUTUTU....

I agreed. A simd should make the T an atomic unit rather than breaking it up.

And I don't think that's interesting to have, especially because pair doesn't have much in terms of operations that simd could parallelize.

That's true for pair, but being able to create simd values of other user defined types is interesting. We have done a few examples of this, where simd operates on types (e.g., fixed-point) that aren't going to be standardised anytime soon, but still have hardware support to back them. We use traits to define what the container for each type looks like, and how to map the various operators onto their hardware instructions. With a little bit of work implementing the trait the full power of std::simd then becomes available - anything that simd allows you to conveniently do (permutation, reductions, predicated operations, resizing, parallel memory operations, come to mind) just works.

Using the mechanisms we have we can already create simd of enum, but it relies on a few implementation details. Exposing the traits in a way that doesn't rely on the implementation is the interesting bit. It would have been useful to whiteboard this at Varna but unfortunately I won't be able to make that meeting.

For "simdize<pair<T, U>>", the result should rather be a pair<simd<T>, simd<U>> and that's not the same as simd<pair<T, U>>.

I like this idea too, but as you say, it's a completely different thing.

@mattkretz
Copy link
Owner Author

create simd values of other user defined types is interesting

Yes! As SG6 regular and chair, please feel free to help getting fixed-point etc. standardized soon! And yes, simd<fixed-point>, simd<saturating_int>, etc. is a design goal. These numeric library types should all be vectorizable types.

I'd like to focus this issue on simd<enum>. Let's move the other topics to their own issues.

@mattkretz mattkretz changed the title New paper on simd<user-defined types> New paper on simd<enum> Jul 3, 2023
@danieltowner
Copy link
Collaborator

simd<enum> falls out of https://isocpp.org/files/papers/P2964R0.html pretty easily, so might not need a paper in its own right.

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

No branches or pull requests

3 participants