我有一个OpenMP循环,我希望在任何其他线程继续之前完成第一次迭代。我尝试过使用全局变量,初始化为' false',设置为' true'当第一次迭代结束时,但这似乎没有按预期工作(我陷入无限循环)。
例如:
bool FirstDone = false; // This is a global variable
...
#pragma omp parallel for
for(int i=0;i<max;i++)
{
while(!FirstDone && i>0){}
if(i==0)
{
// Do something
FirstDone = true;
}
}
任何人都可以解释为什么这不起作用吗?
答案 0 :(得分:2)
在循环外进行第一次迭代,以i = 1开始,如果你想继续你的逻辑,将FirstDone更改为volatile,但它仍然无效,因为无法保证线程排序
答案 1 :(得分:2)
您可以将第一次迭代包装在OpenMP single
构造中。这将确保遇到构造的第一个线程将执行它,并且所有其他线程将等到它完成后再继续其余的计算。
答案 2 :(得分:2)
我将尝试以更明确的方式重新解释@HighPerformanceMark的答案(即使用一些代码草图来支持语句)。只是为了解决问题,让我们说你的循环的串行版本如下:
for(int ii = 0; ii < max; ii++)
{
// Do a lot of work based on ii
if(ii==0)
{
//////////////////////////////////////////////////
// Do something special for the first iteration //
//////////////////////////////////////////////////
}
}
在之前的回答中简要提出的是将其与这个简单的逻辑并行化
// Move the loop body into a function
void loopIteration(const size_t ii) {
// Do a lot of work based on ii
}
#pragma omp parallel
{
// Single directive: the first one enters, the other wait at the implicit barrier
#pragma omp single
{
loopIteration(0);
//////////////////////////////////////////////////
// Do something special for the first iteration //
//////////////////////////////////////////////////
} // single: implicit barrier
// Loop work-sharing construct on the remaining iterations
#pragma omp for
for(int ii = 1; ii < max; ii++)
{
loopIteration(ii);
} // for: implicit barrier
} // parallel
主要思想是将循环体移动到一个函数中以避免代码重复并显式地从循环中展开第一次迭代。
答案 3 :(得分:1)
使用此
#pragma omp parallel for
默认情况下会在第一次迭代时启动。
答案 4 :(得分:1)
我认为您可以通过使用ordered
子句和区域来实现此目的,例如
#pragma omp parallel for ordered
for(int i=0;i<max;i++)
{
#pragma omp ordered
if (i == 0)
{
// Do stuff in the first iteration, others wait.
}
}
这可能会产生性能开销。
答案 5 :(得分:0)
您是否尝试过简单地删除while循环并在if语句后设置障碍?