Pointers are variables whose value is the address of a given memory cell (or the beginning of a group of cells). Sharing a pointer shares the variable itself, i.e. the named memory location, where the address is being stored.
Heap memory pointed to by pointers is always shared since nothing prevents you from accessing it from other threads through existing valid pointers.
The following cases are possible:
shared(a)
means that the pointer is shared by all threads. If any thread modifies a
, e.g. executes a++
or assigns a new value to it, the pointer changes in all other threads too. Since the value of the pointer is the same in all threads, they all can access the memory that it points to, i.e. the memory is shared;
private(a)
means that the pointer is private to each thread. Every threads gets its own uninitialised pointer variable. If one thread assigns to a
, the change is not visible in the other threads. Since the private copies are not initialised, the memory pointed by a
outside the parallel region is not visible inside the threads unless there is another pointer to it or unless another mechanism to obtain a pointer to the memory exists;
firstprivate(a)
means that the pointer is private to each thread but initially all private copies are set to the value of a
before the parallel region. In that case each thread can modify the value of a
and those modifications won't be visible by the other threads. As long as all copies of a
point somewhere within the memory that the original value of a
points to, modifications to it done through the local copies of a
are visible by all threads and hence the memory block is shared.
The private(a)
case makes little sense and it is advisable that one uses block-local variables instead. That means, instead of
int *p;
#pragma omp parallel private(p)
{
...
}
one is advised (for the sake of clarity) to use
#pragma omp parallel
{
int *p;
...
}
The data sharing clauses affect only the pointer variable and not the memory it points to. For example, private(a)
does not allocate a private copy of the heap memory originally pointed to by a
:
int *a = malloc(10 * sizeof(int));
#pragma omp parallel private(a)
{
a[1] = ... // <--- WRONG - no memory allocated automatically by OpenMP
}
An useful use case is one where each thread allocates its private heap memory:
#pragma omp parallel
{
int *a = malloc(10 * sizeof(int));
...
free(a);
}
The heap memory remains private to each thread unless its address is shared between the threads using a shared pointer.
The same applies to pointer to pointers.