OpenMP - 在for循环中生成和终止线程时的开销

时间:2017-11-25 16:30:35

标签: c multithreading parallel-processing openmp

我是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的最外层循环,这既不是提问者想要的也不是我想要的。

1 个答案:

答案 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并重复...我希望现在很清楚,这与内循环的行为与以前一样,少了线程管理开销。