Вычисление записей матрицы в OpenMP - PullRequest
0 голосов
/ 03 июня 2018

Я очень новичок в openMP, но пытаюсь написать простую программу, которая генерирует элементы матрицы параллельно, а именно для матрицы A от N до M, пусть A (i, j) = i * j.Ниже приведен минимальный пример:

#include <stdio.h>
#include <stdlib.h>
#include <omp.h>

int main(int argc, 
         char **argv)
{
    int i, j, N, M;

    N = 20; 
    M = 20;

    int* A;
    A = (int*) calloc(N*M, sizeof(int));

    // compute entries of A in parallel 
    #pragma omp parallel for shared(A)
    for (i = 0; i < N; ++i){
        for (j = 0; j < M; ++j){
            A[i*M + j] = i*j;
        }
    }

    // print parallel results
    for (i = 0; i < N; ++i){
        for (j = 0; j < M; ++j){
            printf("%d ", A[i*M + j]);
        }
        printf("\n");
    }

    free(A);

    return 0;
}

Результаты не всегда верны.Теоретически я распараллеливаю только внешний цикл, и каждая итерация цикла for не изменяет записи, которые будут изменять другие итерации.Но я не уверен, как перевести это на openMP.При выполнении аналогичной процедуры для векторного массива (т. Е. Только один для цикла), кажется, нет никаких проблем, например,

#pragma omp parallel for
for (i = 0; i < N; ++i)
{
    v[i] = i*i;
}

Может кто-нибудь объяснить мне, как это исправить?

Ответы [ 2 ]

0 голосов
/ 03 июня 2018

Проблема в этом случае заключается в том, что j равно , совместно используемому между потоками, что мешает потоку управления внутреннего цикла.По умолчанию переменные, объявленные вне параллельной области, shared , тогда как переменные, объявленные внутри параллельной области, private .

Следуйте общему правилу, чтобы объявлять переменныенастолько локально, насколько это возможно .В цикле for это означает:

#pragma omp parallel for
for (int i = 0; i < N; ++i) {
    for (int j = 0; j < M; ++j) {

Это значительно упрощает рассуждения о вашем коде - и код OpenMP в основном корректен по умолчанию.(Примечание. A используется по умолчанию, поскольку оно определено за пределами.)

В качестве альтернативы вы можете указать private(i,j) shared(A) вручную - это более явно и может помочь новичкам.Однако это создает избыточность и также может быть опасным: private переменные неинициализированы, даже если они имели допустимое значение за пределами параллельной области.Поэтому я настоятельно рекомендую неявный подход по умолчанию, если это не требуется для расширенного использования.

0 голосов
/ 03 июня 2018

В соответствии, например, с этим
http://supercomputingblog.com/openmp/tutorial-parallel-for-loops-with-openmp/

Объявление переменных вне распараллеленной части опасно.
Его можно разрядить, явно сделав переменную цикла внутреннего цикла приватной.

Для этого измените это

#pragma omp parallel for shared(A)

на

#pragma omp parallel for private(j) shared(A)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...