如果在OpenMP中共享指针(以及指向...的指针),将共享什么

时间:2014-04-08 14:43:18

标签: c arrays openmp

我有一个结构

typedef struct mystruct {
int* a;
float** b;
} mystruct;


mystruct* s = (mystruct*) calloc(1, sizeof(mystruct));
s->a  = (int*) calloc(100, sizeof(int));
s->b  = (float**) calloc(100, sizeof(float*));

for (int i=0; i<100; i++)
s->b[i]  = (float*) calloc(100, sizeof(float));

如果我声明{* 1}}在OpenMP中共享为:

s

将所有线程共享内存中的所有以下变量:

  • 指针#pragma omp parallel for shared(s) schedule(auto)

  • a指向的数组,即a

  • 指针a[i], i=0,...,99

  • b指向的数组,即b

  • b[i], i=0,...,99指向的数组,即b[i], i=0,...,99

如果在OpenMP

中共享指针(以及指向...的指针),将共享什么

谢谢!

1 个答案:

答案 0 :(得分:2)

指针是变量,其值是给定存储单元的地址(或一组单元的开头)。共享指针共享变量本身,即存储地址的命名存储单元。

指针指向的堆内存总是共享的,因为没有什么能阻止您通过现有的有效指针从其他线程访问它。

以下情况是可能的:

  • shared(a)表示指针由所有线程共享。如果任何线程修改a,例如执行a++或为其分配一个新值,指针也会在所有其他线程中更改。由于指针的值在所有线程中都是相同的,因此它们都可以访问它指向的内存,即共享内存;

  • private(a)表示指针对每个线程都是私有的。每个线程都有自己的未初始化指针变量。如果一个线程分配给a,则更改在其他线程中不可见。由于私有副本未初始化,因此并行区域外a指向的内存在线程内部不可见,除非有另一个指向它的指针或除非存在另一种获取指向内存的指针的机制;

  • firstprivate(a)表示指针对每个线程都是私有的,但最初所有私有副本在并行区域之前都设置为a的值。在这种情况下,每个线程都可以修改a的值,其他线程将无法看到这些修改。只要a的所有副本都指向内存中a的原始值所指向的某个位置,所有线程都可以看到通过a的本地副本对其进行的修改内存块是共享的。

private(a)情况没有意义,建议使用块局部变量。这意味着,而不是

int *p;

#pragma omp parallel private(p)
{
   ...
}

建议使用

(为清晰起见)
#pragma omp parallel
{
   int *p;
   ...
}

数据共享子句仅影响指针变量,指向它所指向的内存。例如,private(a) 分配a最初指向的堆内存的私有副本:

int *a = malloc(10 * sizeof(int));

#pragma omp parallel private(a)
{
   a[1] = ... // <--- WRONG - no memory allocated automatically by OpenMP
}

一个有用的用例是每个线程分配其私有堆内存的用例:

#pragma omp parallel
{
    int *a = malloc(10 * sizeof(int));
    ...
    free(a);
}

堆内存对每个线程保持私有,除非使用共享指针在线程之间共享其地址。

这同样适用于指针指针。