c++ - 使用 OpenMP 并行化嵌套循环

标签 c++ parallel-processing nested openmp

我试图在我的代码中使用 OpenMP 并行化以下循环

 double pottemp,pot2body;
 pot2body=0.0;
 pottemp=0.0;

 #pragma omp parallel for reduction(+:pot2body) private(pottemp) schedule(dynamic)
 for(int i=0;i<nc2;i++)
    {
     pottemp=ener2body[i]->calculatePot(ener2body[i]->m_mols);
     pot2body+=pottemp;
    }

对于函数'calculatePot',这个函数中一个非常重要的循环也被OpenMP并行化了

   CEnergymulti::calculatePot(vector<CMolecule*> m_mols)
   {
        ...

        #pragma omp parallel for reduction(+:dev) schedule(dynamic)
        for (int i = 0; i < i_max; i++)
        {
         ...
         }
     }

看来我的并行化涉及嵌套循环。当我删除最外层循环的并行化时, 该程序似乎比最外层循环并行化的程序运行得快得多。测试在8核上进行。

我认为这种并行化的低效率可能与嵌套循环有关。有人建议我在并行化最外层循环时使用“collapse”。但是,由于最外层循环和内层循环之间还有一些东西,所以说在这种情况下不能使用'collapse'。在仍然使用 OpenMP 的同时,是否有任何其他方法可以尝试提高这种并行化的效率?

非常感谢。

最佳答案

如果 i_max 独立于 outerloop 中的 i,您可以尝试融合循环(本质上是崩溃)。这是我经常做的事情,它经常给我一个小小的插入。我也更喜欢“手动”融合循环而不是使用 OpenMP,因为 Visual Studio 只支持没有崩溃的 OpenMP 2.0,我希望我的代码可以在 Windows 和 Linux 上运行。

#pragma omp parallel for reduction(+:pot2body) schedule(dynamic)
for(int n=0; n<(nc2*i_max); n++) {
    int i = n/i_max; //i from outer loop
    int j = n%i_max; //i from inner loop 
    double pottmp_j = ... 
    pot2body += pottmp_j;
}

如果 i_max 依赖于 j 那么这将不起作用。在这种情况下,请遵循 Grizzly 的建议。但是你还可以尝试一件事。 OpenMP 有开销。如果 i_max 太小,那么使用 OpenMP 实际上可能会更慢。如果您在 pragma 末尾添加 if 子句,则 OpenMP 将仅在语句为真时运行。像这样:

const int threshold = ... // smallest value for which OpenMP gives a speedup.
#pragma omp parallel for reduction(+:dev) schedule(dynamic) if(i_max > threshold)

关于c++ - 使用 OpenMP 并行化嵌套循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15896048/

相关文章:

c++ - 分配给派生类的基组件

c++ - 使用 QML ListView 和 C++ QList<QObject*> 时如何实现过渡动画?

c - 如何使用 MPI_Gather 函数从变量中获取数据

python - 并行: Import a python file from sibling folder

Java多播接收数据及并行处理

css - 父 div 被子插入,在父 div 中产生间隙

C++ 类继承段错误

c++ - 使用 mmap 时出现段错误

c# - 选择具有特定数量的嵌套文档项目的文档

r - 如何优化循环 R 的嵌套