2 ms·
Leveraging auto vectorization can be nice, as you can compile for different targets with one set of code, and not have to write out intrinsics for SSE2, AVX2, A
by gameswithgo 8y ago
Leveraging auto vectorization can be nice, as you can compile for different targets with one set of code, and not have to write out intrinsics for SSE2, AVX2, AVX512 etc.
But yeah it is tricky, you might get it all sorted and a compiler upgrade ruins it, or it won't work on another compiler, or someone updates your function later not realizing you carefully tuned it to get vectorized and it ruins it.
Also there are some clever hacks you can do with intrinsics that compilers won't figure out sometimes.
I made a library in Rust that will let you write a single function using abstracted intrinsics, that can produce SSE2/SSE41/AVX2 versions at compile time:
https://github.com/jackmott/simdeez https://github.com/jackmott/simdeez
- Asooka 8y agoSeems to me like it would be a good idea to have a tool (superoptimiser?) that can take your simple code and rewrite it with intrinsics, which you then check into source control. So you have a doFooGeneric and have the tool generate doFooSSE, doFooSSE4, doFooAVX2, doFooNEON and select one at runtime (like Intel's compiler does) or at compile time. Since you'll only run the tool infrequently, it can spend a lot of time trying to find the best vectorisation.
- colejohnson66 8y agoSide note: GCC supports feature based dispatch too[0] [0]: https://lwn.net/Articles/691932/ https://lwn.net/Articles/691932/
- gnufx 8y agoYes, but target_clones, at least, isn't a panacea. If you know how to make it work in a shared library, I'm rather interested.
- gameswithgo 8y agoanother Rust library "Faster" attempts to do that. Its cool, but the downside is simple code can't always translate optimally to intrinsics. Like if you ask for a "floor" operation for instance. With SSE2 you have no floor operation. So you either can do a floor one at a time, or use some clever combinations of other SSE2 intrinsics to do a floor, or, if you can accept certain constraints, you can use a faster option using less intrinsics. So your simple code needs to specify which you want, which ends up being kind of like intrinsics. Also your simple code has to line everything up in arrays anyway so intrinsics don't add that much complexity. I do overload operators in SIMDeez so some of the time your code can look pretty simple.
- stochastic_monk 8y agoI have a similar project in C++ supporting SSE2,AVX2, and AVX512 here: https://github.com/dnbaker/vec https://github.com/dnbaker/vec. I've used it for numerical code and sketch data structures, for example. (See https://github.com/dnbaker/frp https://github.com/dnbaker/frp or https://github.com/dnbaker/sketch https://github.com/dnbaker/sketch, respectively). Most of the work I do, the compiler just isn't able to vectorize, so I just write intrinsics. I similarly wrapped FFTW and the Sleef trigonometric function library so that I can generate optimal code for a variety of types and architectures.