我有一个包含2个并行for循环的并行块:
int i, j;
#pragma omp parallel
{
#pragma omp for
for(i=0; i < foo; i++)
work();
#pragma omp for private(j)
for(i=0; i < foo; i++)
for(j=0, j < foo; j++)
work();
}
如果我像这样把它私有化:
int i, j;
#pragma omp parallel private(i)
{
#pragma omp for
for(i=0; i < foo; i++)
work();
#pragma omp for private(j)
for(i=0; i < foo; i++)
for(j=0, j < foo; j++)
work();
}
然后我有NUM_THREADS个i份。 openMP是否仍然能够基于i并行调度我的线程for循环以及如何?如果我不通过这种方式将其设为私有(请参阅第一个代码示例),那么我可以从两个for循环中获得什么样的行为?
它不是duplicate,因为我知道你通常可以让parralel循环隐式创建i的私有版本,但是我更关心的是它是否与之前私有的变量一样有效甚至在临时保密之前就已经开始工作了。
答案 0 :(得分:1)
回答你的问题
我可以从两个for循环中得到什么样的行为?
在您的第一个示例中,i
仅在工作共享区域(在for循环中)中是私有的。在两个工作共享区域之间,它仍然是共享的。在第二个示例中,因为您为并行区域声明了i
私有,所以它在任何地方都是私有的。
很容易显示。
i = 1;
#pragma omp parallel
{
#pragma omp for
for(i=0; i<10; i++);
i = 10;
}
printf("%d\n", i);
这会打印10
,因为i
是共享的,除了工作共享区域,并且每个帖子都将10
写入共享的i
。
然而,
i = 1;
#pragma omp parallel private(i)
{
#pragma omp for
for(i=0; i<10; i++);
i = 10;
}
printf("%d\n", i);
打印1
因为i
在整个并行区域中是私有的,并且不会修改并行区域外的i
。
在您当前的代码中,因为您只在工作共享区域中使用i
,所以它没有区别,但如果使用i
不在循环之间的工作共享区域中,则可能会有所不同。这可能会导致一个微妙的错误。由于您只在工作共享区域中使用i
,因此我建议您使用i
在工作共享区域中声明for(int i=0; ...
,或者将整个区域声明为私有。 j
也是如此。
答案 1 :(得分:0)
除非您将代码更改为
,否则您的第二个for循环将无法编译#pragma omp parallel
{
#pragma omp for
for(i=0; i < foo; i++)
work();
#pragma omp for private(j)
for(i=0; i < foo; i++)
for(j=0, j < foo; j++)
work();
}
和
int i, j;
#pragma omp parallel private(i)
{
#pragma omp for
for(i=0; i < foo; i++)
do();
#pragma omp for private(j)
for(i=0; i < foo; i++)
for(j=0, j < foo; j++)
work();
}
现在很清楚私人i
的范围是什么。
修改后,所有4个for循环都将按预期工作。
openMP是否仍然能够基于i并行调度我的线程for循环以及如何?
是的,在每个#pragma omp for
,私有i
将被正确初始化并在并行中使用。
如果我不通过这种方式将其设为私有(请参阅第一个代码示例),那么我可以在两个for循环之间从
i
获得什么样的行为?
即使您将其声明为共享,#pragma omp for
定义的并行索引也始终是私有的。所以你的第一个代码示例仍然有用。
实际上,根据这个答案,您是否将i
宣布为私有并不重要。