OpenMP 中的默认变量作用域

Default Variable Scope in OpenMP

我正在学习 C 编程中的 OpenMP,并试图了解不同情况下变量的默认范围。

鉴于这段代码,我对指针的范围和它们各自的变量值有点困惑。 例如 *x 和 x,以及 *y 和 y。据我了解,从并行区域调用的函数变量是“私有”的,除了变为“共享”的静态变量。

根据此规则,变量 *x、*y 和 z 应为“私有”,因为它们是从并行区域调用的函数 'fvg2' 的变量。此外,变量 x 和 y 也应该是私有的。

我的推理是否正确?

同样在并行编程中,最好的做法是显式指定每个变量范围而不是依赖默认值吗?

谢谢。

void fvg1 ( int *a, int n)
{
    int i, j, m = 3;
    #pragma omp parallel for
        for (i = 0; i < n; i ++)
        {
            int k = m;
            for (j = 0; j < 5; j ++)
            fvg2 (&( a[i]), &k, j);
        }
}

    extern int c;

void fvg2 ( int *x, int *y, int z)
{
    int ii;
    static int cnt ;
    cnt ++
        for (ii = 0; ii < z; ii ++)
        {
        *x = *y + c;
        }
}

在函数内声明的变量确实是私有的,但是您的 a 数组来自共享数组变量,因此变量 x 作为函数参数是共享的:函数的每次调用获取指向同一个原始数组 a.

的指针

私人(j,m)

这个 int k = m; 并不是真正在循环内的 默认 位置。通过使用 private 子句,就不需要了。

但是 j 所需要的是相同的:必须是“私有的”。 i 也是,但这已经是定义。

所以简化的函数可以是:

void fvg1 (int *a, int n) {

    int i, j, m = 3;

    #pragma omp parallel for private(m,j)

    for (i = 0; i < n; i ++)
        for (j = 0; j < 2; j ++)
            printf("_%d_ %p %p %d %p\n", omp_get_thread_num(), &i, &j, j, &m);
}

生产:

_4_ 0x7fc82be22d4c 0x7fc82be22d50 0 0x7fc82be22d54
_4_ 0x7fc82be22d4c 0x7fc82be22d50 1 0x7fc82be22d54
_0_ 0x7fffe840b0ac 0x7fffe840b0b0 0 0x7fffe840b0b4
_0_ 0x7fffe840b0ac 0x7fffe840b0b0 1 0x7fffe840b0b4
_3_ 0x7fc82c623d4c 0x7fc82c623d50 0 0x7fc82c623d54
_3_ 0x7fc82c623d4c 0x7fc82c623d50 1 0x7fc82c623d54
_5_ 0x7fc82b621d4c 0x7fc82b621d50 0 0x7fc82b621d54
_5_ 0x7fc82b621d4c 0x7fc82b621d50 1 0x7fc82b621d54
_1_ 0x7fc82d625d4c 0x7fc82d625d50 0 0x7fc82d625d54
_1_ 0x7fc82d625d4c 0x7fc82d625d50 1 0x7fc82d625d54
_2_ 0x7fc82ce24d4c 0x7fc82ce24d50 0 0x7fc82ce24d54
_2_ 0x7fc82ce24d4c 0x7fc82ce24d50 1 0x7fc82ce24d54

每个线程都有自己的变量 i、j 和 m。 (中间数字不同,0为特殊)

没有 private(j,m) 子句行丢失:

_4_ 0x7fec97c4bd54 0x7fffb280a80c 0 0x7fffb280a808
_4_ 0x7fec97c4bd54 0x7fffb280a80c 1 0x7fffb280a808
_0_ 0x7fffb280a784 0x7fffb280a80c 0 0x7fffb280a808
_3_ 0x7fec9844cd54 0x7fffb280a80c 0 0x7fffb280a808
_2_ 0x7fec98c4dd54 0x7fffb280a80c 0 0x7fffb280a808
_1_ 0x7fec9944ed54 0x7fffb280a80c 0 0x7fffb280a808
_5_ 0x7fec9744ad54 0x7fffb280a80c 0 0x7fffb280a808

现在 &j 对所有线程都是一样的,这会混淆下一个线程。