OpenMP并行for循环减少

时间:2014-02-27 15:54:59

标签: parallel-processing reduction openmp

我有一个for循环来迭代相当大量的点(大约20000),每个点检查点是否在某个圆柱内(每个圆柱的圆柱是相同的)。 此外,我希望从这组点中得到最高的Y坐标。 由于我必须进行很多计算,而且速度很慢,我想使用OpenMP来并行化循环。目前我(略有减少):

#pragma omp parallel for default(shared) private(reducedCloudSize, reducedCloud, cylinderBottom, cylinderTop) reduction(+:ptsInside, ptsInsideLarger)
for (int i = 0; i < reducedCloudSize; i++){
    highestYCoord = highestYCoord > testPt.y ? highestYCoord : testPt.y;

    if (CylTest_CapsFirst(cylinderBottom,cylinderTop,cylinderHeight*cylinderHeight,cylinderRadius*cylinderRadius,testPt) != -1){
        ptsInside++;
    }

}

CylTest_CapsFirst将检查该点是否在圆柱内。 但是,此代码不起作用。如果我省略了减少(+:ptsInside,ptsInsideLarger)部分它实际上工作,但比非并行版本慢得多。如果我包含减少子句,程序似乎永远不会进入for循环!

我做错了什么?

谢谢!

1 个答案:

答案 0 :(得分:1)

假设您的函数CylTest_CapsFirst没有写入任何内容(仅读取),则需要共享的唯一变量是highestYCoordptsInside。唯一需要私有的变量是i。您不需要明确声明这些。 但是您确实需要确保没有线程同时写入共享变量。为了有效地执行此操作,您应该创建在并行循环中编写的highestYCoordptsInside的私有版本。然后,您可以将私有版本与关键部分中的共享版本合并。只要reducedCloudSize >> number_of_threads

,这是有效的
#pragma omp parallel
{
    double highestYCoord_private = highestYCoord;
    int ptsInside_private = 0;
    #pragma omp for
    for (int i = 0; i < reducedCloudSize; i++){
        highestYCoord_private = highestYCoord_private > testPt.y ? highestYCoord_private : testPt.y;
        if (CylTest_CapsFirst(cylinderBottom,cylinderTop,cylinderHeight*cylinderHeight,cylinderRadius*cylinderRadius,testPt) != -1) {
                ptsInside_private++;
        }
    }
    #pragma omp critical 
    {
        highestYCoord = highestYCoord_private > highestYCoord : highestYcoord_private ? highestYCoord
        ptsInside += ptsInside_private;
    }
}