OpenMP缓慢的私人功能
我想使用OpenMP来并行化一个函数,该函数在c ++中由main调用。
我的代码运行速度比顺序模式慢得多:没有OpenMP的for-loop需要大约6.1s(挂钟)(只是注释#pragma ...命令),使用OpenMP需要11.8s。
我的机器有8个CPU和8183Mb的物理存储器,并配有64位Windows 7操作系统。 我在调试模式下使用Visual Studio编译器来处理64位系统。
我已经读过,性能下降可能是由于应声明为私有变量,但我不确定如何正确执行此操作,以及哪些变量需要声明为私有变量。
这是相关的循环:
vec DecenterOffsetParallel(const real_1d_array &x22, vec vDistance, double dOffsetXp, double dOffsetYp, double dOffsetXm, double dOffsetYm, double dOffsetXpY, double dOffsetYpX, double dOffsetXmY, double dOffsetYmX, double* dDeltaXp, double* dDeltaYp, double* dDeltaXm, double* dDeltaYm, double* dDeltaXpY, double* dDeltaYpX, double* dDeltaXmY, double* dDeltaYmX, double* delta0, /*local variables for the parallel code: */ const int nRaysn, double PupilDian, mat mRxNn, mat mRyNn, mat mRzNn, mat mRxN1n, mat mRyN1n, mat mRzN1n, mat mRxN2n, mat mRyN2n, mat mRzN2n, mat mRxN3n, mat mRyN3n, mat mRzN3n, mat mRcxNn, mat mRcyNn, mat mRczNn, mat mRcxN1n, mat mRcyN1n, mat mRczN1n, mat mRcxN2n, mat mRcyN2n, mat mRczN2n, mat mRcxN3n, mat mRcyN3n, mat mRczN3n, mat mPathNn, mat mPath1Nn, mat mPath00Nn, mat mPathN1n, mat mPath1N1n, mat mPath00N1n, mat mPathN2n, mat mPath1N2n, mat mPath00N2n, mat mPathN3n, mat mPath1N3n, mat mPath00N3n)
{
#pragma omp parallel for
for (int xy = 0; xy < nRaysn * nRaysn; xy++){
mat temp = mat(nRaysn, nRaysn);
mat mScxn(nRaysn, nRaysn);
mat mScyn(nRaysn, nRaysn);
mat mSczn(nRaysn, nRaysn);
int i = xy / nRaysn;
int j = xy % nRaysn;
// only rays inside entrance pupil:t
if (sqrt(((10.0 / nRaysn) * i - 5.0)*((10.0 / nRaysn) * i - 5.0) + ((10.0 / nRaysn)*j - 5.0) *((10.0 / nRaysn)*j - 5.0)) <= PupilDian / 2.0){
// Initialize the matrices
mRxNn(i, j) = (10.0 / nRaysn) * i - 5.0;
mRyNn(i, j) = (10.0 / nRaysn) * j - 5.0;
mRzNn(i, j) = 0.0;
//... everything is repeated 3 more times to simulate all in all 4 cases...: mRxNn1(i,j) = (10.0/nRaysn)*i-5.0; and so on...
mRcxNn(i, j) = sign(vDistance(0)) *(mRxNn(i, j) - dOffsetYmX) / (sqrt(vDistance(0)*vDistance(0) + (mRxNn(i, j) - dOffsetYmX) * (mRxNn(i, j) - dOffsetYmX) + (mRyNn(i, j) - dOffsetYm) *(mRyNn(i, j) - dOffsetYm)));
mRcyNn(i, j) = sign(vDistance(0)) *(mRyNn(i, j) - dOffsetYm) / (sqrt(vDistance(0)*vDistance(0) + (mRxNn(i, j) - dOffsetYmX) * (mRxNn(i, j) - dOffsetYmX) + (mRyNn(i, j) - dOffsetYm) *(mRyNn(i, j) - dOffsetYm)));
mRczNn(i, j) = sqrt(1 - mRcxNn(i, j)*mRcxNn(i, j) - mRcyNn(i, j)*mRcyNn(i, j));
mPathNn(i, j) = 0.0;
mPath1Nn(i, j) = sign(vDistance(0)) *nAir * vDistance(0) / mRczNn(i, j);
mPath00Nn(i, j) = mPath1Nn(i, j);
//... everything is repeated 3 more times to simulate 4 different cases...
//trace rays through cornea
temp(i, j) = RayIntersect(ZernAnt, ZernRadAnt, &mRxNn(i, j), &mRyNn(i, j), P2DAnt, UAnt, VAnt, &mRzNn(i, j), mRcxNn(i, j), mRcyNn(i, j), mRczNn(i, j), &mPathNn(i, j), xNullAnt, yNullAnt, NknotsUAnt, NknotsVAnt); // find the intersection (modifies mRz, mRy, mRx, mPath)
mPathNn(i, j) = mPath1Nn(i, j) + nAir*mPathNn(i, j);
temp(i, j) = Surface(P2DAnt, UAnt, VAnt, ZernAnt, ZernRadAnt, mRxNn(i, j), mRyNn(i, j), mRzNn(i, j), &mScxn(i, j), &mScyn(i, j), &mSczn(i, j), KnotIntervallSizeAnt, xNullAnt, yNullAnt);
// *Ant are identical for all four cases!
temp(i, j) = Refract(nAir, nCornea, &mRcxNn(i, j), &mRcyNn(i, j), &mRczNn(i, j), mScxn(i, j), mScyn(i, j), mSczn(i, j));
//... everything is repeated 3 more times to simulate all in all 4 cases...
}
else{
mRxNn(i, j) = mRyNn(i, j) = mRzNn(i, j) = mRcxNn(i, j) = mRcyNn(i, j) = mRczNn(i, j) = mPathNn(i, j) = mPath1Nn(i, j) = NAN;
//... everything is repeated 3 more times to simulate all in all 4 cases...
}
}
// some other stuff, that is not relevant to the questions...
}
任何人都可以给我一个提示,什么可能会导致性能下降? 谢谢!
PS:犰狳库用于矩阵和向量。
您不需要在并行构造中声明任何私有变量,因为所有变量都是只读的( nS
, Dia
等)或需要共享( mX
, mY
等)。
关于性能下降的问题,你应该提供更多的信息@Zulan在评论中解释。 这里一个非常有用的指标是你的函数被调用了多少次,以及它所花费的应用程序总时间中的哪一部分(检查这实际上是一个热点)。 具有应用程序执行时间和累积的功能时间会很好。
您可以使用许多工具(如gprof
的调用图)来执行此操作,但在没有OpenMP的情况下运行它。
上一篇: OpenMP slow private function
下一篇: problems getting OpenMP 4.0 to run in eclipse (Linux Mint)