我有一个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循环!
我做错了什么?
谢谢!
答案 0 :(得分:1)
假设您的函数CylTest_CapsFirst
没有写入任何内容(仅读取),则需要共享的唯一变量是highestYCoord
和ptsInside
。唯一需要私有的变量是i
。您不需要明确声明这些。
但是您确实需要确保没有线程同时写入共享变量。为了有效地执行此操作,您应该创建在并行循环中编写的highestYCoord
和ptsInside
的私有版本。然后,您可以将私有版本与关键部分中的共享版本合并。只要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;
}
}