Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Standard outputs
- #include <iostream>
- // get AVX intrinsics
- #include <immintrin.h>
- // get CPUID capability
- //#include <intrin.h>
- #ifdef __MACH__ // OS X (32-bit and 64-bit)
- #include <mach/mach.h>
- #include <mach/mach_time.h>
- #include <unistd.h>
- #elif defined(WIN32) // WIN32
- extern __declspec(dllimport) BOOL __stdcall QueryPerformanceFrequency(LONGLONG * f);
- extern __declspec(dllimport) BOOL __stdcall QueryPerformanceCounter(LONGLONG * t);
- #else // Linux et al
- #include <time.h>
- #endif
- #include <math.h> // floor()
- typedef struct
- {
- uint64_t timestamp[2];
- } TimeStamp_t;
- typedef struct
- {
- uint32_t secs;
- uint32_t ns;
- } TimeStampDiff_t;
- static void TimeStamp(TimeStamp_t *timeStamp)
- {
- #ifdef __MACH__
- *(uint64_t *)timeStamp = mach_absolute_time();
- #elif defined(WIN32)
- (void)QueryPerformanceCounter((LONGLONG *)timeStamp);
- #else
- clock_gettime(CLOCK_PROCESS_CPUTIME_ID, (struct timespec *)timeStamp);
- #endif
- }
- static void TimeStampDiff(
- const TimeStamp_t *timeStamp1,
- const TimeStamp_t *timeStamp2,
- TimeStampDiff_t *timeStampDiff)
- {
- double ns, s;
- #ifdef __MACH__
- static mach_timebase_info_data_t sTimebaseInfo;
- uint64_t t1, t2;
- if (sTimebaseInfo.denom == 0)
- {
- (void)mach_timebase_info(&sTimebaseInfo);
- }
- t1 = *(uint64_t *)timeStamp1;
- t2 = *(uint64_t *)timeStamp2;
- ns = (double)(t2 - t1) * (double)sTimebaseInfo.numer / (double)sTimebaseInfo.denom;
- // get difference in ns
- #elif defined(WIN32)
- static int64_t sTimeBaseFreq = 0;
- int64_t t1, t2;
- if (sTimeBaseFreq == 0)
- {
- (void)QueryPerformanceFrequency((LONGLONG *)&sTimeBaseFreq);
- }
- t1 = *(int64_t *)timeStamp1;
- t2 = *(int64_t *)timeStamp2;
- ns = (double)(t2 - t1) / (double)sTimeBaseFreq * 1.0e9;
- #else
- struct timespec t1 = *(struct timespec *)timeStamp1;
- struct timespec t2 = *(struct timespec *)timeStamp2;
- ns = (double)(t2.tv_sec - t1.tv_sec) * 1.0e9 + (double)(t2.tv_nsec - t1.tv_nsec);
- // get difference in ns
- #endif
- s = ns * 1.0e-9; // get difference in s
- timeStampDiff->secs = (uint32_t)floor(s); // get integer seconds
- timeStampDiff->ns = (uint32_t)((s - (double)timeStampDiff->secs) * 1.0e9);
- // get integer ns
- }
- using namespace std;
- #define ONE 0x80000000
- #define ZERO 0x00000009
- static const __m256d SIGNMASK = _mm256_castsi256_pd(_mm256_set_epi32(ONE,ZERO,ONE,ZERO,ONE,ZERO,ONE,ZERO));
- const int dim = 4;
- typedef void (*Test_Function)(
- double lam_11[4][4],
- double lam_12[4][4],
- double lam_13[4][4],
- double lam_22[4][4],
- double lam_23[4][4],
- double lam_33[4][4],
- const double rjk[4],
- const double a[4],
- const double b[4],
- const double sqrt_gamma,
- const double SPab,
- const double d1_phi[16],
- double d2_phi[192]);
- static void foo_ref(
- double lam_11[4][4],
- double lam_12[4][4],
- double lam_13[4][4],
- double lam_22[4][4],
- double lam_23[4][4],
- double lam_33[4][4],
- const double rjk[4],
- const double a[4],
- const double b[4],
- const double sqrt_gamma,
- const double SPab,
- const double d1_phi[16],
- double d2_phi[192])
- {
- const double re_sqrt_gamma = 1.0 / sqrt_gamma;
- memset(d2_phi, 0.0, 192*sizeof(double));
- for (int alpha=0; alpha < 4; alpha++) {
- for (int k=0; k < 3; k++) {
- for (int beta=0; beta < 4; beta++) {
- for (int l=0; l < 4 ; l++) {
- d2_phi[(alpha*3+k)*16 + beta*dim+l] =
- SPab * d1_phi[alpha*dim+k] * d1_phi[beta*dim+l]
- + a[k] * ( lam_11[alpha][ beta]* a[l]
- + lam_12[alpha][ beta]* b[l]
- + lam_13[alpha][ beta]*rjk[l] );
- }
- }
- }
- }
- for (int alpha=0; alpha < 4; alpha++) {
- for (int k=0; k < 3; k++) {
- for (int beta=0; beta < 4; beta++) {
- for (int l=0; l < 4 ; l++) {
- d2_phi[(alpha*3+k)*16 + beta*4+l] = - ( d2_phi[(alpha*3+k)*16 + beta*dim+l]
- + b[k] * ( lam_12[ beta][alpha] * a[l]
- + lam_22[alpha][ beta] * b[l]
- + lam_23[alpha][ beta] * rjk[l] )
- + rjk[k] * ( lam_13[ beta][alpha] * a[l]
- + lam_23[ beta][alpha] * b[l]
- + lam_33[alpha][ beta] *rjk[l] )
- ) * re_sqrt_gamma;
- }
- }
- }
- }
- }
- static void foo_ref_1(
- double lam_11[4][4],
- double lam_12[4][4],
- double lam_13[4][4],
- double lam_22[4][4],
- double lam_23[4][4],
- double lam_33[4][4],
- const double rjk[4],
- const double a[4],
- const double b[4],
- const double sqrt_gamma,
- const double SPab,
- const double d1_phi[16],
- double d2_phi[192])
- {
- const double re_sqrt_gamma = 1.0 / sqrt_gamma;
- memset(d2_phi, 0.0, 192*sizeof(double));
- for (int alpha=0; alpha < 4; alpha++) {
- for (int beta=0; beta < 4; beta++) {
- for (int k=0; k < 3; k++) {
- for (int l=0; l < 4 ; l++) {
- d2_phi[(alpha*3+k)*16 + beta*dim+l] =
- SPab * d1_phi[alpha*dim+k] * d1_phi[beta*dim+l]
- + a[k] * ( lam_11[alpha][ beta]* a[l]
- + lam_12[alpha][ beta]* b[l]
- + lam_13[alpha][ beta]*rjk[l] );
- }
- }
- }
- }
- for (int alpha=0; alpha < 4; alpha++) {
- for (int beta=0; beta < 4; beta++) {
- for (int k=0; k < 3; k++) {
- for (int l=0; l < 4 ; l++) {
- d2_phi[(alpha*3+k)*16 + beta*4+l] = - ( d2_phi[(alpha*3+k)*16 + beta*dim+l]
- + b[k] * ( lam_12[ beta][alpha] * a[l]
- + lam_22[alpha][ beta] * b[l]
- + lam_23[alpha][ beta] * rjk[l] )
- + rjk[k] * ( lam_13[ beta][alpha] * a[l]
- + lam_23[ beta][alpha] * b[l]
- + lam_33[alpha][ beta] *rjk[l] )
- ) * re_sqrt_gamma;
- }
- }
- }
- }
- }
- static void foo_test(
- double lam_11[4][4],
- double lam_12[4][4],
- double lam_13[4][4],
- double lam_22[4][4],
- double lam_23[4][4],
- double lam_33[4][4],
- const double rjk[4],
- const double a[4],
- const double b[4],
- const double sqrt_gamma,
- const double SPab,
- const double d1_phi[16],
- double d2_phi[192])
- {
- const double re_sqrt_gamma = 1.0 / sqrt_gamma;
- const double * const lam_11_p = &lam_11[0][0];
- const double * const lam_12_p = &lam_12[0][0];
- const double * const lam_13_p = &lam_13[0][0];
- const double * const lam_22_p = &lam_22[0][0];
- const double * const lam_23_p = &lam_23[0][0];
- const double * const lam_33_p = &lam_33[0][0];
- memset(d2_phi, 0.0, 192*sizeof(double));
- double* addr = d2_phi;
- __m256d ymm0; __m256d ymm1; __m256d ymm2; __m256d ymm3;
- __m256d ymm4; __m256d ymm5; __m256d ymm6; __m256d ymm7;
- __m256d ymm8; __m256d ymm9; __m256d ymm10; __m256d ymm11;
- __m256d ymm12; __m256d ymm13; __m256d ymm14; __m256d ymm15;
- // load SPab, because it is constant
- ymm0 = _mm256_broadcast_sd(&SPab);
- for (int alpha=0; alpha < 4; alpha++) {
- for (int k=0; k < 3; k++) {
- ymm1 = _mm256_broadcast_sd(d1_phi + alpha*4 + k); // load d1_phi[alpha*dim+k] to all
- ymm2 = _mm256_broadcast_sd(a + k); // load a[k] to all
- // Precalculate a part here, because it is reusable
- ymm10 = _mm256_mul_pd(ymm0, ymm1); // SPab * d1_phi[alpha*dim+k] = PRE
- for (int beta=0; beta < 4; beta++) {
- // Load the three lambdas to all
- ymm3 = _mm256_broadcast_sd(lam_11_p + alpha*4 + beta);
- ymm4 = _mm256_broadcast_sd(lam_12_p + alpha*4 + beta);
- ymm5 = _mm256_broadcast_sd(lam_13_p + alpha*4 + beta);
- ymm6 = _mm256_load_pd(a); // load the whole 4-vector 'a' into register
- ymm7 = _mm256_load_pd(b); // load the whole 4-vector 'b' into register
- ymm8 = _mm256_load_pd(rjk); // load the whole 4-vector 'b' into register
- ymm9 = _mm256_load_pd(d1_phi + beta*4);
- ymm11 = _mm256_mul_pd(ymm10, ymm9); // PRE * d1_phi[beta*dim+l] = SUM1
- // Do the three Multiplications
- ymm12 = _mm256_mul_pd(ymm3,ymm6); // lam_11[alpha][ beta] * a[l] = PROD1
- ymm13 = _mm256_mul_pd(ymm4,ymm7); // lam_12[alpha][ beta] * b[l] = PROD2
- ymm14 = _mm256_mul_pd(ymm5,ymm8); // lam_13[alpha][ beta] * rjk[l] = PROD3
- ymm12 = _mm256_add_pd(ymm12, ymm13); // PROD1 + PROD2 = PROD12
- ymm12 = _mm256_add_pd(ymm12, ymm14); // PROD12 + PROD3 = PROD123
- ymm12 = _mm256_mul_pd(ymm12, ymm2); // a[k] * PROD123 = SUM2
- ymm12 = _mm256_add_pd(ymm11, ymm12); // SUM1 + SUM2
- _mm256_stream_pd(addr, ymm12);
- addr+=4;
- }
- }
- }
- addr = d2_phi;
- // load sqrt_gamma, because it is constant
- ymm7 = _mm256_broadcast_sd(&re_sqrt_gamma);
- for (int alpha=0; alpha < 4; alpha++) {
- for (int k=0; k < 3; k++) {
- // Load values that are only dependent on k
- ymm9 = _mm256_broadcast_sd(b+k); // all b[k]
- ymm8 = _mm256_broadcast_sd(rjk+k); // all rjk[k]
- for (int beta=0; beta < 4; beta++) {
- // Load the lambdas, because they will stay the same for nine iterations
- ymm15 = _mm256_broadcast_sd(lam_12_p + 4*beta + alpha); // all lam_12[ beta][alpha]
- ymm14 = _mm256_broadcast_sd(lam_22_p + 4*alpha + beta); // all lam_22[alpha][ beta]
- ymm13 = _mm256_broadcast_sd(lam_23_p + 4*alpha + beta); // all lam_23[alpha][ beta]
- ymm12 = _mm256_broadcast_sd(lam_13_p + 4*beta + alpha); // all lam_13[ beta][alpha]
- ymm11 = _mm256_broadcast_sd(lam_23_p + 4*beta + alpha); // all lam_23[ beta][alpha]
- ymm10 = _mm256_broadcast_sd(lam_33_p + 4*alpha + beta); // lam_33[alpha][ beta]
- // Load the values that depend on the innermost loop, which is removed do to AVX
- ymm6 =_mm256_load_pd(a); // a[i] until a[l+3]
- ymm5 =_mm256_load_pd(b); // b[i] until b[l+3]
- ymm4 =_mm256_load_pd(rjk); // rjk[i] until rjk[l+3]
- //__m256d ymm3 =_mm256_load_pd(d2_phi + (alpha*3+k)*16 + beta*dim); // d2_phi[(alpha*3+k)*12 + beta*dim] until d2_phi[(alpha*3+k)*12 + beta*dim +3]
- ymm3 =_mm256_load_pd(addr);
- // Block that is later on multiplied with b[k]
- ymm2 = _mm256_mul_pd(ymm15 , ymm6); // lam_12[ beta][alpha] * a[l]
- ymm1 = _mm256_mul_pd(ymm14 , ymm5); // lam_22[alpha][ beta] * b[l];
- ymm0 = _mm256_add_pd(ymm2, ymm1); // lam_12[ beta][alpha]* a[l] + lam_22[alpha][ beta]*b[l];
- ymm2 = _mm256_mul_pd(ymm13 , ymm4); // lam_23[alpha][ beta] * rjk[l]
- ymm0 = _mm256_add_pd(ymm2, ymm0); // lam_12[ beta][alpha]* a[l] + lam_22[alpha][ beta]*b[l] + lam_23[alpha][ beta] * b[i];
- ymm0 = _mm256_mul_pd(ymm9 , ymm0); // b[k] * (first sum of three)
- // Block that is later on multiplied with rjk[k]
- ymm2 = _mm256_mul_pd(ymm12 , ymm6); // lam_13[ beta][alpha] * a[l]
- ymm1 = _mm256_mul_pd(ymm11 , ymm5); // lam_23[ beta][alpha] * b[l]
- ymm2 = _mm256_add_pd(ymm2, ymm1); // lam_13[ beta][alpha] * a[l] + lam_22[alpha][ beta]*b[l];
- ymm1 = _mm256_mul_pd(ymm10 , ymm4); // lam_33[alpha][ beta] * rjk[l]
- ymm2 = _mm256_add_pd(ymm2 , ymm1); // lam_13[ beta][alpha] * a[l] + lam_22[alpha][ beta]*b[l] + lam_33[alpha][ beta] *rjk[l]
- ymm2 = _mm256_mul_pd(ymm2 , ymm8); // rjk[k] * (second sum of three)
- ymm0 = _mm256_add_pd(ymm0, ymm2); // add to temporal result in ymm0
- ymm0 = _mm256_add_pd(ymm3, ymm0); // Old value of d2 Phi;
- ymm0 = _mm256_mul_pd(ymm0, ymm7); // all divided by sqrt_gamma
- ymm0 = _mm256_xor_pd(ymm0, SIGNMASK);
- _mm256_store_pd(addr, ymm0);
- //_mm256_stream_pd(d2_phi + (alpha*3+k)*16 + beta*dim, ymm0);
- addr += 4;
- }
- }
- }
- }
- static void foo_test_1(
- double lam_11[4][4],
- double lam_12[4][4],
- double lam_13[4][4],
- double lam_22[4][4],
- double lam_23[4][4],
- double lam_33[4][4],
- const double rjk[4],
- const double a[4],
- const double b[4],
- const double sqrt_gamma,
- const double SPab,
- const double d1_phi[16],
- double d2_phi[192])
- {
- const double re_sqrt_gamma = 1.0 / sqrt_gamma;
- memset(d2_phi, 0.0, 192*sizeof(double));
- const __m256d ymm6 = _mm256_load_pd(a); // load the whole 4-vector 'a' into register
- {
- // load SPab, because it is constant
- const __m256d ymm0 = _mm256_broadcast_sd(&SPab);
- const __m256d ymm7 = _mm256_load_pd(b); // load the whole 4-vector 'b' into register
- const __m256d ymm8 = _mm256_load_pd(rjk); // load the whole 4-vector 'rjk' into register
- double* addr = d2_phi;
- for (int alpha=0; alpha < 4; alpha++)
- {
- for (int k=0; k < 3; k++)
- {
- const __m256d ymm1 = _mm256_broadcast_sd(&d1_phi[alpha*dim + k]); // load d1_phi[alpha*dim+k] to all
- const __m256d ymm2 = _mm256_broadcast_sd(&a[k]); // load a[k] to all
- const __m256d ymm10 = _mm256_mul_pd(ymm0, ymm1); // SPab * d1_phi[alpha*dim+k] = PRE
- for (int beta=0; beta < 4; beta++) {
- // Load the three lambdas to all
- const __m256d ymm3 = _mm256_broadcast_sd(&lam_11[alpha][beta]);
- const __m256d ymm4 = _mm256_broadcast_sd(&lam_12[alpha][beta]);
- const __m256d ymm5 = _mm256_broadcast_sd(&lam_13[alpha][beta]);
- const __m256d ymm9 = _mm256_load_pd(d1_phi + beta*4);
- const __m256d ymm11 = _mm256_mul_pd(ymm10, ymm9); // PRE * d1_phi[beta*dim+l] = SUM1
- // Do the three Multiplications
- __m256d ymm12 = _mm256_mul_pd(ymm3,ymm6); // lam_11[alpha][ beta] * a[l] = PROD1
- const __m256d ymm13 = _mm256_mul_pd(ymm4,ymm7); // lam_12[alpha][ beta] * b[l] = PROD2
- const __m256d ymm14 = _mm256_mul_pd(ymm5,ymm8); // lam_13[alpha][ beta] * rjk[l] = PROD3
- __m256d ymm15 = _mm256_add_pd(ymm12, ymm13); // PROD1 + PROD2 = PROD12
- ymm12 = _mm256_add_pd(ymm15, ymm14); // PROD12 + PROD3 = PROD123
- ymm15 = _mm256_mul_pd(ymm12, ymm2); // a[k] * PROD123 = SUM2
- ymm12 = _mm256_add_pd(ymm11, ymm15); // SUM1 + SUM2
- _mm256_stream_pd(addr, ymm12);
- addr+=4;
- }
- }
- }
- }
- {
- const __m256d ymm4 =_mm256_load_pd(rjk); // rjk[i] until rjk[l+3]
- const __m256d ymm5 =_mm256_load_pd(b); // b[l] until b[l+3]
- // load sqrt_gamma, because it is constant
- const __m256d ymm7 = _mm256_broadcast_sd(&re_sqrt_gamma);
- double* addr = d2_phi;
- for (int alpha=0; alpha < 4; alpha++)
- {
- for (int k=0; k < 3; k++)
- {
- // Load values that are only dependent on k
- const __m256d ymm9 = _mm256_broadcast_sd(b+k); // all b[k]
- const __m256d ymm8 = _mm256_broadcast_sd(rjk+k); // all rjk[k]
- for (int beta=0; beta < 4; beta++)
- {
- __m256d ymm0, ymm1, ymm2;
- // Load the lambdas, because they will stay the same for nine iterations
- const __m256d ymm15 = _mm256_broadcast_sd(&lam_12[beta][alpha]); // all lam_12[ beta][alpha]
- const __m256d ymm14 = _mm256_broadcast_sd(&lam_22[alpha][beta]); // all lam_22[alpha][ beta]
- const __m256d ymm13 = _mm256_broadcast_sd(&lam_23[alpha][beta]); // all lam_23[alpha][ beta]
- const __m256d ymm12 = _mm256_broadcast_sd(&lam_13[beta][alpha]); // all lam_13[ beta][alpha]
- const __m256d ymm11 = _mm256_broadcast_sd(&lam_23[beta][alpha]); // all lam_23[ beta][alpha]
- const __m256d ymm10 = _mm256_broadcast_sd(&lam_33[alpha][beta]); // lam_33[alpha][ beta]
- // Load the values that depend on the innermost loop, which is removed do to AVX
- const __m256d ymm3 =_mm256_load_pd(addr);
- // Block that is later on multiplied with b[k]
- ymm2 = _mm256_mul_pd(ymm15 , ymm6); // lam_12[ beta][alpha] * a[l]
- ymm1 = _mm256_mul_pd(ymm14 , ymm5); // lam_22[alpha][ beta] * b[l];
- ymm0 = _mm256_add_pd(ymm2, ymm1); // lam_12[ beta][alpha]* a[l] + lam_22[alpha][ beta]*b[l];
- ymm2 = _mm256_mul_pd(ymm13 , ymm4); // lam_23[alpha][ beta] * rjk[l]
- ymm0 = _mm256_add_pd(ymm2, ymm0); // lam_12[ beta][alpha]* a[l] + lam_22[alpha][ beta]*b[l] + lam_23[alpha][ beta] * b[i];
- ymm0 = _mm256_mul_pd(ymm9 , ymm0); // b[k] * (first sum of three)
- // Block that is later on multiplied with rjk[k]
- ymm2 = _mm256_mul_pd(ymm12 , ymm6); // lam_13[ beta][alpha] * a[l]
- ymm1 = _mm256_mul_pd(ymm11 , ymm5); // lam_23[ beta][alpha] * b[l]
- ymm2 = _mm256_add_pd(ymm2, ymm1); // lam_13[ beta][alpha] * a[l] + lam_22[alpha][ beta]*b[l];
- ymm1 = _mm256_mul_pd(ymm10 , ymm4); // lam_33[alpha][ beta] * rjk[l]
- ymm2 = _mm256_add_pd(ymm2 , ymm1); // lam_13[ beta][alpha] * a[l] + lam_22[alpha][ beta]*b[l] + lam_33[alpha][ beta] *rjk[l]
- ymm1 = _mm256_mul_pd(ymm2 , ymm8); // rjk[k] * (second sum of three)
- ymm2 = _mm256_add_pd(ymm0, ymm1); // add to temporal result in ymm0
- ymm1 = _mm256_add_pd(ymm3, ymm2); // Old value of d2 Phi;
- ymm2 = _mm256_mul_pd(ymm1, ymm7); // all divided by sqrt_gamma
- ymm1 = _mm256_xor_pd(ymm2, SIGNMASK);
- _mm256_store_pd(addr, ymm1);
- //_mm256_stream_pd(d2_phi + (alpha*3+k)*16 + beta*dim, ymm0);
- addr += 4;
- }
- }
- }
- }
- }
- static void foo_test_2(
- double lam_11[4][4],
- double lam_12[4][4],
- double lam_13[4][4],
- double lam_22[4][4],
- double lam_23[4][4],
- double lam_33[4][4],
- const double rjk[4],
- const double a[4],
- const double b[4],
- const double sqrt_gamma,
- const double SPab,
- const double d1_phi[16],
- double d2_phi[192])
- {
- const double re_sqrt_gamma = 1.0 / sqrt_gamma;
- memset(d2_phi, 0.0, 192*sizeof(double));
- const __m256d ymm6 = _mm256_load_pd(a); // load the whole 4-vector 'a' into register
- {
- // load SPab, because it is constant
- const __m256d ymm0 = _mm256_broadcast_sd(&SPab);
- const __m256d ymm7 = _mm256_load_pd(b); // load the whole 4-vector 'b' into register
- const __m256d ymm8 = _mm256_load_pd(rjk); // load the whole 4-vector 'rjk' into register
- for (int alpha=0; alpha < 4; alpha++)
- {
- for (int beta=0; beta < 4; beta++)
- {
- // Load the three lambdas to all
- const __m256d ymm3 = _mm256_broadcast_sd(&lam_11[alpha][beta]);
- const __m256d ymm4 = _mm256_broadcast_sd(&lam_12[alpha][beta]);
- const __m256d ymm5 = _mm256_broadcast_sd(&lam_13[alpha][beta]);
- const __m256d ymm9 = _mm256_load_pd(d1_phi + beta*4);
- // Do the three Multiplications
- const __m256d ymm13 = _mm256_mul_pd(ymm4,ymm7); // lam_12[alpha][ beta] * b[l] = PROD2
- const __m256d ymm14 = _mm256_mul_pd(ymm5,ymm8); // lam_13[alpha][ beta] * rjk[l] = PROD3
- const __m256d ymm15 = _mm256_mul_pd(ymm3,ymm6); // lam_11[alpha][ beta] * a[l] = PROD1
- __m256d ymm12 = _mm256_add_pd(ymm15, ymm13); // PROD1 + PROD2 = PROD12
- ymm12 = _mm256_add_pd(ymm12, ymm14); // PROD12 + PROD3 = PROD123
- double* addr = d2_phi + alpha*3*16 + beta*dim;
- for (int k=0; k < 3; k++)
- {
- const __m256d ymm1 = _mm256_broadcast_sd(&d1_phi[alpha*dim + k]); // load d1_phi[alpha*dim+k] to all
- const __m256d ymm2 = _mm256_broadcast_sd(&a[k]); // load a[k] to all
- const __m256d ymm10 = _mm256_mul_pd(ymm0, ymm1); // SPab * d1_phi[alpha*dim+k] = PRE
- const __m256d ymm11 = _mm256_mul_pd(ymm10, ymm9); // PRE * d1_phi[beta*dim+l] = SUM1
- __m256d ymm12t = _mm256_mul_pd(ymm12, ymm2); // a[k] * PROD123 = SUM2
- ymm12t = _mm256_add_pd(ymm11, ymm12t); // SUM1 + SUM2
- _mm256_store_pd(addr, ymm12t);
- addr+=16;
- }
- }
- }
- }
- {
- const __m256d ymm4 =_mm256_load_pd(rjk); // rjk[i] until rjk[l+3]
- const __m256d ymm5 =_mm256_load_pd(b); // b[l] until b[l+3]
- // load sqrt_gamma, because it is constant
- const __m256d ymm7 = _mm256_broadcast_sd(&re_sqrt_gamma);
- for (int alpha=0; alpha < 4; alpha++)
- {
- for (int beta=0; beta < 4; beta++)
- {
- // Load the lambdas, because they will stay the same for nine iterations
- const __m256d ymm15 = _mm256_broadcast_sd(&lam_12[beta][alpha]); // all lam_12[ beta][alpha]
- const __m256d ymm14 = _mm256_broadcast_sd(&lam_22[alpha][beta]); // all lam_22[alpha][ beta]
- const __m256d ymm13 = _mm256_broadcast_sd(&lam_23[alpha][beta]); // all lam_23[alpha][ beta]
- const __m256d ymm12 = _mm256_broadcast_sd(&lam_13[beta][alpha]); // all lam_13[ beta][alpha]
- const __m256d ymm11 = _mm256_broadcast_sd(&lam_23[beta][alpha]); // all lam_23[ beta][alpha]
- const __m256d ymm10 = _mm256_broadcast_sd(&lam_33[alpha][beta]); // lam_33[alpha][ beta]
- __m256d ymm0, ymm1, ymm2;
- // Block that is later on multiplied with b[k]
- ymm2 = _mm256_mul_pd(ymm15 , ymm6); // lam_12[ beta][alpha] * a[l]
- ymm1 = _mm256_mul_pd(ymm14 , ymm5); // lam_22[alpha][ beta] * b[l];
- ymm0 = _mm256_add_pd(ymm2, ymm1); // lam_12[ beta][alpha]* a[l] + lam_22[alpha][ beta]*b[l];
- ymm2 = _mm256_mul_pd(ymm13 , ymm4); // lam_23[alpha][ beta] * rjk[l]
- ymm0 = _mm256_add_pd(ymm2, ymm0); // lam_12[ beta][alpha]* a[l] + lam_22[alpha][ beta]*b[l] + lam_23[alpha][ beta] * b[i];
- // Block that is later on multiplied with rjk[k]
- ymm2 = _mm256_mul_pd(ymm12 , ymm6); // lam_13[ beta][alpha] * a[l]
- ymm1 = _mm256_mul_pd(ymm11 , ymm5); // lam_23[ beta][alpha] * b[l]
- ymm2 = _mm256_add_pd(ymm2, ymm1); // lam_13[ beta][alpha] * a[l] + lam_22[alpha][ beta]*b[l];
- ymm1 = _mm256_mul_pd(ymm10 , ymm4); // lam_33[alpha][ beta] * rjk[l]
- ymm2 = _mm256_add_pd(ymm2 , ymm1); // lam_13[ beta][alpha] * a[l] + lam_22[alpha][ beta]*b[l] + lam_33[alpha][ beta] *rjk[l]
- double* addr = d2_phi + alpha*3*16 + beta*dim;
- for (int k=0; k < 3; k++)
- {
- // Load values that are only dependent on k
- const __m256d ymm9 = _mm256_broadcast_sd(b+k); // all b[k]
- const __m256d ymm8 = _mm256_broadcast_sd(rjk+k); // all rjk[k]
- // Load the values that depend on the innermost loop, which is removed do to AVX
- const __m256d ymm3 =_mm256_load_pd(addr);
- __m256d ymm0t, ymm1t, ymm2t;
- // Block that is later on multiplied with b[k]
- ymm0t = _mm256_mul_pd(ymm9 , ymm0); // b[k] * (first sum of three)
- // Block that is later on multiplied with rjk[k]
- ymm1t = _mm256_mul_pd(ymm2 , ymm8); // rjk[k] * (second sum of three)
- ymm2t = _mm256_add_pd(ymm0t, ymm1t); // add to temporal result in ymm0
- ymm1t = _mm256_add_pd(ymm3, ymm2t); // Old value of d2 Phi;
- ymm2t = _mm256_mul_pd(ymm1t, ymm7); // all divided by sqrt_gamma
- ymm1t = _mm256_xor_pd(ymm2t, SIGNMASK);
- _mm256_store_pd(addr, ymm1t);
- addr += 16;
- }
- }
- }
- }
- }
- static void test(const char *foo_name, Test_Function foo)
- {
- TimeStamp_t t0, t1;
- TimeStampDiff_t t_diff;
- double dtime;
- double tmp;
- __declspec(align(64)) double lam_11[4][4] = {
- {217.91920572807675,-363.19867621346157,217.91920572807777,-72.639735242692979},
- {-363.19867621346157,651.03497117894915,-396.79589782952706,108.95960286403944},
- {217.91920572807777,-396.79589782952706,215.19655972279568,-36.319867621346461},
- {-72.639735242692979,108.95960286403944,-36.319867621346461,0.00000000000000000}};
- __declspec(align(64)) double lam_12[4][4] = {{-72.639735242692979,145.27947048538556,-145.27947048538485,72.639735242692254},
- {108.95960286403944,-287.83629496548929,324.15616258683468,-145.27947048538482},
- {-36.319867621346461,178.87669210145020,-287.83629496548929,145.27947048538559},
- {0.00000000000000000,-36.319867621346489,108.95960286403948,-72.639735242692979}};
- __declspec(align(64)) double lam_13[4][4] = {{0.00000000000000000,0.00000000000000000,0.00000000000000000,0.00000000000000000},
- {-441.12078924256735,882.24157848513676,-882.24157848514119,441.12078924257179},
- {441.12078924256735,-882.24157848513676,882.24157848514119,-441.12078924257179},
- {0.00000000000000000,0.00000000000000000,0.00000000000000000,0.00000000000000000}};
- __declspec(align(64)) double lam_22[4][4] = {{0.00000000000000000,-36.319867621346489,108.95960286403948,-72.639735242692979},
- {-36.319867621346489,215.19655972279583,-396.79589782952723,217.91920572807783},
- {108.95960286403948,-396.79589782952723,651.03497117894938,-363.19867621346168},
- {-72.639735242692979,217.91920572807783,-363.19867621346168,217.91920572807675}};
- __declspec(align(64)) double lam_23[4][4] = {{-0.00000000000000000,-0.00000000000000000,-0.00000000000000000,-0.00000000000000000},
- {441.12078924257179,-882.24157848514119,882.24157848513676,-441.12078924256735},
- {-441.12078924257179,882.24157848514119,-882.24157848513676,441.12078924256735},
- {-0.00000000000000000,-0.00000000000000000,-0.00000000000000000,-0.00000000000000000}};
- __declspec(align(64)) double lam_33[4][4] = {{3759.6260671131017,-7519.2521342262207,7519.2521342262580,-3759.6260671131390},
- {-7519.2521342262207,15038.504268452458,-15038.504268452496,7519.2521342262580},
- {7519.2521342262589,-15038.504268452496,15038.504268452458,-7519.2521342262207},
- {-3759.6260671131390,7519.2521342262580,-7519.2521342262207,3759.6260671131017}};
- __declspec(align(64)) double rjk[4] = {0.13900000000000001,0.00000000000000000,0.00000000000000000,0.00000000000000000};
- __declspec(align(64)) double a [4] = {0.00000000000000000,-0.92388179295480133,0.38267797512611235,0.00000000000000000};
- __declspec(align(64)) double b [4] = {0.00000000000000000,-0.92388179295480133,0.38267797512611235,0.00000000000000000};
- const double sqrt_gamma=1.4136482746161726e-007;
- const double SPab=0.99999999999999001;
- __declspec(align(64)) const double d1_phi[16] = {-0.00000000000000000, 5.5917642862595271e-007, -2.2932516454884578e-007, 0.00000000000000000,
- -0.00000000000000000, -5.5289354740543637e-007,2.2618372393858761e-007, 0.00000000000000000,
- -0.00000000000000000,-5.5289354740543637e-007, 2.2618372393858761e-007, 0.00000000000000000,
- -0.00000000000000000, 5.5917642862595271e-007, -2.2932516454884578e-007, 0.00000000000000000};
- __declspec(align(64)) double d2_phi[192] = { 0 };
- TimeStamp(&t0);
- for(int j=0; j<10; j++)
- {
- for(int i=0; i<100000; i++)
- {
- memset(d2_phi, 0.0, 192*sizeof(double));
- foo(lam_11, lam_12, lam_13,
- lam_22, lam_23, lam_33,
- rjk, a, b,
- sqrt_gamma, SPab,
- d1_phi,
- d2_phi);
- }
- }
- TimeStamp(&t1);
- TimeStampDiff(&t0, &t1, &t_diff);
- dtime = (double)t_diff.secs + (double)t_diff.ns * 1.0e-9;
- cout << foo_name << ": needed " << dtime * 1000.0 << " milliseconds to complete.\n";
- tmp = 0.0;
- for(int i=0; i<192; i++) {
- tmp += d2_phi[i];
- tmp /= 2.0;
- }
- cout << foo_name << ": Lala " << tmp << "\n";
- }
- int main()
- {
- test("foo_ref ", &foo_ref);
- test("foo_ref_1 ", &foo_ref_1);
- test("foo_test ", &foo_test);
- test("foo_test_1", &foo_test_1);
- test("foo_test_2", &foo_test_2);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement