> Code written for too high a SIMD capability will generally crash (it’s undefined behavior), while code written for too low a SIMD capability will fall short of the performance available. I can't help but think that SIMD intrinsics are the wrong level of abstraction. Literally assembly being moved into a high level language but without the ability for the compiler to optimize well. Hand written intrinsics can really…
As someone coming from CUDA I think you‘re on the right path. CUDA unifies multicore and vectorization parallelims. Crucial here is hardware support for branching (including early returns) even if it degrades performance. This allows a CUDA kernel being programmed in a programmer friendly way that is often already fairly performant, and the actual mapping to hardware is deferred to kernel invocation where it‘s straig…
Towards fearless SIMD
41–50 of 82 posts
Re: Towards fearless SIMD
#42I’ve found template metaprogramming to be an efficient, generic way to generate SIMD-accelerated code. (See [0].) By giving the type functions associated with each operation, the same interface can support 128, 256, or 512-bit SIMD, depending on hardware. It’s C++, so while it’s outside of the Rust ecosystem, it’s still a workable solution I’ve used in a half dozen projects. [0] https://github.com/dnbaker/vec
That doesn't give you run-time dispatch based on available hardware capabilities. So you either need virtual functions (and take the associated perf hit), or some other solution like the linker tricks mentions, or cached JIT, or....
that is what the Rust libs are doing, just using traits or macros instead of templates.
Re: Towards fearless SIMD
#43Earlier quoted context omitted.
As usual, things aren't quite that simple. While it certainly can happen that the compiler can pessimize carefully crafted SIMD code by applying undesirable transformations, simply not optimizing intrinsics would lead to other problems. If you consider SIMD code that spans more than just one small function, then it is quite useful if the compiler can SROA (e.g. you pass around an array of vectors instead of having 8…
> it is quite useful if the compiler can SROA __attribute__((always_inline)) / __forceinline usually help. > LICM (you're calling a function that needs a constant vector in a loop) I can calculate that vector outside of the loop. > link in an assembly file. Way more complex, I need to write outer scalar code in assembly too, need to manually allocate registers, also C++ templates are sometimes very useful for that ki…
Re: Towards fearless SIMD
#44> Code written for too high a SIMD capability will generally crash (it’s undefined behavior), while code written for too low a SIMD capability will fall short of the performance available. I can't help but think that SIMD intrinsics are the wrong level of abstraction. Literally assembly being moved into a high level language but without the ability for the compiler to optimize well. Hand written intrinsics can really…
As someone coming from CUDA I think you‘re on the right path. CUDA unifies multicore and vectorization parallelims. Crucial here is hardware support for branching (including early returns) even if it degrades performance. This allows a CUDA kernel being programmed in a programmer friendly way that is often already fairly performant, and the actual mapping to hardware is deferred to kernel invocation where it‘s straig…
Re: Towards fearless SIMD
#45> Code written for too high a SIMD capability will generally crash (it’s undefined behavior), while code written for too low a SIMD capability will fall short of the performance available. I can't help but think that SIMD intrinsics are the wrong level of abstraction. Literally assembly being moved into a high level language but without the ability for the compiler to optimize well. Hand written intrinsics can really…
As someone coming from CUDA I think you‘re on the right path. CUDA unifies multicore and vectorization parallelims. Crucial here is hardware support for branching (including early returns) even if it degrades performance. This allows a CUDA kernel being programmed in a programmer friendly way that is often already fairly performant, and the actual mapping to hardware is deferred to kernel invocation where it‘s straig…
Re: Towards fearless SIMD
#46Earlier quoted context omitted.
Single Instruction Multiple Data https://en.wikipedia.org/wiki/SIMD ELI5: Your processor can process more data in parallel. If you have for example loop that has something like this in the body: a[i] + b[i] = c[i] Using SIMD processor can make all this operations same time: a[i] + b[i] = c[i] a[i+1] + b[i+1] = c[i+1] a[i+2] + b[i+2] = c[i+2] a[i+3] + b[i+3] = c[i+3] Normally in one iteration you would only get one of…
Thanks! I get that if you don't already know the acronym, you're not the audience, but it is helpful to not have to search externally for a reference. Could you imagine if that was in a general programming magazine before global internet search engines were popular? You'd have to cross your fingers that your local encyclopedia has an entry! ETA: My bad - I did not think to click that. Embarrassing. Thanks for pointin…
Re: Towards fearless SIMD
#47> Code written for too high a SIMD capability will generally crash (it’s undefined behavior), while code written for too low a SIMD capability will fall short of the performance available. I can't help but think that SIMD intrinsics are the wrong level of abstraction. Literally assembly being moved into a high level language but without the ability for the compiler to optimize well. Hand written intrinsics can really…
Even using intrinsics is dicey sometimes - compilers spill registers more often than can make sense. I think the ideal situation would be if you could somehow hint at register scheduling without writing asm yourself, but compiler are still a long ways from that.
Re: Towards fearless SIMD
#48The simplest target-independent fearless SIMD is autovectorization[1] . But taking maximum advantage of that probably means writing some code that feels a little unnatural. Also, IIRC bounds checks thwart some autovectorization. [1] https://llvm.org/docs/Vectorizers.html
This makes sense when you think about it. The compiler would either need to be extremely capable of generalizing about some kinds of arithmetic, or it would need millions of special cases to recognize. By writing your own vectorization, you are basically covering your singular special case on your own.
Re: Towards fearless SIMD
#49Earlier quoted context omitted.
> it is quite useful if the compiler can SROA __attribute__((always_inline)) / __forceinline usually help. > LICM (you're calling a function that needs a constant vector in a loop) I can calculate that vector outside of the loop. > link in an assembly file. Way more complex, I need to write outer scalar code in assembly too, need to manually allocate registers, also C++ templates are sometimes very useful for that ki…
Can’t just isolate those in a compilation unit with -O0?
I usually want to optimize the scalar code outside of the manually-vectorized body of the loops. A function call to that external compilation unit will be slower than inlining I have when everything is in the same unit. However, it could be the call overhead is small enough, obviously need to profile.
Re: Towards fearless SIMD
#50Earlier quoted context omitted.
Intel has made quite a few contributions to Hotspot, including AVX support. ART started supporting SIMD on Oreo, and it was further expanded on Pie. Naturally very few devices have gotten those improvements thanks the state of Android's updates. So on Android's case Renderscript is still the best way for a JIT like approach for SIMD.
As far as I know the JVM will only auto-vectorize integers. Is there a way to tag a function such that you want floats vectorized too now? ART is a good point, compile on install lets you do this.
http://cr.openjdk.java.net/~vlivanov/talks/2017_Vectorizatio...
https://software.intel.com/sites/default/files/managed/19/ae...
Also the Vector API development is ongoing and there is a talk at this week's Oracle ONE about the current state.
ART no longer compiles on install since Android 7, that behaviour is specific to Android 5 and 6 versions.
Since 7 it is a multistage runtime with hand written in Assembly interpreter, JIT + PGO, AOT + PGO on idle device. And as of 9, PGO data gets uploaded into the store and shared across devices on installation.