用于嵌套 for 循环的 OpenMP?
Posted
技术标签:
【中文标题】用于嵌套 for 循环的 OpenMP?【英文标题】:OpenMP for nested for loops? 【发布时间】: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 循环不会阻碍并行化(例如,数据依赖) 【参考方案1】:是的,添加编译指示是正确的。内存被所有线程隐式共享。但这并不意味着它会更快地工作。有多个问题需要考虑:
您的系统有多少个处理器? 您使用整数还是浮点数?对于整数,顺序无关紧要,但对于浮点则不是这样 哪些变量只能由最内层循环访问?您可以将它们声明为私有以获得更好的性能。【讨论】:
在***.com/questions/2100490/…,您可以找到一些浮点问题的示例。使用多线程时,问题3(四舍五入)会影响结果(差异可能很小,但这取决于算法)【参考方案2】:我可以简单地在第一个循环前面添加“#pragma omp parallel for”来分配工作吗?
这取决于你在并行部分会做什么。为了获得更好的性能,您可能会更改并行代码的算法,而不仅仅是将#pragma omp parallel
放入您的序列代码中。请记住,并行编程的关键是共享变量。在某些情况下,使用序列代码比使用并行代码更好。
如果我这样做,我的程序会运行得更快,但我担心它所做的计算可能不准确。
确实,您必须确保代码中没有竞争条件才能获得正确的计算结果。
【讨论】:
【参考方案3】:确保影响相同数据的交互 i,j
和 j,i
不会导致数据争用。您可以仔细调整工作的分布,或在必要时使用omp critical
或omp 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,j
和 j,i
两个交互的计算次数。
【讨论】:
以上是关于用于嵌套 for 循环的 OpenMP?的主要内容,如果未能解决你的问题,请参考以下文章
在 OpenMP 中并行化嵌套循环并使用更多线程执行内部循环
使用 OpenMP 在 C、C++ 中并行化嵌套 for 循环的几种方法之间的区别