QDP++
sse_blas_local_vcdot_double.cc
Go to the documentation of this file.
1
6
7#include "qdp_diagnostics.h"
8
9#include <xmmintrin.h>
10#include "qdp_config.h"
12
13namespace QDP {
14
15#ifndef QDP_USE_SSE3
16
17 /* SSE 2 */
18
19#define CONJMUL(z,x,y) \
20 { \
21 __m128d t1,t2,t3,t4; \
22 t1 = _mm_mul_pd(x,y); \
23 t2 = _mm_shuffle_pd(t1,t1,0x1); \
24 t3 = _mm_shuffle_pd(y,y,0x1);\
25 z = _mm_add_pd(t1,t2); \
26 t2 = _mm_mul_pd(x,t3); \
27 t3 = _mm_shuffle_pd(t2,t2,0x1); \
28 t3 = _mm_sub_pd(t2,t3); \
29 z= _mm_shuffle_pd(z,t3,0x2); \
30 }
31
32#define CONJMADD(z,x,y) \
33 { \
34 __m128d t1,t2,t3,t4; \
35 t1 = _mm_mul_pd(x,y); \
36 t2 = _mm_shuffle_pd(t1,t1,0x1); \
37 t3 = _mm_shuffle_pd(y,y,0x1);\
38 t4 = _mm_add_pd(t1,t2); \
39 t2 = _mm_mul_pd(x,t3); \
40 t3 = _mm_shuffle_pd(t2,t2,0x1); \
41 t3 = _mm_sub_pd(t2,t3); \
42 t4= _mm_shuffle_pd(t4,t3,0x2); \
43 z = _mm_add_pd(z,t4); \
44 }
45
46#else
47QDPXX_MESSAGE("Using SSE3")
48 /* SSE 3 */
49#include <pmmintrin.h>
50
51#define CONJMUL(z,x,y) \
52 { \
53 __m128d t1; \
54 t1 = _mm_mul_pd((x),(y)); \
55 (z) = _mm_hadd_pd(t1,t1); \
56 t1 = _mm_shuffle_pd((x),(x),0x1);\
57 t1 = _mm_mul_pd((y),t1); \
58 t1 = _mm_hsub_pd(t1,t1); \
59 (z)= _mm_shuffle_pd((z),t1,0x2); \
60 }
61
62#define CONJMADD(z,x,y) \
63 { \
64 __m128d t1,t2; \
65 t1 = _mm_mul_pd((x),(y)); \
66 t1 = _mm_hadd_pd(t1,t1); \
67 t2 = _mm_shuffle_pd((x),(x),0x1);\
68 t2 = _mm_mul_pd((y),t2); \
69 t2 = _mm_hsub_pd(t2,t2); \
70 t1= _mm_shuffle_pd(t1,t2,0x2); \
71 (z) = _mm_add_pd((z),t1); \
72 }
73
74
75
76#endif
77
78
79 // Re < y^\dag , x >
80 // = sum ( y.re x.re + y.im x.im )
81 // = sum ( y.re x.re ) + sum( y.im x.im )
82 //
83 // Load in [ x.re | x.im ]
84 // [ y.re | y.im ]
85 // Make [ x.re y.re | x.im y.im ]
86 // accumulate sum
87 //
88 // At the end do a single crossing:
89 //
90 // [ sum (x.re y.re) | sum(x.im y.im) ]
91 // + [ sum (x.im y.im) | sum(x.re y.re) ]
92 // = [ innerProdReal | innerProdReal ]
93 //
94 // then srore either half.
95 void local_vcdot4(REAL64 *sum, REAL64 *y, REAL64* x,int n_4spin)
96{
97 // Use _mm_setzero_pd() to initialize the sums rather than xors
98 __m128d sum1 = _mm_setzero_pd();
99 __m128d sum2 = _mm_setzero_pd();
100 __m128d sum3 = _mm_setzero_pd();
101 __m128d sum4 = _mm_setzero_pd();
102
103 __m128d tmp1;
104 __m128d tmp2;
105 __m128d tmp3;
106 __m128d tmp4;
107 __m128d tmp5;
108 __m128d tmp6;
109 __m128d tmp7;
110 __m128d tmp8;
111
112
113 double *x_p=x;
114 double *y_p=y;
115
116
117 for(int i=0; i < n_4spin; i++) {
118
119 tmp1 = _mm_load_pd(x_p); // tmp1 = x
120 tmp2 = _mm_load_pd(y_p); // tmp2 = y
121
122 CONJMADD(sum1,tmp1,tmp2);
123
124 tmp3 = _mm_load_pd(x_p+2); // tmp1 = x
125 tmp4 = _mm_load_pd(y_p+2); // tmp2 = y
126
127 CONJMADD(sum2,tmp3,tmp4);
128
129 tmp5 = _mm_load_pd(x_p+4); // tmp1 = x
130 tmp6 = _mm_load_pd(y_p+4); // tmp2 = y
131
132 CONJMADD(sum3,tmp5,tmp6);
133
134 tmp7 = _mm_load_pd(x_p+6); // tmp1 = x
135 tmp8 = _mm_load_pd(y_p+6); // tmp2 = y
136
137 CONJMADD(sum4,tmp7,tmp8);
138
139 tmp1 = _mm_load_pd(x_p+8); // tmp1 = x
140 tmp2 = _mm_load_pd(y_p+8); // tmp2 = y
141
142 CONJMADD(sum1,tmp1,tmp2);
143
144 tmp3 = _mm_load_pd(x_p+10); // tmp1 = x
145 tmp4 = _mm_load_pd(y_p+10); // tmp2 = y
146
147 CONJMADD(sum2,tmp3,tmp4);
148
149 tmp5 = _mm_load_pd(x_p+12); // tmp1 = x
150 tmp6 = _mm_load_pd(y_p+12); // tmp2 = y
151
152 CONJMADD(sum3,tmp5,tmp6);
153
154 tmp7 = _mm_load_pd(x_p+14); // tmp1 = x
155 tmp8 = _mm_load_pd(y_p+14); // tmp2 = y
156
157 CONJMADD(sum4,tmp7,tmp8);
158
159 tmp1 = _mm_load_pd(x_p+16); // tmp1 = x
160 tmp2 = _mm_load_pd(y_p+16); // tmp2 = y
161
162 CONJMADD(sum1,tmp1,tmp2);
163
164 tmp3 = _mm_load_pd(x_p+18); // tmp1 = x
165 tmp4 = _mm_load_pd(y_p+18); // tmp2 = y
166
167 CONJMADD(sum2,tmp3,tmp4);
168
169 tmp5 = _mm_load_pd(x_p+20); // tmp1 = x
170 tmp6 = _mm_load_pd(y_p+20); // tmp2 = y
171
172 CONJMADD(sum3,tmp5,tmp6);
173
174 tmp7 = _mm_load_pd(x_p+22); // tmp1 = x
175 tmp8 = _mm_load_pd(y_p+22); // tmp2 = y
176
177 CONJMADD(sum4,tmp7,tmp8);
178
179 x_p+=24; y_p+=24;
180 }
181
182
183 // Collect the sums
184 sum1 = _mm_add_pd(sum1,sum2);
185 sum3 = _mm_add_pd(sum3,sum4);
186 sum1 = _mm_add_pd(sum1,sum3);
187
188 // Single store -- has to be unaligned in case
189 // return value is not aligned. THe vectors should be aligned tho
190 _mm_storeu_pd(sum,sum1);
191
192}
193
194
195
196} // namespace QDP;
double REAL64
UnaryReturn< C, FnSum >::Type_t sum(const QDPType< T, C > &s1)
OScalar = sum(source).
Yet another random number generator.
void local_vcdot4(REAL64 *sum, REAL64 *y, REAL64 *x, int n_4spin)
#define QDPXX_MESSAGE(s)
#define CONJMADD(z, x, y)
Generic Scalar VAXPY routine.