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
对所有线程都是一样的,这会混淆下一个线程。
我正在学习 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
对所有线程都是一样的,这会混淆下一个线程。