2017-11-25 133 views
0

我对OpenMP相当陌生,并且我尝试了一些Monte Carlo代码并行化。OpenMP - 在for循环中产生并终止线程时的开销

我有一个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询问确切同样的事情,但(取消选中)的答案是刚刚parallelise运行循环4000 * num_threads最外层的环既不是什么提问者想和我想要的东西。

回答

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,然后重复......我希望现在清楚的是,这与内部循环的行为相同,并且线程管理开销较小。

+0

这很有道理,谢谢你的好解释。我确实有一些后续问题(如果你不介意):我将如何让每个线程以我原本以为的方式执行for-loop,即num_threads * MAX_VAL次? – BodneyC

+0

实际上它实际上是被执行了'num_threads * MAX_VAL',但是由于工作共享,内部循环迭代只执行了'MAX_VAL * N'次。因此,除去内部的'omp for'会导致内部循环体执行'num_threads * MAX_VAL * N'次这样的执行。 – Zulan

+0

现货,这是非常有道理的。再次感谢。 – BodneyC