没有for循环的OpenMP不等负载

Posted

技术标签:

【中文标题】没有for循环的OpenMP不等负载【英文标题】:OpenMP unequal load without for loop 【发布时间】:2018-05-04 03:48:44 【问题描述】:

我有一个如下所示的 OpenMP 代码

while(counter < MAX)  
  #pragma omp parallel reduction(+:counter) 
  
     // do monte carlo stuff
     // if a certain condition is met, counter is incremented

  

因此,只要计数器低于某个值,并行部分就会由可用线程执行。根据场景的不同(我在这里做 MC 的东西,所以它是随机的),计算可能比其他计算需要更长的时间,因此这里的工作人员之间存在不平衡,由于并行结束时的隐式障碍而变得明显部分。

似乎#pragma omp parallel for 可能有办法规避这个问题(即 nowait 指令/动态调度),但我不能使用它,因为我不知道 for 循环的上迭代次数。

任何想法/设计模式如何处理这种情况?

最好的问候!

【问题讨论】:

【参考方案1】:

在单个并行部分中运行所有内容并以原子方式访问counter

int counter = 0;
#pragma omp parallel
while(1) 
     int local_counter;
     #pragma omp atomic read
     local_counter = counter;
     if (local_counter >= MAX) 
          break;
     
     // do monte carlo stuff
     // if a certain condition is met, counter is incremented
     if (certain_condition) 
         #pragma omp atomic update
         counter++;
     

由于原子访问,您不能直接在 while 条件中检查。 请注意,此代码会过冲,即counter &gt; MAX 可能在并行部分之后。请记住,counter 由多个线程共享和读取/更新。

【讨论】:

谢谢您-我会立即尝试。我想减少条款就不再需要了吧?我的意思是,使用原子操作,代码已经在处理这个问题了,对吧? 是的,在这种情况下,减少条款是错误的 - 抱歉,很好。 Atomics 会注意 1) counter 更新的总次数是正确的,并且 2) 你总是读取一个有效的值。 一个更普遍的问题:处理线程必须以只读方式访问复杂结构(例如,动态分配数组的成员)的情况的最佳方法是什么?我目前的方法只是简单地共享,我没有注意到任何问题。但是,我想知道:为什么我需要 #pragma atomic 读取呢?那么 firstprivate 是否更适合该结构? 如果只有来自所有线程的读访问,它可以并且应该在没有原子访问的情况下共享。我的示例中的读取访问是必要的,因为其他线程确实同时写入。注意:声明结构 firstprivate 不会影响指针/动态分配的内存。 谢谢,这真的很有用。我想知道为什么使用 openmp 很难找到一个好的 while 循环示例。

以上是关于没有for循环的OpenMP不等负载的主要内容,如果未能解决你的问题,请参考以下文章

非for循环的OpenMP并行化

openMP 嵌套并行 for 循环与内部并行 for

用于嵌套 for 循环的 OpenMP?

OpenMP指定for循环迭代的线程号

OpenMP 并行 for 循环异常

如何使用 OpenMP 通过 C++ std::list 并行化 for 循环?