【问题标题】:OpenMP for nested for loops?用于嵌套 for 循环的 OpenMP?
【发布时间】:2010-08-22 23:06:14
【问题描述】:

我试图在我的项目中使用 OpenMP,该项目在模拟中包含 N 个代理。每个代理都有一个位置向量。在我的程序中,我执行以下操作:

for(int i=0;i<agents.size();i++){
 for(int j=0;j<agents.size();j++){
   if(i==j) continue;
   if(distance_between(i,j)<10){
     //do a lot of calculations for interaction between i and j,
     //and a bunch of changes to variables of the Agents stored in the list
   }
 }
}

我可以简单地在第一个循环前面添加“#pragma omp parallel for”来分配工作吗?如果我这样做,我的程序会运行得更快,但我担心它所做的计算可能不准确。

这些计算的顺序无关紧要,只要处理每个 i,j 对,并且在最内层循环内定义的变量之外没有任何变量,并且我的 Agents 类中的变量曾经更改过(只读) .

我不是系统专家,我很难理解 OpenMP 的内部工作原理,并且对此有点怀疑。感谢您对此的任何帮助!

【问题讨论】:

  • 你必须确保你的 for 循环不会阻碍并行化(例如,数据依赖)

标签: c++ simulation openmp parallel-processing


【解决方案1】:

是的,添加编译指示是正确的。内存被所有线程隐式共享。但这并不意味着它会更快地工作。有多个问题需要考虑:

  • 您的系统有多少个处理器?
  • 您使用整数还是浮点数?对于整数,顺序无关紧要,但对于浮点则不是这样
  • 哪些变量只能由最内层循环访问?您可以将它们声明为私有以获得更好的性能。

【讨论】:

  • stackoverflow.com/questions/2100490/…,您可以找到一些浮点问题的示例。使用多线程时,问题3(四舍五入)会影响结果(差异可能很小,但这取决于算法)
【解决方案2】:

我可以简单地在第一个循环前面添加“#pragma omp parallel for”来分配工作吗?

这取决于你在并行部分会做什么。为了获得更好的性能,您可能会更改并行代码的算法,而不仅仅是将#pragma omp parallel 放入您的序列代码中。请记住,并行编程的关键是共享变量。在某些情况下,使用序列代码比使用并行代码更好。

如果我这样做,我的程序会运行得更快,但我担心它所做的计算可能不准确。

确实,您必须确保代码中没有竞争条件才能获得正确的计算结果。

【讨论】:

    【解决方案3】:

    确保影响相同数据的交互 i,jj,i 不会导致数据争用。您可以仔细调整工作的分布,或在必要时使用omp criticalomp atomic 构造。

    除此之外,仅通过在外循环上使用omp parallel for 构造来使您的代码运行得更快完全没有问题。请记住,如果您的处理器具有的处理单元(核心、硬件线程等)的数量,或者如果您使用的是 ccNUMA 机器,那么做一些额外的事情可能是一个好主意,因为您的代码的可扩展性将做得不够好。

    最简单的改进是将collapse(2) 添加到您的omp for 子句中。这将告诉 OpenMP 您希望完全分发这两个循环的迭代。

    #pragma omp parallel for collapse(2)
    for(int i=0;i<agents.size();i++){
     for(int j=0;j<agents.size();j++){
       if(i==j) continue;
       if(distance_between(i,j)<10){
         //do a lot of calculations for interaction between i and j,
         //and a bunch of changes to variables of the Agents stored in the list
       }
      }
    }
    

    一旦您遇到大量粒子(或您所称的代理),根据它们的位置对所有粒子进行排序可能是明智之举。这将导致最内层循环内的if 条件具有更稳定的行为,从而可以更好地预测分支(请参阅why is it faster to process a sorted array)。

    此外,如果将几何空间划分为 bin,则可以完全删除分支。这是因为您确切地知道非相邻存储桶距离太远而无法成功。

    这类问题众所周知,您可能已经知道,它们被称为n-body problems。存储桶优化版本称为Barnes-Hut simulation,尽管您可能会发现其他方法工作得更快(虽然更难并行化,但大多数时候仍然更有效),例如Fast Multipole Method,它或多或少包括减少通过在同一步骤中解决 i,jj,i 两个交互的计算次数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-24
      • 1970-01-01
      • 1970-01-01
      • 2017-04-20
      • 2012-05-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多