root/src/testbed/testbed.cpp @ 176:54f2be22f60d

Revision 176:54f2be22f60d, 37.4 KB (checked in by Andreas Schaefer <gentryx@…>, 13 months ago)

testing smaller problem sizes with long lines

Line 
1#include <cmath>
2#include <typeinfo>
3// #include <CL/cl.h>
4#include <iostream>
5#include <emmintrin.h>
6// #include <pmmintrin.h>
7#include <sys/time.h>
8#include <vector>
9#include <libgeodecomp/misc/grid.h>
10
11using namespace LibGeoDecomp;
12
13class Scalar2D
14{
15public:
16    static int coefficients()
17    {
18        return 0;
19    }
20
21    inline void step(double *src, double *dst, int offset, int startX, int endX)
22    {
23        for (int x = startX; x < endX; ++x) {
24            dst[x] = (src[x - offset] + src[x - 1] + src[x] + src[x + 1] + src[x + offset]) * 0.2;
25        }
26    }
27
28    int flops()
29    {
30        return 5;
31    }
32};
33
34class VectorizedSSEMelbourneShuffle2D
35{
36public:
37    static int coefficients()
38    {
39        return 0;
40    }
41
42    inline void step(double *src, double *dst, int offset, int startX, int endX)
43    {
44        int x = startX;
45        Scalar2D scalarUpdater;
46
47        if ((x & 1) == 1) {
48            scalarUpdater.step(src, dst, offset, x, x + 1);
49            x += 1;
50        }
51
52        __m128d oneFifth = _mm_set_pd(1.0/3.0, 1.0/3.0);
53        __m128d buff0 = _mm_loadu_pd(src + x - 1);
54        __m128d same0 = _mm_load_pd(src + x + 0);
55
56        int paddedEndX = endX - 7;
57        for (; x < paddedEndX; x += 8) {
58            // load center row
59            __m128d same1 = _mm_load_pd(src + x + 2);
60            __m128d same2 = _mm_load_pd(src + x + 4);
61            __m128d same3 = _mm_load_pd(src + x + 6);
62            __m128d same4 = _mm_load_pd(src + x + 8);
63           
64            // shuffle values obtain left/right neighbors
65            __m128d buff1 = _mm_shuffle_pd(same0, same1, (1 << 0) | (0 << 2));
66            __m128d buff2 = _mm_shuffle_pd(same1, same2, (1 << 0) | (0 << 2));
67            __m128d buff3 = _mm_shuffle_pd(same2, same3, (1 << 0) | (0 << 2));
68            __m128d buff4 = _mm_shuffle_pd(same3, same4, (1 << 0) | (0 << 2));
69
70            // load top row
71            __m128d temp0 = _mm_load_pd(src - offset + x + 0);
72            __m128d temp1 = _mm_load_pd(src - offset + x + 2);
73            __m128d temp2 = _mm_load_pd(src - offset + x + 4);
74            __m128d temp3 = _mm_load_pd(src - offset + x + 6);
75
76            // add center row with left...
77            same0 = _mm_add_pd(same0, buff0);
78            same1 = _mm_add_pd(same1, buff1);
79            same2 = _mm_add_pd(same2, buff2);
80            same3 = _mm_add_pd(same3, buff3);
81
82            // ...and right neighbors
83            same0 = _mm_add_pd(same0, buff1);
84            same1 = _mm_add_pd(same1, buff2);
85            same2 = _mm_add_pd(same2, buff3);
86            same3 = _mm_add_pd(same3, buff4);
87   
88            // load bottom row
89            buff0 = _mm_load_pd(src + offset + x + 0);
90            buff1 = _mm_load_pd(src + offset + x + 2);
91            buff2 = _mm_load_pd(src + offset + x + 4);
92            buff3 = _mm_load_pd(src + offset + x + 6);
93       
94            // add top row
95            same0 = _mm_add_pd(same0, temp0);
96            same1 = _mm_add_pd(same1, temp1);
97            same2 = _mm_add_pd(same2, temp2);
98            same3 = _mm_add_pd(same3, temp3);
99
100            // add bottom row
101            same0 = _mm_add_pd(same0, buff0);
102            same1 = _mm_add_pd(same1, buff1);
103            same2 = _mm_add_pd(same2, buff2);
104            same3 = _mm_add_pd(same3, buff3);
105
106            // scale down...
107            same0 = _mm_mul_pd(same0, oneFifth);
108            same1 = _mm_mul_pd(same1, oneFifth);
109            same2 = _mm_mul_pd(same2, oneFifth);
110            same3 = _mm_mul_pd(same3, oneFifth);
111
112            // ...and store
113            _mm_store_pd(dst + 0, same0);
114            _mm_store_pd(dst + 2, same1);
115            _mm_store_pd(dst + 4, same2);
116            _mm_store_pd(dst + 6, same3);
117
118            same0 = same4;
119            buff0 = buff4;
120        }
121
122        scalarUpdater.step(src, dst, offset, x, endX);
123    }
124
125    int flops()
126    {
127        return 5;
128    }
129};
130
131
132template<typename UPDATER, int DIM>
133class Benchmark
134{
135public:
136    typedef Grid<double, typename Topologies::Cube<DIM>::Topology> GridType;
137
138
139    void run(Coord<DIM> dim, int repeats)
140    {
141        Coord<DIM> coeffDim = dim;
142        coeffDim.c[DIM - 1] *= UPDATER::coefficients();
143        GridType coeff(coeffDim, 0.1);
144        GridType a(dim, 1.0);
145        GridType b(dim, 1.0);
146
147        GridType *oldGrid = &a;
148        GridType *newGrid = &b;
149
150        UPDATER updater;
151
152        long long tStart = getUTtime();
153        std::vector<double*> coefficients(UPDATER::coefficients());
154
155        for (int t = 0; t < repeats; ++t) {
156            for (int z = 1; z < dim.c[2] - 1; ++z) {
157                for (int y = 1; y < dim.c[1] - 1; ++y) {
158                    Coord<DIM> c(0, y, z);
159                    Coord<DIM> coeffCoord = c;
160                    for (int i = 0; i < UPDATER::coefficients(); ++i) {
161                        coefficients[i] = &coeff.at(coeffCoord);
162                        coeffCoord.c[DIM - 1] += dim.c[DIM - 1];
163                    }
164                    updater.step(&coefficients[0], &oldGrid->at(c), &newGrid->at(c), dim.c[1], dim.c[2], 1, dim.c[0] - 1);
165                    // double *source[9] = {
166                    //     &oldGrid->at(Coord<DIM>(0, y - 1, z + 1)),
167                    //     &oldGrid->at(Coord<DIM>(0, y - 1, z    )),
168                    //     &oldGrid->at(Coord<DIM>(0, y - 1, z - 1)),
169                    //     &oldGrid->at(Coord<DIM>(0, y,     z + 1)),
170                    //     &oldGrid->at(Coord<DIM>(0, y,     z    )),
171                    //     &oldGrid->at(Coord<DIM>(0, y,     z - 1)),
172                    //     &oldGrid->at(Coord<DIM>(0, y + 1, z + 1)),
173                    //     &oldGrid->at(Coord<DIM>(0, y + 1, z    )),
174                    //     &oldGrid->at(Coord<DIM>(0, y + 1, z - 1))
175                    // };
176                    // updater.update(source, &newGrid->at(c), 1, dim.c[0] - 1);
177                }
178            }
179            std::swap(newGrid, oldGrid);
180        }
181
182        long long tEnd = getUTtime();
183        evaluate(dim, repeats, tEnd - tStart);
184    }
185
186    void exercise() 
187    {
188        std::cout << "# " << typeid(UPDATER).name() << "\n";
189        int lastDim = 0;
190        for (int i = 4; i <= 4096; i *= 2) {
191            int intermediateSteps = 8;
192            for (int j = 0; j < intermediateSteps; ++j) {
193                int d = i * std::pow(2, j * (1.0 / intermediateSteps));
194                if (d % 2) {
195                    d += 1;
196                }
197
198                if (d > lastDim) {
199                    lastDim = d;
200                    Coord<DIM> dim;
201                    dim.c[0] = d;
202                    dim.c[1] = 4;
203                    dim.c[2] = 4;
204                    // for (int i = 0; i < DIM; ++i)
205                    //     dim.c[i] = d;
206                    int repeats = std::max(1, 10000000 / dim.prod());
207                    run(dim, repeats);
208                }
209            }
210        }
211        std::cout << "\n";
212    }
213
214private:
215    long long getUTtime()
216    {
217        timeval t;
218        gettimeofday(&t, 0);
219        return (long long)t.tv_sec * 1000000 + t.tv_usec;
220    }
221
222    void evaluate(Coord<DIM> dim, int repeats, long long uTime)
223    {
224        double seconds = 1.0 * uTime / 1000 / 1000;
225        Coord<DIM> inner = dim;
226        for (int i = 0; i < DIM; ++i)
227            inner.c[i] -= 2;
228        double gflops = 1.0 * UPDATER().flops() * inner.prod() * 
229            repeats / 1000 / 1000 / 1000 / seconds;
230        std::cout << dim.x() << " " << gflops << "\n";
231    }
232
233
234};
235
236#define TN 0
237#define T  1
238#define TS 2
239#define N  3
240#define C  4
241#define S  5
242#define BN 6
243#define B  7
244#define BS 8
245
246class Jacobi3D
247{
248public:
249    static int coefficients()
250    {
251        return 1;
252    }
253
254    inline void update(double **src, double *dst, int startX, int endX)
255    {
256       int x = startX;
257
258       if ((x & 1) == 1) {
259           updateScalar(src, dst, x, x + 1);
260           x += 1;
261       }
262
263       __m128d oneSeventh = _mm_set_pd(1.0/7.0, 1.0/7.0);
264       __m128d buff0 = _mm_loadu_pd(src[C] + x - 1);
265       __m128d same0 = _mm_load_pd(src[C] + x + 0);
266
267       int paddedEndX = endX - 7;
268       for (; x < paddedEndX; x += 8) {
269           // load center row
270           __m128d same1 = _mm_load_pd(src[0] + x + 2);
271           __m128d same2 = _mm_load_pd(src[0] + x + 4);
272           __m128d same3 = _mm_load_pd(src[0] + x + 6);
273           __m128d same4 = _mm_load_pd(src[0] + x + 8);
274           
275           // shuffle values obtain left/right neighbors
276           __m128d buff1 = _mm_shuffle_pd(same0, same1, (1 << 0) | (0 << 2));
277           __m128d buff2 = _mm_shuffle_pd(same1, same2, (1 << 0) | (0 << 2));
278           __m128d buff3 = _mm_shuffle_pd(same2, same3, (1 << 0) | (0 << 2));
279           __m128d buff4 = _mm_shuffle_pd(same3, same4, (1 << 0) | (0 << 2));
280   
281           // load top row
282           __m128d temp0 = _mm_load_pd(src[T] + x + 0);
283           __m128d temp1 = _mm_load_pd(src[T] + x + 2);
284           __m128d temp2 = _mm_load_pd(src[T] + x + 4);
285           __m128d temp3 = _mm_load_pd(src[T] + x + 6);
286
287           // add center row with left...
288           same0 = _mm_add_pd(same0, buff0);
289           same1 = _mm_add_pd(same1, buff1);
290           same2 = _mm_add_pd(same2, buff2);
291           same3 = _mm_add_pd(same3, buff3);
292
293           // ...and right neighbors
294           same0 = _mm_add_pd(same0, buff1);
295           same1 = _mm_add_pd(same1, buff2);
296           same2 = _mm_add_pd(same2, buff3);
297           same3 = _mm_add_pd(same3, buff4);
298   
299           // load bottom row
300           buff0 = _mm_load_pd(src[B] + x + 0);
301           buff1 = _mm_load_pd(src[B] + x + 2);
302           buff2 = _mm_load_pd(src[B] + x + 4);
303           buff3 = _mm_load_pd(src[B] + x + 6);
304       
305           // add top row
306           same0 = _mm_add_pd(same0, temp0);
307           same1 = _mm_add_pd(same1, temp1);
308           same2 = _mm_add_pd(same2, temp2);
309           same3 = _mm_add_pd(same3, temp3);
310
311           // load north row
312           temp0 = _mm_load_pd(src[N] + x + 0);
313           temp1 = _mm_load_pd(src[N] + x + 2);
314           temp2 = _mm_load_pd(src[N] + x + 4);
315           temp3 = _mm_load_pd(src[N] + x + 6);
316
317           // add bottom row
318           same0 = _mm_add_pd(same0, buff0);
319           same1 = _mm_add_pd(same1, buff1);
320           same2 = _mm_add_pd(same2, buff2);
321           same3 = _mm_add_pd(same3, buff3);
322           
323           // load south row
324           buff0 = _mm_load_pd(src[S] + x + 0);
325           buff1 = _mm_load_pd(src[S] + x + 2);
326           buff2 = _mm_load_pd(src[S] + x + 4);
327           buff3 = _mm_load_pd(src[S] + x + 6);
328
329           // add north row
330           same0 = _mm_add_pd(same0, temp0);
331           same1 = _mm_add_pd(same1, temp1);
332           same2 = _mm_add_pd(same2, temp2);
333           same3 = _mm_add_pd(same3, temp3);
334
335           // add south row
336           same0 = _mm_add_pd(same0, buff0);
337           same1 = _mm_add_pd(same1, buff1);
338           same2 = _mm_add_pd(same2, buff2);
339           same3 = _mm_add_pd(same3, buff3);
340
341           // scale down...
342           same0 = _mm_mul_pd(same0, oneSeventh);
343           same1 = _mm_mul_pd(same1, oneSeventh);
344           same2 = _mm_mul_pd(same2, oneSeventh);
345           same3 = _mm_mul_pd(same3, oneSeventh);
346
347           // ...and store
348           _mm_store_pd(dst + x + 0, same0);
349           _mm_store_pd(dst + x + 2, same1);
350           _mm_store_pd(dst + x + 4, same2);
351           _mm_store_pd(dst + x + 6, same3);
352
353           same0 = same4;
354           buff0 = buff4;
355       }
356
357       updateScalar(src, dst, x, endX);
358    }
359
360    inline void updateScalar(double *src[9], double *dst, int startX, int endX)
361    {
362        for (int x = startX; x < endX; ++x) {
363            dst[x] = 
364                (src[S][x] +
365                 src[T][x] +
366                 src[C][x - 1] +
367                 src[C][x] +
368                 src[C][x + 1] +
369                 src[B][x] +
370                 src[N][x]) * (1.0 / 7.0);
371        }
372    }
373
374    int flops()
375    {
376        return 8;
377    }
378};
379
380
381class Scalar3D
382{
383public:
384    static int coefficients()
385    {
386        return 7;
387    }
388
389    inline void step(double *coeff[7], double *src, double *dst, int offsetY, int offsetZ, int startX, int endX)
390    {
391        for (int x = startX; x < endX; ++x) {
392            dst[x] = 
393                coeff[0][x] * src[x - offsetZ] +
394                coeff[1][x] * src[x - offsetY] +
395                coeff[2][x] * src[x - 1] +
396                coeff[3][x] * src[x] +
397                coeff[4][x] * src[x + 1] +
398                coeff[5][x] * src[x + offsetY] +
399                coeff[6][x] * src[x + offsetZ];
400        }
401    }
402
403    int flops()
404    {
405        return 13;
406    }
407};
408
409class Vectorized3D
410{
411public:
412    static int coefficients()
413    {
414        return 7;
415    }
416
417    inline void step(double **coeff, double *src, double *dst, int offsetY, int offsetZ, int startX, int endX)
418    {
419        int x = startX;
420        Scalar3D scalarUpdater;
421
422        if ((x & 1) == 1) {
423            scalarUpdater.step(coeff, src, dst, offsetY, offsetZ, x, x + 1);
424            x += 1;
425        }
426
427        __m128d same0 = _mm_load_pd(src + x + 0);
428        __m128d neig0 = _mm_loadu_pd(src + x + 1);
429       
430        int paddedEndX = endX - 7;
431        for (; x < paddedEndX; x += 8) {
432            __m128d same1 = _mm_load_pd(src + x + 2);
433            __m128d same2 = _mm_load_pd(src + x + 4);
434            __m128d same3 = _mm_load_pd(src + x + 6);
435            __m128d same4 = _mm_load_pd(src + x + 8);
436
437            __m128d neig1 = _mm_shuffle_pd(same0, same1, (1 << 0) | (0 << 2));
438            __m128d neig2 = _mm_shuffle_pd(same1, same2, (1 << 0) | (0 << 2));
439            __m128d neig3 = _mm_shuffle_pd(same2, same3, (1 << 0) | (0 << 2));
440            __m128d neig4 = _mm_shuffle_pd(same3, same4, (1 << 0) | (0 << 2));
441
442            same0 = _mm_mul_pd(same0, _mm_load_pd(&coeff[3][x + 0]));
443            same1 = _mm_mul_pd(same1, _mm_load_pd(&coeff[3][x + 2]));
444            same2 = _mm_mul_pd(same2, _mm_load_pd(&coeff[3][x + 4]));
445            same3 = _mm_mul_pd(same3, _mm_load_pd(&coeff[3][x + 6]));
446
447            __m128d temp1 = _mm_mul_pd(neig0, _mm_load_pd(&coeff[2][x + 0]));
448            __m128d temp2 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[2][x + 2]));
449            __m128d temp3 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[2][x + 4]));
450            __m128d temp4 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[2][x + 6]));
451
452            same0 = _mm_add_pd(same0, temp1);
453            same1 = _mm_add_pd(same1, temp2);
454            same2 = _mm_add_pd(same2, temp3);
455            same3 = _mm_add_pd(same3, temp4);
456
457            temp1 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[4][x + 0]));
458            temp2 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[4][x + 2]));
459            temp3 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[4][x + 4]));
460            temp4 = _mm_mul_pd(neig4, _mm_load_pd(&coeff[4][x + 6]));
461
462            same0 = _mm_add_pd(same0, temp1);
463            same1 = _mm_add_pd(same1, temp2);
464            same2 = _mm_add_pd(same2, temp3);
465            same3 = _mm_add_pd(same3, temp4);
466
467            neig0 = _mm_load_pd(src + x - offsetZ + 0);
468            neig1 = _mm_load_pd(src + x - offsetZ + 2);
469            neig2 = _mm_load_pd(src + x - offsetZ + 4);
470            neig3 = _mm_load_pd(src + x - offsetZ + 6);
471
472            temp1 = _mm_mul_pd(neig0, _mm_load_pd(&coeff[0][x + 0]));
473            temp2 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[0][x + 2]));
474            temp3 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[0][x + 4]));
475            temp4 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[0][x + 6]));
476
477            same0 = _mm_add_pd(same0, temp1);
478            same1 = _mm_add_pd(same1, temp2);
479            same2 = _mm_add_pd(same2, temp3);
480            same3 = _mm_add_pd(same3, temp4);
481
482            neig0 = _mm_load_pd(src + x - offsetY + 0);
483            neig1 = _mm_load_pd(src + x - offsetY + 2);
484            neig2 = _mm_load_pd(src + x - offsetY + 4);
485            neig3 = _mm_load_pd(src + x - offsetY + 6);
486
487            temp1 = _mm_mul_pd(neig0, _mm_load_pd(&coeff[1][x + 0]));
488            temp2 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[1][x + 2]));
489            temp3 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[1][x + 4]));
490            temp4 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[1][x + 6]));
491
492            same0 = _mm_add_pd(same0, temp1);
493            same1 = _mm_add_pd(same1, temp2);
494            same2 = _mm_add_pd(same2, temp3);
495            same3 = _mm_add_pd(same3, temp4);
496
497            neig0 = _mm_load_pd(src + x + offsetY + 0);
498            neig1 = _mm_load_pd(src + x + offsetY + 2);
499            neig2 = _mm_load_pd(src + x + offsetY + 4);
500            neig3 = _mm_load_pd(src + x + offsetY + 6);
501
502            temp1 = _mm_mul_pd(neig0, _mm_load_pd(&coeff[5][x + 0]));
503            temp2 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[5][x + 2]));
504            temp3 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[5][x + 4]));
505            temp4 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[5][x + 6]));
506
507            same0 = _mm_add_pd(same0, temp1);
508            same1 = _mm_add_pd(same1, temp2);
509            same2 = _mm_add_pd(same2, temp3);
510            same3 = _mm_add_pd(same3, temp4);
511
512            neig0 = _mm_load_pd(src + x + offsetZ + 0);
513            neig1 = _mm_load_pd(src + x + offsetZ + 2);
514            neig2 = _mm_load_pd(src + x + offsetZ + 4);
515            neig3 = _mm_load_pd(src + x + offsetZ + 6);
516
517            temp1 = _mm_mul_pd(neig0, _mm_load_pd(&coeff[6][x + 0]));
518            temp2 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[6][x + 2]));
519            temp3 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[6][x + 4]));
520            temp4 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[6][x + 6]));
521
522            same0 = _mm_add_pd(same0, temp1);
523            same1 = _mm_add_pd(same1, temp2);
524            same2 = _mm_add_pd(same2, temp3);
525            same3 = _mm_add_pd(same3, temp4);
526
527            _mm_store_pd(dst + 0, same0);
528            _mm_store_pd(dst + 2, same1);
529            _mm_store_pd(dst + 4, same2);
530            _mm_store_pd(dst + 6, same3);
531
532            same0 = same4;
533            neig0 = neig4;
534
535            // dst[x] =
536            //     coeff[0][x] * src[x - offsetZ] +
537            //     coeff[1][x] * src[x - offsetY] +
538            //     coeff[2][x] * src[x - 1] +
539            //     coeff[3][x] * src[x] +
540            //     coeff[4][x] * src[x + 1] +
541            //     coeff[5][x] * src[x + offsetY] +
542            //     coeff[6][x] * src[x + offsetZ];
543        }
544
545        scalarUpdater.step(coeff, src, dst, offsetY, offsetZ, x, endX);
546    }
547
548    int flops()
549    {
550        return 13;
551    }
552};
553
554class ExtendedScalar3D
555{
556public:
557    static int coefficients()
558    {
559        return 13;
560    }
561
562    inline void step(double *coeff[13], double *src, double *dst, int offsetY, int offsetZ, int startX, int endX)
563    {
564        for (int x = startX; x < endX; ++x) {
565            dst[x] = 
566                coeff[ 0][x] * src[x - offsetZ - offsetY] +
567                coeff[ 1][x] * src[x - offsetZ] +
568                coeff[ 2][x] * src[x - offsetZ + offsetY] +
569                coeff[ 3][x] * src[x - offsetY] +
570                coeff[ 4][x] * src[x - 1] +
571                coeff[ 5][x] * src[x] +
572                coeff[ 6][x] * src[x + 1] +
573                coeff[ 7][x] * src[x + offsetY] +
574                coeff[ 8][x] * src[x + offsetZ - offsetY] +
575                coeff[ 9][x] * src[x + offsetZ] +
576                coeff[10][x] * src[x + offsetZ + offsetY] +
577                coeff[11][x - offsetZ - offsetY] +
578                coeff[11][x - offsetZ] +
579                coeff[11][x - offsetZ + offsetY] +
580                coeff[11][x - offsetY] +
581                coeff[11][x] +
582                coeff[11][x + offsetY] +
583                coeff[11][x + offsetZ - offsetY] +
584                coeff[11][x + offsetZ] +
585                coeff[11][x + offsetZ + offsetY] +
586                coeff[12][x - offsetZ - offsetY] +
587                coeff[12][x - offsetZ] +
588                coeff[12][x - offsetZ + offsetY] +
589                coeff[12][x - offsetY] +
590                coeff[12][x] +
591                coeff[12][x + offsetY] +
592                coeff[12][x + offsetZ - offsetY] +
593                coeff[12][x + offsetZ] +
594                coeff[12][x + offsetZ + offsetY];
595        }
596    }
597
598    int flops()
599    {
600        return 40;
601    }
602};
603
604class ExtendedVectorized3D
605{
606public:
607    static int coefficients()
608    {
609        return 13;
610    }
611
612    inline void step(double *coeff[13], double *src, double *dst, int offsetY, int offsetZ, int startX, int endX)
613    {
614        int x = startX;
615        ExtendedScalar3D scalarUpdater;
616
617        if ((x & 1) == 1) {
618            scalarUpdater.step(coeff, src, dst, offsetY, offsetZ, x, x + 1);
619            x += 1;
620        }
621
622        __m128d same0 = _mm_load_pd(src + x + 0);
623        __m128d neig0 = _mm_loadu_pd(src + x + 1);
624       
625        int paddedEndX = endX - 7;
626        for (; x < paddedEndX; x += 8) {
627            __m128d same1 = _mm_load_pd(src + x + 2);
628            __m128d same2 = _mm_load_pd(src + x + 4);
629            __m128d same3 = _mm_load_pd(src + x + 6);
630            __m128d same4 = _mm_load_pd(src + x + 8);
631
632            __m128d neig1 = _mm_shuffle_pd(same0, same1, (1 << 0) | (0 << 2));
633            __m128d neig2 = _mm_shuffle_pd(same1, same2, (1 << 0) | (0 << 2));
634            __m128d neig3 = _mm_shuffle_pd(same2, same3, (1 << 0) | (0 << 2));
635            __m128d neig4 = _mm_shuffle_pd(same3, same4, (1 << 0) | (0 << 2));
636
637            same0 = _mm_mul_pd(same0, _mm_load_pd(&coeff[3][x + 0]));
638            same1 = _mm_mul_pd(same1, _mm_load_pd(&coeff[3][x + 2]));
639            same2 = _mm_mul_pd(same2, _mm_load_pd(&coeff[3][x + 4]));
640            same3 = _mm_mul_pd(same3, _mm_load_pd(&coeff[3][x + 6]));
641
642            __m128d temp1 = _mm_mul_pd(neig0, _mm_load_pd(&coeff[2][x + 0]));
643            __m128d temp2 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[2][x + 2]));
644            __m128d temp3 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[2][x + 4]));
645            __m128d temp4 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[2][x + 6]));
646
647            same0 = _mm_add_pd(same0, temp1);
648            same1 = _mm_add_pd(same1, temp2);
649            same2 = _mm_add_pd(same2, temp3);
650            same3 = _mm_add_pd(same3, temp4);
651
652            temp1 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[4][x + 0]));
653            temp2 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[4][x + 2]));
654            temp3 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[4][x + 4]));
655            temp4 = _mm_mul_pd(neig4, _mm_load_pd(&coeff[4][x + 6]));
656
657            same0 = _mm_add_pd(same0, temp1);
658            same1 = _mm_add_pd(same1, temp2);
659            same2 = _mm_add_pd(same2, temp3);
660            same3 = _mm_add_pd(same3, temp4);
661
662            neig0 = _mm_load_pd(src + x - offsetZ + 0);
663            neig1 = _mm_load_pd(src + x - offsetZ + 2);
664            neig2 = _mm_load_pd(src + x - offsetZ + 4);
665            neig3 = _mm_load_pd(src + x - offsetZ + 6);
666
667            temp1 = _mm_mul_pd(neig0, _mm_load_pd(&coeff[0][x + 0]));
668            temp2 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[0][x + 2]));
669            temp3 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[0][x + 4]));
670            temp4 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[0][x + 6]));
671
672            same0 = _mm_add_pd(same0, temp1);
673            same1 = _mm_add_pd(same1, temp2);
674            same2 = _mm_add_pd(same2, temp3);
675            same3 = _mm_add_pd(same3, temp4);
676
677            neig0 = _mm_load_pd(src + x - offsetY + 0);
678            neig1 = _mm_load_pd(src + x - offsetY + 2);
679            neig2 = _mm_load_pd(src + x - offsetY + 4);
680            neig3 = _mm_load_pd(src + x - offsetY + 6);
681
682            temp1 = _mm_mul_pd(neig0, _mm_load_pd(&coeff[1][x + 0]));
683            temp2 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[1][x + 2]));
684            temp3 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[1][x + 4]));
685            temp4 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[1][x + 6]));
686
687            same0 = _mm_add_pd(same0, temp1);
688            same1 = _mm_add_pd(same1, temp2);
689            same2 = _mm_add_pd(same2, temp3);
690            same3 = _mm_add_pd(same3, temp4);
691
692            neig0 = _mm_load_pd(src + x + offsetY + 0);
693            neig1 = _mm_load_pd(src + x + offsetY + 2);
694            neig2 = _mm_load_pd(src + x + offsetY + 4);
695            neig3 = _mm_load_pd(src + x + offsetY + 6);
696
697            temp1 = _mm_mul_pd(neig0, _mm_load_pd(&coeff[5][x + 0]));
698            temp2 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[5][x + 2]));
699            temp3 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[5][x + 4]));
700            temp4 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[5][x + 6]));
701
702            same0 = _mm_add_pd(same0, temp1);
703            same1 = _mm_add_pd(same1, temp2);
704            same2 = _mm_add_pd(same2, temp3);
705            same3 = _mm_add_pd(same3, temp4);
706
707            //xxxxxxxxxxxxx
708            neig0 = _mm_load_pd(src + x + offsetZ + 0);
709            neig1 = _mm_load_pd(src + x + offsetZ + 2);
710            neig2 = _mm_load_pd(src + x + offsetZ + 4);
711            neig3 = _mm_load_pd(src + x + offsetZ + 6);
712
713            temp1 = _mm_mul_pd(neig0, _mm_load_pd(&coeff[6][x + 0]));
714            temp2 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[6][x + 2]));
715            temp3 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[6][x + 4]));
716            temp4 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[6][x + 6]));
717
718            same0 = _mm_add_pd(same0, temp1);
719            same1 = _mm_add_pd(same1, temp2);
720            same2 = _mm_add_pd(same2, temp3);
721            same3 = _mm_add_pd(same3, temp4);
722
723            //xxxxxxxxxxxxx
724            neig0 = _mm_load_pd(src + x - offsetZ - offsetY + 0);
725            neig1 = _mm_load_pd(src + x - offsetZ - offsetY + 2);
726            neig2 = _mm_load_pd(src + x - offsetZ - offsetY + 4);
727            neig3 = _mm_load_pd(src + x - offsetZ - offsetY + 6);
728
729            temp1 = _mm_mul_pd(neig0, _mm_load_pd(&coeff[7][x + 0]));
730            temp2 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[7][x + 2]));
731            temp3 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[7][x + 4]));
732            temp4 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[7][x + 6]));
733
734            same0 = _mm_add_pd(same0, temp1);
735            same1 = _mm_add_pd(same1, temp2);
736            same2 = _mm_add_pd(same2, temp3);
737            same3 = _mm_add_pd(same3, temp4);
738
739            //xxxxxxxxxxxxx
740            neig0 = _mm_load_pd(src + x - offsetZ + offsetY + 0);
741            neig1 = _mm_load_pd(src + x - offsetZ + offsetY + 2);
742            neig2 = _mm_load_pd(src + x - offsetZ + offsetY + 4);
743            neig3 = _mm_load_pd(src + x - offsetZ + offsetY + 6);
744
745            temp1 = _mm_mul_pd(neig0, _mm_load_pd(&coeff[8][x + 0]));
746            temp2 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[8][x + 2]));
747            temp3 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[8][x + 4]));
748            temp4 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[8][x + 6]));
749
750            same0 = _mm_add_pd(same0, temp1);
751            same1 = _mm_add_pd(same1, temp2);
752            same2 = _mm_add_pd(same2, temp3);
753            same3 = _mm_add_pd(same3, temp4);
754
755            //xxxxxxxxxxxxx
756            neig0 = _mm_load_pd(src + x + offsetZ - offsetY + 0);
757            neig1 = _mm_load_pd(src + x + offsetZ - offsetY + 2);
758            neig2 = _mm_load_pd(src + x + offsetZ - offsetY + 4);
759            neig3 = _mm_load_pd(src + x + offsetZ - offsetY + 6);
760
761            temp1 = _mm_mul_pd(neig0, _mm_load_pd(&coeff[9][x + 0]));
762            temp2 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[9][x + 2]));
763            temp3 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[9][x + 4]));
764            temp4 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[9][x + 6]));
765
766            same0 = _mm_add_pd(same0, temp1);
767            same1 = _mm_add_pd(same1, temp2);
768            same2 = _mm_add_pd(same2, temp3);
769            same3 = _mm_add_pd(same3, temp4);
770
771            //xxxxxxxxxxxxx
772            neig0 = _mm_load_pd(src + x + offsetZ + offsetY + 0);
773            neig1 = _mm_load_pd(src + x + offsetZ + offsetY + 2);
774            neig2 = _mm_load_pd(src + x + offsetZ + offsetY + 4);
775            neig3 = _mm_load_pd(src + x + offsetZ + offsetY + 6);
776
777            temp1 = _mm_mul_pd(neig0, _mm_load_pd(&coeff[10][x + 0]));
778            temp2 = _mm_mul_pd(neig1, _mm_load_pd(&coeff[10][x + 2]));
779            temp3 = _mm_mul_pd(neig2, _mm_load_pd(&coeff[10][x + 4]));
780            temp4 = _mm_mul_pd(neig3, _mm_load_pd(&coeff[10][x + 6]));
781
782            same0 = _mm_add_pd(same0, temp1);
783            same1 = _mm_add_pd(same1, temp2);
784            same2 = _mm_add_pd(same2, temp3);
785            same3 = _mm_add_pd(same3, temp4);
786
787            //xxxxxxxxxxxxx
788            neig0 = _mm_load_pd(coeff[11] + x - offsetZ - offsetY + 0);
789            neig1 = _mm_load_pd(coeff[11] + x - offsetZ - offsetY + 2);
790            neig2 = _mm_load_pd(coeff[11] + x - offsetZ - offsetY + 4);
791            neig3 = _mm_load_pd(coeff[11] + x - offsetZ - offsetY + 6);
792
793            same0 = _mm_add_pd(same0, neig0);
794            same1 = _mm_add_pd(same1, neig1);
795            same2 = _mm_add_pd(same2, neig2);
796            same3 = _mm_add_pd(same3, neig3);
797
798            //xxxxxxxxxxxxx
799            neig0 = _mm_load_pd(coeff[11] + x - offsetZ + 0);
800            neig1 = _mm_load_pd(coeff[11] + x - offsetZ + 2);
801            neig2 = _mm_load_pd(coeff[11] + x - offsetZ + 4);
802            neig3 = _mm_load_pd(coeff[11] + x - offsetZ + 6);
803
804            same0 = _mm_add_pd(same0, neig0);
805            same1 = _mm_add_pd(same1, neig1);
806            same2 = _mm_add_pd(same2, neig2);
807            same3 = _mm_add_pd(same3, neig3);
808
809            //xxxxxxxxxxxxx
810            neig0 = _mm_load_pd(coeff[11] + x - offsetZ + offsetY + 0);
811            neig1 = _mm_load_pd(coeff[11] + x - offsetZ + offsetY + 2);
812            neig2 = _mm_load_pd(coeff[11] + x - offsetZ + offsetY + 4);
813            neig3 = _mm_load_pd(coeff[11] + x - offsetZ + offsetY + 6);
814
815            same0 = _mm_add_pd(same0, neig0);
816            same1 = _mm_add_pd(same1, neig1);
817            same2 = _mm_add_pd(same2, neig2);
818            same3 = _mm_add_pd(same3, neig3);
819
820            //xxxxxxxxxxxxx
821            neig0 = _mm_load_pd(coeff[11] + x - offsetY + 0);
822            neig1 = _mm_load_pd(coeff[11] + x - offsetY + 2);
823            neig2 = _mm_load_pd(coeff[11] + x - offsetY + 4);
824            neig3 = _mm_load_pd(coeff[11] + x - offsetY + 6);
825
826            same0 = _mm_add_pd(same0, neig0);
827            same1 = _mm_add_pd(same1, neig1);
828            same2 = _mm_add_pd(same2, neig2);
829            same3 = _mm_add_pd(same3, neig3);
830
831            //xxxxxxxxxxxxx
832            neig0 = _mm_load_pd(coeff[11] + offsetY + x + 0);
833            neig1 = _mm_load_pd(coeff[11] + offsetY + x + 2);
834            neig2 = _mm_load_pd(coeff[11] + offsetY + x + 4);
835            neig3 = _mm_load_pd(coeff[11] + offsetY + x + 6);
836
837            same0 = _mm_add_pd(same0, neig0);
838            same1 = _mm_add_pd(same1, neig1);
839            same2 = _mm_add_pd(same2, neig2);
840            same3 = _mm_add_pd(same3, neig3);
841
842            //xxxxxxxxxxxxx
843            neig0 = _mm_load_pd(coeff[11] + x + 0);
844            neig1 = _mm_load_pd(coeff[11] + x + 2);
845            neig2 = _mm_load_pd(coeff[11] + x + 4);
846            neig3 = _mm_load_pd(coeff[11] + x + 6);
847
848            same0 = _mm_add_pd(same0, neig0);
849            same1 = _mm_add_pd(same1, neig1);
850            same2 = _mm_add_pd(same2, neig2);
851            same3 = _mm_add_pd(same3, neig3);
852
853            //xxxxxxxxxxxxx
854            neig0 = _mm_load_pd(coeff[11] + x + offsetZ - offsetY + 0);
855            neig1 = _mm_load_pd(coeff[11] + x + offsetZ - offsetY + 2);
856            neig2 = _mm_load_pd(coeff[11] + x + offsetZ - offsetY + 4);
857            neig3 = _mm_load_pd(coeff[11] + x + offsetZ - offsetY + 6);
858
859            same0 = _mm_add_pd(same0, neig0);
860            same1 = _mm_add_pd(same1, neig1);
861            same2 = _mm_add_pd(same2, neig2);
862            same3 = _mm_add_pd(same3, neig3);
863
864            //xxxxxxxxxxxxx
865            neig0 = _mm_load_pd(coeff[11] + x + offsetZ + 0);
866            neig1 = _mm_load_pd(coeff[11] + x + offsetZ + 2);
867            neig2 = _mm_load_pd(coeff[11] + x + offsetZ + 4);
868            neig3 = _mm_load_pd(coeff[11] + x + offsetZ + 6);
869
870            same0 = _mm_add_pd(same0, neig0);
871            same1 = _mm_add_pd(same1, neig1);
872            same2 = _mm_add_pd(same2, neig2);
873            same3 = _mm_add_pd(same3, neig3);
874
875            //xxxxxxxxxxxxx
876            neig0 = _mm_load_pd(coeff[11] + x + offsetZ + offsetY + 0);
877            neig1 = _mm_load_pd(coeff[11] + x + offsetZ + offsetY + 2);
878            neig2 = _mm_load_pd(coeff[11] + x + offsetZ + offsetY + 4);
879            neig3 = _mm_load_pd(coeff[11] + x + offsetZ + offsetY + 6);
880
881            same0 = _mm_add_pd(same0, neig0);
882            same1 = _mm_add_pd(same1, neig1);
883            same2 = _mm_add_pd(same2, neig2);
884            same3 = _mm_add_pd(same3, neig3);
885
886            //xxxxxxxxxxxxx
887            neig0 = _mm_load_pd(coeff[12] + x - offsetZ - offsetY + 0);
888            neig1 = _mm_load_pd(coeff[12] + x - offsetZ - offsetY + 2);
889            neig2 = _mm_load_pd(coeff[12] + x - offsetZ - offsetY + 4);
890            neig3 = _mm_load_pd(coeff[12] + x - offsetZ - offsetY + 6);
891
892            same0 = _mm_add_pd(same0, neig0);
893            same1 = _mm_add_pd(same1, neig1);
894            same2 = _mm_add_pd(same2, neig2);
895            same3 = _mm_add_pd(same3, neig3);
896
897            //xxxxxxxxxxxxx
898            neig0 = _mm_load_pd(coeff[12] + x - offsetZ + 0);
899            neig1 = _mm_load_pd(coeff[12] + x - offsetZ + 2);
900            neig2 = _mm_load_pd(coeff[12] + x - offsetZ + 4);
901            neig3 = _mm_load_pd(coeff[12] + x - offsetZ + 6);
902
903            same0 = _mm_add_pd(same0, neig0);
904            same1 = _mm_add_pd(same1, neig1);
905            same2 = _mm_add_pd(same2, neig2);
906            same3 = _mm_add_pd(same3, neig3);
907
908            //xxxxxxxxxxxxx
909            neig0 = _mm_load_pd(coeff[12] + x - offsetZ + offsetY + 0);
910            neig1 = _mm_load_pd(coeff[12] + x - offsetZ + offsetY + 2);
911            neig2 = _mm_load_pd(coeff[12] + x - offsetZ + offsetY + 4);
912            neig3 = _mm_load_pd(coeff[12] + x - offsetZ + offsetY + 6);
913
914            same0 = _mm_add_pd(same0, neig0);
915            same1 = _mm_add_pd(same1, neig1);
916            same2 = _mm_add_pd(same2, neig2);
917            same3 = _mm_add_pd(same3, neig3);
918
919            //xxxxxxxxxxxxx
920            neig0 = _mm_load_pd(coeff[12] + x - offsetY + 0);
921            neig1 = _mm_load_pd(coeff[12] + x - offsetY + 2);
922            neig2 = _mm_load_pd(coeff[12] + x - offsetY + 4);
923            neig3 = _mm_load_pd(coeff[12] + x - offsetY + 6);
924
925            same0 = _mm_add_pd(same0, neig0);
926            same1 = _mm_add_pd(same1, neig1);
927            same2 = _mm_add_pd(same2, neig2);
928            same3 = _mm_add_pd(same3, neig3);
929
930            //xxxxxxxxxxxxx
931            neig0 = _mm_load_pd(coeff[12] + offsetY + x + 0);
932            neig1 = _mm_load_pd(coeff[12] + offsetY + x + 2);
933            neig2 = _mm_load_pd(coeff[12] + offsetY + x + 4);
934            neig3 = _mm_load_pd(coeff[12] + offsetY + x + 6);
935
936            same0 = _mm_add_pd(same0, neig0);
937            same1 = _mm_add_pd(same1, neig1);
938            same2 = _mm_add_pd(same2, neig2);
939            same3 = _mm_add_pd(same3, neig3);
940
941            //xxxxxxxxxxxxx
942            neig0 = _mm_load_pd(coeff[12] + x + 0);
943            neig1 = _mm_load_pd(coeff[12] + x + 2);
944            neig2 = _mm_load_pd(coeff[12] + x + 4);
945            neig3 = _mm_load_pd(coeff[12] + x + 6);
946
947            same0 = _mm_add_pd(same0, neig0);
948            same1 = _mm_add_pd(same1, neig1);
949            same2 = _mm_add_pd(same2, neig2);
950            same3 = _mm_add_pd(same3, neig3);
951
952            //xxxxxxxxxxxxx
953            neig0 = _mm_load_pd(coeff[12] + x + offsetZ - offsetY + 0);
954            neig1 = _mm_load_pd(coeff[12] + x + offsetZ - offsetY + 2);
955            neig2 = _mm_load_pd(coeff[12] + x + offsetZ - offsetY + 4);
956            neig3 = _mm_load_pd(coeff[12] + x + offsetZ - offsetY + 6);
957
958            same0 = _mm_add_pd(same0, neig0);
959            same1 = _mm_add_pd(same1, neig1);
960            same2 = _mm_add_pd(same2, neig2);
961            same3 = _mm_add_pd(same3, neig3);
962
963            //xxxxxxxxxxxxx
964            neig0 = _mm_load_pd(coeff[12] + x + offsetZ + 0);
965            neig1 = _mm_load_pd(coeff[12] + x + offsetZ + 2);
966            neig2 = _mm_load_pd(coeff[12] + x + offsetZ + 4);
967            neig3 = _mm_load_pd(coeff[12] + x + offsetZ + 6);
968
969            same0 = _mm_add_pd(same0, neig0);
970            same1 = _mm_add_pd(same1, neig1);
971            same2 = _mm_add_pd(same2, neig2);
972            same3 = _mm_add_pd(same3, neig3);
973
974            //xxxxxxxxxxxxx
975            neig0 = _mm_load_pd(coeff[12] + x + offsetZ + offsetY + 0);
976            neig1 = _mm_load_pd(coeff[12] + x + offsetZ + offsetY + 2);
977            neig2 = _mm_load_pd(coeff[12] + x + offsetZ + offsetY + 4);
978            neig3 = _mm_load_pd(coeff[12] + x + offsetZ + offsetY + 6);
979
980            same0 = _mm_add_pd(same0, neig0);
981            same1 = _mm_add_pd(same1, neig1);
982            same2 = _mm_add_pd(same2, neig2);
983            same3 = _mm_add_pd(same3, neig3);
984
985            //yyyyyyyyyyyyy
986            _mm_store_pd(dst + 0, same0);
987            _mm_store_pd(dst + 2, same1);
988            _mm_store_pd(dst + 4, same2);
989            _mm_store_pd(dst + 6, same3);
990
991            same0 = same4;
992            neig0 = neig4;
993
994            // dst[x] =
995            //     coeff[0][x] * src[x - offsetZ] +
996            //     coeff[1][x] * src[x - offsetY] +
997            //     coeff[2][x] * src[x - 1] +
998            //     coeff[3][x] * src[x] +
999            //     coeff[4][x] * src[x + 1] +
1000            //     coeff[5][x] * src[x + offsetY] +
1001            //     coeff[6][x] * src[x + offsetZ];
1002        }
1003
1004        scalarUpdater.step(coeff, src, dst, offsetY, offsetZ, x, endX);
1005    }
1006
1007    int flops()
1008    {
1009        return 40;
1010    }
1011};
1012
1013
1014int main(int argc, char *argv[])
1015{
1016    // Benchmark<Scalar3D, 3>().exercise();
1017    // Benchmark<Vectorized3D, 3>().exercise();
1018    // Benchmark<VectorizedSSEMelbourneShuffle2D>().exercise();
1019    Benchmark<ExtendedVectorized3D, 3>().exercise();
1020    // Benchmark<Jacobi3D, 3>().exercise();
1021
1022
1023    // std::vector<cl::Platform> platforms;
1024    // cl::Platform::get(&platforms);
1025
1026    // for (int i = 0; i < platforms.size(); ++i) {
1027    //     std::string str;
1028    //     platforms[i].getInfo(CL_PLATFORM_NAME, &str);
1029    //     std::cout << "Platform[" << i << "] = " << str << std::endl;
1030    // }
1031
1032    return 0;
1033}
Note: See TracBrowser for help on using the browser.