在应用 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)
不要嵌套太深。通常,确定并行化的好点并仅使用一个指令就足够了。
一些评论,可能是您问题的根源:
#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 参考卡使用不同的调度算法对其进行微调。
并将您的变量声明放在您真正需要它们的地方。不要覆盖兄弟线程读取的内容。
| 归档时间: |
|
| 查看次数: |
13761 次 |
| 最近记录: |