Reputation: 41
When I use icc compiler on mac, I could not obtain same answer with other compiler such as gcc, clang. Using icc compiler, the result was below
0.000000e+00
0.000000e+00
0.000000e+00
0.000000e+00
0.000000e+00
0.000000e+00
0.000000e+00
0.000000e+00
The expected answer is here
1.000000e+00
2.000000e+00
3.000000e+00
4.000000e+00
2.500000e+01
3.000000e+01
3.500000e+01
4.000000e+01
I compiled like this:
icc test1.c -fopenmp -mavx -Wall
gcc test1.c -fopenmp -mavx -Wall
clang test1.c -fopenmp -mavx -Wall
My code is as follows:
#include "stdio.h"
#include "time.h"
#include "math.h"
#include "stdlib.h"
#include "omp.h"
#include "x86intrin.h"
void dd_m_dd(double *ahi, double *bhi, double *chi, int m, int n)
{
int j;
#pragma omp parallel
{
__m256d vahi,vbhi,vchi;
#pragma omp for private(vahi,vbhi,vchi)
for (j = 0; j < m*n; j+=4) {
vbhi = _mm256_broadcast_sd(&bhi[j]);
vahi = _mm256_load_pd(&ahi[j]);
vchi = _mm256_load_pd(&chi[j]);
vchi=vahi*vbhi;
chi[j]=vchi[0];
chi[j+1]=vchi[1];
chi[j+2]=vchi[2];
chi[j+3]=vchi[3];
}
}
}
int main(int argc, const char * argv[]){
// Matrix Vector Product with DD
// set variables
int m;
double* xhi;
double* yhi;
double* z;
int i;
m=(int)pow(2,3);
// main program
// set vector or matrix
xhi=(double *)malloc(sizeof(double) * m*1);
yhi=(double *)malloc(sizeof(double) * m*1);
z=(double *)malloc(sizeof(double) * m*1);
//preset
for (i=0;i<m;i++) {
xhi[i]=i+1;
yhi[i]=i+1;
z[i]=0;
}
dd_m_dd(xhi,yhi,z,m,1);
for (i=0;i<m;i++) {
printf("%e\n",z[i]);
}
free(xhi);
free(yhi);
free(z);
return 0;
}
What is happening here?
Upvotes: 1
Views: 106
Reputation: 9509
I'm not used to vector intrinsics, but this looks very suspicious to me:
chi[j]=vchi[0];
chi[j+1]=vchi[1];
chi[j+2]=vchi[2];
chi[j+3]=vchi[3];
And as a matter of fact, replacing it with what looks very much like the right function for the job, namely _mm256_store_pd()
seems to be fixing the issue.
Your function could now look like this (with a few stylistic fixes as well)
void dd_m_dd(double *ahi, double *bhi, double *chi, int m, int n) {
#pragma omp parallel for
for (int j = 0; j < m*n; j+=4) {
__m256d vbhi = _mm256_broadcast_sd(&bhi[j]);
__m256d vahi = _mm256_load_pd(&ahi[j]);
__m256d vchi=vahi*vbhi;
_mm256_store_pd( &chi[j], vchi );
}
}
Another issue is that you do not enforce the proper alignment of your pointers... Rewriting the allocations like this just fixes it:
double *xhi=(double *)aligned_alloc(256, sizeof(double) * m*1);
double *yhi=(double *)aligned_alloc(256, sizeof(double) * m*1);
double *z=(double *)aligned_alloc(256, sizeof(double) * m*1);
Upvotes: 3