Умножение матриц паралеллизуется с помощью openmp и векторизируется с помощью avx2 - PullRequest
0 голосов
/ 26 апреля 2020

(1) Для некоторых размеров (размер матрицы) код работает нормально, но для некоторых размеров он вычисляет неправильное умножение матриц, хотя я осторожно использую набор инструкций Avx2, но я не могу понять, где проблема.

(2) Когда я только векторизовал код с Avx2, время выполнения набора команд меньше, чем когда я векторизовал код с avx2 и распараллелил с Openmp. Хотя время выполнения должно быть меньше, когда используются как векторизация (Avx2), так и распараллеливание (Openmp).

void mat_mul_pl(int size, double **mat1, double **mat2, double **result)
{
__m256d vec_multi_res = _mm256_setzero_pd(); //Initialize vector to zero
__m256d vec_mat1 = _mm256_setzero_pd(); //Initialize vector to zero
__m256d vec_mat2 = _mm256_setzero_pd();


int i, j, k;

// #pragma omp parallel for schedule(static)
for (i = 0; i < size; i++)
{
    for (j = 0; j < size; ++j)
    {
        //Stores one element in mat1 and use it in all computations needed before proceeding
        //Stores as vector to increase computations per cycle
        vec_mat1 = _mm256_set1_pd(mat1[i][j]);
#pragma omp parallel for
        for (k = 0; k < size; k += 8)
        {
            vec_mat2 = _mm256_loadu_pd((void*)&mat2[j][k]); //Stores row of second matrix (eight in each iteration)
            vec_multi_res = _mm256_loadu_pd((void*)&result[i][k]); //Loads the result matrix row as a vector
            vec_multi_res = _mm256_add_pd(vec_multi_res ,_mm256_mul_pd(vec_mat1, vec_mat2));//Multiplies the vectors and adds to th the result vector

            _mm256_storeu_pd((void*)&result[i][k], vec_multi_res); //Stores the result vector into the result array
        }
    }
    }
}

1 Ответ

0 голосов
/ 28 апреля 2020

Я не сталкиваюсь ни с какими ошибками при компиляции, но когда я выполняю программу, я получаю ошибку сегментации (дамп памяти). Отладкой я заметил, что ядро ​​выгружено в определенный размер (больше 100) в vec_mat2 = _mm256_load_pd ((void *) & mat2 [j] [k]) этой инструкции. Пожалуйста, смотрите обновленный код ниже как согласно вашим инструкциям.

void mat_mul_pl(int size, double **mat1, double **mat2, double **result)
{

int i, j, k;

#pragma omp Parallel shared(vec_mat1,vec_mat2,vec_multi_res) private(i,j,k)
{

#pragma omp for schedule(static)
    for (i = 0; i < size; i++)
    {       
        for (j = 0; j < size; ++j)
        {
            __m256d vec_mat1 = _mm256_setzero_pd(); 
            vec_mat1 = _mm256_set1_pd(mat1[i][j]);
            for (k = 0; k < size; k += 4)
            { 
                __m256d vec_multi_res = _mm256_setzero_pd(); 
                __m256d vec_mat2 = _mm256_setzero_pd();
                vec_mat2 = _mm256_load_pd((void*)&mat2[j][k]); 
                vec_multi_res = _mm256_load_pd((void*)&result[i][k]); 
                vec_multi_res = _mm256_add_pd(vec_multi_res ,_mm256_mul_pd(vec_mat1, vec_mat2));
                _mm256_store_pd((void*)&result[i][k], vec_multi_res);
            } 
        }
    }
    }
}
...