mattkretz / wg21-papers

my papers to WG21 — the C++ committee
5 stars 7 forks source link

New paper on simd<enum> #75

Open mattkretz opened 4 years ago

mattkretz commented 4 years ago

Make the following types vectorizable:

mattkretz commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

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.

danieltowner commented 4 months ago

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