4 ms·
Can't you test for the capabilities of the processor once and use the right SIMD code from then on? Maybe it makes sense to introduce a block around the SIMD co
by ibotty 9y ago
Can't you test for the capabilities of the processor once and use the right SIMD code from then on? Maybe it makes sense to introduce a block around the SIMD code, which gets compiled into different blocks of SIMD instructions. Then you only pay for choosing the right block once. That's what I would do in Haskell at least.
- AstralStorm 9y agoIt is the typical approach taken by libraries in C and C++ too (though you can usually hardwire to avoid paying the initial cost). Say, Eigen, OpenCL, fftw, ATLAS to name a few.
- exDM69 9y agoThis has to be done at a granularity coarse enough that the function call overhead doesn't kill the performance. It has to be entire loops, for example, not just some primitive operation like a dot product (which has at least 3 different implementations on x86). On my C code, I have a build script that rebuilds a shared library 3-4 times for different CPUs (e.g. with and without -mavx2) and then uses dlopen() to choose the right one at runtime. The actual SIMD code has a bunch of #ifdefs to choose the appropriate implementation for primitive operations. GCC has function multiversioning [0][1] (__attribute__((target("sse4.2")))) to enable choosing a function implementation based on CPU capabilities at runtime, but that is not suitable for the use case I describe. I want my "high level" code to be the same, but using the right implementation for "primitive" ops like dot product. Using multiversioning would completely kill the optimizer and cause excessive register spilling and other unwanted artifacts. [0] https://gcc.gnu.org/wiki/FunctionMultiVersioning https://gcc.gnu.org/wiki/FunctionMultiVersioning [1] https://gcc.gnu.org/onlinedocs/gcc-6.2.0/gcc/Function-Multiversioning.html https://gcc.gnu.org/onlinedocs/gcc-6.2.0/gcc/Function-Multiv...
- ibotty 9y ago> This has to be done at a granularity coarse enough that the function call overhead doesn't kill the performance. It has to be entire loops, for example, not just some primitive operation like a dot product. Yes, You are right! I understood, that they wanted to add the branch to _every_ SIMD instruction. I concur with branching outside of loops. Re Rust: I expect that one could use a macro around the function (or annotate it, if the macro system is good enough) that generates these different functions and branches to the right one.