我是OpenMP的新手,我有一些我试图并行的蒙特卡罗代码。
我有一个for循环,必须串行运行,调用new_value()
函数:
for(int i = 0; i < MAX_VAL; i++)
new_value();
此功能在每次通话时打开一个平行区域:
void new_value()
{
#pragma omp parallel default(shared)
{
int thread_rank = omp_get_thread_num();
#pragma omp for schedule(static)
for(int i = 0; i < N; i++)
arr[i] = update(thread_rank);
}
}
哪个有效,但是产生和终止线程会产生大量的开销;我想知道是否有人知道如何在进入循环之前产生线程(并获得thread_rank
)而不平行循环?
有几个问题提出同样的问题,但它们是错误的或没有答案的,其中的例子包括:
This question询问类似的事情,答案建议创建一个并行区域,然后在最外层循环上使用#pragma omp single
,但正如'Joe C'所说在答案评论中,这不起作用。我可以确认程序刚刚挂起。
This question询问完全同样的事情,但(未标记的)答案只是为了并行运行循环4000 * num_threads
的最外层循环,这既不是提问者想要的也不是我想要的。
答案 0 :(得分:0)
第二个问题的答案实际上是正确的。
#pragma omp parallel
for(int i = 0; i < MAX_VAL; i++)
new_value();
void new_value()
{
int thread_rank = omp_get_thread_num();
#pragma omp for schedule(static)
for(int i = 0; i < N; i++)
arr[i] = update(thread_rank);
}
是否正确而且正是您想要的。它与您问题中的代码具有相同的语义。区别在于只有一个并行区域,循环变量i
现在由整个团队计算。请注意,外部循环不以工作共享方式(omp parallel for
)进行并行化。
因此,当运行此代码时,num_threads
个线程将执行一次new_value
的循环标头,并使用其私有omp for
到达i == 0
。他们将分享内循环的工作。然后他们会等到每个人都在隐式屏障上完成循环,增加他们的私有i
并重复...我希望现在很清楚,这与内循环的行为与以前一样,少了线程管理开销。