Objects with dynamic storage duration are shared

Forum for the public review of the OpenMP 4.0 API Release Candidates. (Read Only)
Forum rules
This forum is now closed.

Objects with dynamic storage duration are shared

Postby muphof » Sun Apr 07, 2013 10:04 pm

Hi,

I am quoting p. 123 of the specifications. I cannot understand the purpose of this statement. Assume I use a pointer for a dynamically allocated object as in:
Code: Select all
    int * x = new int[10];
#pragma omp parallel private(x)
   {             
        int tid = omp_get_thread_num();       
        x = new int;
        *x = tid;
        sleep(1);
        printf("tid, x = %d %d\n", tid, *x);
    }

This code is correct. In this code, each thread has its own copy of the pointer x, allocates memory, assign a value to *x, and prints it. x is a private variable. It seems to me that this case is not the one described in the specification for dynamically allocated objects.

What I don't understand is why the specification has to clarify the data-sharing attribute of an object with dynamic storage duration. Is there an example where this rule applies and is used?

How can one use an object with dynamic storage duration without a pointer? One can use a reference to refer to a dynamically allocated object. But then the specification on p. 137 already states that a reference is not possible in the private clause. So a reference must be shared.

I tried to compiled different codes. Here are some results.

If I compile the following code
Code: Select all
    int z = 3;
    int & y = z;
#pragma omp parallel shared(y)
    {
    }

I get:
Code: Select all
test_sharing.c:17: error: ‘y’ is predetermined ‘shared’ for ‘shared’

That's using
Code: Select all
$ gcc --version
i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.9.00)

It feels this is a bug in the compiler since the data-sharing attribute of y is not in fact pre-determined.
If I use a dynamically allocated pointer, it's the same thing:
Code: Select all
    int * x = new int;
    int & y = *x;
#pragma omp parallel shared(y)
    {
    }

This time, the data-sharing attribute of y may in fact be pre-determined since it is referring to a dynamically allocated object.

If this reasoning is correct, it seems that the specification should really say something about references rather than dynamically allocated objects.

I would appreciate some clarification on this technical point. Thank you.
muphof
 
Posts: 5
Joined: Wed Mar 27, 2013 4:17 pm

Re: Objects with dynamic storage duration are shared

Postby jakub » Mon Apr 08, 2013 12:40 pm

[quote="muphof"]
Yes, x is a private variable, *x is shared, but as you never pass the address from one thread to another one, it doesn't really matter much whether it is shared or private. But if you did
Code: Select all
x = new int;

and then somehow passed that int * pointer to some other thread (master construct, atomic store + atomic read, lastprivate on single construct, etc., then it should be very clear why the standard says it is shared.
I get:
Code: Select all
test_sharing.c:17: error: ‘y’ is predetermined ‘shared’ for ‘shared’


That's because you are using very old compiler (4.2.0 is almost 6 years old now, and not maintained by the GCC projects for almost 5 years now, also it has been the very first GCC version to support OpenMP at all (2.5 version)).
If you try any supported compiler, it won't emit this bogus error (note, while reference type vars aren't predetermined shared, they are only allowed in shared clause, can't be {first,last,}private or can't be used in reduction clause.
jakub
 
Posts: 74
Joined: Fri Oct 26, 2007 3:19 am

Re: Objects with dynamic storage duration are shared

Postby muphof » Mon Apr 08, 2013 3:55 pm

Hi,

Thank you for your answer.

I am still somewhat unclear about your reply.

First off, I updated the compiler:
Code: Select all
g++-mp-4.7 --version
g++-mp-4.7 (MacPorts gcc47 4.7.2_2) 4.7.2
Copyright (C) 2012 Free Software Foundation, Inc.

which got rid of the error message as you pointed out. Thank you.

I understand that x is private but how can we say that *x is shared?

According to the definition in the specs:

shared variable: With respect to a given set of task regions that bind to the same parallel region, a variable whose name provides access to the same block of storage for each task region.

private variable: With respect to a given set of task regions that bind to the same parallel region, a variable whose name provides access to a different block of storage for each task region.

Here is the code again:
Code: Select all
   #pragma omp parallel
       {                 
          int * x = new int;
          ...
       }

*x is referring to a different memory location for each thread ("name provides access to a different block of storage"). Therefore it should be, strictly speaking, a private object. We could say that *x is shared if in fact new int was able to create a single object shared by all threads. This is not the case.

I tried to implement what you suggested, that is pass the pointer to some other thread. However, that does not seem to address the question of what the data sharing attribute is, since again each thread allocates separate memory space to store *x. What am I missing? Perhaps I am confused about the meaning of shared variable.

Code: Select all
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
   int * y = NULL;
   
#pragma omp parallel
   {                 
      int * x = new int;      
      
#pragma omp single
      {
         y = x;
         *y = 5;
      }
      
         // Flush the variables
#pragma omp barrier
      
        int tid = omp_get_thread_num();       
        printf("tid, y = %d %d\n", tid, *y);
    }
    return 0;
}

Output:
Code: Select all
tid, y = 1 5
tid, y = 3 5
tid, y = 4 5
tid, y = 5 5
tid, y = 6 5
tid, y = 2 5
tid, y = 7 5
tid, y = 0 5


In case this helps, I also implemented the incorrect code where y points to an automatic variable. That results in a bug:
Code: Select all
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
   int * y = NULL;
   
#pragma omp parallel
   {                 
      int x = 5;
      
#pragma omp master
      {
         y = &x;
      }
      
         // Flush the variables
#pragma omp barrier
      
        int tid = omp_get_thread_num();       
      if (tid == 1) sleep(1);
        printf("tid, y = %d %d\n", tid, *y);
    }
    return 0;
}

Output:
Code: Select all
tid, y = 2 5
tid, y = 4 5
tid, y = 6 5
tid, y = 3 5
tid, y = 5 5
tid, y = 0 5
tid, y = 7 5
tid, y = 1 1648941056

Thread 1 waits until all threads are done so that y no longer points to a valid address and therefore *y no longer contains the expected value.

Thank you for the help again.
muphof
 
Posts: 5
Joined: Wed Mar 27, 2013 4:17 pm


Return to OpenMP 4.0 Public Review Release Candidates

Who is online

Users browsing this forum: No registered users and 3 guests

cron