Can You Write a Vectorized Reduction Operation? (2016)
software.intel.com
software.intel.com
Edit: ok I understand now. Not deleting the comment just in case someone is also wondering : there are 4 values with the total points in the domino being considered. So you must co side the total number of dots in each of the 4 dominos. The choice here is a bit unfortunate, it would have been clearer to say ymm0(2,3,2,5) + ymm1(3,2,5,2) -> ymm2 (5,5,8,8) in a table.
This has been my M.O. for a number of years, but sadly on modern platforms there seems to be little logic to which code is fast and which isn't. Even if the compiler emits vector instructions, that is no guarantee that the code will be particularly fast IME. Things like cache misses play a role obviously, but sometimes it's just a plain mystery why fast-looking is a bit slow. For that purpose I keep a benchmark of various ways of doing common array operations that I can run on each platform, it's quite handy.
Kepler introduced a 'shuffle' intrinsic to accelerate the kind of 'horizontal' reductions discussed in the article, see http://on-demand.gputechconf.com/gtc/2013/presentations/S317....
The general technique of restructuring arrays of data structures is a standard optimization. However, if you just write the computation described straight down in Fortran, (at least recent) gfortran -Ofast unrolls and vectorizes it. Hooray for Fortran types.
I don't really see any explanation of why you'd want to do this? Not only is there a instruction for doing exactly this in most vector instruction sets, but you typically don't need to do it inside your hot loop anyway.
"Reduce" or "fold" is a standard term for applying a binary operation (like +) to all elements of a vector/list/more general data structure: https://en.wikipedia.org/wiki/Fold_(higher-order_function)
> Not only is there a instruction for doing exactly this in most vector instruction sets
Is there a single one in AVX for adding all the components of a vector register? Is it fast? How does it associate the computation? If there is such an instruction, GCC and Clang seem reluctant to emit it: https://gcc.godbolt.org/z/vkaeYi though I might be missing some magic flags.
edit:
apparently GCC doesn't specifically optimize reductions [2] and does a generic vectorization instead.
vhaddpd %xmm0, %xmm0, %xmm0
$ gcc --version | head -1
gcc (Debian 8.3.0-6) 8.3.0
$ cat x.c
#include <x86intrin.h>
double f(__m128d v){return v[1]+v[0];}
$ gcc -Ofast -march=haswell -S x.c
$ grep -C1 hadd x.s
.cfi_startproc
vhaddpd %xmm0, %xmm0, %xmm0
ret
GCC 4.8.5 with adjusted options does the same, and 7.5, so perhaps there was some regression in early 8.(-ffast-math is redundant with -Ofast.)