我试图用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'。但是,由于在最外圈和内圈之间仍然存在某些东西,因此在这种情况下不能使用“崩溃”。还有其他方法可以让我们在使用OpenMP时更有效地使这个parllelization更有效吗?
非常感谢。
答案 0 :(得分:1)
如果i_max独立于外环中的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子句,则只有在语句为true时才会运行OpenMP。像这样:
const int threshold = ... // smallest value for which OpenMP gives a speedup.
#pragma omp parallel for reduction(+:dev) schedule(dynamic) if(i_max > threshold)