openmp在孤立任务中显式共享指针

时间:2014-03-06 21:17:26

标签: pointers openmp shared

我有一个关于OpenMP的非常奇怪的问题。对于下面的示例,默认情况下,变量“a”应根据OpenMP规则进行“共享”(章节:2.9.1.2:区域中引用的变量的数据共享属性规则,但不包含在构造中:具有动态的对象)存储持续时间是共享的)。当我运行它时,我得到:

adre1: 0x7f51640008c0
adre2: 0x7f51640008c0
adre3: 0x1122d40
adre4: 0x7f51640008c0

这是有道理的。

void jl()
{

   char *a=(char *)malloc(10);
   printf("adre1: %p\n",a);
   #pragma omp task
   {

       printf("adre2: %p\n",a); 
       a=(char *)malloc(10);
       printf("adre3: %p\n",a);
   }
   #pragma omp taskwait
   printf("adre4: %p\n",a);
}

但是如果我在这样的任务后添加“共享”:

void jl()
{
    char *a=(char *)malloc(10);
    a[1]='c';
    printf("adre1: %p\n",a);

    #pragma omp task shared(a)
    {

        printf("adre2: %p\n",a);
        a=(char *)malloc(10);
        printf("adre3: %p\n",a);
    }
    #pragma omp taskwait
    printf("adre4: %p\n",a);
}

输出是:

adre1: 0x1cefd40
adre2: 0x1cefd40
adre3: 0x7f93d00008c0
adre4: 0x7f93d00008c0
我在这里很困惑。当你在任务中重定向变量“a”的地址时,看到它在外面是可见的,但我在Openmp中找不到这样的数据属性规则。 这两种情况有什么区别?

2 个答案:

答案 0 :(得分:1)

第一种情况中的a变量为firstprivate。如果没有其他规则适用,这是task构造中引用的变量的默认隐式确定的数据共享属性。实际上,如果你遵守规则(见§2.9.1.1)并逐一审阅,你就会看到其他规则都不适用:

  
      
  • paralleltask构造中,这些变量的数据共享属性是   由default子句确定(如果存在)。
  •   

不是这种情况,因为default构造中没有task子句。

  
      
  • parallel构造中,如果不存在default子句,则这些变量是   共享。
  •   

不是parallel构造。

  
      
  • 对于task以外的构造,如果不存在default子句,则为这些变量   从封闭的上下文继承他们的数据共享属性。
  •   

同样,这是一个task构造,规则不适用。

  
      
  • task构造中,如果不存在default子句,则为...中的变量   确定封闭上下文由绑定到当前的所有隐式任务共享   团队是共享的。
  •   

a是一个具有自动存储持续时间的变量,在被调用的例程中声明。因此,其数据共享属性被预先确定为私有(参见§2.9.1.2),该规则不适用。

  
      
  • task构造中,如果不存在default子句,则为数据共享的变量   属性不是由上面的规则确定的firstprivate。
  •   

这个包罗万象的规则是唯一适用的规则。

Firstprivate变量最初取外部变量的值,但对它们的任何更改在构造/区域外都不可见。这与OpenMP任务一样,就像闭包一样 - 任务在创建时捕获变量的值,并在执行任务时稍后使用这些值。

答案 1 :(得分:-1)

答案取决于编译器, 在某些实现中,默认共享= firstprivate而在其他实现(包括我的)默认=共享,

例如:        void main()         {

    char *a=(char *)malloc(10);
       printf("adre1: %p\n",a);

    omp_set_num_threads(1);
    #pragma omp parallel 
    {

    //#pragma omp single
    {
       #pragma omp task firstprivate(a)
       {

           printf("adre2: %p\n",a);
           a=(char *)malloc(10);
           printf("adre3: %p\n",a);
       }
       #pragma omp taskwait

       printf("adre4: %p\n",a);
    }

       printf("adre5: %p\n",a);
    }

       printf("adre6: %p\n",a);
    }

输出:

  • adre1:0x948a008
  • adre2:0x948a008<
  • adre3:0x948a6b0<<
  • adre4:0x948a008<
  • adre5:0x948a008
  • adre6:0x948a008

如果我们改变#pragma omp task firstprivate(a)==> #pragma omp task shared(a)

  • adre1:0x9b96008
  • adre2:0x9b96008<
  • adre3:0x9b966b0<<
  • adre4:0x9b966b0<
  • adre5:0x9b966b0
  • adre6:0x9b966b0

将来为了避免与数据共享相关的混淆,请始终使用:

#pragma omp parallel default(none) 
{
//my code
}.