14

I'm working in C with openMP using gcc on a linux machine. In an openmp parallel for loop, I can declare a statically allocated array as private. Consider the code fragment:

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

And everything works as expected. But if instead I allocate a dynamically,

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

the values of a (at least a[1...9]) are not protected but act as if they are shared. This is understandable as nothing in the pragma command seems to tell omp how big the array a is that needs to be private. How can I pass this information to openmp? How do I declare the entire the dynamically allocated array as private?

cboettig
  • 12,377
  • 13
  • 70
  • 113

2 Answers2

15

I don't think you do - what I did to solve this problem was used a parallel region #pragma omp parallel shared(...) private(...) and allocated the array dynamically inside the parallel region. Try this:

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

That to me produced the same results as my earlier experiment program:

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

At a guess I'd say because OpenMP can't deduce the size of the array it can't be private - only compile-time arrays can be done this way. I get segfaults when I try to private a dynamically allocated array, presumably because of access violations. Allocating the array on each thread as if you'd written this using pthreads makes sense and solves the issue.

  • Thanks, separating the openmp declaration and the parallel for declaration seems to have worked perfectly. – cboettig Mar 01 '10 at 01:13
  • @Ninefingers: I know this post is old, but I had a quick question. Do you even need the `#pragma omp for` statement at all? Wouldn't it perform that loop in parallel regardless? – Amit Jun 08 '12 at 18:39
  • 1
    @Amit nope, you need to tell the compiler to break out threads, otherwise it won't. –  Jun 09 '12 at 16:23
9

You told OpenMP that the pointer a is private, i.e. replicated in each thread. Your array is just some arbitrary data a points to, and OpenMP will not replicate it (perhaps because this would make it necessary to allocate and deallocate the replicated arrays).

Riko Jacob
  • 353
  • 1
  • 4
  • 9
  • 1
    So how could one make OpenMP create an array for each thread? In my case there is a buffer array that each thread needs his own. – Royi Sep 18 '18 at 08:36