#include "avxintrin.h"
#include "windows.h"
#include "math.h"
#include "time.h"
#include "iostream"
using namespace std;
typedef unsigned long uL;
//cal PI
double calPI(size_t dt){
double pi = 0;
double delta = 1.0 / delta;
for(size_t i = 0; i < dt; i++){
double x = (double) i / dt;
pi += delta / (1.0 + x * x);
}
return pi * 4.0;
}
//cal PI with AVX
double calPIWithAVX(size_t dt){
double pi = 0;
double delta = 1.0 / dt;
__m256d ymm0, ymm1, ymm2, ymm3, ymm4;
ymm0 = _mm256_set1_pd(1.0); //赋值
ymm1 = _mm256_set1_pd(delta);
ymm2 = _mm256_set_pd(delta*3, delta*2, delta, 0.0);
ymm4 = _mm256_setzero_pd();
for(int i = 0; i <= dt-4; i+=4){
ymm3 = _mm256_set1_pd(i * delta);
ymm3 = _mm256_add_pd(ymm3, ymm2);
ymm3 = _mm256_mul_pd(ymm3, ymm3);
ymm3 = _mm256_add_pd(ymm0, ymm3);
ymm3 = _mm256_div_pd(ymm1, ymm3);
ymm4 = _mm256_add_pd(ymm4, ymm3);
}
double tmp[4] __attribute__((aligned(32))); //_attribute__((aligned(n)))
// 此属性指定了指定类型的变量的最小对齐(以字节为单位)。
// 如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。
_mm256_store_pd(tmp, ymm4); //对齐存储
pi += tmp[0] + tmp[1] + tmp[2] + tmp[3];
return pi * 4.0;
}
//cal PI with AVX and LOOP EXPANSION
double calPIWITHAVX2(size_t dt){
double pi = 0;
double delta = 1.0 / dt;
__m256d ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, temp;
ymm0 = _mm256_set1_pd(1.0);
ymm1 = _mm256_set1_pd(delta);
ymm2 = _mm256_set_pd(delta*3, delta*2, delta, 0.0);
temp = _mm256_set_pd(delta*7, delta*6, delta*5, delta*4);
ymm4 = _mm256_setzero_pd();
ymm5 = _mm256_setzero_pd();
for(int i = 0; i <= dt - 8; i += 8){
ymm3 = _mm256_set1_pd(i * delta);
ymm3 = _mm256_add_pd(ymm3, ymm2);
ymm3 = _mm256_mul_pd(ymm3, ymm3);
ymm3 = _mm256_add_pd(ymm0, ymm3);
ymm3 = _mm256_div_pd(ymm1, ymm3);
ymm4 = _mm256_add_pd(ymm4, ymm3);
ymm6 = _mm256_set1_pd((i+4) * delta);
ymm6 = _mm256_mul_pd(ymm6, temp);
ymm6 = _mm256_add_pd(ymm0, ymm6);
ymm6 = _mm256_div_pd(ymm1, ymm6);
ymm5 = _mm256_add_pd(ymm5, ymm6);
}
ymm4 = _mm256_add_pd(ymm4, ymm5);
double tmp[4] __attribute__((aligned(32))); //_attribute__((aligned(n)))
// 此属性指定了指定类型的变量的最小对齐(以字节为单位)。
// 如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。
_mm256_store_pd(tmp, ymm4); //对齐存储
pi += tmp[0] + tmp[1] + tmp[2] + tmp[3];
return pi * 4.0;
}
int main(){
clock_t st = clock();
calPI(1000000000);
clock_t en = clock();
double t = (double)(en - st) / CLOCKS_PER_SEC;
printf("%.5f\n", t);
st = clock();
calPIWithAVX(10000000000);
en = clock();
t = (double)(en - st) / CLOCKS_PER_SEC;
printf("%.5f\n", t);
st = clock();
calPIWITHAVX2(10000000000);
en = clock();
t = (double)(en - st) / CLOCKS_PER_SEC;
printf("%.5f\n", t);
return 0;
}