Как обеспечить, чтобы динамически размещенный массив был закрытым в openmp - PullRequest
10 голосов
/ 01 марта 2010

Я работаю в C с openMP, используя gcc на Linux-машине. В openmp параллельном цикле я могу объявить статически размещенный массив как закрытый. Рассмотрим фрагмент кода:

int a[10];
#pragma omp parallel for shared(none) firstprivate(a)
for(i=0;i<4;i++){

И все работает как положено. Но если вместо этого я выделю динамически,

int * a = (int *) malloc(10*sizeof(int));
#pragma omp parallel for shared(none) firstprivate(a)

значения (по крайней мере, [1 ... 9]) не защищены, но действуют так, как если бы они были общими. Это понятно, поскольку ничто в команде pragma, кажется, не говорит omp, насколько большой массив a должен быть закрытым. Как я могу передать эту информацию в openmp? Как мне объявить весь динамически размещенный массив как частный?

Ответы [ 2 ]

13 голосов
/ 01 марта 2010

Я не думаю, что вы делаете - для решения этой проблемы я использовал параллельную область #pragma omp parallel shared(...) private(...) и динамически размещал массив внутри параллельной области. Попробуйте это:

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

/* compile with gcc -o test2 -fopenmp test2.c */

int main(int argc, char** argv)
{
    int i = 0;
    int size = 20;
    int* a = (int*) calloc(size, sizeof(int));
    int* b = (int*) calloc(size, sizeof(int));
    int* c;

    for ( i = 0; i < size; i++ )
    {
        a[i] = i;
        b[i] = size-i;
        printf("[BEFORE] At %d: a=%d, b=%d\n", i, a[i], b[i]);
    }

    #pragma omp parallel shared(a,b) private(c,i)
    {
        c = (int*) calloc(3, sizeof(int));

        #pragma omp for
        for ( i = 0; i < size; i++ )
        {
            c[0] = 5*a[i];
            c[1] = 2*b[i];
            c[2] = -2*i;
            a[i] = c[0]+c[1]+c[2];

            c[0] = 4*a[i];
            c[1] = -1*b[i];
            c[2] = i;
            b[i] = c[0]+c[1]+c[2];
        }

        free(c);
    }

    for ( i = 0; i < size; i++ )
    {
        printf("[AFTER] At %d: a=%d, b=%d\n", i, a[i], b[i]);
    }
}

Это дало мне те же результаты, что и моя предыдущая экспериментальная программа:

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

/* compile with gcc -o test1 -fopenmp test1.c */

int main(int argc, char** argv)
{
    int i = 0;
    int size = 20;
    int* a = (int*) calloc(size, sizeof(int));
    int* b = (int*) calloc(size, sizeof(int));

    for ( i = 0; i < size; i++ )
    {
        a[i] = i;
        b[i] = size-i;
        printf("[BEFORE] At %d: a=%d, b=%d\n", i, a[i], b[i]);
    }

    #pragma omp parallel for shared(a,b) private(i)
    for ( i = 0; i < size; i++ )
    {
        a[i] = 5*a[i]+2*b[i]-2*i;
        b[i] = 4*a[i]-b[i]+i;
    }

    for ( i = 0; i < size; i++ )
    {
        printf("[AFTER] At %d: a=%d, b=%d\n", i, a[i], b[i]);
    }
}

По-моему, я бы сказал, потому что OpenMP не может определить размер массива, он не может быть закрытым - таким образом можно создавать только массивы времени компиляции. Я получаю segfaults, когда пытаюсь скрыть динамически распределенный массив, предположительно из-за нарушений доступа. Выделение массива в каждом потоке, как если бы вы написали это с использованием pthreads, имеет смысл и решает проблему.

7 голосов
/ 17 февраля 2011

Вы сказали OpenMP, что указатель a является частным, то есть реплицируется в каждом потоке. Ваш массив - это просто произвольные данные, на которые указывает a, и OpenMP не будет его реплицировать (возможно, потому что это потребует выделения и освобождения реплицируемых массивов).

...