# Computing butterflies with better performance

I have a code that computes butterflies and from a little profiling I found out that it is a little bit slow. So, it seemed that the better way to optimize its performance is vectorizing it using Intel SIMD Intrinsics.

This is the scalar version of the code that I want to optimize:

float bfly0_re, bfly1_re, bfly2_re, bfly3_re;
float bfly0_im, bfly1_im, bfly2_im, bfly3_im;
float x_n2, x_N2, x_N2_2, x_N2_3;
float y_n2, y_N2, y_N2_2, y_N2_3;

x_n2 =      x[n2];
x_N2 =      x[N2];
x_N2_2 =    x[N2_2];
x_N2_3 =    x[N2_3];

y_n2 =      y[n2];
y_N2 =      y[N2];
y_N2_2 =    y[N2_2];
y_N2_3 =    y[N2_3];

SUB(a_c_sub_re, x_n2, x_N2_2)//SUB(res,op1,op2){res=op1-op2}
SUB(a_c_sub_im, y_n2, y_N2_2)
SUB(b_d_sub_im, y_N2, y_N2_3)
SUB(b_d_sub_re, x_N2, x_N2_3)

SUB(bfly1_im, a_c_sub_im, b_d_sub_re)
SUB(bfly3_re, a_c_sub_re, b_d_sub_im)


And Then this is the SIMD version that I intend to use:

__m128 Xn2_vec,XN22_vec;
__m128 YN2_vec,YN22_vec;

__m128 YXN2_vec,YXN23_vec;
__m128 XYN2_vec,XYN23_vec;

__m128 A_vec,B_vec,C_vec,D_vec;
__m128 bfly_iv,bfly_rv;

YXN2_vec  = _mm_set_ps   (X[N2], Y[N2], X[N2], Y[N2] );
YXN23_vec = _mm_set_ps   (X[N23],Y[N23],X[N23],Y[N23]);

XYN2_vec  = _mm_shuffle_ps(YXN2_vec, YXN2_vec, _MM_SHUFFLE(2,3,0,1));
XYN23_vec = _mm_shuffle_ps(YXN23_vec,YXN23_vec,_MM_SHUFFLE(2,3,0,1));

/*Then Do another shuffling instructions on the butterflies to reorder them*/


n2, N2, N22, N23 are just indices because the values are not contiguous. I am using a Haswell architecture.

Here are my questions:

• Is this code worth optimizing or not, knowing that it is repeated more than 1000 times?

• Shall I use the _mm_load1_ps() instead of the _mm_broadcast_ps()intrinsic, or is there no difference?

• Do you think that there is a better way of doing it?

• Did you compare your code against your compiler's own vectorisation? I usually find that the latter comfortably beats my own attempts, without the maintenance penalty of per-target source code - and it may improve without any work just by upgrading the compiler. It sometimes helps to add a #pragma omp simd. – Toby Speight Jul 12 '17 at 13:24
• Well, what if I decided to use different compilers or different hardware ... So, I think that it well not be possible to use it. – A.nechi Jul 12 '17 at 13:51
• Not sure what you mean - using the compiler's own vectorisation means you can build for different platforms without re-writing your code. Why do you say it might be "not possible"? – Toby Speight Jul 12 '17 at 14:28
• Oh ... ok, I misunderstood you. – A.nechi Jul 12 '17 at 14:37
• Are you compiling with an OpenMP-capable compiler (such as gcc -fopenmp)? I think it needs to support OpenMP 4.0 to have the simd directive. If that's not an option for you, it may well be instructive to compile with -march=native -O3 (or similar) and inspect the generated assembly. – Toby Speight Jul 13 '17 at 15:08