嵌套#pragma omp 指令的正确用法

Gol*_*Lee 4 c++ openmp

在应用 OpenMP 并行化之前,以下代码运行起来就像一个魅力。事实上,下面的代码处于死循环状态!我确信这是由于我对 OpenMP 指令的错误使用造成的。你能告诉我正确的方法吗?非常感谢。

          #pragma omp parallel for
          for (int nY = nYTop; nY <= nYBottom; nY++)
          {   
              for (int nX = nXLeft; nX <= nXRight; nX++)
              {   
                  // Use look-up table for performance
                  dLon = theApp.m_LonLatLUT.LonGrid()[nY][nX] + m_FavoriteSVISSRParams.m_dNadirLon;
                  dLat = theApp.m_LonLatLUT.LatGrid()[nY][nX];

                  // If you don't want to use longitude/latitude look-up table, uncomment the following line
                  //NOMGeoLocate.XYToGEO(dLon, dLat, nX, nY);

                  if (dLon > 180 || dLat > 180)
                  {  
                     continue;
                  }

                  if (Navigation.GeoToXY(dX, dY, dLon, dLat, 0) > 0) 
                  {  
                     continue;
                  }

                  // Skip void data scanline
                  dY = dY - nScanlineOffset;

                  // Compute coefficients as well as its four neighboring points' values
                  nX1 = int(dX);
                  nX2 = nX1 + 1;
                  nY1 = int(dY);
                  nY2 = nY1 + 1;

                  dCx = dX - nX1;
                  dCy = dY - nY1;

                  dP1 = pIRChannelData->operator [](nY1)[nX1];
                  dP2 = pIRChannelData->operator [](nY1)[nX2];
                  dP3 = pIRChannelData->operator [](nY2)[nX1];
                  dP4 = pIRChannelData->operator [](nY2)[nX2];

                  // Bilinear interpolation
                  usNomDataBlock[nY][nX] = (unsigned short)BilinearInterpolation(dCx, dCy, dP1, dP2, dP3, dP4);
              } 
          }
Run Code Online (Sandbox Code Playgroud)

Seb*_*ach 5

不要嵌套太深。通常,确定并行化的好点并仅使用一个指令就足够了。

一些评论,可能是您问题的根源:

      #pragma omp parallel default(shared)  // Here you open several threads ...
      {   
          #pragma omp for
          for (int nY = nYTop; nY <= nYBottom; nY++)  
          {                                          

              #pragma omp parallel shared(nY, nYBottom) // Same here ...
              {   
                  #pragma omp for
                  for (int nX = nXLeft; nX <= nXRight; nX++)
                  { 
Run Code Online (Sandbox Code Playgroud)

(从概念上讲)您正在打开许多线程,在每个线程中您再次在 for 循环中打开许多线程。对于 for 循环中的每个线程,您再次打开许多线程,对于其中的每一个,您又在另一个 for 循环中再次打开许多线程。

那是(thread (thread)*)+在模式匹配词中;应该有thread+

只需做一个平行的。不要细粒度,在外循环上并行化,每个线程都应该尽可能长地运行:

#pragma omp parallel for
for (int nY = nYTop; nY <= nYBottom; nY++)
{      
    for (int nX = nXLeft; nX <= nXRight; nX++)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

避免线程之间的数据和缓存共享(线程不应该对数据进行太细粒度的另一个原因)。

如果它运行稳定并显示出良好的速度,您可以根据您的 OpenMP 参考卡使用不同的调度算法对其进行微调。

并将您的变量声明放在您真正需要它们的地方。不要覆盖兄弟线程读取的内容。