2014-10-03 56 views
-1

我一直在试图并行化我写的一个粒子模拟代码。但在并行化过程中,当从1个处理器移动到12个处理器时,性能没有增加,甚至更糟的是代码不再返回准确的结果。我一直把头撞在墙上,无法弄清楚。以下是循环被并行化:OpenMP循环中的函数调用?

#pragma omp parallel 
{ 
omp_set_dynamic(1); 
omp_set_num_threads(12); 

#pragma omp for 
// Loop over azimuth ejection angle, from 0-360. 
for(int i=0; i<360; i++) 
{ 
    // Declare temporary variables 
    double *y = new double[12]; 
    vector<double> ejecVel(3); 
    vector<double> colLoc(7); 
    double azimuth, inc; 
    bool collision; 

    // Loop over inclincation ejection angle from 1-max_angle, increasing by 1 degree. 
    for(int j=1; j<=15; j++) 
    { 
     // Update azimuth and inclination angle and get velocity direction vector. 
     azimuth = (double) i; 
     inc  = (double) j; 
     ejecVel = Jet::GetEjecVelocity(azimuth,inc); 
     collision = false; 

     // Update initial conditions. 
     y[0] = m_parPos[0]; 
     y[1] = m_parPos[1]; 
      ... (define pointer values) 

     // Simulate particle 
     systemSolver.ParticleSim(simSteps,dt,y,collision,colLoc); 

     if(collision == true) 
     { 
      cout << "Collision! " << endl; 
     } 
    } 
    delete [] y; 
} 

的目标是要遍历,模拟了在循环不同的初始条件,并存储在那里,他们已经走了,在主变量densCount和collisionStates发生碰撞时的状态向量颗粒。模拟发生在另一个类(systemSolver.ParticleSim())的函数中,并且它看起来像来自不同线程的每个求解都不是独立的。我读过的所有内容都表明它应该是这样,但是我不明白为什么其他结果只有在我实现了Open MP的情况下才是正确的。任何想法都不胜感激。

-ben


SOLUTION:模拟是修改一个单独的(systemSolver)类的成员变量。由于我为所有线程提供了一个单独的类对象,它们都同时修改了一个重要的成员变量。以为我会张贴这个以防其他n00bs遇到类似问题。

+0

如何定义结果是准确和正确的?通过比较串行情况下的collisionState和并行情况,如果是这样,那么你不能指望他们是相同的。值应该是相同的,但顺序可能不一样。 – 2014-10-03 09:27:38

+0

这里有太多而且没有足够的代码来帮助我们确定问题;你可以减少代码到[最小完整的有效示例](http://stackoverflow.com/help/mcve)?另外,尽管与你的问题无关,我认为公司应该是j,而不是我? – 2014-10-03 12:25:30

+0

@Zboson我通过检查碰撞的粒子来定义'精确'。如果我应该有一个显着数量的碰撞(并且没有Open MP)时循环访问一个集合,那么在Open MP循环中就会有零个冲突。 – 2014-10-03 14:34:14

回答

1

我相信有一个错误是在并行区域内调用omp_set_ *函数。最好的情况是,它们只对后续区域有效。尝试重新排列如下:

omp_set_dynamic(1); 
omp_set_num_threads(12); 
#pragma omp parallel