【问题标题】:OpenMP: 'parallel for loop' bottle neckOpenMP:“并行循环”瓶颈
【发布时间】:2014-11-25 15:55:30
【问题描述】:

我正在尝试用 c++ (vs2010) 编写一段代码,它将使用 openMP 在并行模式下运行。一切运行完美(我的所有处理器都很忙,for 循环进度符合预期,但是当我达到时间步 i = 211 时,一切都变慢了。在进程监视器中,我看到我只使用了 14%),然后过了一会儿它再次加速,但在时间步上再次减慢i = 316。它会定期执行此操作,直到完成。我不确定发生了什么。由于我是新手,如果我的问题不够清楚,请原谅我。

这是代码:

xyQadrant 是在代码前面创建的向量 - 它包含结构! 方法GetUx(..), GetUY(..), CalcVelocity(...), CalcDisplacement(..) 在访问数据时使用锁定和解锁,因此多个线程对同一数据的多次访问应该不会有任何问题。

for(int i = 0; i < 1250; i++)
{
    #pragma omp parallel num_threads(numCPU) shared(xyQuadrant)
    {
    #pragma omp for 

        for(int j = 0; j < xyQuadrant.size(); j++)
        {
            SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
            for(int k = 0; k < xyQuadrant[j].qPoints.size(); k++)
            {
                point* targetPoint = &xyQuadrant[j].qPoints[k];
                double strainX = 0;
                double strainY = 0;
                for (int n = 0; n < targetPoint->family.size(); n++)
                {

                    point* curPoint = targetPoint->family[n];

                    if(fabs(curPoint->x - targetPoint->x) < 0.000001)
                    {
                        strainX = 0;
                    }
                    else
                    {
                        double directionX = (curPoint->GetUX(i-1) - targetPoint->GetUX(i-1) + curPoint->x - targetPoint->x)/fabs((curPoint->GetUX(i-1) - targetPoint->GetUX(i-1) + curPoint->x - targetPoint->x));
                        double stretchX = fabs((curPoint->GetUX(i-1) - targetPoint->GetUX(i-1) + curPoint->x - targetPoint->x - fabs((curPoint->x - targetPoint->x))))/fabs(curPoint->x - targetPoint->x);

                        strainX += directionX*c*stretchX*targetPoint->volumeCorrect[n]*(targetPoint->surfaceCorrectX + curPoint->surfaceCorrectX)/2;

                    }

                    if(fabs(curPoint->y - targetPoint->y) < 0.000001)
                    {
                        strainY = 0;
                    }
                    else
                    {
                        double directionY = (curPoint->GetUY(i-1) - targetPoint->GetUY(i-1) + curPoint->y - targetPoint->y)/fabs((curPoint->GetUY(i-1) - targetPoint->GetUY(i-1) + curPoint->y - targetPoint->y));
                        double stretchY = fabs((curPoint->GetUY(i-1) - targetPoint->GetUY(i-1) + curPoint->y - targetPoint->y - fabs((curPoint->y - targetPoint->y))))/fabs(curPoint->y - targetPoint->y);

                        strainY += directionY*c*stretchY*targetPoint->volumeCorrect[n]*(targetPoint->surfaceCorrectY+curPoint->surfaceCorrectY)/2;
                    }
                }


                targetPoint->aX = strainX*deltaV/density;
                targetPoint->aY = strainY*deltaV/density;
                targetPoint->CalcVelocity(deltaT);
                targetPoint->CalcDisplacement(deltaT,i-1);
            }

        }
    }


}

最后一点:我使用 i7-3770 处理器(4 个 proc 8 个线程)- 当一切都变慢时,我只能看到 4 个线程在工作,而其他 4 个线程显示 CPU 已停放!

【问题讨论】:

  • 什么是xyQuadrant.size()?它有多大?还可以尝试设置线程亲和性,以避免操作系统的核心停放计划。
  • xyQadrant 是一个结构向量,其中每个结构都包含属于它的点向量。 xyQuadrant 有 7140 个成员,每个 qPoints 向量有 cca​​ 36 个成员!
  • 好吧,它足够大,可以忘记负载平衡。线程亲和性建议仍然存在。如果您看到冻结与特定 i 值的相关性,请检查取决于 i 的代码,即 CalcDisplacement 和 GetUX/UY
  • 我不确定如何在 Visual Studio 中设置线程亲和性!!一些帮助将不胜感激!
  • 通读this question 并从那里选择一个工具。

标签: c++ multithreading loops for-loop openmp


【解决方案1】:

其实我已经知道为什么会这样了!那是因为记忆。我试图为所有时间步长保存象限中每个点的结果。我将结果保存在双精度向量中,因为象限结构变得太大。当我只保存当前时间步长数据时,一切正常!谢谢大家的帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-31
    相关资源
    最近更新 更多