Неправильный ответ при использовании компилятора icc - PullRequest
0 голосов
/ 14 мая 2018

Когда я использую ICC-компилятор на Mac, я не мог получить такой же ответ с другим компилятором, таким как gcc, clang. Используя компилятор icc, результат был ниже

0.000000e+00
0.000000e+00
0.000000e+00
0.000000e+00
0.000000e+00
0.000000e+00
0.000000e+00
0.000000e+00

Ожидаемый ответ здесь

1.000000e+00
2.000000e+00
3.000000e+00
4.000000e+00
2.500000e+01
3.000000e+01
3.500000e+01
4.000000e+01

Я скомпилировал так:

  • icc: icc test1.c -fopenmp -mavx -Wall
  • gcc: gcc test1.c -fopenmp -mavx -Wall
  • лязг: clang test1.c -fopenmp -mavx -Wall

Мой код выглядит следующим образом:

#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;
}

Что здесь происходит?

1 Ответ

0 голосов
/ 14 мая 2018

Я не привык к векторизации, но мне это кажется очень подозрительным:

    chi[j]=vchi[0];
    chi[j+1]=vchi[1];
    chi[j+2]=vchi[2];
    chi[j+3]=vchi[3];

И на самом деле, замена его на то, что очень похоже на правильную функцию для работы, а именно _mm256_store_pd(), похоже, решает проблему.

Ваша функция теперь может выглядеть так (с несколькими стилистическими исправлениями)

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 );
    }
}

Другая проблема заключается в том, что вы не применяете правильное выравнивание ваших указателей ... Переписывание распределений, как это, просто исправляет это:

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);
...